excellent 1.5.4

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 (106) hide show
  1. data/History.txt +69 -0
  2. data/README.rdoc +72 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/excellent +34 -0
  5. data/lib/simplabs/excellent.rb +16 -0
  6. data/lib/simplabs/excellent/checks.rb +33 -0
  7. data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +43 -0
  8. data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +39 -0
  9. data/lib/simplabs/excellent/checks/base.rb +62 -0
  10. data/lib/simplabs/excellent/checks/case_missing_else_check.rb +34 -0
  11. data/lib/simplabs/excellent/checks/class_line_count_check.rb +36 -0
  12. data/lib/simplabs/excellent/checks/class_name_check.rb +38 -0
  13. data/lib/simplabs/excellent/checks/control_coupling_check.rb +35 -0
  14. data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +48 -0
  15. data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +23 -0
  16. data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +48 -0
  17. data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +31 -0
  18. data/lib/simplabs/excellent/checks/flog_block_check.rb +40 -0
  19. data/lib/simplabs/excellent/checks/flog_check.rb +27 -0
  20. data/lib/simplabs/excellent/checks/flog_class_check.rb +40 -0
  21. data/lib/simplabs/excellent/checks/flog_method_check.rb +40 -0
  22. data/lib/simplabs/excellent/checks/for_loop_check.rb +42 -0
  23. data/lib/simplabs/excellent/checks/global_variable_check.rb +33 -0
  24. data/lib/simplabs/excellent/checks/line_count_check.rb +27 -0
  25. data/lib/simplabs/excellent/checks/method_line_count_check.rb +36 -0
  26. data/lib/simplabs/excellent/checks/method_name_check.rb +38 -0
  27. data/lib/simplabs/excellent/checks/module_line_count_check.rb +36 -0
  28. data/lib/simplabs/excellent/checks/module_name_check.rb +38 -0
  29. data/lib/simplabs/excellent/checks/name_check.rb +27 -0
  30. data/lib/simplabs/excellent/checks/nested_iterators_check.rb +34 -0
  31. data/lib/simplabs/excellent/checks/parameter_number_check.rb +38 -0
  32. data/lib/simplabs/excellent/checks/rails.rb +22 -0
  33. data/lib/simplabs/excellent/checks/rails/attr_accessible_check.rb +38 -0
  34. data/lib/simplabs/excellent/checks/rails/attr_protected_check.rb +39 -0
  35. data/lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb +37 -0
  36. data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +37 -0
  37. data/lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb +38 -0
  38. data/lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb +38 -0
  39. data/lib/simplabs/excellent/checks/rails/validations_check.rb +36 -0
  40. data/lib/simplabs/excellent/checks/singleton_variable_check.rb +33 -0
  41. data/lib/simplabs/excellent/command_line_runner.rb +37 -0
  42. data/lib/simplabs/excellent/extensions/sexp.rb +21 -0
  43. data/lib/simplabs/excellent/extensions/string.rb +28 -0
  44. data/lib/simplabs/excellent/formatters.rb +13 -0
  45. data/lib/simplabs/excellent/formatters/base.rb +49 -0
  46. data/lib/simplabs/excellent/formatters/html.rb +153 -0
  47. data/lib/simplabs/excellent/formatters/text.rb +40 -0
  48. data/lib/simplabs/excellent/parsing.rb +10 -0
  49. data/lib/simplabs/excellent/parsing/abc_measure.rb +52 -0
  50. data/lib/simplabs/excellent/parsing/block_context.rb +43 -0
  51. data/lib/simplabs/excellent/parsing/call_context.rb +52 -0
  52. data/lib/simplabs/excellent/parsing/case_context.rb +31 -0
  53. data/lib/simplabs/excellent/parsing/class_context.rb +99 -0
  54. data/lib/simplabs/excellent/parsing/code_processor.rb +165 -0
  55. data/lib/simplabs/excellent/parsing/conditional_context.rb +25 -0
  56. data/lib/simplabs/excellent/parsing/cvar_context.rb +28 -0
  57. data/lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb +73 -0
  58. data/lib/simplabs/excellent/parsing/flog_measure.rb +192 -0
  59. data/lib/simplabs/excellent/parsing/for_loop_context.rb +15 -0
  60. data/lib/simplabs/excellent/parsing/gvar_context.rb +21 -0
  61. data/lib/simplabs/excellent/parsing/if_context.rb +38 -0
  62. data/lib/simplabs/excellent/parsing/ivar_context.rb +32 -0
  63. data/lib/simplabs/excellent/parsing/method_context.rb +50 -0
  64. data/lib/simplabs/excellent/parsing/module_context.rb +29 -0
  65. data/lib/simplabs/excellent/parsing/parser.rb +35 -0
  66. data/lib/simplabs/excellent/parsing/resbody_context.rb +39 -0
  67. data/lib/simplabs/excellent/parsing/scopeable.rb +34 -0
  68. data/lib/simplabs/excellent/parsing/sexp_context.rb +125 -0
  69. data/lib/simplabs/excellent/parsing/singleton_method_context.rb +55 -0
  70. data/lib/simplabs/excellent/parsing/until_context.rb +24 -0
  71. data/lib/simplabs/excellent/parsing/while_context.rb +24 -0
  72. data/lib/simplabs/excellent/rake.rb +1 -0
  73. data/lib/simplabs/excellent/rake/excellent_task.rb +61 -0
  74. data/lib/simplabs/excellent/runner.rb +143 -0
  75. data/lib/simplabs/excellent/warning.rb +53 -0
  76. data/spec/checks/abc_metric_method_check_spec.rb +122 -0
  77. data/spec/checks/assignment_in_conditional_check_spec.rb +90 -0
  78. data/spec/checks/case_missing_else_check_spec.rb +42 -0
  79. data/spec/checks/class_line_count_check_spec.rb +62 -0
  80. data/spec/checks/class_name_check_spec.rb +48 -0
  81. data/spec/checks/control_coupling_check_spec.rb +103 -0
  82. data/spec/checks/cyclomatic_complexity_block_check_spec.rb +47 -0
  83. data/spec/checks/cyclomatic_complexity_method_check_spec.rb +210 -0
  84. data/spec/checks/empty_rescue_body_check_spec.rb +170 -0
  85. data/spec/checks/flog_block_check_spec.rb +28 -0
  86. data/spec/checks/flog_class_check_spec.rb +28 -0
  87. data/spec/checks/flog_method_check_spec.rb +46 -0
  88. data/spec/checks/for_loop_check_spec.rb +52 -0
  89. data/spec/checks/global_variable_check_spec.rb +66 -0
  90. data/spec/checks/method_line_count_check_spec.rb +49 -0
  91. data/spec/checks/method_name_check_spec.rb +112 -0
  92. data/spec/checks/module_line_count_check_spec.rb +48 -0
  93. data/spec/checks/module_name_check_spec.rb +61 -0
  94. data/spec/checks/nested_iterators_check_spec.rb +44 -0
  95. data/spec/checks/parameter_number_check_spec.rb +97 -0
  96. data/spec/checks/rails/attr_accessible_check_spec.rb +79 -0
  97. data/spec/checks/rails/attr_protected_check_spec.rb +77 -0
  98. data/spec/checks/rails/custom_initialize_method_check_spec.rb +58 -0
  99. data/spec/checks/rails/instance_var_in_partial_check_spec.rb +40 -0
  100. data/spec/checks/rails/params_hash_in_view_check_spec.rb +40 -0
  101. data/spec/checks/rails/session_hash_in_view_check_spec.rb +40 -0
  102. data/spec/checks/rails/validations_check_spec.rb +81 -0
  103. data/spec/checks/singleton_variable_check_spec.rb +66 -0
  104. data/spec/extensions/string_spec.rb +13 -0
  105. data/spec/spec_helper.rb +13 -0
  106. metadata +189 -0
