reek 1.6.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +6 -9
- data/features/command_line_interface/options.feature +20 -16
- data/features/command_line_interface/stdin.feature +1 -1
- data/features/rake_task/rake_task.feature +0 -12
- data/features/reports/reports.feature +63 -23
- data/features/reports/yaml.feature +3 -3
- data/features/samples.feature +3 -3
- data/lib/reek/cli/application.rb +5 -5
- data/lib/reek/cli/input.rb +1 -1
- data/lib/reek/cli/option_interpreter.rb +77 -0
- data/lib/reek/cli/options.rb +89 -82
- data/lib/reek/cli/report/formatter.rb +33 -24
- data/lib/reek/cli/report/heading_formatter.rb +45 -0
- data/lib/reek/cli/report/location_formatter.rb +23 -0
- data/lib/reek/cli/report/report.rb +32 -17
- data/lib/reek/configuration/app_configuration.rb +2 -2
- data/lib/reek/configuration/configuration_file_finder.rb +10 -10
- data/lib/reek/core/smell_repository.rb +3 -28
- data/lib/reek/rake/task.rb +35 -76
- data/lib/reek/smell_warning.rb +31 -16
- data/lib/reek/smells/nested_iterators.rb +1 -1
- data/lib/reek/smells/smell_detector.rb +9 -0
- data/lib/reek/smells/utility_function.rb +2 -1
- data/lib/reek/spec/should_reek.rb +0 -3
- data/lib/reek/spec/should_reek_of.rb +61 -12
- data/lib/reek/spec/should_reek_only_of.rb +12 -10
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +2 -2
- data/spec/factories/factories.rb +2 -5
- data/spec/reek/cli/html_report_spec.rb +28 -0
- data/spec/reek/cli/option_interperter_spec.rb +14 -0
- data/spec/reek/cli/text_report_spec.rb +95 -0
- data/spec/reek/cli/yaml_report_spec.rb +23 -0
- data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -6
- data/spec/reek/core/module_context_spec.rb +1 -1
- data/spec/reek/core/smell_repository_spec.rb +17 -0
- data/spec/reek/smell_warning_spec.rb +9 -11
- data/spec/reek/smells/boolean_parameter_spec.rb +11 -11
- data/spec/reek/smells/control_parameter_spec.rb +40 -40
- data/spec/reek/smells/data_clump_spec.rb +17 -17
- data/spec/reek/smells/duplicate_method_call_spec.rb +56 -33
- data/spec/reek/smells/feature_envy_spec.rb +44 -40
- data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
- data/spec/reek/smells/long_parameter_list_spec.rb +12 -12
- data/spec/reek/smells/long_yield_list_spec.rb +4 -4
- data/spec/reek/smells/module_initialize_spec.rb +3 -3
- data/spec/reek/smells/nested_iterators_spec.rb +71 -52
- data/spec/reek/smells/nil_check_spec.rb +6 -6
- data/spec/reek/smells/prima_donna_method_spec.rb +2 -2
- data/spec/reek/smells/too_many_statements_spec.rb +34 -34
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +7 -3
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +12 -12
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +28 -38
- data/spec/reek/smells/unused_parameters_spec.rb +16 -17
- data/spec/reek/smells/utility_function_spec.rb +21 -8
- data/spec/reek/spec/should_reek_of_spec.rb +18 -5
- data/spec/reek/spec/should_reek_only_of_spec.rb +7 -1
- data/spec/spec_helper.rb +22 -14
- metadata +15 -20
- data/lib/reek/cli/help_command.rb +0 -15
- data/lib/reek/cli/report/strategy.rb +0 -64
- data/lib/reek/cli/version_command.rb +0 -16
- data/spec/matchers/smell_of_matcher.rb +0 -95
- data/spec/reek/cli/help_command_spec.rb +0 -25
- data/spec/reek/cli/report_spec.rb +0 -132
- data/spec/reek/cli/version_command_spec.rb +0 -31
@@ -14,7 +14,7 @@ shared_examples_for 'a data clump detector' do
|
|
14
14
|
def third(pa) pa - pb + @fred; end
|
15
15
|
end
|
16
16
|
EOS
|
17
|
-
expect(src).not_to
|
17
|
+
expect(src).not_to reek_of(DataClump)
|
18
18
|
end
|
19
19
|
|
20
20
|
context 'with 3 identical pairs' do
|
@@ -62,9 +62,9 @@ EOS
|
|
62
62
|
def tri(pa, pb) pa - pb + @fred; end
|
63
63
|
end
|
64
64
|
EOS
|
65
|
-
expect(src).to
|
66
|
-
|
67
|
-
|
65
|
+
expect(src).to reek_of(DataClump,
|
66
|
+
count: 3,
|
67
|
+
parameters: ['pa', 'pb'])
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'reports 3 identical parameter sets' do
|
@@ -75,9 +75,9 @@ EOS
|
|
75
75
|
def third(pa, pb, pc) pa - pb + @fred; end
|
76
76
|
end
|
77
77
|
EOS
|
78
|
-
expect(src).to
|
79
|
-
|
80
|
-
|
78
|
+
expect(src).to reek_of(DataClump,
|
79
|
+
count: 3,
|
80
|
+
parameters: ['pa', 'pb', 'pc'])
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'reports re-ordered identical parameter sets' do
|
@@ -88,9 +88,9 @@ EOS
|
|
88
88
|
def third(pa, pb, pc) pa - pb + @fred; end
|
89
89
|
end
|
90
90
|
EOS
|
91
|
-
expect(src).to
|
92
|
-
|
93
|
-
|
91
|
+
expect(src).to reek_of(DataClump,
|
92
|
+
count: 3,
|
93
|
+
parameters: ['pa', 'pb', 'pc'])
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'counts only identical parameter sets' do
|
@@ -101,7 +101,7 @@ EOS
|
|
101
101
|
def fc(name, windowW, windowH) end
|
102
102
|
end
|
103
103
|
EOS
|
104
|
-
expect(src).not_to
|
104
|
+
expect(src).not_to reek_of(DataClump)
|
105
105
|
end
|
106
106
|
|
107
107
|
it 'gets a real example right' do
|
@@ -114,7 +114,7 @@ EOS
|
|
114
114
|
def c_raw_singleton (src, options) end
|
115
115
|
end
|
116
116
|
EOS
|
117
|
-
expect(src).to
|
117
|
+
expect(src).to reek_of(DataClump, count: 5)
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'correctly checks number of occurences' do
|
@@ -127,7 +127,7 @@ EOS
|
|
127
127
|
def fe(p5, p1, p2) end
|
128
128
|
end
|
129
129
|
EOS
|
130
|
-
expect(src).not_to
|
130
|
+
expect(src).not_to reek_of(DataClump)
|
131
131
|
end
|
132
132
|
|
133
133
|
it 'detects clumps smaller than the total number of arguments' do
|
@@ -138,8 +138,8 @@ EOS
|
|
138
138
|
def fc(p4, p1, p2) end
|
139
139
|
end
|
140
140
|
EOS
|
141
|
-
expect(src).to
|
142
|
-
|
141
|
+
expect(src).to reek_of(DataClump,
|
142
|
+
parameters: %w(p1 p2))
|
143
143
|
end
|
144
144
|
|
145
145
|
it 'ignores anonymous parameters' do
|
@@ -150,8 +150,8 @@ EOS
|
|
150
150
|
def fc(p1, p2, *) end
|
151
151
|
end
|
152
152
|
EOS
|
153
|
-
expect(src).to
|
154
|
-
|
153
|
+
expect(src).to reek_of(DataClump,
|
154
|
+
parameters: %w(p1 p2))
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
@@ -12,13 +12,13 @@ describe DuplicateMethodCall do
|
|
12
12
|
before :each do
|
13
13
|
@source_name = 'copy-cat'
|
14
14
|
@detector = DuplicateMethodCall.new(@source_name)
|
15
|
-
src =
|
16
|
-
def double_thing(other)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
EOS
|
15
|
+
src = <<-EOS
|
16
|
+
def double_thing(other)
|
17
|
+
other[@thing]
|
18
|
+
not_the_sam(at = all)
|
19
|
+
other[@thing]
|
20
|
+
end
|
21
|
+
EOS
|
22
22
|
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
23
23
|
smells = @detector.examine_context(ctx)
|
24
24
|
expect(smells.length).to eq(1)
|
@@ -39,24 +39,28 @@ EOS
|
|
39
39
|
context 'with repeated method calls' do
|
40
40
|
it 'reports repeated call' do
|
41
41
|
src = 'def double_thing() @other.thing + @other.thing end'
|
42
|
-
expect(src).to
|
42
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
|
43
43
|
end
|
44
|
+
|
44
45
|
it 'reports repeated call to lvar' do
|
45
46
|
src = 'def double_thing(other) other[@thing] + other[@thing] end'
|
46
|
-
expect(src).to
|
47
|
+
expect(src).to reek_of(DuplicateMethodCall, name: 'other[@thing]')
|
47
48
|
end
|
49
|
+
|
48
50
|
it 'reports call parameters' do
|
49
51
|
src = 'def double_thing() @other.thing(2,3) + @other.thing(2,3) end'
|
50
|
-
expect(src).to
|
52
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing(2, 3)')
|
51
53
|
end
|
54
|
+
|
52
55
|
it 'should report nested calls' do
|
53
56
|
src = 'def double_thing() @other.thing.foo + @other.thing.foo end'
|
54
|
-
expect(src).to
|
55
|
-
|
57
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
|
58
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing.foo')
|
56
59
|
end
|
60
|
+
|
57
61
|
it 'should ignore calls to new' do
|
58
62
|
src = 'def double_thing() @other.new + @other.new end'
|
59
|
-
expect(src).not_to
|
63
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
60
64
|
end
|
61
65
|
end
|
62
66
|
|
@@ -72,7 +76,7 @@ EOS
|
|
72
76
|
end
|
73
77
|
end
|
74
78
|
EOS
|
75
|
-
expect(src).not_to
|
79
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
@@ -84,7 +88,7 @@ EOS
|
|
84
88
|
bar { baz }
|
85
89
|
end
|
86
90
|
EOS
|
87
|
-
expect(src).to
|
91
|
+
expect(src).to reek_of(DuplicateMethodCall)
|
88
92
|
end
|
89
93
|
|
90
94
|
it 'reports no smell if the blocks are different' do
|
@@ -94,7 +98,7 @@ EOS
|
|
94
98
|
bar { qux }
|
95
99
|
end
|
96
100
|
EOS
|
97
|
-
expect(src).not_to
|
101
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
@@ -106,7 +110,7 @@ EOS
|
|
106
110
|
bar.qux { baz }
|
107
111
|
end
|
108
112
|
EOS
|
109
|
-
expect(src).to
|
113
|
+
expect(src).to reek_of(DuplicateMethodCall)
|
110
114
|
end
|
111
115
|
|
112
116
|
it 'reports a smell if the blocks are different' do
|
@@ -116,14 +120,14 @@ EOS
|
|
116
120
|
bar.qux { qux }
|
117
121
|
end
|
118
122
|
EOS
|
119
|
-
expect(src).to
|
123
|
+
expect(src).to reek_of(DuplicateMethodCall)
|
120
124
|
end
|
121
125
|
end
|
122
126
|
|
123
127
|
context 'with repeated attribute assignment' do
|
124
128
|
it 'reports repeated assignment' do
|
125
129
|
src = 'def double_thing(thing) @other[thing] = true; @other[thing] = true; end'
|
126
|
-
expect(src).to
|
130
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other[thing] = true')
|
127
131
|
end
|
128
132
|
it 'does not report multi-assignments' do
|
129
133
|
src = <<EOS
|
@@ -132,61 +136,80 @@ def _parse ctxt
|
|
132
136
|
error, ctxt.index = @err, @err_ind
|
133
137
|
end
|
134
138
|
EOS
|
135
|
-
expect(src).not_to
|
139
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
136
140
|
end
|
137
141
|
end
|
138
142
|
|
139
143
|
context 'non-repeated method calls' do
|
140
144
|
it 'should not report similar calls' do
|
141
145
|
src = 'def equals(other) other.thing == self.thing end'
|
142
|
-
expect(src).not_to
|
146
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
143
147
|
end
|
144
148
|
it 'should respect call parameters' do
|
145
149
|
src = 'def double_thing() @other.thing(3) + @other.thing(2) end'
|
146
|
-
expect(src).not_to
|
150
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
147
151
|
end
|
148
152
|
end
|
149
153
|
|
150
154
|
context 'allowing up to 3 calls' do
|
151
155
|
before :each do
|
152
|
-
@config = { DuplicateMethodCall::MAX_ALLOWED_CALLS_KEY => 3 }
|
156
|
+
@config = { DuplicateMethodCall: { DuplicateMethodCall::MAX_ALLOWED_CALLS_KEY => 3 } }
|
153
157
|
end
|
158
|
+
|
154
159
|
it 'does not report double calls' do
|
155
160
|
src = 'def double_thing() @other.thing + @other.thing end'
|
156
|
-
|
161
|
+
with_test_config(@config) do
|
162
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
163
|
+
end
|
157
164
|
end
|
165
|
+
|
158
166
|
it 'does not report triple calls' do
|
159
167
|
src = 'def double_thing() @other.thing + @other.thing + @other.thing end'
|
160
|
-
|
168
|
+
with_test_config(@config) do
|
169
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
170
|
+
end
|
161
171
|
end
|
172
|
+
|
162
173
|
it 'reports quadruple calls' do
|
163
174
|
src = '
|
164
175
|
def double_thing()
|
165
176
|
@other.thing + @other.thing + @other.thing + @other.thing
|
166
177
|
end
|
167
178
|
'
|
168
|
-
|
169
|
-
|
179
|
+
with_test_config(@config) do
|
180
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing', count: 4)
|
181
|
+
end
|
170
182
|
end
|
171
183
|
end
|
172
184
|
|
173
185
|
context 'allowing calls to some methods' do
|
174
186
|
before :each do
|
175
|
-
@config = { DuplicateMethodCall
|
187
|
+
@config = { DuplicateMethodCall:
|
188
|
+
{ DuplicateMethodCall::ALLOW_CALLS_KEY => ['@some.thing', /puts/] } }
|
176
189
|
end
|
190
|
+
|
177
191
|
it 'does not report calls to some methods' do
|
178
192
|
src = 'def double_some_thing() @some.thing + @some.thing end'
|
179
|
-
|
193
|
+
|
194
|
+
with_test_config(@config) do
|
195
|
+
expect(src).not_to reek_of(DuplicateMethodCall)
|
196
|
+
end
|
180
197
|
end
|
198
|
+
|
181
199
|
it 'reports calls to other methods' do
|
182
200
|
src = 'def double_other_thing() @other.thing + @other.thing end'
|
183
|
-
|
184
|
-
|
201
|
+
|
202
|
+
with_test_config(@config) do
|
203
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
|
204
|
+
end
|
185
205
|
end
|
206
|
+
|
186
207
|
it 'does not report calls to methods specifed with a regular expression' do
|
187
208
|
src = 'def double_puts() puts @other.thing; puts @other.thing end'
|
188
|
-
|
189
|
-
|
209
|
+
|
210
|
+
with_test_config(@config) do
|
211
|
+
expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
|
212
|
+
end
|
190
213
|
end
|
191
214
|
end
|
192
215
|
end
|
@@ -10,60 +10,64 @@ describe FeatureEnvy do
|
|
10
10
|
it 'should not report use of self' do
|
11
11
|
expect('def simple() self.to_s + self.to_i end').not_to reek_of(:FeatureEnvy)
|
12
12
|
end
|
13
|
+
|
13
14
|
it 'should not report vcall with no argument' do
|
14
15
|
expect('def simple() func; end').not_to reek_of(:FeatureEnvy)
|
15
16
|
end
|
17
|
+
|
16
18
|
it 'should not report single use' do
|
17
19
|
expect('def no_envy(arga) arga.barg(@item) end').not_to reek_of(:FeatureEnvy)
|
18
20
|
end
|
21
|
+
|
19
22
|
it 'should not report return value' do
|
20
23
|
expect('def no_envy(arga) arga.barg(@item); arga end').not_to reek_of(:FeatureEnvy)
|
21
24
|
end
|
25
|
+
|
22
26
|
it 'should ignore global variables' do
|
23
27
|
expect('def no_envy() $s2.to_a; $s2[@item] end').not_to reek_of(:FeatureEnvy)
|
24
28
|
end
|
29
|
+
|
25
30
|
it 'should not report class methods' do
|
26
31
|
expect('def simple() self.class.new.flatten_merge(self) end').
|
27
32
|
not_to reek_of(:FeatureEnvy)
|
28
33
|
end
|
34
|
+
|
29
35
|
it 'should not report single use of an ivar' do
|
30
36
|
expect('def no_envy() @item.to_a end').not_to reek_of(:FeatureEnvy)
|
31
37
|
end
|
38
|
+
|
32
39
|
it 'should not report returning an ivar' do
|
33
40
|
expect('def no_envy() @item.to_a; @item end').not_to reek_of(:FeatureEnvy)
|
34
41
|
end
|
42
|
+
|
35
43
|
it 'should not report ivar usage in a parameter' do
|
36
44
|
expect('def no_envy() @item.price + tax(@item) - savings(@item) end').
|
37
45
|
not_to reek_of(:FeatureEnvy)
|
38
46
|
end
|
47
|
+
|
39
48
|
it 'should not report single use of an lvar' do
|
40
49
|
expect('def no_envy() lv = @item; lv.to_a end').not_to reek_of(:FeatureEnvy)
|
41
50
|
end
|
51
|
+
|
42
52
|
it 'should not report returning an lvar' do
|
43
53
|
expect('def no_envy() lv = @item; lv.to_a; lv end').not_to reek_of(:FeatureEnvy)
|
44
54
|
end
|
55
|
+
|
45
56
|
it 'ignores lvar usage in a parameter' do
|
46
57
|
expect('def no_envy() lv = @item; lv.price + tax(lv) - savings(lv); end').
|
47
58
|
not_to reek_of(:FeatureEnvy)
|
48
59
|
end
|
60
|
+
|
49
61
|
it 'ignores multiple ivars' do
|
50
|
-
src =
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
EOS
|
62
|
+
src = <<-EOS
|
63
|
+
def func
|
64
|
+
@other.a
|
65
|
+
@other.b
|
66
|
+
@nother.c
|
67
|
+
@nother.d
|
68
|
+
end
|
69
|
+
EOS
|
58
70
|
expect(src).not_to reek_of(:FeatureEnvy)
|
59
|
-
#
|
60
|
-
# def other.func(me)
|
61
|
-
# a
|
62
|
-
# b
|
63
|
-
# me.nother_c
|
64
|
-
# me.nother_d
|
65
|
-
# end
|
66
|
-
#
|
67
71
|
end
|
68
72
|
end
|
69
73
|
|
@@ -73,34 +77,34 @@ EOS
|
|
73
77
|
def envy(arga)
|
74
78
|
arga.b(arga) + arga.c(@fred)
|
75
79
|
end
|
76
|
-
').to reek_only_of(:FeatureEnvy
|
80
|
+
').to reek_only_of(:FeatureEnvy)
|
77
81
|
end
|
78
82
|
end
|
79
83
|
|
80
84
|
it 'should report highest affinity' do
|
81
|
-
src =
|
82
|
-
def total_envy
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
89
|
-
EOS
|
90
|
-
expect(src).to reek_only_of(:FeatureEnvy
|
85
|
+
src = <<-EOS
|
86
|
+
def total_envy
|
87
|
+
fred = @item
|
88
|
+
total = 0
|
89
|
+
total += fred.price
|
90
|
+
total += fred.tax
|
91
|
+
total *= 1.15
|
92
|
+
end
|
93
|
+
EOS
|
94
|
+
expect(src).to reek_only_of(:FeatureEnvy)
|
91
95
|
end
|
92
96
|
|
93
97
|
it 'should report multiple affinities' do
|
94
|
-
src =
|
95
|
-
def total_envy
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
101
|
-
EOS
|
102
|
-
expect(src).to reek_of(:FeatureEnvy,
|
103
|
-
expect(src).to reek_of(:FeatureEnvy,
|
98
|
+
src = <<-EOS
|
99
|
+
def total_envy
|
100
|
+
fred = @item
|
101
|
+
total = 0
|
102
|
+
total += fred.price
|
103
|
+
total += fred.tax
|
104
|
+
end
|
105
|
+
EOS
|
106
|
+
expect(src).to reek_of(:FeatureEnvy, name: 'total')
|
107
|
+
expect(src).to reek_of(:FeatureEnvy, name: 'fred')
|
104
108
|
end
|
105
109
|
|
106
110
|
it 'should not be fooled by duplication' do
|
@@ -109,7 +113,7 @@ EOS
|
|
109
113
|
@cow.feed_to(thing.pig)
|
110
114
|
@duck.feed_to(thing.pig)
|
111
115
|
end
|
112
|
-
').to reek_only_of(:Duplication
|
116
|
+
').to reek_only_of(:Duplication)
|
113
117
|
end
|
114
118
|
|
115
119
|
it 'should count local calls' do
|
@@ -118,7 +122,7 @@ EOS
|
|
118
122
|
cow.feed_to(thing.pig)
|
119
123
|
duck.feed_to(thing.pig)
|
120
124
|
end
|
121
|
-
').to reek_only_of(:Duplication
|
125
|
+
').to reek_only_of(:Duplication)
|
122
126
|
end
|
123
127
|
|
124
128
|
it 'should report many calls to lvar' do
|
@@ -127,7 +131,7 @@ EOS
|
|
127
131
|
lv = @item
|
128
132
|
lv.price + lv.tax
|
129
133
|
end
|
130
|
-
').to reek_only_of(:FeatureEnvy
|
134
|
+
').to reek_only_of(:FeatureEnvy)
|
131
135
|
#
|
132
136
|
# def moved_version
|
133
137
|
# price + tax
|