reek 1.6.6 → 2.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.
- 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
|