reek 1.1.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +44 -4
- data/License.txt +20 -0
- data/README.rdoc +83 -0
- data/Rakefile +0 -1
- data/bin/reek +3 -11
- data/config/defaults.reek +20 -1
- data/features/masking_smells.feature +111 -0
- data/features/options.feature +49 -0
- data/features/reports.feature +90 -0
- data/features/samples.feature +284 -0
- data/features/stdin.feature +43 -0
- data/features/step_definitions/reek_steps.rb +35 -0
- data/features/support/env.rb +38 -0
- data/lib/reek.rb +1 -1
- data/lib/reek/adapters/application.rb +47 -0
- data/lib/reek/adapters/config_file.rb +31 -0
- data/lib/reek/adapters/core_extras.rb +72 -0
- data/lib/reek/{object_source.rb → adapters/object_source.rb} +15 -19
- data/lib/reek/{rake_task.rb → adapters/rake_task.rb} +2 -2
- data/lib/reek/adapters/report.rb +91 -0
- data/lib/reek/adapters/source.rb +53 -0
- data/lib/reek/{spec.rb → adapters/spec.rb} +45 -60
- data/lib/reek/block_context.rb +1 -1
- data/lib/reek/class_context.rb +26 -6
- data/lib/reek/code_context.rb +8 -0
- data/lib/reek/code_parser.rb +82 -39
- data/lib/reek/command_line.rb +85 -0
- data/lib/reek/configuration.rb +51 -0
- data/lib/reek/detector_stack.rb +39 -0
- data/lib/reek/exceptions.reek +8 -1
- data/lib/reek/method_context.rb +53 -11
- data/lib/reek/module_context.rb +1 -2
- data/lib/reek/name.rb +8 -2
- data/lib/reek/sexp_formatter.rb +2 -0
- data/lib/reek/smell_warning.rb +26 -8
- data/lib/reek/smells/control_couple.rb +8 -4
- data/lib/reek/smells/data_clump.rb +88 -0
- data/lib/reek/smells/duplication.rb +11 -9
- data/lib/reek/smells/feature_envy.rb +3 -4
- data/lib/reek/smells/large_class.rb +17 -17
- data/lib/reek/smells/long_method.rb +10 -8
- data/lib/reek/smells/long_parameter_list.rb +16 -10
- data/lib/reek/smells/long_yield_list.rb +1 -1
- data/lib/reek/smells/nested_iterators.rb +3 -3
- data/lib/reek/smells/simulated_polymorphism.rb +58 -0
- data/lib/reek/smells/smell_detector.rb +94 -27
- data/lib/reek/smells/uncommunicative_name.rb +23 -23
- data/lib/reek/smells/utility_function.rb +27 -11
- data/lib/reek/sniffer.rb +183 -0
- data/reek.gemspec +5 -5
- data/spec/quality/reek_source_spec.rb +15 -0
- data/spec/reek/adapters/report_spec.rb +49 -0
- data/spec/reek/adapters/should_reek_of_spec.rb +108 -0
- data/spec/reek/adapters/should_reek_only_of_spec.rb +87 -0
- data/spec/reek/adapters/should_reek_spec.rb +92 -0
- data/spec/reek/block_context_spec.rb +7 -1
- data/spec/reek/class_context_spec.rb +39 -16
- data/spec/reek/code_context_spec.rb +7 -7
- data/spec/reek/code_parser_spec.rb +6 -1
- data/spec/reek/config_spec.rb +3 -3
- data/spec/reek/configuration_spec.rb +12 -0
- data/spec/reek/method_context_spec.rb +2 -2
- data/spec/reek/name_spec.rb +24 -0
- data/spec/reek/object_source_spec.rb +23 -0
- data/spec/reek/singleton_method_context_spec.rb +2 -2
- data/spec/reek/smell_warning_spec.rb +53 -0
- data/spec/reek/smells/data_clump_spec.rb +87 -0
- data/spec/reek/smells/duplication_spec.rb +13 -17
- data/spec/reek/smells/feature_envy_spec.rb +23 -28
- data/spec/reek/smells/large_class_spec.rb +109 -34
- data/spec/reek/smells/long_method_spec.rb +140 -3
- data/spec/reek/smells/long_parameter_list_spec.rb +1 -2
- data/spec/reek/smells/simulated_polymorphism_spec.rb +50 -0
- data/spec/reek/smells/smell_detector_spec.rb +53 -0
- data/spec/reek/smells/uncommunicative_name_spec.rb +20 -7
- data/spec/reek/smells/utility_function_spec.rb +76 -67
- data/spec/reek/sniffer_spec.rb +10 -0
- data/spec/samples/all_but_one_masked/clean_one.rb +6 -0
- data/spec/samples/all_but_one_masked/dirty.rb +7 -0
- data/spec/samples/all_but_one_masked/masked.reek +5 -0
- data/spec/samples/clean_due_to_masking/clean_one.rb +6 -0
- data/spec/samples/clean_due_to_masking/clean_three.rb +6 -0
- data/spec/samples/clean_due_to_masking/clean_two.rb +6 -0
- data/spec/samples/clean_due_to_masking/dirty_one.rb +7 -0
- data/spec/samples/clean_due_to_masking/dirty_two.rb +7 -0
- data/spec/samples/clean_due_to_masking/masked.reek +7 -0
- data/spec/samples/corrupt_config_file/corrupt.reek +1 -0
- data/spec/samples/corrupt_config_file/dirty.rb +7 -0
- data/spec/samples/empty_config_file/dirty.rb +7 -0
- data/spec/samples/empty_config_file/empty.reek +0 -0
- data/spec/samples/exceptions.reek +4 -0
- data/spec/{slow/samples → samples}/inline.rb +0 -0
- data/spec/samples/masked/dirty.rb +7 -0
- data/spec/samples/masked/masked.reek +3 -0
- data/spec/samples/mixed_results/clean_one.rb +6 -0
- data/spec/samples/mixed_results/clean_three.rb +6 -0
- data/spec/samples/mixed_results/clean_two.rb +6 -0
- data/spec/samples/mixed_results/dirty_one.rb +7 -0
- data/spec/samples/mixed_results/dirty_two.rb +7 -0
- data/spec/samples/not_quite_masked/dirty.rb +8 -0
- data/spec/samples/not_quite_masked/masked.reek +5 -0
- data/spec/{slow/samples → samples}/optparse.rb +0 -0
- data/spec/samples/overrides/masked/dirty.rb +7 -0
- data/spec/samples/overrides/masked/lower.reek +5 -0
- data/spec/samples/overrides/upper.reek +5 -0
- data/spec/{slow/samples → samples}/redcloth.rb +0 -0
- data/spec/samples/three_clean_files/clean_one.rb +6 -0
- data/spec/samples/three_clean_files/clean_three.rb +6 -0
- data/spec/samples/three_clean_files/clean_two.rb +6 -0
- data/spec/samples/two_smelly_files/dirty_one.rb +7 -0
- data/spec/samples/two_smelly_files/dirty_two.rb +7 -0
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +4 -4
- data/tasks/reek.rake +8 -5
- data/tasks/test.rake +51 -0
- metadata +75 -25
- data/README.txt +0 -6
- data/lib/reek/options.rb +0 -92
- data/lib/reek/report.rb +0 -81
- data/lib/reek/smells/smells.rb +0 -81
- data/lib/reek/source.rb +0 -127
- data/spec/reek/options_spec.rb +0 -13
- data/spec/reek/report_spec.rb +0 -48
- data/spec/reek/smells/smell_spec.rb +0 -24
- data/spec/slow/inline_spec.rb +0 -43
- data/spec/slow/optparse_spec.rb +0 -108
- data/spec/slow/redcloth_spec.rb +0 -101
- data/spec/slow/reek_source_spec.rb +0 -20
- data/spec/slow/script_spec.rb +0 -55
- data/spec/slow/source_list_spec.rb +0 -40
- data/tasks/rspec.rake +0 -21
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/data_clump'
|
4
|
+
|
5
|
+
include Reek::Smells
|
6
|
+
|
7
|
+
describe DataClump do
|
8
|
+
it 'should not report small parameter sets' do
|
9
|
+
src = <<EOS
|
10
|
+
class Scrunch
|
11
|
+
def first(pa) @field == :sym ? 0 : 3; end
|
12
|
+
def second(pa) @field == :sym; end
|
13
|
+
def third(pa) pa - pb + @fred; end
|
14
|
+
end
|
15
|
+
EOS
|
16
|
+
|
17
|
+
src.should_not reek
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should report 3 identical pairs in a class' do
|
21
|
+
src = <<EOS
|
22
|
+
class Scrunch
|
23
|
+
def first(pa, pb) @field == :sym ? 0 : 3; end
|
24
|
+
def second(pa, pb) @field == :sym; end
|
25
|
+
def third(pa, pb) pa - pb + @fred; end
|
26
|
+
end
|
27
|
+
EOS
|
28
|
+
|
29
|
+
src.should reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should report 3 swapped pairs in a class' do
|
33
|
+
src = <<EOS
|
34
|
+
class Scrunch
|
35
|
+
def one(pa, pb) @field == :sym ? 0 : 3; end
|
36
|
+
def two(pb, pa) @field == :sym; end
|
37
|
+
def tri(pa, pb) pa - pb + @fred; end
|
38
|
+
end
|
39
|
+
EOS
|
40
|
+
|
41
|
+
src.should reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should report 3 identical parameter sets in a class' do
|
45
|
+
src = <<EOS
|
46
|
+
class Scrunch
|
47
|
+
def first(pa, pb, pc) @field == :sym ? 0 : 3; end
|
48
|
+
def second(pa, pb, pc) @field == :sym; end
|
49
|
+
def third(pa, pb, pc) pa - pb + @fred; end
|
50
|
+
end
|
51
|
+
EOS
|
52
|
+
|
53
|
+
src.should reek_of(:DataClump, /\[pa, pb, pc\]/, /3 methods/)
|
54
|
+
src.should_not reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
55
|
+
src.should_not reek_of(:DataClump, /\[pa, pc\]/, /3 methods/)
|
56
|
+
src.should_not reek_of(:DataClump, /\[pb, pc\]/, /3 methods/)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should recognise re-ordered identical parameter sets' do
|
60
|
+
src = <<EOS
|
61
|
+
class Scrunch
|
62
|
+
def first(pb, pa, pc) @field == :sym ? 0 : 3; end
|
63
|
+
def second(pc, pb, pa) @field == :sym; end
|
64
|
+
def third(pa, pb, pc) pa - pb + @fred; end
|
65
|
+
end
|
66
|
+
EOS
|
67
|
+
|
68
|
+
src.should reek_of(:DataClump, /\[pa, pb, pc\]/, /3 methods/)
|
69
|
+
src.should_not reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
|
70
|
+
src.should_not reek_of(:DataClump, /\[pa, pc\]/, /3 methods/)
|
71
|
+
src.should_not reek_of(:DataClump, /\[pb, pc\]/, /3 methods/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should count only identical parameter sets' do
|
75
|
+
src = <<EOS
|
76
|
+
class RedCloth
|
77
|
+
def fa(p1, p2, p3, conten) end
|
78
|
+
def fb(p1, p2, p3, conten) end
|
79
|
+
def fc(name, windowW, windowH) end
|
80
|
+
end
|
81
|
+
EOS
|
82
|
+
|
83
|
+
src.should_not reek_of(:DataClump)
|
84
|
+
end
|
85
|
+
|
86
|
+
# TODO: include singleton methods in the calcs
|
87
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
-
|
2
|
+
|
3
|
+
require 'reek/configuration'
|
3
4
|
require 'reek/method_context'
|
4
5
|
require 'reek/stop_context'
|
5
6
|
require 'reek/smells/duplication'
|
@@ -21,7 +22,7 @@ describe Duplication, "repeated method calls" do
|
|
21
22
|
end
|
22
23
|
|
23
24
|
it 'should report nested calls' do
|
24
|
-
ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.
|
25
|
+
ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.sniff
|
25
26
|
ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
|
26
27
|
ruby.should reek_of(:Duplication, /@other.thing.foo/)
|
27
28
|
end
|
@@ -41,41 +42,36 @@ describe Duplication, "non-repeated method calls" do
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
|
-
require 'ostruct'
|
45
|
-
|
46
45
|
describe Duplication, '#examine' do
|
47
46
|
before :each do
|
48
|
-
@mc =
|
47
|
+
@mc = MethodContext.new(StopContext.new, s(:defn, :fred))
|
49
48
|
@dup = Duplication.new
|
50
49
|
end
|
51
50
|
|
52
51
|
it 'should return true when reporting a smell' do
|
53
|
-
@mc.
|
54
|
-
@dup.examine(@mc
|
52
|
+
3.times { @mc.record_call_to(s(:call, nil, :other, s(:arglist)))}
|
53
|
+
@dup.examine(@mc).should == true
|
55
54
|
end
|
56
|
-
|
55
|
+
|
57
56
|
it 'should return false when not reporting a smell' do
|
58
|
-
@mc.
|
59
|
-
@dup.examine(@mc, []).should == false
|
57
|
+
@dup.examine(@mc).should == false
|
60
58
|
end
|
61
|
-
|
59
|
+
|
62
60
|
it 'should return false when not reporting calls to new' do
|
63
|
-
@mc.
|
64
|
-
@dup.examine(@mc
|
61
|
+
4.times { @mc.record_call_to(s(:call, s(:Set), :new, s(:arglist)))}
|
62
|
+
@dup.examine(@mc).should == false
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
68
66
|
describe Duplication, 'when disabled' do
|
69
67
|
before :each do
|
70
68
|
@ctx = MethodContext.new(StopContext.new, [0, :double_thing])
|
71
|
-
@dup = Duplication.new({
|
72
|
-
@rpt = Report.new
|
69
|
+
@dup = Duplication.new({SmellConfiguration::ENABLED_KEY => false})
|
73
70
|
end
|
74
71
|
|
75
72
|
it 'should not report repeated call' do
|
76
73
|
@ctx.record_call_to([:fred])
|
77
74
|
@ctx.record_call_to([:fred])
|
78
|
-
@dup.examine(@ctx
|
79
|
-
@rpt.length.should == 0
|
75
|
+
@dup.examine(@ctx).should == false
|
80
76
|
end
|
81
77
|
end
|
@@ -27,9 +27,9 @@ describe FeatureEnvy do
|
|
27
27
|
|
28
28
|
it 'should not report return value' do
|
29
29
|
'def no_envy(arga)
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
arga.barg(@item)
|
31
|
+
arga
|
32
|
+
end'.should_not reek
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'should report many calls to parameter' do
|
@@ -133,22 +133,6 @@ describe FeatureEnvy do
|
|
133
133
|
end'.should_not reek
|
134
134
|
end
|
135
135
|
|
136
|
-
it 'reports the most-used ivar' do
|
137
|
-
pending('bug')
|
138
|
-
'def func
|
139
|
-
@other.a
|
140
|
-
@other.b
|
141
|
-
@nother.c
|
142
|
-
end'.should reek_of(:FeatureEnvy, /@other/)
|
143
|
-
#
|
144
|
-
# def other.func(me)
|
145
|
-
# a
|
146
|
-
# b
|
147
|
-
# me.nother_c
|
148
|
-
# end
|
149
|
-
#
|
150
|
-
end
|
151
|
-
|
152
136
|
it 'ignores multiple ivars' do
|
153
137
|
'def func
|
154
138
|
@other.a
|
@@ -177,12 +161,8 @@ describe FeatureEnvy do
|
|
177
161
|
it 'counts self references correctly' do
|
178
162
|
'def adopt!(other)
|
179
163
|
other.keys.each do |key|
|
180
|
-
|
181
|
-
|
182
|
-
self[key] += ov
|
183
|
-
else
|
184
|
-
self[key] = ov
|
185
|
-
end
|
164
|
+
self[key] += 3
|
165
|
+
self[key] = o4
|
186
166
|
end
|
187
167
|
self
|
188
168
|
end'.should_not reek
|
@@ -202,7 +182,22 @@ def report
|
|
202
182
|
@report
|
203
183
|
end
|
204
184
|
EOS
|
205
|
-
|
185
|
+
|
186
|
+
ruby.should_not reek
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'interprets << correctly' do
|
190
|
+
ruby = <<EOS
|
191
|
+
def report_on(report)
|
192
|
+
if @is_masked
|
193
|
+
report.record_masked_smell(self)
|
194
|
+
else
|
195
|
+
report << self
|
196
|
+
end
|
197
|
+
end
|
198
|
+
EOS
|
199
|
+
|
200
|
+
ruby.should_not reek
|
206
201
|
end
|
207
202
|
end
|
208
203
|
|
@@ -216,10 +211,10 @@ describe FeatureEnvy, '#examine' do
|
|
216
211
|
it 'should return true when reporting a smell' do
|
217
212
|
@context.refs.record_ref([:lvar, :thing])
|
218
213
|
@context.refs.record_ref([:lvar, :thing])
|
219
|
-
@fe.examine(@context
|
214
|
+
@fe.examine(@context).should == true
|
220
215
|
end
|
221
216
|
|
222
217
|
it 'should return false when not reporting a smell' do
|
223
|
-
@fe.examine(@context
|
218
|
+
@fe.examine(@context).should == false
|
224
219
|
end
|
225
220
|
end
|
@@ -1,44 +1,67 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/class_context'
|
4
|
+
require 'reek/stop_context'
|
2
5
|
require 'reek/code_parser'
|
3
|
-
require 'reek/report'
|
4
6
|
require 'reek/smells/large_class'
|
5
7
|
|
6
8
|
include Reek
|
7
9
|
include Reek::Smells
|
8
10
|
|
9
|
-
describe LargeClass do
|
11
|
+
describe LargeClass, 'checking Class objects' do
|
10
12
|
|
11
|
-
it 'should report
|
13
|
+
it 'should not report class with 26 methods' do
|
14
|
+
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
12
15
|
class BigOne
|
13
16
|
26.times do |i|
|
14
|
-
define_method "method#{i}".to_sym do
|
17
|
+
define_method "method#{i}x".to_sym do
|
15
18
|
@melting
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
19
|
-
BigOne.
|
22
|
+
BigOne.should_not reek
|
20
23
|
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe LargeClass do
|
24
24
|
|
25
25
|
it 'should not report short class' do
|
26
|
+
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
26
27
|
class ShortClass
|
27
|
-
def
|
28
|
-
def
|
29
|
-
def
|
30
|
-
def
|
31
|
-
def
|
32
|
-
def
|
28
|
+
def method_a() @var_a; end
|
29
|
+
def method_b() @var_b; end
|
30
|
+
def method_c() @var_c; end
|
31
|
+
def method_d() @var_d; end
|
32
|
+
def method_e() @var_e; end
|
33
|
+
def method_f() @var_f; end
|
33
34
|
end
|
34
35
|
ShortClass.should_not reek
|
35
36
|
end
|
37
|
+
|
38
|
+
describe LargeClass, 'counting instance variables' do
|
39
|
+
it 'should not report class with 10 ivars' do
|
40
|
+
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
41
|
+
class ManyIvars
|
42
|
+
def meth
|
43
|
+
@vara = @varb = @varc = @vard = @vare
|
44
|
+
@varf = @varg = @varh = @vari = @varj
|
45
|
+
end
|
46
|
+
end
|
47
|
+
ManyIvars.should_not reek
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'ignores class with only a couple of ivars' do
|
51
|
+
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
52
|
+
LargeClass.should_not reek_of(:LargeClass)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'ignores fq class with only a couple of ivars' do
|
56
|
+
pending('test requires ParseTree') unless ObjectSource.can_parse_objects?
|
57
|
+
Reek::Smells::LargeClass.should_not reek_of(:LargeClass)
|
58
|
+
end
|
59
|
+
end
|
36
60
|
end
|
37
61
|
|
38
62
|
describe LargeClass, 'when exceptions are listed' do
|
39
63
|
|
40
64
|
before(:each) do
|
41
|
-
@rpt = Report.new
|
42
65
|
@ctx = ClassContext.create(StopContext.new, [0, :Humungous])
|
43
66
|
30.times { |num| @ctx.record_method("method#{num}") }
|
44
67
|
@config = LargeClass.default_config
|
@@ -47,41 +70,93 @@ describe LargeClass, 'when exceptions are listed' do
|
|
47
70
|
it 'should ignore first excepted name' do
|
48
71
|
@config[LargeClass::EXCLUDE_KEY] = ['Humungous']
|
49
72
|
lc = LargeClass.new(@config)
|
50
|
-
lc.examine(@ctx
|
51
|
-
@rpt.length.should == 0
|
73
|
+
lc.examine(@ctx).should == false
|
52
74
|
end
|
53
75
|
|
54
76
|
it 'should ignore second excepted name' do
|
55
77
|
@config[LargeClass::EXCLUDE_KEY] = ['Oversized', 'Humungous']
|
56
78
|
lc = LargeClass.new(@config)
|
57
|
-
lc.examine(@ctx
|
58
|
-
@rpt.length.should == 0
|
79
|
+
lc.examine(@ctx).should == false
|
59
80
|
end
|
60
81
|
|
61
82
|
it 'should report non-excepted name' do
|
62
83
|
@config[LargeClass::EXCLUDE_KEY] = ['SmellMe']
|
63
84
|
lc = LargeClass.new(@config)
|
64
|
-
lc.examine(@ctx
|
65
|
-
@rpt.length.should == 1
|
85
|
+
lc.examine(@ctx).should == true
|
66
86
|
end
|
67
87
|
end
|
68
88
|
|
69
|
-
describe LargeClass, '
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
89
|
+
describe LargeClass, 'checking source code' do
|
90
|
+
|
91
|
+
describe 'counting instance variables' do
|
92
|
+
it 'should not report empty class' do
|
93
|
+
ClassContext.from_s('class Empty;end').should have(0).variable_names
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should count ivars in one method' do
|
97
|
+
ClassContext.from_s('class Empty;def ivars() @aa=@ab=@ac=@ad; end;end').should have(4).variable_names
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should count ivars in 2 methods' do
|
101
|
+
ClassContext.from_s('class Empty;def iv1() @aa=@ab; end;def iv2() @aa=@ac; end;end').should have(3).variable_names
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should not report 9 ivars' do
|
105
|
+
'class Empty;def ivars() @aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai; end;end'.should_not reek
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should report 10 ivars' do
|
109
|
+
'class Empty;def ivars() @aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=@aj; end;end'.should reek_of(:LargeClass)
|
76
110
|
end
|
77
|
-
ManyIvars.should reek_of(:LargeClass, /10/)
|
78
|
-
end
|
79
111
|
|
80
|
-
|
81
|
-
|
112
|
+
it 'should not report 10 ivars in 2 extensions' do
|
113
|
+
src = <<EOS
|
114
|
+
class Full;def ivars_a() @aa=@ab=@ac=@ad=@ae; end;end
|
115
|
+
class Full;def ivars_b() @af=@ag=@ah=@ai=@aj; end;end
|
116
|
+
EOS
|
117
|
+
|
118
|
+
src.should_not reek
|
119
|
+
end
|
82
120
|
end
|
83
121
|
|
84
|
-
|
85
|
-
|
122
|
+
describe 'counting methods' do
|
123
|
+
it 'should not report empty class' do
|
124
|
+
ClassContext.from_s('class Empty;end').num_methods.should == 0
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should count 1 method' do
|
128
|
+
ClassContext.from_s('class Empty;def ivars() @aa=@ab; end;end').num_methods.should == 1
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should count 2 methods' do
|
132
|
+
ClassContext.from_s('class Empty;def meth1() @aa=@ab;end;def meth2() @aa=@ab;end;end').num_methods.should == 2
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should not report 25 methods' do
|
136
|
+
src = <<EOS
|
137
|
+
class Full
|
138
|
+
def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
|
139
|
+
def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
|
140
|
+
def me21x()3 end;def me22x()3 end;def me23x()3 end;def me24x()3 end;def me25x()3 end
|
141
|
+
def me31x()3 end;def me32x()3 end;def me33x()3 end;def me34x()3 end;def me35x()3 end
|
142
|
+
def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
|
143
|
+
end
|
144
|
+
EOS
|
145
|
+
src.should_not reek
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should report 26 methods' do
|
149
|
+
src = <<EOS
|
150
|
+
class Full
|
151
|
+
def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
|
152
|
+
def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
|
153
|
+
def me21x()3 end;def me22x()3 end;def me23x()3 end;def me24x()3 end;def me25x()3 end
|
154
|
+
def me31x()3 end;def me32x()3 end;def me33x()3 end;def me34x()3 end;def me35x()3 end
|
155
|
+
def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
|
156
|
+
def me51x()3 end
|
157
|
+
end
|
158
|
+
EOS
|
159
|
+
src.should reek_of(:LargeClass)
|
160
|
+
end
|
86
161
|
end
|
87
162
|
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
2
|
|
3
3
|
require 'reek/code_parser'
|
4
|
-
require 'reek/
|
4
|
+
require 'reek/sniffer'
|
5
|
+
require 'reek/smells/long_method'
|
5
6
|
|
6
7
|
include Reek
|
8
|
+
include Reek::Smells
|
9
|
+
|
10
|
+
def process_method(src)
|
11
|
+
source = src.to_reek_source
|
12
|
+
sniffer = Sniffer.new(source)
|
13
|
+
CodeParser.new(sniffer).process_defn(source.syntax_tree)
|
14
|
+
end
|
7
15
|
|
8
16
|
describe LongMethod do
|
9
17
|
it 'should not report short methods' do
|
@@ -19,7 +27,7 @@ describe LongMethod do
|
|
19
27
|
end
|
20
28
|
|
21
29
|
it 'should only report a long method once' do
|
22
|
-
|
30
|
+
src = <<EOS
|
23
31
|
def standard_entries(rbconfig)
|
24
32
|
@abc = rbconfig
|
25
33
|
rubypath = File.join(@abc['bindir'], @abcf['ruby_install_name'] + cff['EXEEXT'])
|
@@ -37,7 +45,7 @@ def standard_entries(rbconfig)
|
|
37
45
|
end
|
38
46
|
end
|
39
47
|
EOS
|
40
|
-
|
48
|
+
src.should reek_only_of(:LongMethod)
|
41
49
|
end
|
42
50
|
|
43
51
|
it 'should report long inner block' do
|
@@ -57,3 +65,132 @@ EOS
|
|
57
65
|
src.should reek_only_of(:LongMethod)
|
58
66
|
end
|
59
67
|
end
|
68
|
+
|
69
|
+
describe LongMethod do
|
70
|
+
it 'counts 1 assignment' do
|
71
|
+
method = process_method('def one() val = 4; end')
|
72
|
+
method.num_statements.should == 1
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'counts 3 assignments' do
|
76
|
+
method = process_method('def one() val = 4; val = 4; val = 4; end')
|
77
|
+
method.num_statements.should == 3
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'counts 1 attr assignment' do
|
81
|
+
method = process_method('def one() val[0] = 4; end')
|
82
|
+
method.num_statements.should == 1
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'counts 1 increment assignment' do
|
86
|
+
method = process_method('def one() val += 4; end')
|
87
|
+
method.num_statements.should == 1
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'counts 1 increment attr assignment' do
|
91
|
+
method = process_method('def one() val[0] += 4; end')
|
92
|
+
method.num_statements.should == 1
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'counts 1 nested assignment' do
|
96
|
+
method = process_method('def one() val = fred = 4; end')
|
97
|
+
method.num_statements.should == 1
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'counts returns' do
|
101
|
+
method = process_method('def one() val = 4; true; end')
|
102
|
+
method.num_statements.should == 2
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe LongMethod, 'does not count control statements' do
|
107
|
+
it 'counts 1 statement in a conditional expression' do
|
108
|
+
method = process_method('def one() if val == 4; callee(); end; end')
|
109
|
+
method.num_statements.should == 1
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'counts 3 statements in a conditional expression' do
|
113
|
+
method = process_method('def one() if val == 4; callee(); callee(); callee(); end; end')
|
114
|
+
method.num_statements.should == 3
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'does not count empty conditional expression' do
|
118
|
+
method = process_method('def one() if val == 4; ; end; end')
|
119
|
+
method.num_statements.should == 0
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'counts 1 statement in a while loop' do
|
123
|
+
method = process_method('def one() while val < 4; callee(); end; end')
|
124
|
+
method.num_statements.should == 1
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'counts 3 statements in a while loop' do
|
128
|
+
method = process_method('def one() while val < 4; callee(); callee(); callee(); end; end')
|
129
|
+
method.num_statements.should == 3
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'counts 1 statement in a until loop' do
|
133
|
+
method = process_method('def one() until val < 4; callee(); end; end')
|
134
|
+
method.num_statements.should == 1
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'counts 3 statements in a until loop' do
|
138
|
+
method = process_method('def one() until val < 4; callee(); callee(); callee(); end; end')
|
139
|
+
method.num_statements.should == 3
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'counts 1 statement in a for loop' do
|
143
|
+
method = process_method('def one() for i in 0..4; callee(); end; end')
|
144
|
+
method.num_statements.should == 1
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'counts 3 statements in a for loop' do
|
148
|
+
method = process_method('def one() for i in 0..4; callee(); callee(); callee(); end; end')
|
149
|
+
method.num_statements.should == 3
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'counts 1 statement in a rescue' do
|
153
|
+
method = process_method('def one() begin; callee(); rescue; callee(); end; end')
|
154
|
+
method.num_statements.should == 2
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'counts 3 statements in a rescue' do
|
158
|
+
method = process_method('def one() begin; callee(); callee(); callee(); rescue; callee(); callee(); callee(); end; end')
|
159
|
+
method.num_statements.should == 6
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'counts 1 statement in a when' do
|
163
|
+
method = process_method('def one() case fred; when "hi"; callee(); end; end')
|
164
|
+
method.num_statements.should == 1
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'counts 3 statements in a when' do
|
168
|
+
method = process_method('def one() case fred; when "hi"; callee(); callee(); when "lo"; callee(); end; end')
|
169
|
+
method.num_statements.should == 3
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'does not count empty case' do
|
173
|
+
method = process_method('def one() case fred; when "hi"; ; when "lo"; ; end; end')
|
174
|
+
method.num_statements.should == 0
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'counts else statement' do
|
178
|
+
src = <<EOS
|
179
|
+
def parse(arg, argv, &error)
|
180
|
+
if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
|
181
|
+
return nil, block, nil
|
182
|
+
end
|
183
|
+
opt = (val = parse_arg(val, &error))[1]
|
184
|
+
val = conv_arg(*val)
|
185
|
+
if opt and !arg
|
186
|
+
argv.shift
|
187
|
+
else
|
188
|
+
val[0] = nil
|
189
|
+
end
|
190
|
+
val
|
191
|
+
end
|
192
|
+
EOS
|
193
|
+
method = process_method(src)
|
194
|
+
method.num_statements.should == 6
|
195
|
+
end
|
196
|
+
end
|