metric_fu-roodi 2.2.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 (66) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +6 -0
  4. data/History.txt +93 -0
  5. data/Manifest.txt +56 -0
  6. data/README.txt +98 -0
  7. data/Rakefile +35 -0
  8. data/bin/metric_fu-roodi +21 -0
  9. data/bin/metric_fu-roodi-describe +7 -0
  10. data/lib/roodi.rb +3 -0
  11. data/lib/roodi/checks.rb +18 -0
  12. data/lib/roodi/checks/abc_metric_method_check.rb +79 -0
  13. data/lib/roodi/checks/assignment_in_conditional_check.rb +32 -0
  14. data/lib/roodi/checks/case_missing_else_check.rb +20 -0
  15. data/lib/roodi/checks/check.rb +76 -0
  16. data/lib/roodi/checks/class_line_count_check.rb +28 -0
  17. data/lib/roodi/checks/class_name_check.rb +31 -0
  18. data/lib/roodi/checks/class_variable_check.rb +24 -0
  19. data/lib/roodi/checks/control_coupling_check.rb +20 -0
  20. data/lib/roodi/checks/cyclomatic_complexity_block_check.rb +41 -0
  21. data/lib/roodi/checks/cyclomatic_complexity_check.rb +50 -0
  22. data/lib/roodi/checks/cyclomatic_complexity_method_check.rb +42 -0
  23. data/lib/roodi/checks/empty_rescue_body_check.rb +32 -0
  24. data/lib/roodi/checks/for_loop_check.rb +20 -0
  25. data/lib/roodi/checks/line_count_check.rb +22 -0
  26. data/lib/roodi/checks/method_line_count_check.rb +29 -0
  27. data/lib/roodi/checks/method_name_check.rb +31 -0
  28. data/lib/roodi/checks/missing_foreign_key_index_check.rb +99 -0
  29. data/lib/roodi/checks/module_line_count_check.rb +28 -0
  30. data/lib/roodi/checks/module_name_check.rb +31 -0
  31. data/lib/roodi/checks/name_check.rb +16 -0
  32. data/lib/roodi/checks/npath_complexity_check.rb +75 -0
  33. data/lib/roodi/checks/npath_complexity_method_check.rb +29 -0
  34. data/lib/roodi/checks/parameter_number_check.rb +34 -0
  35. data/lib/roodi/core.rb +1 -0
  36. data/lib/roodi/core/checking_visitor.rb +26 -0
  37. data/lib/roodi/core/error.rb +17 -0
  38. data/lib/roodi/core/parser.rb +30 -0
  39. data/lib/roodi/core/runner.rb +81 -0
  40. data/lib/roodi/core/visitable_sexp.rb +25 -0
  41. data/lib/roodi/version.rb +3 -0
  42. data/lib/roodi_task.rb +35 -0
  43. data/roodi.gemspec +26 -0
  44. data/roodi.yml +25 -0
  45. data/spec/roodi/checks/abc_metric_method_check_spec.rb +89 -0
  46. data/spec/roodi/checks/assignment_in_conditional_check_spec.rb +105 -0
  47. data/spec/roodi/checks/case_missing_else_check_spec.rb +32 -0
  48. data/spec/roodi/checks/class_line_count_check_spec.rb +39 -0
  49. data/spec/roodi/checks/class_name_check_spec.rb +39 -0
  50. data/spec/roodi/checks/class_variable_check_spec.rb +17 -0
  51. data/spec/roodi/checks/control_coupling_check_spec.rb +23 -0
  52. data/spec/roodi/checks/cyclomatic_complexity_block_check_spec.rb +67 -0
  53. data/spec/roodi/checks/cyclomatic_complexity_method_check_spec.rb +200 -0
  54. data/spec/roodi/checks/empty_rescue_body_check_spec.rb +140 -0
  55. data/spec/roodi/checks/for_loop_check_spec.rb +18 -0
  56. data/spec/roodi/checks/method_line_count_check_spec.rb +56 -0
  57. data/spec/roodi/checks/method_name_check_spec.rb +76 -0
  58. data/spec/roodi/checks/missing_foreign_key_index_check_spec.rb +33 -0
  59. data/spec/roodi/checks/module_line_count_check_spec.rb +39 -0
  60. data/spec/roodi/checks/module_name_check_spec.rb +27 -0
  61. data/spec/roodi/checks/npath_complexity_method_check_spec.rb +53 -0
  62. data/spec/roodi/checks/parameter_number_check_spec.rb +47 -0
  63. data/spec/roodi/core/runner_spec.rb +25 -0
  64. data/spec/roodi/roodi.yml +2 -0
  65. data/spec/spec_helper.rb +3 -0
  66. metadata +149 -0
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Roodi::Checks::ControlCouplingCheck do
4
+ before(:each) do
5
+ @roodi = Roodi::Core::Runner.new(Roodi::Checks::ControlCouplingCheck.make)
6
+ end
7
+
8
+ it "should reject methods with if checks using a parameter" do
9
+ content = <<-END
10
+ def write(quoted, foo)
11
+ if quoted
12
+ write_quoted(@value)
13
+ else
14
+ puts @value
15
+ end
16
+ end
17
+ END
18
+ @roodi.check_content(content)
19
+ errors = @roodi.errors
20
+ errors.should_not be_empty
21
+ errors[0].to_s.should match(/dummy-file.rb:[2-3] - Method \"write\" uses the argument \"quoted\" for internal control./)
22
+ end
23
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Roodi::Checks::CyclomaticComplexityBlockCheck do
4
+ before(:each) do
5
+ @roodi = Roodi::Core::Runner.new(Roodi::Checks::CyclomaticComplexityBlockCheck.make({'complexity' => 0}))
6
+ end
7
+
8
+ def verify_content_complexity(content, complexity)
9
+ @roodi.check_content(content)
10
+ errors = @roodi.errors
11
+ errors.should_not be_empty
12
+ errors[0].to_s.should match(/dummy-file.rb:[2-4] - Block cyclomatic complexity is #{complexity}. It should be 0 or less./)
13
+ end
14
+
15
+ it "should find a simple block" do
16
+ content = <<-END
17
+ def method_name
18
+ it "should be a simple block" do
19
+ call_foo
20
+ end
21
+ end
22
+ END
23
+ verify_content_complexity(content, 1)
24
+ end
25
+
26
+ it "should find a block with multiple paths" do
27
+ content = <<-END
28
+ def method_name
29
+ it "should be a complex block" do
30
+ call_foo if some_condition
31
+ end
32
+ end
33
+ END
34
+ verify_content_complexity(content, 2)
35
+ end
36
+
37
+ it "should evaluate real example 1 correctly" do
38
+ content = <<-END
39
+ def method_name
40
+ UNIXMbox.lock(@filename) {|f|
41
+ begin
42
+ f.each do |line|
43
+ if /\AFrom / === line
44
+ w.close if w
45
+ File.utime time, time, port.filename if time
46
+
47
+ port = @real.new_port
48
+ w = port.wopen
49
+ time = fromline2time(line)
50
+ else
51
+ w.print line if w
52
+ end
53
+ end
54
+ ensure
55
+ if w and not w.closed?
56
+ w.close
57
+ File.utime time, time, port.filename if time
58
+ end
59
+ end
60
+ f.truncate(0) unless @readonly
61
+ @updated = Time.now
62
+ }
63
+ end
64
+ END
65
+ verify_content_complexity(content, 9)
66
+ end
67
+ end
@@ -0,0 +1,200 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Roodi::Checks::CyclomaticComplexityMethodCheck do
4
+ before(:each) do
5
+ @roodi = Roodi::Core::Runner.new(Roodi::Checks::CyclomaticComplexityMethodCheck.make({'complexity' => 0}))
6
+ end
7
+
8
+ def verify_content_complexity(content, complexity)
9
+ @roodi.check_content(content)
10
+ errors = @roodi.errors
11
+ errors.should_not be_empty
12
+ errors[0].to_s.should eql("dummy-file.rb:1 - Method name \"method_name\" cyclomatic complexity is #{complexity}. It should be 0 or less.")
13
+ end
14
+
15
+ it "should find an if block" do
16
+ content = <<-END
17
+ def method_name
18
+ call_foo if some_condition
19
+ end
20
+ END
21
+ verify_content_complexity(content, 2)
22
+ end
23
+
24
+ it "should find an unless block" do
25
+ content = <<-END
26
+ def method_name
27
+ call_foo unless some_condition
28
+ end
29
+ END
30
+ verify_content_complexity(content, 2)
31
+ end
32
+
33
+ it "should find an elsif block" do
34
+ content = <<-END
35
+ def method_name
36
+ if first_condition then
37
+ call_foo
38
+ elsif second_condition then
39
+ call_bar
40
+ else
41
+ call_bam
42
+ end
43
+ end
44
+ END
45
+ verify_content_complexity(content, 3)
46
+ end
47
+
48
+ it "should find a ternary operator" do
49
+ content = <<-END
50
+ def method_name
51
+ value = some_condition ? 1 : 2
52
+ end
53
+ END
54
+ verify_content_complexity(content, 2)
55
+ end
56
+
57
+ it "should find a while loop" do
58
+ content = <<-END
59
+ def method_name
60
+ while some_condition do
61
+ call_foo
62
+ end
63
+ end
64
+ END
65
+ verify_content_complexity(content, 2)
66
+ end
67
+
68
+ it "should find an until loop" do
69
+ content = <<-END
70
+ def method_name
71
+ until some_condition do
72
+ call_foo
73
+ end
74
+ end
75
+ END
76
+ verify_content_complexity(content, 2)
77
+ end
78
+
79
+ it "should find a for loop" do
80
+ content = <<-END
81
+ def method_name
82
+ for i in 1..2 do
83
+ call_method
84
+ end
85
+ end
86
+ END
87
+ verify_content_complexity(content, 2)
88
+ end
89
+
90
+ it "should find a rescue block" do
91
+ content = <<-END
92
+ def method_name
93
+ begin
94
+ call_foo
95
+ rescue Exception
96
+ call_bar
97
+ end
98
+ end
99
+ END
100
+ verify_content_complexity(content, 2)
101
+ end
102
+
103
+ it "should find a case and when block" do
104
+ content = <<-END
105
+ def method_name
106
+ case value
107
+ when 1
108
+ call_foo
109
+ when 2
110
+ call_bar
111
+ end
112
+ end
113
+ END
114
+ verify_content_complexity(content, 4)
115
+ end
116
+
117
+ it "should find the && symbol" do
118
+ content = <<-END
119
+ def method_name
120
+ call_foo && call_bar
121
+ end
122
+ END
123
+ verify_content_complexity(content, 2)
124
+ end
125
+
126
+ it "should find the and symbol" do
127
+ content = <<-END
128
+ def method_name
129
+ call_foo and call_bar
130
+ end
131
+ END
132
+ verify_content_complexity(content, 2)
133
+ end
134
+
135
+ it "should find the || symbol" do
136
+ content = <<-END
137
+ def method_name
138
+ call_foo || call_bar
139
+ end
140
+ END
141
+ verify_content_complexity(content, 2)
142
+ end
143
+
144
+ it "should find the or symbol" do
145
+ content = <<-END
146
+ def method_name
147
+ call_foo or call_bar
148
+ end
149
+ END
150
+ verify_content_complexity(content, 2)
151
+ end
152
+
153
+ it "should deal with nested if blocks containing && and ||" do
154
+ content = <<-END
155
+ def method_name
156
+ if first_condition then
157
+ call_foo if second_condition && third_condition
158
+ call_bar if fourth_condition || fifth_condition
159
+ end
160
+ end
161
+ END
162
+ verify_content_complexity(content, 6)
163
+ end
164
+
165
+ it "should count stupid nested if and else blocks" do
166
+ content = <<-END
167
+ def method_name
168
+ if first_condition then
169
+ call_foo
170
+ else
171
+ if second_condition then
172
+ call_bar
173
+ else
174
+ call_bam if third_condition
175
+ end
176
+ call_baz if fourth_condition
177
+ end
178
+ end
179
+ END
180
+ verify_content_complexity(content, 5)
181
+ end
182
+
183
+ it "should count only a single method" do
184
+ content = <<-END
185
+ def method_name_1
186
+ call_foo if some_condition
187
+ end
188
+ def method_name_2
189
+ call_foo if some_condition
190
+ end
191
+ END
192
+
193
+ @roodi.check_content(content)
194
+ errors = @roodi.errors
195
+ errors.should_not be_empty
196
+ errors[0].to_s.should eql("dummy-file.rb:1 - Method name \"method_name_1\" cyclomatic complexity is 2. It should be 0 or less.")
197
+ errors[1].to_s.should eql("dummy-file.rb:4 - Method name \"method_name_2\" cyclomatic complexity is 2. It should be 0 or less.")
198
+ end
199
+
200
+ end
@@ -0,0 +1,140 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Roodi::Checks::EmptyRescueBodyCheck do
4
+ before(:each) do
5
+ @roodi = Roodi::Core::Runner.new(Roodi::Checks::EmptyRescueBodyCheck.make)
6
+ end
7
+
8
+ it "should accept a rescue body with content and no parameter" do
9
+ content = <<-END
10
+ begin
11
+ call_method
12
+ rescue
13
+ puts "Recover from the call"
14
+ end
15
+ END
16
+ @roodi.check_content(content)
17
+ @roodi.errors.should be_empty
18
+ end
19
+
20
+ it "should accept a rescue body with a return" do
21
+ content = <<-END
22
+ begin
23
+ call_method
24
+ rescue
25
+ return true
26
+ end
27
+ END
28
+ @roodi.check_content(content)
29
+ @roodi.errors.should be_empty
30
+ end
31
+
32
+ it "should accept a method call that Ruby won't tell apart from a variable (a vcall)" do
33
+ content = <<-END
34
+ begin
35
+ call_method
36
+ rescue
37
+ show_error
38
+ end
39
+ END
40
+ @roodi.check_content(content)
41
+ @roodi.errors.should be_empty
42
+ end
43
+
44
+ it "should accept a rescue body with content and a parameter" do
45
+ content = <<-END
46
+ begin
47
+ call_method
48
+ rescue Exception => e
49
+ puts "Recover from the call"
50
+ end
51
+ END
52
+ @roodi.check_content(content)
53
+ @roodi.errors.should be_empty
54
+ end
55
+
56
+ it "should accept a rescue body with an assignment" do
57
+ content = <<-END
58
+ begin
59
+ call_method
60
+ rescue Exception => e
61
+ my_var = 1
62
+ end
63
+ END
64
+ @roodi.check_content(content)
65
+ @roodi.errors.should be_empty
66
+ end
67
+
68
+ it "should accept a rescue body with an attribute assignment" do
69
+ content = <<-END
70
+ begin
71
+ call_method
72
+ rescue Exception => e
73
+ self.var = 1
74
+ end
75
+ END
76
+ @roodi.check_content(content)
77
+ @roodi.errors.should be_empty
78
+ end
79
+
80
+ it "should reject an empty rescue block with no parameter" do
81
+ content = <<-END
82
+ begin
83
+ call_method
84
+ rescue
85
+ end
86
+ END
87
+ @roodi.check_content(content)
88
+ errors = @roodi.errors
89
+ errors.should_not be_empty
90
+ errors[0].to_s.should match(/dummy-file.rb:[3-4] - Rescue block should not be empty./)
91
+ end
92
+
93
+ it "should accept a rescue block with an explicit nil" do
94
+ content = <<-END
95
+ call_method rescue nil
96
+ END
97
+ @roodi.check_content(content)
98
+ errors = @roodi.errors
99
+ errors.should be_empty
100
+ end
101
+
102
+ it "should reject an empty rescue block with a parameter" do
103
+ content = <<-END
104
+ begin
105
+ call_method
106
+ rescue Exception => e
107
+ end
108
+ END
109
+ @roodi.check_content(content)
110
+ errors = @roodi.errors
111
+ errors.should_not be_empty
112
+ errors[0].to_s.should match(/dummy-file.rb:[3-4] - Rescue block should not be empty./)
113
+ end
114
+
115
+ it "should accept a rescue block that returns true" do
116
+ content = <<-END
117
+ begin
118
+ call_method
119
+ rescue Exception => e
120
+ true
121
+ end
122
+ END
123
+ @roodi.check_content(content)
124
+ errors = @roodi.errors
125
+ errors.should be_empty
126
+ end
127
+
128
+ it "should accept a rescue block that returns false" do
129
+ content = <<-END
130
+ begin
131
+ call_method
132
+ rescue Exception => e
133
+ false
134
+ end
135
+ END
136
+ @roodi.check_content(content)
137
+ errors = @roodi.errors
138
+ errors.should be_empty
139
+ end
140
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Roodi::Checks::ForLoopCheck do
4
+ before(:each) do
5
+ @roodi = Roodi::Core::Runner.new(Roodi::Checks::ForLoopCheck.make)
6
+ end
7
+
8
+ it "should reject for loops" do
9
+ content = <<-END
10
+ for i in 1..2
11
+ end
12
+ END
13
+ @roodi.check_content(content)
14
+ errors = @roodi.errors
15
+ errors.should_not be_empty
16
+ errors[0].to_s.should eql("dummy-file.rb:1 - Don't use 'for' loops. Use Enumerable.each instead.")
17
+ end
18
+ end