metric_fu-roodi 2.2.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/bin/metric_fu-roodi +2 -19
  3. data/bin/metric_fu-roodi-describe +2 -5
  4. data/lib/roodi.rb +6 -2
  5. data/lib/roodi/version.rb +1 -1
  6. metadata +13 -119
  7. data/.gitignore +0 -3
  8. data/.rspec +0 -2
  9. data/Gemfile +0 -6
  10. data/History.txt +0 -111
  11. data/Manifest.txt +0 -56
  12. data/README.txt +0 -98
  13. data/Rakefile +0 -31
  14. data/TODO.md +0 -3
  15. data/lib/roodi/checks.rb +0 -18
  16. data/lib/roodi/checks/abc_metric_method_check.rb +0 -79
  17. data/lib/roodi/checks/assignment_in_conditional_check.rb +0 -32
  18. data/lib/roodi/checks/case_missing_else_check.rb +0 -20
  19. data/lib/roodi/checks/check.rb +0 -76
  20. data/lib/roodi/checks/class_line_count_check.rb +0 -28
  21. data/lib/roodi/checks/class_name_check.rb +0 -31
  22. data/lib/roodi/checks/class_variable_check.rb +0 -24
  23. data/lib/roodi/checks/control_coupling_check.rb +0 -20
  24. data/lib/roodi/checks/cyclomatic_complexity_block_check.rb +0 -41
  25. data/lib/roodi/checks/cyclomatic_complexity_check.rb +0 -50
  26. data/lib/roodi/checks/cyclomatic_complexity_method_check.rb +0 -42
  27. data/lib/roodi/checks/empty_rescue_body_check.rb +0 -32
  28. data/lib/roodi/checks/for_loop_check.rb +0 -20
  29. data/lib/roodi/checks/line_count_check.rb +0 -28
  30. data/lib/roodi/checks/method_line_count_check.rb +0 -29
  31. data/lib/roodi/checks/method_name_check.rb +0 -31
  32. data/lib/roodi/checks/missing_foreign_key_index_check.rb +0 -99
  33. data/lib/roodi/checks/module_line_count_check.rb +0 -28
  34. data/lib/roodi/checks/module_name_check.rb +0 -31
  35. data/lib/roodi/checks/name_check.rb +0 -16
  36. data/lib/roodi/checks/npath_complexity_check.rb +0 -75
  37. data/lib/roodi/checks/npath_complexity_method_check.rb +0 -29
  38. data/lib/roodi/checks/parameter_number_check.rb +0 -34
  39. data/lib/roodi/core.rb +0 -1
  40. data/lib/roodi/core/checking_visitor.rb +0 -26
  41. data/lib/roodi/core/error.rb +0 -17
  42. data/lib/roodi/core/parser.rb +0 -48
  43. data/lib/roodi/core/runner.rb +0 -81
  44. data/lib/roodi/core/visitable_sexp.rb +0 -25
  45. data/lib/roodi_task.rb +0 -35
  46. data/roodi.gemspec +0 -26
  47. data/roodi.yml +0 -25
  48. data/spec/roodi/checks/abc_metric_method_check_spec.rb +0 -89
  49. data/spec/roodi/checks/assignment_in_conditional_check_spec.rb +0 -105
  50. data/spec/roodi/checks/case_missing_else_check_spec.rb +0 -32
  51. data/spec/roodi/checks/class_line_count_check_spec.rb +0 -39
  52. data/spec/roodi/checks/class_name_check_spec.rb +0 -39
  53. data/spec/roodi/checks/class_variable_check_spec.rb +0 -17
  54. data/spec/roodi/checks/control_coupling_check_spec.rb +0 -23
  55. data/spec/roodi/checks/cyclomatic_complexity_block_check_spec.rb +0 -67
  56. data/spec/roodi/checks/cyclomatic_complexity_method_check_spec.rb +0 -200
  57. data/spec/roodi/checks/empty_rescue_body_check_spec.rb +0 -154
  58. data/spec/roodi/checks/for_loop_check_spec.rb +0 -18
  59. data/spec/roodi/checks/method_line_count_check_spec.rb +0 -56
  60. data/spec/roodi/checks/method_name_check_spec.rb +0 -76
  61. data/spec/roodi/checks/missing_foreign_key_index_check_spec.rb +0 -33
  62. data/spec/roodi/checks/module_line_count_check_spec.rb +0 -39
  63. data/spec/roodi/checks/module_name_check_spec.rb +0 -27
  64. data/spec/roodi/checks/npath_complexity_method_check_spec.rb +0 -53
  65. data/spec/roodi/checks/parameter_number_check_spec.rb +0 -47
  66. data/spec/roodi/core/runner_spec.rb +0 -25
  67. data/spec/roodi/roodi.yml +0 -2
  68. data/spec/spec_helper.rb +0 -3