@@ -0,0 +1,47 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::CyclomaticComplexityBlockCheck do
4
+
5
+ before(:each) do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::CyclomaticComplexityBlockCheck.new({ :threshold => 0 }))
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should find a simple block' do
12
+ code = <<-END
13
+ it 'should be a simple block' do
14
+ call_foo
15
+ end
16
+ END
17
+
18
+ verify_code_complexity(code, 1)
19
+ end
20
+
21
+ it 'should find a block with multiple paths' do
22
+ code = <<-END
23
+ it 'should be a complex block' do
24
+ if some_condition
25
+ call_foo
26
+ else
27
+ call_bar
28
+ end
29
+ end
30
+ END
31
+
32
+ verify_code_complexity(code, 2)
33
+ end
34
+
35
+ end
36
+
37
+ def verify_code_complexity(code, score)
38
+ @excellent.check_code(code)
39
+ warnings = @excellent.warnings
40
+
41
+ warnings.should_not be_empty
42
+ warnings[0].info.should == { :block => 'block', :score => score }
43
+ warnings[0].line_number.should == 1
44
+ warnings[0].message.should == "block has cyclomatic complexity of #{score}."
45
+ end
46
+
47
+ end
@@ -0,0 +1,210 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::CyclomaticComplexityMethodCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::CyclomaticComplexityMethodCheck.new({ :threshold => 0 }))
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should find an if block' do
12
+ code = <<-END
13
+ def method_name
14
+ call_foo if some_condition
15
+ end
16
+ END
17
+
18
+ verify_code_complexity(code, 2)
19
+ end
20
+
21
+ it 'should find an unless block' do
22
+ code = <<-END
23
+ def method_name
24
+ call_foo unless some_condition
25
+ end
26
+ END
27
+
28
+ verify_code_complexity(code, 2)
29
+ end
30
+
31
+ it 'should find an elsif block' do
32
+ code = <<-END
33
+ def method_name
34
+ if first_condition then
35
+ call_foo
36
+ elsif second_condition then
37
+ call_bar
38
+ else
39
+ call_bam
40
+ end
41
+ end
42
+ END
43
+
44
+ verify_code_complexity(code, 3)
45
+ end
46
+
47
+ it 'should find a ternary operator' do
48
+ code = <<-END
49
+ def method_name
50
+ value = some_condition ? 1 : 2
51
+ end
52
+ END
53
+
54
+ verify_code_complexity(code, 2)
55
+ end
56
+
57
+ it 'should find a while loop' do
58
+ code = <<-END
59
+ def method_name
60
+ while some_condition do
61
+ call_foo
62
+ end
63
+ end
64
+ END
65
+
66
+ verify_code_complexity(code, 2)
67
+ end
68
+
69
+ it 'should find an until loop' do
70
+ code = <<-END
71
+ def method_name
72
+ until some_condition do
73
+ call_foo
74
+ end
75
+ end
76
+ END
77
+
78
+ verify_code_complexity(code, 2)
79
+ end
80
+
81
+ it 'should find a for loop' do
82
+ code = <<-END
83
+ def method_name
84
+ for i in 1..2 do
85
+ call_method
86
+ end
87
+ end
88
+ END
89
+
90
+ verify_code_complexity(code, 2)
91
+ end
92
+
93
+ it 'should find a rescue block' do
94
+ code = <<-END
95
+ def method_name
96
+ begin
97
+ call_foo
98
+ rescue Exception
99
+ call_bar
100
+ end
101
+ end
102
+ END
103
+
104
+ verify_code_complexity(code, 2)
105
+ end
106
+
107
+ it 'should find a case and when block' do
108
+ code = <<-END
109
+ def method_name
110
+ case value
111
+ when 1
112
+ call_foo
113
+ when 2
114
+ call_bar
115
+ end
116
+ end
117
+ END
118
+
119
+ verify_code_complexity(code, 4)
120
+ end
121
+
122
+ describe 'when processing operators' do
123
+
124
+ ['&&', 'and', '||', 'or'].each do |operator|
125
+
126
+ it "should find #{operator}" do
127
+ code = <<-END
128
+ def method_name
129
+ call_foo #{operator} call_bar
130
+ end
131
+ END
132
+
133
+ verify_code_complexity(code, 2)
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+
140
+ it 'should deal with nested if blocks containing && and ||' do
141
+ code = <<-END
142
+ def method_name
143
+ if first_condition then
144
+ call_foo if second_condition && third_condition
145
+ call_bar if fourth_condition || fifth_condition
146
+ end
147
+ end
148
+ END
149
+
150
+ verify_code_complexity(code, 6)
151
+ end
152
+
153
+ it 'should count stupid nested if and else blocks' do
154
+ code = <<-END
155
+ def method_name
156
+ if first_condition then
157
+ call_foo
158
+ else
159
+ if second_condition then
160
+ call_bar
161
+ else
162
+ call_bam if third_condition
163
+ end
164
+ call_baz if fourth_condition
165
+ end
166
+ end
167
+ END
168
+
169
+ verify_code_complexity(code, 5)
170
+ end
171
+
172
+ it 'should also work on singleton methods' do
173
+ code = <<-END
174
+ class Class
175
+ def self.method_name
176
+ if first_condition then
177
+ call_foo
178
+ else
179
+ if second_condition then
180
+ call_bar
181
+ else
182
+ call_bam if third_condition
183
+ end
184
+ call_baz if fourth_condition
185
+ end
186
+ end
187
+ end
188
+ END
189
+ @excellent.check_code(code)
190
+ warnings = @excellent.warnings
191
+
192
+ warnings.should_not be_empty
193
+ warnings[0].info.should == { :method => 'Class.method_name', :score => 5 }
194
+ warnings[0].line_number.should == 2
195
+ warnings[0].message.should == "Class.method_name has cyclomatic complexity of 5."
196
+ end
197
+
198
+ end
199
+
200
+ def verify_code_complexity(code, score)
201
+ @excellent.check_code(code)
202
+ warnings = @excellent.warnings
203
+
204
+ warnings.should_not be_empty
205
+ warnings[0].info.should == { :method => 'method_name', :score => score }
206
+ warnings[0].line_number.should == 1
207
+ warnings[0].message.should == "method_name has cyclomatic complexity of #{score}."
208
+ end
209
+
210
+ end
@@ -0,0 +1,170 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::EmptyRescueBodyCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::EmptyRescueBodyCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept a rescue body with content and no parameter' do
12
+ code = <<-END
13
+ begin
14
+ call_method
15
+ rescue
16
+ puts "Recover from the call"
17
+ end
18
+ END
19
+ @excellent.check_code(code)
20
+
21
+ @excellent.warnings.should be_empty
22
+ end
23
+
24
+ it 'should accept a rescue body with a return' do
25
+ code = <<-END
26
+ begin
27
+ call_method
28
+ rescue
29
+ return true
30
+ end
31
+ END
32
+ @excellent.check_code(code)
33
+
34
+ @excellent.warnings.should be_empty
35
+ end
36
+
37
+ it "should accept a virtual method call" do
38
+ code = <<-END
39
+ begin
40
+ call_method
41
+ rescue
42
+ show_error
43
+ end
44
+ END
45
+ @excellent.check_code(code)
46
+
47
+ @excellent.warnings.should be_empty
48
+ end
49
+
50
+ it 'should accept a rescue body with code and a parameter' do
51
+ code = <<-END
52
+ begin
53
+ call_method
54
+ rescue Exception => e
55
+ puts "Recover from the call"
56
+ end
57
+ END
58
+ @excellent.check_code(code)
59
+
60
+ @excellent.warnings.should be_empty
61
+ end
62
+
63
+ it 'should accept a rescue body with an assignment' do
64
+ code = <<-END
65
+ begin
66
+ call_method
67
+ rescue Exception => e
68
+ my_var = 1
69
+ end
70
+ END
71
+ @excellent.check_code(code)
72
+
73
+ @excellent.warnings.should be_empty
74
+ end
75
+
76
+ it 'should accept a rescue body with an attribute assignment' do
77
+ code = <<-END
78
+ begin
79
+ call_method
80
+ rescue Exception => e
81
+ self.var = 1
82
+ end
83
+ END
84
+ @excellent.check_code(code)
85
+
86
+ @excellent.warnings.should be_empty
87
+ end
88
+
89
+ it 'should accept an inline rescue statement' do
90
+ code = <<-END
91
+ value = call_method rescue 1
92
+ END
93
+ @excellent.check_code(code)
94
+
95
+ @excellent.warnings.should be_empty
96
+ end
97
+
98
+ it 'should accept an empty array as a statement' do
99
+ code = <<-END
100
+ value = call_method rescue []
101
+ END
102
+
103
+ @excellent.check_code(code)
104
+
105
+ @excellent.warnings.should be_empty
106
+ end
107
+
108
+ it 'should accept an empty hash as a statement' do
109
+ code = <<-END
110
+ value = call_method rescue {}
111
+ END
112
+
113
+ @excellent.check_code(code)
114
+
115
+ @excellent.warnings.should be_empty
116
+ end
117
+
118
+ it 'should accept a boolean as a statement' do
119
+ code = <<-END
120
+ value = call_method rescue false
121
+ END
122
+ @excellent.check_code(code)
123
+
124
+ @excellent.warnings.should be_empty
125
+ end
126
+
127
+ it 'should accept nil as a statement' do
128
+ code = <<-END
129
+ value = call_method rescue nil
130
+ END
131
+ @excellent.check_code(code)
132
+
133
+ @excellent.warnings.should be_empty
134
+ end
135
+
136
+ it 'should reject an empty rescue block with no parameter' do
137
+ code = <<-END
138
+ begin
139
+ call_method
140
+ rescue
141
+ end
142
+ END
143
+
144
+ verify_warning_found(code)
145
+ end
146
+
147
+ it 'should reject an empty rescue block with a parameter' do
148
+ code = <<-END
149
+ begin
150
+ call_method
151
+ rescue Exception => e
152
+ end
153
+ END
154
+
155
+ verify_warning_found(code)
156
+ end
157
+
158
+ end
159
+
160
+ def verify_warning_found(code)
161
+ @excellent.check_code(code)
162
+ warnings = @excellent.warnings
163
+
164
+ warnings.should_not be_empty
165
+ warnings[0].info.should == {}
166
+ warnings[0].line_number.should == 3
167
+ warnings[0].message.should == 'Rescue block is empty.'
168
+ end
169
+
170
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::FlogBlockCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::FlogBlockCheck.new({ :threshold => 0 }))
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should calculate the score correctly' do
12
+ code = <<-END
13
+ method_name do
14
+ puts 'test'
15
+ end
16
+ END
17
+ @excellent.check_code(code)
18
+ warnings = @excellent.warnings
19
+
20
+ warnings.should_not be_empty
21
+ warnings[0].info.should == { :block => 'block', :score => 3 }
22
+ warnings[0].line_number.should == 1
23
+ warnings[0].message.should == "block has flog score of 3."
24
+ end
25
+
26
+ end
27
+
28
+ end