reek 1.4.0 → 1.5.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 +5 -0
- data/README.md +70 -92
- data/config/defaults.reek +3 -0
- data/features/samples.feature +24 -20
- data/features/step_definitions/reek_steps.rb +1 -1
- data/features/support/env.rb +7 -7
- data/lib/reek/core/code_context.rb +1 -1
- data/lib/reek/core/code_parser.rb +19 -18
- data/lib/reek/core/method_context.rb +8 -7
- data/lib/reek/core/module_context.rb +1 -1
- data/lib/reek/core/smell_repository.rb +1 -0
- data/lib/reek/core/sniffer.rb +3 -1
- data/lib/reek/rake/task.rb +1 -5
- data/lib/reek/smell_description.rb +26 -0
- data/lib/reek/smell_warning.rb +35 -49
- data/lib/reek/smells.rb +1 -0
- data/lib/reek/smells/attribute.rb +1 -1
- data/lib/reek/smells/control_parameter.rb +14 -7
- data/lib/reek/smells/data_clump.rb +1 -1
- data/lib/reek/smells/duplicate_method_call.rb +2 -9
- data/lib/reek/smells/module_initialize.rb +38 -0
- data/lib/reek/smells/nested_iterators.rb +1 -1
- data/lib/reek/smells/nil_check.rb +3 -3
- data/lib/reek/smells/repeated_conditional.rb +3 -2
- data/lib/reek/smells/smell_detector.rb +1 -1
- data/lib/reek/smells/too_many_instance_variables.rb +1 -1
- data/lib/reek/smells/too_many_methods.rb +1 -1
- data/lib/reek/smells/uncommunicative_method_name.rb +0 -4
- data/lib/reek/smells/uncommunicative_parameter_name.rb +0 -4
- data/lib/reek/smells/uncommunicative_variable_name.rb +11 -9
- data/lib/reek/smells/utility_function.rb +2 -2
- data/lib/reek/source/ast_node.rb +40 -0
- data/lib/reek/source/ast_node_class_map.rb +37 -0
- data/lib/reek/source/reference_collector.rb +3 -3
- data/lib/reek/source/sexp_extensions.rb +133 -59
- data/lib/reek/source/sexp_formatter.rb +10 -4
- data/lib/reek/source/sexp_node.rb +25 -17
- data/lib/reek/source/source_code.rb +21 -9
- data/lib/reek/source/tree_dresser.rb +10 -33
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +2 -4
- data/spec/matchers/smell_of_matcher.rb +9 -1
- data/spec/quality/reek_source_spec.rb +0 -35
- data/spec/reek/core/code_context_spec.rb +22 -8
- data/spec/reek/core/method_context_spec.rb +10 -10
- data/spec/reek/smell_description_spec.rb +43 -0
- data/spec/reek/smell_warning_spec.rb +0 -3
- data/spec/reek/smells/control_parameter_spec.rb +24 -0
- data/spec/reek/smells/feature_envy_spec.rb +50 -17
- data/spec/reek/smells/irresponsible_module_spec.rb +25 -17
- data/spec/reek/smells/module_initialize_spec.rb +20 -0
- data/spec/reek/smells/prima_donna_method_spec.rb +2 -2
- data/spec/reek/smells/repeated_conditional_spec.rb +10 -4
- data/spec/reek/smells/too_many_instance_variables_spec.rb +47 -21
- data/spec/reek/smells/too_many_statements_spec.rb +11 -1
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
- data/spec/reek/smells/utility_function_spec.rb +26 -25
- data/spec/reek/source/sexp_extensions_spec.rb +164 -91
- data/spec/reek/source/sexp_formatter_spec.rb +13 -1
- data/spec/reek/source/sexp_node_spec.rb +5 -5
- data/spec/reek/source/source_code_spec.rb +18 -6
- data/spec/reek/source/tree_dresser_spec.rb +5 -5
- data/spec/spec_helper.rb +8 -4
- metadata +16 -50
@@ -3,96 +3,138 @@ require 'reek/source/sexp_extensions'
|
|
3
3
|
|
4
4
|
include Reek::Source
|
5
5
|
|
6
|
-
describe SexpExtensions::
|
6
|
+
describe SexpExtensions::DefNode do
|
7
7
|
context 'with no parameters' do
|
8
8
|
before :each do
|
9
|
-
@node = s(:
|
10
|
-
@node.extend(SexpExtensions::DefnNode)
|
9
|
+
@node = s(:def, :hello, s(:args))
|
11
10
|
end
|
11
|
+
|
12
12
|
it 'has no arg names' do
|
13
|
-
expect(@node.arg_names).to eq
|
13
|
+
expect(@node.arg_names).to eq []
|
14
14
|
end
|
15
|
+
|
15
16
|
it 'has no parameter names' do
|
16
|
-
expect(@node.parameter_names).to eq
|
17
|
+
expect(@node.parameter_names).to eq []
|
17
18
|
end
|
19
|
+
|
18
20
|
it 'includes outer scope in its full name' do
|
19
|
-
expect(@node.full_name('Fred')).to eq
|
21
|
+
expect(@node.full_name('Fred')).to eq 'Fred#hello'
|
20
22
|
end
|
23
|
+
|
21
24
|
it 'includes no marker in its full name with empty outer scope' do
|
22
|
-
expect(@node.full_name('')).to eq
|
25
|
+
expect(@node.full_name('')).to eq 'hello'
|
23
26
|
end
|
27
|
+
|
24
28
|
end
|
25
29
|
|
26
30
|
context 'with 1 parameter' do
|
27
31
|
before :each do
|
28
|
-
@node = s(:
|
29
|
-
|
32
|
+
@node = s(:def, :hello,
|
33
|
+
s(:args, s(:arg, :param)))
|
30
34
|
end
|
35
|
+
|
31
36
|
it 'has 1 arg name' do
|
32
|
-
expect(@node.arg_names).to eq
|
37
|
+
expect(@node.arg_names).to eq [:param]
|
33
38
|
end
|
39
|
+
|
34
40
|
it 'has 1 parameter name' do
|
35
|
-
expect(@node.parameter_names).to eq
|
41
|
+
expect(@node.parameter_names).to eq [:param]
|
36
42
|
end
|
43
|
+
|
37
44
|
it 'includes outer scope in its full name' do
|
38
|
-
expect(@node.full_name('Fred')).to eq
|
45
|
+
expect(@node.full_name('Fred')).to eq 'Fred#hello'
|
39
46
|
end
|
47
|
+
|
40
48
|
it 'includes no marker in its full name with empty outer scope' do
|
41
|
-
expect(@node.full_name('')).to eq
|
49
|
+
expect(@node.full_name('')).to eq 'hello'
|
42
50
|
end
|
51
|
+
|
43
52
|
end
|
44
53
|
|
45
|
-
context 'with a block' do
|
54
|
+
context 'with a block parameter' do
|
46
55
|
before :each do
|
47
|
-
@node = s(:
|
48
|
-
|
56
|
+
@node = s(:def, :hello,
|
57
|
+
s(:args,
|
58
|
+
s(:arg, :param),
|
59
|
+
s(:blockarg, :blk)))
|
49
60
|
end
|
61
|
+
|
50
62
|
it 'has 1 arg name' do
|
51
|
-
expect(@node.arg_names).to eq
|
63
|
+
expect(@node.arg_names).to eq [:param]
|
52
64
|
end
|
65
|
+
|
53
66
|
it 'has 2 parameter names' do
|
54
|
-
expect(@node.parameter_names).to eq
|
67
|
+
expect(@node.parameter_names).to eq [:param, :blk]
|
55
68
|
end
|
69
|
+
|
56
70
|
it 'includes outer scope in its full name' do
|
57
|
-
expect(@node.full_name('Fred')).to eq
|
71
|
+
expect(@node.full_name('Fred')).to eq 'Fred#hello'
|
58
72
|
end
|
73
|
+
|
59
74
|
it 'includes no marker in its full name with empty outer scope' do
|
60
|
-
expect(@node.full_name('')).to eq
|
75
|
+
expect(@node.full_name('')).to eq 'hello'
|
61
76
|
end
|
77
|
+
|
62
78
|
end
|
63
79
|
|
64
80
|
context 'with 1 defaulted parameter' do
|
65
81
|
before :each do
|
66
|
-
@node = s(:
|
67
|
-
|
82
|
+
@node = s(:def, :hello,
|
83
|
+
s(:args,
|
84
|
+
s(:optarg, :param, s(:array))))
|
68
85
|
end
|
86
|
+
|
69
87
|
it 'has 1 arg name' do
|
70
|
-
expect(@node.arg_names).to eq
|
88
|
+
expect(@node.arg_names).to eq [:param]
|
71
89
|
end
|
90
|
+
|
72
91
|
it 'has 1 parameter name' do
|
73
|
-
expect(@node.parameter_names).to eq
|
92
|
+
expect(@node.parameter_names).to eq [:param]
|
74
93
|
end
|
94
|
+
|
75
95
|
it 'includes outer scope in its full name' do
|
76
|
-
expect(@node.full_name('Fred')).to eq
|
96
|
+
expect(@node.full_name('Fred')).to eq 'Fred#hello'
|
77
97
|
end
|
98
|
+
|
78
99
|
it 'includes no marker in its full name with empty outer scope' do
|
79
|
-
expect(@node.full_name('')).to eq
|
100
|
+
expect(@node.full_name('')).to eq 'hello'
|
80
101
|
end
|
102
|
+
|
81
103
|
end
|
82
104
|
|
83
105
|
context 'with a body with 2 statements' do
|
84
106
|
before :each do
|
85
|
-
@node = s(:
|
86
|
-
|
107
|
+
@node = s(:def, :hello, s(:args),
|
108
|
+
s(:begin,
|
109
|
+
s(:first),
|
110
|
+
s(:second)))
|
87
111
|
end
|
88
112
|
|
89
113
|
it 'has 2 body statements' do
|
90
|
-
expect(@node.body).to eq
|
114
|
+
expect(@node.body).to eq s(:begin, s(:first), s(:second))
|
91
115
|
end
|
92
116
|
|
93
117
|
it 'has a body extended with SexpNode' do
|
94
118
|
b = @node.body
|
95
|
-
expect(
|
119
|
+
expect(b.class.included_modules.first).to eq SexpNode
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'finds nodes in the body with #body_nodes' do
|
123
|
+
expect(@node.body_nodes([:first])).to eq [s(:first)]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'with no body' do
|
128
|
+
before :each do
|
129
|
+
@node = s(:def, :hello, s(:args), nil)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'has a body that is nil' do
|
133
|
+
expect(@node.body).to be_nil
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'finds no nodes in the body' do
|
137
|
+
expect(@node.body_nodes([:foo])).to eq []
|
96
138
|
end
|
97
139
|
end
|
98
140
|
end
|
@@ -100,157 +142,188 @@ end
|
|
100
142
|
describe SexpExtensions::DefsNode do
|
101
143
|
context 'with no parameters' do
|
102
144
|
before :each do
|
103
|
-
@node = s(:defs, :obj, :hello, s(:args))
|
104
|
-
@node.extend(SexpExtensions::DefsNode)
|
145
|
+
@node = s(:defs, s(:lvar, :obj), :hello, s(:args))
|
105
146
|
end
|
147
|
+
|
106
148
|
it 'has no arg names' do
|
107
|
-
expect(@node.arg_names).to eq
|
149
|
+
expect(@node.arg_names).to eq []
|
108
150
|
end
|
151
|
+
|
109
152
|
it 'has no parameter names' do
|
110
|
-
expect(@node.parameter_names).to eq
|
153
|
+
expect(@node.parameter_names).to eq []
|
111
154
|
end
|
155
|
+
|
112
156
|
it 'includes outer scope in its full name' do
|
113
|
-
expect(@node.full_name('Fred')).to eq
|
157
|
+
expect(@node.full_name('Fred')).to eq 'Fred#obj.hello'
|
114
158
|
end
|
159
|
+
|
115
160
|
it 'includes no marker in its full name with empty outer scope' do
|
116
|
-
expect(@node.full_name('')).to eq
|
161
|
+
expect(@node.full_name('')).to eq 'obj.hello'
|
117
162
|
end
|
163
|
+
|
118
164
|
end
|
119
165
|
|
120
166
|
context 'with 1 parameter' do
|
121
167
|
before :each do
|
122
|
-
@node = s(:defs, :
|
123
|
-
|
168
|
+
@node = s(:defs, s(:lvar, :obj), :hello,
|
169
|
+
s(:args, s(:arg, :param)))
|
124
170
|
end
|
171
|
+
|
125
172
|
it 'has 1 arg name' do
|
126
|
-
expect(@node.arg_names).to eq
|
173
|
+
expect(@node.arg_names).to eq [:param]
|
127
174
|
end
|
175
|
+
|
128
176
|
it 'has 1 parameter name' do
|
129
|
-
expect(@node.parameter_names).to eq
|
177
|
+
expect(@node.parameter_names).to eq [:param]
|
130
178
|
end
|
179
|
+
|
131
180
|
it 'includes outer scope in its full name' do
|
132
|
-
expect(@node.full_name('Fred')).to eq
|
181
|
+
expect(@node.full_name('Fred')).to eq 'Fred#obj.hello'
|
133
182
|
end
|
183
|
+
|
134
184
|
it 'includes no marker in its full name with empty outer scope' do
|
135
|
-
expect(@node.full_name('')).to eq
|
185
|
+
expect(@node.full_name('')).to eq 'obj.hello'
|
136
186
|
end
|
187
|
+
|
137
188
|
end
|
138
189
|
|
139
190
|
context 'with a block' do
|
140
191
|
before :each do
|
141
|
-
@node = s(:defs,
|
142
|
-
|
192
|
+
@node = s(:defs, s(:lvar, :obj), :hello,
|
193
|
+
s(:args,
|
194
|
+
s(:arg, :param),
|
195
|
+
s(:blockarg, :blk)))
|
143
196
|
end
|
197
|
+
|
144
198
|
it 'has 1 arg name' do
|
145
|
-
expect(@node.arg_names).to eq
|
199
|
+
expect(@node.arg_names).to eq [:param]
|
146
200
|
end
|
201
|
+
|
147
202
|
it 'has 2 parameter names' do
|
148
|
-
expect(@node.parameter_names).to eq
|
203
|
+
expect(@node.parameter_names).to eq [:param, :blk]
|
149
204
|
end
|
205
|
+
|
150
206
|
it 'includes outer scope in its full name' do
|
151
|
-
expect(@node.full_name('Fred')).to eq
|
207
|
+
expect(@node.full_name('Fred')).to eq 'Fred#obj.hello'
|
152
208
|
end
|
209
|
+
|
153
210
|
it 'includes no marker in its full name with empty outer scope' do
|
154
|
-
expect(@node.full_name('')).to eq
|
211
|
+
expect(@node.full_name('')).to eq 'obj.hello'
|
155
212
|
end
|
213
|
+
|
156
214
|
end
|
157
215
|
|
158
216
|
context 'with 1 defaulted parameter' do
|
159
217
|
before :each do
|
160
|
-
@node = s(:defs,
|
161
|
-
|
218
|
+
@node = s(:defs, s(:lvar, :obj), :hello,
|
219
|
+
s(:args,
|
220
|
+
s(:optarg, :param, s(:array))))
|
162
221
|
end
|
222
|
+
|
163
223
|
it 'has 1 arg name' do
|
164
|
-
expect(@node.arg_names).to eq
|
224
|
+
expect(@node.arg_names).to eq [:param]
|
165
225
|
end
|
226
|
+
|
166
227
|
it 'has 1 parameter name' do
|
167
|
-
expect(@node.parameter_names).to eq
|
228
|
+
expect(@node.parameter_names).to eq [:param]
|
168
229
|
end
|
230
|
+
|
169
231
|
it 'includes outer scope in its full name' do
|
170
|
-
expect(@node.full_name('Fred')).to eq
|
232
|
+
expect(@node.full_name('Fred')).to eq 'Fred#obj.hello'
|
171
233
|
end
|
234
|
+
|
172
235
|
it 'includes no marker in its full name with empty outer scope' do
|
173
|
-
expect(@node.full_name('')).to eq
|
236
|
+
expect(@node.full_name('')).to eq 'obj.hello'
|
174
237
|
end
|
238
|
+
|
175
239
|
end
|
176
240
|
|
177
241
|
context 'with a body with 2 statements' do
|
178
242
|
before :each do
|
179
|
-
@node = s(:defs, s(:self), :hello, s(:args),
|
180
|
-
|
243
|
+
@node = s(:defs, s(:self), :hello, s(:args),
|
244
|
+
s(:begin,
|
245
|
+
s(:first),
|
246
|
+
s(:second)))
|
181
247
|
end
|
182
248
|
|
183
249
|
it 'has 2 body statements' do
|
184
|
-
expect(@node.body).to eq
|
250
|
+
expect(@node.body).to eq s(:begin, s(:first), s(:second))
|
185
251
|
end
|
186
252
|
|
187
253
|
it 'has a body extended with SexpNode' do
|
188
254
|
b = @node.body
|
189
|
-
expect(
|
255
|
+
expect(b.class.included_modules.first).to eq SexpNode
|
190
256
|
end
|
257
|
+
|
191
258
|
end
|
259
|
+
|
192
260
|
end
|
193
261
|
|
194
|
-
describe SexpExtensions::
|
262
|
+
describe SexpExtensions::SendNode do
|
195
263
|
context 'with no parameters' do
|
196
264
|
before :each do
|
197
|
-
@node = s(:
|
198
|
-
@node.extend(SexpExtensions::CallNode)
|
265
|
+
@node = s(:send, nil, :hello)
|
199
266
|
end
|
200
|
-
|
201
|
-
|
267
|
+
|
268
|
+
it 'has no argument names' do
|
269
|
+
expect(@node.arg_names).to eq []
|
202
270
|
end
|
271
|
+
|
203
272
|
end
|
204
273
|
|
205
274
|
context 'with 1 literal parameter' do
|
206
275
|
before :each do
|
207
|
-
@node = s(:
|
208
|
-
@node.extend(SexpExtensions::CallNode)
|
276
|
+
@node = s(:send, nil, :hello, s(:lit, :param))
|
209
277
|
end
|
278
|
+
|
210
279
|
it 'has 1 argument name' do
|
211
|
-
expect(@node.arg_names).to eq
|
280
|
+
expect(@node.arg_names).to eq [:param]
|
212
281
|
end
|
282
|
+
|
213
283
|
end
|
214
284
|
|
215
285
|
context 'with 2 literal parameters' do
|
216
286
|
before :each do
|
217
|
-
@node = s(:
|
218
|
-
@node.extend(SexpExtensions::CallNode)
|
287
|
+
@node = s(:send, nil, :hello, s(:lit, :x), s(:lit, :y))
|
219
288
|
end
|
289
|
+
|
220
290
|
it 'has 2 argument names' do
|
221
|
-
expect(@node.arg_names).to eq
|
291
|
+
expect(@node.arg_names).to eq [:x, :y]
|
222
292
|
end
|
293
|
+
|
223
294
|
end
|
295
|
+
|
224
296
|
end
|
225
297
|
|
226
|
-
describe SexpExtensions::
|
298
|
+
describe SexpExtensions::BlockNode do
|
227
299
|
context 'with no parameters' do
|
228
300
|
before :each do
|
229
|
-
@node = s(:
|
230
|
-
@node.extend(SexpExtensions::IterNode)
|
301
|
+
@node = s(:block, s(:send, nil, :map), s(:args), nil)
|
231
302
|
end
|
303
|
+
|
232
304
|
it 'has no parameter names' do
|
233
|
-
expect(@node.parameter_names).to eq
|
305
|
+
expect(@node.parameter_names).to eq []
|
234
306
|
end
|
307
|
+
|
235
308
|
end
|
236
309
|
|
237
310
|
context 'with 1 parameter' do
|
238
311
|
before :each do
|
239
|
-
@node = s(:
|
240
|
-
@node.extend(SexpExtensions::IterNode)
|
312
|
+
@node = s(:block, s(:send, nil, :map), s(:args, :param), nil)
|
241
313
|
end
|
314
|
+
|
242
315
|
it 'has 1 parameter name' do
|
243
|
-
expect(@node.parameter_names).to eq
|
316
|
+
expect(@node.parameter_names).to eq [:param]
|
244
317
|
end
|
245
318
|
end
|
246
319
|
|
247
320
|
context 'with 2 parameters' do
|
248
321
|
before :each do
|
249
|
-
@node = s(:
|
250
|
-
@node.extend(SexpExtensions::IterNode)
|
322
|
+
@node = s(:block, s(:send, nil, :map), s(:args, :x, :y), nil)
|
251
323
|
end
|
324
|
+
|
252
325
|
it 'has 2 parameter names' do
|
253
|
-
expect(@node.parameter_names).to eq
|
326
|
+
expect(@node.parameter_names).to eq [:x, :y]
|
254
327
|
end
|
255
328
|
end
|
256
329
|
end
|
@@ -263,49 +336,49 @@ describe SexpExtensions::ModuleNode do
|
|
263
336
|
end
|
264
337
|
|
265
338
|
it 'has the correct #name' do
|
266
|
-
expect(subject.name).to eq
|
339
|
+
expect(subject.name).to eq :Fred
|
267
340
|
end
|
268
341
|
|
269
342
|
it 'has the correct #simple_name' do
|
270
|
-
expect(subject.simple_name).to eq
|
343
|
+
expect(subject.simple_name).to eq :Fred
|
271
344
|
end
|
272
345
|
|
273
346
|
it 'has the correct #text_name' do
|
274
|
-
expect(subject.text_name).to eq
|
347
|
+
expect(subject.text_name).to eq 'Fred'
|
275
348
|
end
|
276
349
|
|
277
350
|
it 'has a simple full_name' do
|
278
|
-
expect(subject.full_name('')).to eq
|
351
|
+
expect(subject.full_name('')).to eq 'Fred'
|
279
352
|
end
|
353
|
+
|
280
354
|
it 'has a fq full_name' do
|
281
|
-
expect(subject.full_name('Blimey::O::Reilly')).to eq
|
355
|
+
expect(subject.full_name('Blimey::O::Reilly')).to eq 'Blimey::O::Reilly::Fred'
|
282
356
|
end
|
283
357
|
end
|
284
358
|
|
285
359
|
context 'with a scoped name' do
|
286
360
|
subject do
|
287
|
-
|
288
|
-
mod
|
361
|
+
s(:module, s(:const, s(:const, nil, :Foo), :Bar), nil)
|
289
362
|
end
|
290
363
|
|
291
364
|
it 'has the correct #name' do
|
292
|
-
expect(subject.name).to eq
|
365
|
+
expect(subject.name).to eq s(:const, s(:const, nil, :Foo), :Bar)
|
293
366
|
end
|
294
367
|
|
295
368
|
it 'has the correct #simple_name' do
|
296
|
-
expect(subject.simple_name).to eq
|
369
|
+
expect(subject.simple_name).to eq :Bar
|
297
370
|
end
|
298
371
|
|
299
372
|
it 'has the correct #text_name' do
|
300
|
-
expect(subject.text_name).to eq
|
373
|
+
expect(subject.text_name).to eq 'Foo::Bar'
|
301
374
|
end
|
302
375
|
|
303
376
|
it 'has a simple full_name' do
|
304
|
-
expect(subject.full_name('')).to eq
|
377
|
+
expect(subject.full_name('')).to eq 'Foo::Bar'
|
305
378
|
end
|
306
379
|
|
307
380
|
it 'has a fq full_name' do
|
308
|
-
expect(subject.full_name('Blimey::O::Reilly')).to eq
|
381
|
+
expect(subject.full_name('Blimey::O::Reilly')).to eq 'Blimey::O::Reilly::Foo::Bar'
|
309
382
|
end
|
310
383
|
end
|
311
384
|
end
|