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
@@ -86,9 +86,6 @@ describe SmellWarning do
|
|
86
86
|
it 'includes the message' do
|
87
87
|
expect(@yaml).to match(/message:\s*#{@message}/)
|
88
88
|
end
|
89
|
-
it 'indicates the masking' do
|
90
|
-
expect(@yaml).to match(/is_active:\s*true/)
|
91
|
-
end
|
92
89
|
it 'includes the line numbers' do
|
93
90
|
@lines.each do |line|
|
94
91
|
expect(@yaml).to match(/lines:[\s\d-]*- #{line}/)
|
@@ -140,6 +140,30 @@ describe ControlParameter do
|
|
140
140
|
src = 'def simple(arg) if arg != :foo then :bar else :foo end end'
|
141
141
|
expect(src).to smell_of(ControlParameter)
|
142
142
|
end
|
143
|
+
|
144
|
+
it 'reports when the argument is compared to a regexp' do
|
145
|
+
src = 'def simple(arg) if arg =~ /foo/ then :foo else :bar end end'
|
146
|
+
expect(src).to smell_of(ControlParameter)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'reports when the argument is reverse-compared to a regexp' do
|
150
|
+
src = 'def simple(arg) if /foo/ =~ arg then :foo else :bar end end'
|
151
|
+
expect(src).to smell_of(ControlParameter)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'reports when the argument is used in a complex regexp' do
|
155
|
+
src = 'def simple(arg) if /foo#{arg}/ =~ bar then :foo else :bar end end'
|
156
|
+
expect(src).to smell_of(ControlParameter)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'reports when the argument is a block parameter' do
|
160
|
+
src = <<-EOS
|
161
|
+
def foo &blk
|
162
|
+
bar(blk || proc {})
|
163
|
+
end
|
164
|
+
EOS
|
165
|
+
expect(src).to smell_of(ControlParameter)
|
166
|
+
end
|
143
167
|
end
|
144
168
|
|
145
169
|
context 'parameter used besides determining code path' do
|
@@ -8,40 +8,43 @@ include Reek::Smells
|
|
8
8
|
describe FeatureEnvy do
|
9
9
|
context 'with no smell' do
|
10
10
|
it 'should not report use of self' do
|
11
|
-
expect('def simple() self.to_s + self.to_i end').not_to
|
11
|
+
expect('def simple() self.to_s + self.to_i end').not_to reek_of(:FeatureEnvy)
|
12
12
|
end
|
13
13
|
it 'should not report vcall with no argument' do
|
14
|
-
expect('def simple() func; end').not_to
|
14
|
+
expect('def simple() func; end').not_to reek_of(:FeatureEnvy)
|
15
15
|
end
|
16
16
|
it 'should not report single use' do
|
17
|
-
expect('def no_envy(arga) arga.barg(@item) end').not_to
|
17
|
+
expect('def no_envy(arga) arga.barg(@item) end').not_to reek_of(:FeatureEnvy)
|
18
18
|
end
|
19
19
|
it 'should not report return value' do
|
20
|
-
expect('def no_envy(arga) arga.barg(@item); arga end').not_to
|
20
|
+
expect('def no_envy(arga) arga.barg(@item); arga end').not_to reek_of(:FeatureEnvy)
|
21
21
|
end
|
22
22
|
it 'should ignore global variables' do
|
23
|
-
expect('def no_envy() $s2.to_a; $s2[@item] end').not_to
|
23
|
+
expect('def no_envy() $s2.to_a; $s2[@item] end').not_to reek_of(:FeatureEnvy)
|
24
24
|
end
|
25
25
|
it 'should not report class methods' do
|
26
|
-
expect('def simple() self.class.new.flatten_merge(self) end').
|
26
|
+
expect('def simple() self.class.new.flatten_merge(self) end').
|
27
|
+
not_to reek_of(:FeatureEnvy)
|
27
28
|
end
|
28
29
|
it 'should not report single use of an ivar' do
|
29
|
-
expect('def no_envy() @item.to_a end').not_to
|
30
|
+
expect('def no_envy() @item.to_a end').not_to reek_of(:FeatureEnvy)
|
30
31
|
end
|
31
32
|
it 'should not report returning an ivar' do
|
32
|
-
expect('def no_envy() @item.to_a; @item end').not_to
|
33
|
+
expect('def no_envy() @item.to_a; @item end').not_to reek_of(:FeatureEnvy)
|
33
34
|
end
|
34
35
|
it 'should not report ivar usage in a parameter' do
|
35
|
-
expect('def no_envy() @item.price + tax(@item) - savings(@item) end').
|
36
|
+
expect('def no_envy() @item.price + tax(@item) - savings(@item) end').
|
37
|
+
not_to reek_of(:FeatureEnvy)
|
36
38
|
end
|
37
39
|
it 'should not report single use of an lvar' do
|
38
|
-
expect('def no_envy() lv = @item; lv.to_a end').not_to
|
40
|
+
expect('def no_envy() lv = @item; lv.to_a end').not_to reek_of(:FeatureEnvy)
|
39
41
|
end
|
40
42
|
it 'should not report returning an lvar' do
|
41
|
-
expect('def no_envy() lv = @item; lv.to_a; lv end').not_to
|
43
|
+
expect('def no_envy() lv = @item; lv.to_a; lv end').not_to reek_of(:FeatureEnvy)
|
42
44
|
end
|
43
45
|
it 'ignores lvar usage in a parameter' do
|
44
|
-
expect('def no_envy() lv = @item; lv.price + tax(lv) - savings(lv); end').
|
46
|
+
expect('def no_envy() lv = @item; lv.price + tax(lv) - savings(lv); end').
|
47
|
+
not_to reek_of(:FeatureEnvy)
|
45
48
|
end
|
46
49
|
it 'ignores multiple ivars' do
|
47
50
|
src = <<EOS
|
@@ -52,7 +55,7 @@ describe FeatureEnvy do
|
|
52
55
|
@nother.d
|
53
56
|
end
|
54
57
|
EOS
|
55
|
-
expect(src).not_to
|
58
|
+
expect(src).not_to reek_of(:FeatureEnvy)
|
56
59
|
#
|
57
60
|
# def other.func(me)
|
58
61
|
# a
|
@@ -120,6 +123,36 @@ EOS
|
|
120
123
|
expect('def func() other.a; other.b; nother.c end').not_to reek_of(:FeatureEnvy)
|
121
124
|
end
|
122
125
|
|
126
|
+
it 'counts =~ as a call' do
|
127
|
+
src = <<-EOS
|
128
|
+
def foo arg
|
129
|
+
arg =~ /bar/
|
130
|
+
end
|
131
|
+
EOS
|
132
|
+
expect(src).to reek_of :FeatureEnvy
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'counts += as a call' do
|
136
|
+
src = <<-EOS
|
137
|
+
def foo arg
|
138
|
+
arg += 1
|
139
|
+
end
|
140
|
+
EOS
|
141
|
+
expect(src).to reek_of :FeatureEnvy
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'counts ivar assignment as call to self' do
|
145
|
+
src = <<-EOS
|
146
|
+
def foo
|
147
|
+
bar = baz(1, 2)
|
148
|
+
|
149
|
+
@quuz = bar.qux
|
150
|
+
@zyxy = bar.foobar
|
151
|
+
end
|
152
|
+
EOS
|
153
|
+
expect(src).not_to reek_of :FeatureEnvy
|
154
|
+
end
|
155
|
+
|
123
156
|
it 'counts self references correctly' do
|
124
157
|
src = <<EOS
|
125
158
|
def adopt(other)
|
@@ -130,7 +163,7 @@ def adopt(other)
|
|
130
163
|
self
|
131
164
|
end
|
132
165
|
EOS
|
133
|
-
expect(src).not_to
|
166
|
+
expect(src).not_to reek_of(:FeatureEnvy)
|
134
167
|
end
|
135
168
|
end
|
136
169
|
|
@@ -147,7 +180,7 @@ def report
|
|
147
180
|
@report
|
148
181
|
end
|
149
182
|
EOS
|
150
|
-
expect(ruby).not_to
|
183
|
+
expect(ruby).not_to reek_of(:FeatureEnvy)
|
151
184
|
end
|
152
185
|
|
153
186
|
it 'interprets << correctly' do
|
@@ -161,7 +194,7 @@ def report_on(report)
|
|
161
194
|
end
|
162
195
|
EOS
|
163
196
|
|
164
|
-
expect(ruby).not_to
|
197
|
+
expect(ruby).not_to reek_of(:FeatureEnvy)
|
165
198
|
end
|
166
199
|
end
|
167
200
|
|
@@ -186,7 +219,7 @@ end
|
|
186
219
|
EOS
|
187
220
|
source = src.to_reek_source
|
188
221
|
sniffer = Sniffer.new(source)
|
189
|
-
@mctx = CodeParser.new(sniffer).
|
222
|
+
@mctx = CodeParser.new(sniffer).process_def(source.syntax_tree)
|
190
223
|
@smells = @detector.examine_context(@mctx)
|
191
224
|
end
|
192
225
|
it 'reports only that smell' do
|
@@ -22,13 +22,14 @@ describe IrresponsibleModule do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'does not report a class having a comment' do
|
25
|
-
src =
|
26
|
-
# test class
|
27
|
-
class Responsible; end
|
28
|
-
EOS
|
25
|
+
src = <<-EOS
|
26
|
+
# test class
|
27
|
+
class Responsible; end
|
28
|
+
EOS
|
29
29
|
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
30
30
|
expect(@detector.examine_context(ctx)).to be_empty
|
31
31
|
end
|
32
|
+
|
32
33
|
it 'reports a class without a comment' do
|
33
34
|
src = "class #{@bad_module_name}; end"
|
34
35
|
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
@@ -39,21 +40,28 @@ EOS
|
|
39
40
|
expect(smells[0].lines).to eq([1])
|
40
41
|
expect(smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY]).to eq(@bad_module_name)
|
41
42
|
end
|
43
|
+
|
42
44
|
it 'reports a class with an empty comment' do
|
43
|
-
src =
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
class #{@bad_module_name}; end
|
48
|
-
EOS
|
49
|
-
|
50
|
-
smells = @detector.examine_context(ctx)
|
51
|
-
expect(smells.length).to eq(1)
|
52
|
-
expect(smells[0].smell_class).to eq(IrresponsibleModule::SMELL_CLASS)
|
53
|
-
expect(smells[0].subclass).to eq(IrresponsibleModule::SMELL_SUBCLASS)
|
54
|
-
expect(smells[0].lines).to eq([4])
|
55
|
-
expect(smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY]).to eq(@bad_module_name)
|
45
|
+
src = <<-EOS
|
46
|
+
#
|
47
|
+
#
|
48
|
+
#
|
49
|
+
class #{@bad_module_name}; end
|
50
|
+
EOS
|
51
|
+
expect(src).to smell_of IrresponsibleModule
|
56
52
|
end
|
53
|
+
|
54
|
+
it 'reports a class with a preceding comment with intermittent material' do
|
55
|
+
src = <<-EOS
|
56
|
+
# This is a valid comment
|
57
|
+
|
58
|
+
require 'foo'
|
59
|
+
|
60
|
+
class Bar; end
|
61
|
+
EOS
|
62
|
+
expect(src).to reek_of(:IrresponsibleModule)
|
63
|
+
end
|
64
|
+
|
57
65
|
it 'reports a fq module name correctly' do
|
58
66
|
src = 'class Foo::Bar; end'
|
59
67
|
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'reek/smells/module_initialize'
|
3
|
+
require 'reek/smells/smell_detector_shared'
|
4
|
+
|
5
|
+
include Reek::Smells
|
6
|
+
|
7
|
+
describe ModuleInitialize do
|
8
|
+
context 'module' do
|
9
|
+
context 'with method named initialize' do
|
10
|
+
it 'smells' do
|
11
|
+
src = <<-EOF
|
12
|
+
module A
|
13
|
+
def initialize; end
|
14
|
+
end
|
15
|
+
EOF
|
16
|
+
expect(src).to smell_of(ModuleInitialize)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -23,8 +23,8 @@ describe PrimaDonnaMethod do
|
|
23
23
|
smells = detector.examine_context(ctx)
|
24
24
|
warning = smells[0]
|
25
25
|
|
26
|
-
expect(warning.
|
27
|
-
expect(warning.
|
26
|
+
expect(warning.smell_class).to eq('PrimaDonnaMethod')
|
27
|
+
expect(warning.subclass).to eq('PrimaDonnaMethod')
|
28
28
|
expect(warning.lines).to eq([1])
|
29
29
|
end
|
30
30
|
end
|
@@ -63,11 +63,17 @@ EOS
|
|
63
63
|
@ctx = CodeContext.new(nil, ast)
|
64
64
|
@conds = @detector.conditional_counts(@ctx)
|
65
65
|
end
|
66
|
+
|
66
67
|
it 'finds both conditionals' do
|
67
68
|
expect(@conds.length).to eq(2)
|
68
69
|
end
|
70
|
+
|
71
|
+
it 'returns the condition expr' do
|
72
|
+
expect(@conds.keys[1]).to eq(@cond_expr)
|
73
|
+
end
|
74
|
+
|
69
75
|
it 'knows there are three copies' do
|
70
|
-
expect(@conds[
|
76
|
+
expect(@conds.values[1].length).to eq(3)
|
71
77
|
end
|
72
78
|
|
73
79
|
context 'looking at the YAML' do
|
@@ -86,7 +92,7 @@ EOS
|
|
86
92
|
expect(@yaml).to match(/subclass:\s*RepeatedConditional/)
|
87
93
|
end
|
88
94
|
it 'reports the expression' do
|
89
|
-
expect(@yaml).to match(/expression:\s*"
|
95
|
+
expect(@yaml).to match(/expression:\s*(! )?['"]?#{@cond}["']?/)
|
90
96
|
end
|
91
97
|
it 'reports the number of occurrences' do
|
92
98
|
expect(@yaml).to match(/occurrences:\s*3/)
|
@@ -125,8 +131,8 @@ EOS
|
|
125
131
|
it 'returns the condition expr' do
|
126
132
|
expect(@conds.keys[0]).to eq(@cond_expr)
|
127
133
|
end
|
128
|
-
it 'knows there are
|
129
|
-
expect(@conds[
|
134
|
+
it 'knows there are two copies' do
|
135
|
+
expect(@conds.values[0].length).to eq(2)
|
130
136
|
end
|
131
137
|
end
|
132
138
|
|
@@ -17,40 +17,66 @@ describe TooManyInstanceVariables do
|
|
17
17
|
|
18
18
|
context 'counting instance variables' do
|
19
19
|
it 'should not report 9 ivars' do
|
20
|
-
|
21
|
-
class Empty
|
20
|
+
src = <<-EOS
|
21
|
+
class Empty
|
22
|
+
def ivars
|
23
|
+
@aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=4
|
24
|
+
end
|
25
|
+
end
|
26
|
+
EOS
|
27
|
+
expect(src).not_to reek_of(:TooManyInstanceVariables)
|
22
28
|
end
|
23
29
|
|
24
30
|
it 'counts each ivar only once' do
|
25
|
-
|
26
|
-
class Empty
|
31
|
+
src = <<-EOS
|
32
|
+
class Empty
|
33
|
+
def ivars
|
34
|
+
@aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=4
|
35
|
+
@aa=3
|
36
|
+
end
|
37
|
+
end
|
38
|
+
EOS
|
39
|
+
expect(src).not_to reek_of(:TooManyInstanceVariables)
|
27
40
|
end
|
28
41
|
|
29
42
|
it 'should report 10 ivars' do
|
30
|
-
|
31
|
-
class Empty
|
43
|
+
src = <<-EOS
|
44
|
+
class Empty
|
45
|
+
def ivars
|
46
|
+
@aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=@aj=4
|
47
|
+
end
|
48
|
+
end
|
49
|
+
EOS
|
50
|
+
expect(src).to reek_of(:TooManyInstanceVariables)
|
32
51
|
end
|
33
52
|
|
34
53
|
it 'should not report 10 ivars in 2 extensions' do
|
35
|
-
src =
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
54
|
+
src = <<-EOS
|
55
|
+
class Full
|
56
|
+
def ivars_a
|
57
|
+
@aa=@ab=@ac=@ad=@ae
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Full
|
62
|
+
def ivars_b
|
63
|
+
@af=@ag=@ah=@ai=@aj
|
64
|
+
end
|
65
|
+
end
|
66
|
+
EOS
|
67
|
+
expect(src).not_to reek_of(:TooManyInstanceVariables)
|
42
68
|
end
|
43
69
|
end
|
44
70
|
|
45
71
|
it 'reports correctly when the class has 10 instance variables' do
|
46
|
-
src =
|
47
|
-
#
|
48
|
-
class Empty
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
EOS
|
72
|
+
src = <<-EOS
|
73
|
+
# Comment
|
74
|
+
class Empty
|
75
|
+
def ivars
|
76
|
+
@aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=@aj=4
|
77
|
+
end
|
78
|
+
end
|
79
|
+
EOS
|
54
80
|
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
55
81
|
@warning = @detector.examine_context(ctx)[0]
|
56
82
|
expect(@warning.source).to eq(@source_name)
|
@@ -10,7 +10,7 @@ include Reek::Smells
|
|
10
10
|
def process_method(src)
|
11
11
|
source = src.to_reek_source
|
12
12
|
sniffer = Core::Sniffer.new(source)
|
13
|
-
Core::CodeParser.new(sniffer).
|
13
|
+
Core::CodeParser.new(sniffer).process_def(source.syntax_tree)
|
14
14
|
end
|
15
15
|
|
16
16
|
def process_singleton_method(src)
|
@@ -148,6 +148,11 @@ describe TooManyStatements, 'does not count control statements' do
|
|
148
148
|
expect(method.num_statements).to eq(0)
|
149
149
|
end
|
150
150
|
|
151
|
+
it 'counts extra statements in an if condition' do
|
152
|
+
method = process_method('def one() if begin val = callee(); val < 4 end; end; end')
|
153
|
+
expect(method.num_statements).to eq(1)
|
154
|
+
end
|
155
|
+
|
151
156
|
it 'counts 1 statement in a while loop' do
|
152
157
|
method = process_method('def one() while val < 4; callee(); end; end')
|
153
158
|
expect(method.num_statements).to eq(1)
|
@@ -158,6 +163,11 @@ describe TooManyStatements, 'does not count control statements' do
|
|
158
163
|
expect(method.num_statements).to eq(3)
|
159
164
|
end
|
160
165
|
|
166
|
+
it 'counts extra statements in a while condition' do
|
167
|
+
method = process_method('def one() while begin val = callee(); val < 4 end; end; end')
|
168
|
+
expect(method.num_statements).to eq(1)
|
169
|
+
end
|
170
|
+
|
161
171
|
it 'counts 1 statement in a until loop' do
|
162
172
|
method = process_method('def one() until val < 4; callee(); end; end')
|
163
173
|
expect(method.num_statements).to eq(1)
|
@@ -18,7 +18,7 @@ describe UncommunicativeVariableName do
|
|
18
18
|
context 'field name' do
|
19
19
|
it 'does not report use of one-letter fieldname' do
|
20
20
|
src = 'class Thing; def simple(fred) @x end end'
|
21
|
-
expect(src).not_to
|
21
|
+
expect(src).not_to reek_of(:UncommunicativeVariableName)
|
22
22
|
end
|
23
23
|
it 'reports one-letter fieldname in assignment' do
|
24
24
|
src = 'class Thing; def simple(fred) @x = fred end end'
|
@@ -29,23 +29,22 @@ describe UtilityFunction do
|
|
29
29
|
expect(@detector.examine_context(ctx)).to be_empty
|
30
30
|
end
|
31
31
|
it 'does not report literal' do
|
32
|
-
expect('def simple() 3; end').not_to
|
32
|
+
expect('def simple() 3; end').not_to reek_of(:UtilityFunction)
|
33
33
|
end
|
34
34
|
it 'does not report instance variable reference' do
|
35
|
-
expect('def simple() @yellow end').not_to
|
35
|
+
expect('def simple() @yellow end').not_to reek_of(:UtilityFunction)
|
36
36
|
end
|
37
37
|
it 'does not report vcall' do
|
38
|
-
expect('def simple() y end').not_to
|
38
|
+
expect('def simple() y end').not_to reek_of(:UtilityFunction)
|
39
39
|
end
|
40
40
|
it 'does not report references to self' do
|
41
|
-
expect('def into; self; end').not_to
|
41
|
+
expect('def into; self; end').not_to reek_of(:UtilityFunction)
|
42
42
|
end
|
43
43
|
it 'recognises an ivar reference within a block' do
|
44
|
-
expect('def clean(text) text.each { @fred = 3} end').not_to
|
44
|
+
expect('def clean(text) text.each { @fred = 3} end').not_to reek_of(:UtilityFunction)
|
45
45
|
end
|
46
46
|
it 'copes with nil superclass' do
|
47
|
-
expect('
|
48
|
-
class Object; def is_maybe?() false end end').not_to reek
|
47
|
+
expect('class Object; def is_maybe?() false end end').not_to reek_of(:UtilityFunction)
|
49
48
|
end
|
50
49
|
end
|
51
50
|
|
@@ -54,7 +53,7 @@ class Object; def is_maybe?() false end end').not_to reek
|
|
54
53
|
expect('def simple(arga) arga.to_s end').not_to reek_of(:UtilityFunction, /simple/)
|
55
54
|
end
|
56
55
|
it 'does not report a call to a constant' do
|
57
|
-
expect('def simple(arga) FIELDS[arga] end').not_to
|
56
|
+
expect('def simple(arga) FIELDS[arga] end').not_to reek_of(:UtilityFunction)
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
@@ -66,36 +65,38 @@ class Object; def is_maybe?() false end end').not_to reek
|
|
66
65
|
expect('def simple(arga=local) arga.to_s end').not_to reek_of(:UtilityFunction)
|
67
66
|
end
|
68
67
|
it 'should count usages of self'do
|
69
|
-
expect('def <=>(other) Options[:sort_order].compare(self, other) end').
|
68
|
+
expect('def <=>(other) Options[:sort_order].compare(self, other) end').
|
69
|
+
not_to reek_of(:UtilityFunction)
|
70
70
|
end
|
71
71
|
it 'should count self reference within a dstr' do
|
72
|
-
expect('def as(alias_name); "#{self} as #{alias_name}".to_sym; end').
|
72
|
+
expect('def as(alias_name); "#{self} as #{alias_name}".to_sym; end').
|
73
|
+
not_to reek_of(:UtilityFunction)
|
73
74
|
end
|
74
75
|
it 'should count calls to self within a dstr' do
|
75
|
-
expect('def to_sql; "\'#{self.gsub(/\'/, "\'\'")}\'"; end').
|
76
|
+
expect('def to_sql; "\'#{self.gsub(/\'/, "\'\'")}\'"; end').
|
77
|
+
not_to reek_of(:UtilityFunction)
|
76
78
|
end
|
77
79
|
it 'should report message chain' do
|
78
80
|
expect('def simple(arga) arga.b.c end').to reek_of(:UtilityFunction, /simple/)
|
79
81
|
end
|
80
82
|
|
81
83
|
it 'does not report a method that calls super' do
|
82
|
-
expect('def child(arg) super; arg.to_s; end').not_to
|
84
|
+
expect('def child(arg) super; arg.to_s; end').not_to reek_of(:UtilityFunction)
|
83
85
|
end
|
84
86
|
|
85
87
|
it 'should recognise a deep call' do
|
86
|
-
src =
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
88
|
+
src = <<-EOS
|
89
|
+
class Red
|
90
|
+
def deep(text)
|
91
|
+
text.each { |mod| atts = shelve(mod) }
|
92
|
+
end
|
92
93
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
EOS
|
98
|
-
expect(src).not_to
|
94
|
+
def shelve(val)
|
95
|
+
@shelf << val
|
96
|
+
end
|
97
|
+
end
|
98
|
+
EOS
|
99
|
+
expect(src).not_to reek_of(:UtilityFunction)
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
@@ -108,7 +109,7 @@ end
|
|
108
109
|
EOS
|
109
110
|
source = src.to_reek_source
|
110
111
|
sniffer = Sniffer.new(source)
|
111
|
-
mctx = CodeParser.new(sniffer).
|
112
|
+
mctx = CodeParser.new(sniffer).process_def(source.syntax_tree)
|
112
113
|
@warning = @detector.examine_context(mctx)[0] # SMELL: too cumbersome!
|
113
114
|
end
|
114
115
|
|