@@ -1,34 +0,0 @@
1
- require 'roodi/checks/check'
2
-
3
- module Roodi
4
- module Checks
5
- # Checks a method to make sure the number of parameters it has is under the specified limit.
6
- #
7
- # A method taking too many parameters is a code smell that indicates it might be doing too
8
- # much, or that the parameters should be grouped into one or more objects of their own. It
9
- # probably needs some refactoring.
10
- class ParameterNumberCheck < Check
11
-
12
- DEFAULT_PARAMETER_COUNT = 5
13
-
14
- attr_accessor :parameter_count
15
-
16
- def initialize
17
- super()
18
- self.parameter_count = DEFAULT_PARAMETER_COUNT
19
- end
20
-
21
- def interesting_nodes
22
- [:defn]
23
- end
24
-
25
- def evaluate_start(node)
26
- method_name = node[1]
27
- arguments = node[2]
28
- actual_parameter_count = arguments.inject(-1) { |count, each| count = count + (each.class == Symbol ? 1 : 0) }
29
- add_error "Method name \"#{method_name}\" has #{actual_parameter_count} parameters. It should have #{@parameter_count} or less." unless actual_parameter_count <= @parameter_count
30
- end
31
-
32
- end
33
- end
34
- end
@@ -1 +0,0 @@
1
- require 'roodi/core/runner'
@@ -1,26 +0,0 @@
1
- module Roodi
2
- module Core
3
- class CheckingVisitor
4
- def initialize(*checks)
5
- @checks ||= {}
6
- checks.first.each do |check|
7
- nodes = check.interesting_nodes
8
- nodes.each do |node|
9
- @checks[node] ||= []
10
- @checks[node] << check
11
- @checks[node].uniq!
12
- end
13
- end
14
- end
15
-
16
- def visit(node)
17
- checks = @checks[node.node_type]
18
- checks.each {|check| check.evaluate_node_start(node)} unless checks.nil?
19
-
20
- node.visitable_children.each {|sexp| sexp.accept(self)}
21
-
22
- checks.each {|check| check.evaluate_node_end(node)} unless checks.nil?
23
- end
24
- end
25
- end
26
- end
@@ -1,17 +0,0 @@
1
- module Roodi
2
- module Core
3
- class Error
4
- attr_reader :filename, :line_number, :message
5
-
6
- def initialize(filename, line_number, message)
7
- @filename = filename
8
- @line_number = line_number
9
- @message = message
10
- end
11
-
12
- def to_s
13
- "#{@filename}:#{@line_number} - #{@message}"
14
- end
15
- end
16
- end
17
- end
@@ -1,48 +0,0 @@
1
- require 'rubygems'
2
- require 'ruby_parser'
3
- require 'rbconfig'
4
-
5
- module Roodi
6
- module Core
7
- class Parser
8
- def parse(content, filename)
9
- silence_stream(STDERR) do
10
- return silent_parse(content, filename)
11
- end
12
- end
13
-
14
- private
15
-
16
- def silence_stream(stream)
17
- old_stream = stream.dup
18
- stream.reopen(null_stream_output)
19
- stream.sync = true
20
- yield
21
- ensure
22
- stream.reopen(old_stream)
23
- end
24
-
25
- def silent_parse(content, filename)
26
- @parser ||= RubyParser.new
27
- @parser.parse(content, filename)
28
- end
29
-
30
- def null_stream_output
31
- null_output_for_platform(RbConfig::CONFIG['host_os'])
32
- end
33
-
34
- def null_output_for_platform(host_os)
35
- case host_os
36
- when windows_host_os_matcher
37
- 'NUL:'
38
- else
39
- '/dev/null'
40
- end
41
- end
42
-
43
- def windows_host_os_matcher
44
- /mingw|mswin32|cygwin/o
45
- end
46
- end
47
- end
48
- end
@@ -1,81 +0,0 @@
1
- require 'pp'
2
- require 'yaml'
3
-
4
- require 'roodi/core/checking_visitor'
5
- require 'roodi/core/parser'
6
- require 'roodi/core/visitable_sexp'
7
-
8
- module Roodi
9
- module Core
10
- class Runner
11
- DEFAULT_CONFIG = File.join(File.dirname(__FILE__), "..", "..", "..", "roodi.yml")
12
-
13
- attr_writer :config
14
-
15
- def initialize(*checks)
16
- @config = DEFAULT_CONFIG
17
- @checks = checks unless checks.empty?
18
- end
19
-
20
- def check(filename, content)
21
- @checks ||= load_checks
22
- @checker ||= CheckingVisitor.new(@checks)
23
- @checks.each {|check| check.start_file(filename)}
24
- node = parse(filename, content)
25
- node.accept(@checker) if node
26
- @checks.each {|check| check.end_file(filename)}
27
- end
28
-
29
- def check_content(content, filename = "dummy-file.rb")
30
- check(filename, content)
31
- end
32
-
33
- def check_file(filename)
34
- return unless File.exists?(filename)
35
- check(filename, File.read(filename))
36
- end
37
-
38
- def print(filename, content)
39
- node = parse(filename, content)
40
- puts "Line: #{node.line}"
41
- pp node
42
- end
43
-
44
- def print_content(content)
45
- print("dummy-file.rb", content)
46
- end
47
-
48
- def print_file(filename)
49
- print(filename, File.read(filename))
50
- end
51
-
52
- def errors
53
- @checks ||= []
54
- all_errors = @checks.collect {|check| check.errors}
55
- all_errors.flatten
56
- end
57
-
58
- private
59
-
60
- def parse(filename, content)
61
- begin
62
- Parser.new.parse(content, filename)
63
- rescue Exception => e
64
- puts "#{filename} looks like it's not a valid Ruby file. Skipping..." if ENV["ROODI_DEBUG"]
65
- nil
66
- end
67
- end
68
-
69
- def load_checks
70
- check_objects = []
71
- checks = YAML.load_file @config
72
- checks.each do |check_class_name, options|
73
- check_class = Roodi::Checks.const_get(check_class_name)
74
- check_objects << check_class.make(options || {})
75
- end
76
- check_objects
77
- end
78
-
79
- end
80
- end
81
- end
@@ -1,25 +0,0 @@
1
- require 'rubygems'
2
- require 'sexp'
3
-
4
- class Sexp
5
- def accept(visitor)
6
- visitor.visit(self)
7
- end
8
-
9
- def node_type
10
- first
11
- end
12
-
13
- def children
14
- find_all { | sexp | Sexp === sexp }
15
- end
16
-
17
- def is_language_node?
18
- first.class == Symbol
19
- end
20
-
21
- def visitable_children
22
- parent = is_language_node? ? sexp_body : self
23
- parent.children
24
- end
25
- end
@@ -1,35 +0,0 @@
1
- class RoodiTask < Rake::TaskLib
2
- attr_accessor :name
3
- attr_accessor :patterns
4
- attr_accessor :config
5
- attr_accessor :verbose
6
-
7
- def initialize name = :roodi, patterns = nil, config = nil
8
- @name = name
9
- @patterns = patterns || %w(app/**/*.rb lib/**/*.rb spec/**/*.rb test/**/*.rb)
10
- @config = config
11
- @verbose = Rake.application.options.trace
12
-
13
- yield self if block_given?
14
-
15
- define
16
- end
17
-
18
- def define
19
- desc "Check for design issues in: #{patterns.join(', ')}"
20
- task name do
21
- runner = Roodi::Core::Runner.new
22
-
23
- runner.config = config if config
24
-
25
- patterns.each do |pattern|
26
- Dir.glob(pattern).each { |file| runner.check_file(file) }
27
- end
28
-
29
- runner.errors.each {|error| puts error}
30
-
31
- raise "Found #{runner.errors.size} errors." unless runner.errors.empty?
32
- end
33
- self
34
- end
35
- end
@@ -1,26 +0,0 @@
1
- $: << File.expand_path("../lib", __FILE__)
2
- require "roodi/version"
3
-
4
- Gem::Specification.new do |gem|
5
-
6
- gem.name = "metric_fu-roodi"
7
- gem.summary = "Roodi stands for Ruby Object Oriented Design Inferometer"
8
- gem.description = "Roodi stands for Ruby Object Oriented Design Inferometer"
9
- gem.homepage = "http://roodi.rubyforge.org"
10
- gem.authors = ["Marty Andrews"]
11
- gem.email = "marty@cogent.co"
12
-
13
- gem.version = Roodi::VERSION.dup
14
- gem.platform = Gem::Platform::RUBY
15
- gem.add_runtime_dependency("ruby_parser")
16
- gem.homepage = "http://github.com/metricfu/roodi"
17
- # TODO check if this is necessary
18
- # gem.required_ruby_version = ">= 1.8.7"
19
- # gem.required_rubygems_version = ">= 1.3.6"
20
- gem.files = `git ls-files`.split($\)
21
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
- gem.require_paths = ["lib"]
24
- gem.license = 'MIT'
25
-
26
- end
data/roodi.yml DELETED
@@ -1,25 +0,0 @@
1
- AssignmentInConditionalCheck:
2
- CaseMissingElseCheck:
3
- ClassLineCountCheck:
4
- line_count: 300
5
- ClassNameCheck:
6
- pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
7
- ClassVariableCheck:
8
- CyclomaticComplexityBlockCheck:
9
- complexity: 4
10
- CyclomaticComplexityMethodCheck:
11
- complexity: 8
12
- EmptyRescueBodyCheck:
13
- ForLoopCheck:
14
- MethodLineCountCheck:
15
- line_count: 20
16
- MethodNameCheck:
17
- pattern: !ruby/regexp /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
18
- # MissingForeignKeyIndexCheck:
19
- ModuleLineCountCheck:
20
- line_count: 300
21
- ModuleNameCheck:
22
- pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
23
- ParameterNumberCheck:
24
- parameter_count: 5
25
-
@@ -1,89 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe Roodi::Checks::AbcMetricMethodCheck do
4
- before(:each) do
5
- @roodi = Roodi::Core::Runner.new(Roodi::Checks::AbcMetricMethodCheck.make({'score' => 0}))
6
- end
7
-
8
- def verify_content_score(content, a, b, c)
9
- score = Math.sqrt(a*a + b*b + c*c)
10
- @roodi.check_content(content)
11
- errors = @roodi.errors
12
- errors.should_not be_empty
13
- errors[0].to_s.should eql("dummy-file.rb:1 - Method name \"method_name\" has an ABC metric score of <#{a},#{b},#{c}> = #{score}. It should be 0 or less.")
14
- end
15
-
16
- # 1. Add one to the assignment count for each occurrence of an assignment
17
- # operator, excluding constant declarations:
18
- #
19
- # = *= /= %= += <<= >>= &= |= ^=
20
- describe "when processing assignments" do
21
- ['=', '*=', '/=', '%=', '+=', '<<=', '>>=', '&=', '|=', '^='].each do |each|
22
- it "should find #{each}" do
23
- content = <<-END
24
- def method_name
25
- foo #{each} 1
26
- end
27
- END
28
- verify_content_score(content, 1, 0, 0)
29
- end
30
- end
31
- end
32
-
33
- # 3. Add one to the branch count for each function call or class method
34
- # call.
35
- #
36
- # 4. Add one to the branch count for each occurrence of the new operator.
37
- describe "when processing branches" do
38
- it "should find a virtual method call" do
39
- content = <<-END
40
- def method_name
41
- call_foo
42
- end
43
- END
44
- verify_content_score(content, 0, 1, 0)
45
- end
46
-
47
- it "should find an explicit method call" do
48
- content = <<-END
49
- def method_name
50
- @object.call_foo
51
- end
52
- END
53
- verify_content_score(content, 0, 1, 0)
54
- end
55
-
56
- it "should exclude a condition" do
57
- content = <<-END
58
- def method_name
59
- @object.call_foo < 10
60
- end
61
- END
62
- verify_content_score(content, 0, 1, 1)
63
- end
64
- end
65
-
66
- # 5. Add one to the condition count for each use of a conditional operator:
67
- #
68
- # == != <= >= < >
69
- #
70
- # 6. Add one to the condition count for each use of the following
71
- # keywords:
72
- #
73
- # else case default try catch ?
74
- #
75
- # 7. Add one to the condition count for each unary conditional
76
- # expression.
77
- describe "when processing conditions" do
78
- ['==', '!=', '<=', '>=', '<', '>'].each do |each|
79
- it "should find #{each}" do
80
- content = <<-END
81
- def method_name
82
- 2 #{each} 1
83
- end
84
- END
85
- verify_content_score(content, 0, 0, 1)
86
- end
87
- end
88
- end
89
- end
@@ -1,105 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe Roodi::Checks::AssignmentInConditionalCheck do
4
- before(:each) do
5
- @roodi = Roodi::Core::Runner.new(Roodi::Checks::AssignmentInConditionalCheck.make)
6
- end
7
-
8
- it "should accept an assignment before an if clause" do
9
- content = <<-END
10
- count = count + 1 if some_condition
11
- END
12
- @roodi.check_content(content)
13
- errors = @roodi.errors
14
- errors.should be_empty
15
- end
16
-
17
- it "should reject an assignment inside an if clause" do
18
- content = <<-END
19
- call_foo if bar = bam
20
- END
21
- @roodi.check_content(content)
22
- errors = @roodi.errors
23
- errors.should_not be_empty
24
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
25
- end
26
-
27
- it "should reject an assignment inside an unless clause" do
28
- content = <<-END
29
- call_foo unless bar = bam
30
- END
31
- @roodi.check_content(content)
32
- errors = @roodi.errors
33
- errors.should_not be_empty
34
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
35
- end
36
-
37
- it "should reject an assignment inside a while clause" do
38
- content = <<-END
39
- call_foo while bar = bam
40
- END
41
- @roodi.check_content(content)
42
- errors = @roodi.errors
43
- errors.should_not be_empty
44
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
45
- end
46
-
47
- it "should reject an assignment inside an unless clause" do
48
- content = <<-END
49
- call_foo while bar = bam
50
- END
51
- @roodi.check_content(content)
52
- errors = @roodi.errors
53
- errors.should_not be_empty
54
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
55
- end
56
-
57
- it "should reject an assignment inside a a ternary operator check clause" do
58
- content = 'call_foo (bar = bam) ? baz : bad'
59
- @roodi.check_content(content)
60
- errors = @roodi.errors
61
- errors.should_not be_empty
62
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
63
- end
64
-
65
- it "should reject an assignment after an 'and'" do
66
- content = <<-END
67
- call_foo if bar and bam = baz
68
- END
69
- @roodi.check_content(content)
70
- errors = @roodi.errors
71
- errors.should_not be_empty
72
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
73
- end
74
-
75
-
76
- it "should reject an assignment after an 'or'" do
77
- content = <<-END
78
- call_foo if bar or bam = baz
79
- END
80
- @roodi.check_content(content)
81
- errors = @roodi.errors
82
- errors.should_not be_empty
83
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
84
- end
85
-
86
- it "should reject an assignment after an '&&'" do
87
- content = <<-END
88
- call_foo if bar && bam = baz
89
- END
90
- @roodi.check_content(content)
91
- errors = @roodi.errors
92
- errors.should_not be_empty
93
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
94
- end
95
-
96
- it "should reject an assignment after an '||'" do
97
- content = <<-END
98
- call_foo if bar || bam = baz
99
- END
100
- @roodi.check_content(content)
101
- errors = @roodi.errors
102
- errors.should_not be_empty
103
- errors[0].to_s.should eql("dummy-file.rb:1 - Found = in conditional. It should probably be an ==")
104
- end
105
- end