teksymmetry-reek 1.1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +131 -0
- data/README.txt +36 -0
- data/Rakefile +17 -0
- data/bin/reek +27 -0
- data/config/defaults.reek +51 -0
- data/lib/reek/block_context.rb +59 -0
- data/lib/reek/class_context.rb +68 -0
- data/lib/reek/code_context.rb +54 -0
- data/lib/reek/code_parser.rb +221 -0
- data/lib/reek/exceptions.reek +13 -0
- data/lib/reek/if_context.rb +25 -0
- data/lib/reek/method_context.rb +91 -0
- data/lib/reek/module_context.rb +33 -0
- data/lib/reek/name.rb +49 -0
- data/lib/reek/object_refs.rb +52 -0
- data/lib/reek/object_source.rb +53 -0
- data/lib/reek/options.rb +100 -0
- data/lib/reek/rake_task.rb +121 -0
- data/lib/reek/report.rb +81 -0
- data/lib/reek/sexp_formatter.rb +10 -0
- data/lib/reek/singleton_method_context.rb +27 -0
- data/lib/reek/smell_warning.rb +49 -0
- data/lib/reek/smells/control_couple.rb +61 -0
- data/lib/reek/smells/duplication.rb +50 -0
- data/lib/reek/smells/feature_envy.rb +58 -0
- data/lib/reek/smells/large_class.rb +69 -0
- data/lib/reek/smells/long_method.rb +43 -0
- data/lib/reek/smells/long_parameter_list.rb +43 -0
- data/lib/reek/smells/long_yield_list.rb +18 -0
- data/lib/reek/smells/nested_iterators.rb +28 -0
- data/lib/reek/smells/smell_detector.rb +66 -0
- data/lib/reek/smells/smells.rb +81 -0
- data/lib/reek/smells/uncommunicative_name.rb +97 -0
- data/lib/reek/smells/utility_function.rb +34 -0
- data/lib/reek/source.rb +127 -0
- data/lib/reek/spec.rb +146 -0
- data/lib/reek/stop_context.rb +50 -0
- data/lib/reek/yield_call_context.rb +12 -0
- data/lib/reek.rb +7 -0
- data/reek.gemspec +44 -0
- data/spec/reek/block_context_spec.rb +40 -0
- data/spec/reek/class_context_spec.rb +169 -0
- data/spec/reek/code_context_spec.rb +93 -0
- data/spec/reek/code_parser_spec.rb +34 -0
- data/spec/reek/config_spec.rb +42 -0
- data/spec/reek/if_context_spec.rb +17 -0
- data/spec/reek/method_context_spec.rb +66 -0
- data/spec/reek/module_context_spec.rb +38 -0
- data/spec/reek/name_spec.rb +13 -0
- data/spec/reek/object_refs_spec.rb +131 -0
- data/spec/reek/options_spec.rb +13 -0
- data/spec/reek/report_spec.rb +48 -0
- data/spec/reek/singleton_method_context_spec.rb +17 -0
- data/spec/reek/smells/control_couple_spec.rb +23 -0
- data/spec/reek/smells/duplication_spec.rb +81 -0
- data/spec/reek/smells/feature_envy_spec.rb +221 -0
- data/spec/reek/smells/large_class_spec.rb +87 -0
- data/spec/reek/smells/long_method_spec.rb +195 -0
- data/spec/reek/smells/long_parameter_list_spec.rb +85 -0
- data/spec/reek/smells/nested_iterators_spec.rb +33 -0
- data/spec/reek/smells/smell_spec.rb +24 -0
- data/spec/reek/smells/uncommunicative_name_spec.rb +123 -0
- data/spec/reek/smells/utility_function_spec.rb +93 -0
- data/spec/slow/inline_spec.rb +40 -0
- data/spec/slow/optparse_spec.rb +109 -0
- data/spec/slow/redcloth_spec.rb +101 -0
- data/spec/slow/reek_source_spec.rb +20 -0
- data/spec/slow/samples/inline.rb +704 -0
- data/spec/slow/samples/optparse.rb +1788 -0
- data/spec/slow/samples/redcloth.rb +1130 -0
- data/spec/slow/script_spec.rb +55 -0
- data/spec/slow/source_list_spec.rb +40 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +13 -0
- data/tasks/reek.rake +7 -0
- data/tasks/rspec.rake +22 -0
- metadata +163 -0
@@ -0,0 +1,221 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
require 'reek/smells/feature_envy'
|
3
|
+
require 'reek/method_context'
|
4
|
+
require 'reek/stop_context'
|
5
|
+
|
6
|
+
include Reek
|
7
|
+
include Reek::Smells
|
8
|
+
|
9
|
+
describe FeatureEnvy do
|
10
|
+
it 'should not report use of self' do
|
11
|
+
'def simple() self.to_s + self.to_i end'.should_not reek
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should not report vcall with no argument' do
|
15
|
+
'def simple() func; end'.should_not reek
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should not report vcall with argument' do
|
19
|
+
'def simple(arga) func(17); end'.should_not reek
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should not report single use' do
|
23
|
+
'def no_envy(arga)
|
24
|
+
arga.barg(@item)
|
25
|
+
end'.should_not reek
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should not report return value' do
|
29
|
+
'def no_envy(arga)
|
30
|
+
arga.barg(@item)
|
31
|
+
arga
|
32
|
+
end'.should_not reek
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should report many calls to parameter' do
|
36
|
+
'def envy(arga)
|
37
|
+
arga.b(arga) + arga.c(@fred)
|
38
|
+
end'.should reek_only_of(:FeatureEnvy, /arga/)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should report highest affinity' do
|
42
|
+
ruby = 'def total_envy
|
43
|
+
fred = @item
|
44
|
+
total = 0
|
45
|
+
total += fred.price
|
46
|
+
total += fred.tax
|
47
|
+
total *= 1.15
|
48
|
+
end'
|
49
|
+
ruby.should reek_only_of(:FeatureEnvy, /total/)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should report multiple affinities' do
|
53
|
+
ruby = 'def total_envy
|
54
|
+
fred = @item
|
55
|
+
total = 0
|
56
|
+
total += fred.price
|
57
|
+
total += fred.tax
|
58
|
+
end'
|
59
|
+
ruby.should reek_of(:FeatureEnvy, /total/)
|
60
|
+
ruby.should reek_of(:FeatureEnvy, /fred/)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should ignore global variables' do
|
64
|
+
'def no_envy() $s2.to_a; $s2[@item] end'.should_not reek
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should not report class methods' do
|
68
|
+
'def simple() self.class.new.flatten_merge(self) end'.should_not reek
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should not report single use of an ivar' do
|
72
|
+
'def no_envy() @item.to_a end'.should_not reek
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should not report returning an ivar' do
|
76
|
+
'def no_envy() @item.to_a; @item end'.should_not reek
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should not report ivar usage in a parameter' do
|
80
|
+
'def no_envy
|
81
|
+
@item.price + tax(@item) - savings(@item)
|
82
|
+
end'.should_not reek
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should not be fooled by duplication' do
|
86
|
+
'def feed(thing)
|
87
|
+
@cow.feed_to(thing.pig)
|
88
|
+
@duck.feed_to(thing.pig)
|
89
|
+
end'.should reek_only_of(:Duplication, /thing.pig/)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should count local calls' do
|
93
|
+
'def feed(thing)
|
94
|
+
cow.feed_to(thing.pig)
|
95
|
+
duck.feed_to(thing.pig)
|
96
|
+
end'.should reek_only_of(:Duplication, /thing.pig/)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should not report single use of an lvar' do
|
100
|
+
'def no_envy()
|
101
|
+
lv = @item
|
102
|
+
lv.to_a
|
103
|
+
end'.should_not reek
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should not report returning an lvar' do
|
107
|
+
'def no_envy()
|
108
|
+
lv = @item
|
109
|
+
lv.to_a
|
110
|
+
lv
|
111
|
+
end'.should_not reek
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should report many calls to lvar' do
|
115
|
+
'def envy
|
116
|
+
lv = @item
|
117
|
+
lv.price + lv.tax
|
118
|
+
end'.should reek_only_of(:FeatureEnvy, /lv/)
|
119
|
+
#
|
120
|
+
# def moved_version
|
121
|
+
# price + tax
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# def envy
|
125
|
+
# @item.moved_version
|
126
|
+
# end
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'ignores lvar usage in a parameter' do
|
130
|
+
'def no_envy
|
131
|
+
lv = @item
|
132
|
+
lv.price + tax(lv) - savings(lv)
|
133
|
+
end'.should_not reek
|
134
|
+
end
|
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
|
+
it 'ignores multiple ivars' do
|
153
|
+
'def func
|
154
|
+
@other.a
|
155
|
+
@other.b
|
156
|
+
@nother.c
|
157
|
+
@nother.d
|
158
|
+
end'.should_not reek
|
159
|
+
#
|
160
|
+
# def other.func(me)
|
161
|
+
# a
|
162
|
+
# b
|
163
|
+
# me.nother_c
|
164
|
+
# me.nother_d
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'ignores frequent use of a call' do
|
170
|
+
'def func
|
171
|
+
other.a
|
172
|
+
other.b
|
173
|
+
nother.c
|
174
|
+
end'.should_not reek_of(:FeatureEnvy)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'counts self references correctly' do
|
178
|
+
'def adopt!(other)
|
179
|
+
other.keys.each do |key|
|
180
|
+
self[key] += 3
|
181
|
+
self[key] = o4
|
182
|
+
end
|
183
|
+
self
|
184
|
+
end'.should_not reek
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe FeatureEnvy do
|
189
|
+
it 'counts references to self correctly' do
|
190
|
+
ruby = <<EOS
|
191
|
+
def report
|
192
|
+
unless @report
|
193
|
+
@report = Report.new
|
194
|
+
cf = SmellConfig.new
|
195
|
+
cf = cf.load_local(@dir) if @dir
|
196
|
+
CodeParser.new(@report, cf.smell_listeners).check_source(@source)
|
197
|
+
end
|
198
|
+
@report
|
199
|
+
end
|
200
|
+
EOS
|
201
|
+
ruby.should_not reek
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe FeatureEnvy, '#examine' do
|
206
|
+
|
207
|
+
before :each do
|
208
|
+
@context = MethodContext.new(StopContext.new, [:defn, :cool])
|
209
|
+
@fe = FeatureEnvy.new
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should return true when reporting a smell' do
|
213
|
+
@context.refs.record_ref([:lvar, :thing])
|
214
|
+
@context.refs.record_ref([:lvar, :thing])
|
215
|
+
@fe.examine(@context, []).should == true
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'should return false when not reporting a smell' do
|
219
|
+
@fe.examine(@context, []).should == false
|
220
|
+
end
|
221
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
require 'reek/code_parser'
|
3
|
+
require 'reek/report'
|
4
|
+
require 'reek/smells/large_class'
|
5
|
+
|
6
|
+
include Reek
|
7
|
+
include Reek::Smells
|
8
|
+
|
9
|
+
describe LargeClass do
|
10
|
+
|
11
|
+
it 'should report large class' do
|
12
|
+
class BigOne
|
13
|
+
26.times do |i|
|
14
|
+
define_method "method#{i}".to_sym do
|
15
|
+
@melting
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
BigOne.should reek_only_of(:LargeClass, /BigOne/)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe LargeClass do
|
24
|
+
|
25
|
+
it 'should not report short class' do
|
26
|
+
class ShortClass
|
27
|
+
def method1() @var1; end
|
28
|
+
def method2() @var2; end
|
29
|
+
def method3() @var3; end
|
30
|
+
def method4() @var4; end
|
31
|
+
def method5() @var5; end
|
32
|
+
def method6() @var6; end
|
33
|
+
end
|
34
|
+
ShortClass.should_not reek
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe LargeClass, 'when exceptions are listed' do
|
39
|
+
|
40
|
+
before(:each) do
|
41
|
+
@rpt = Report.new
|
42
|
+
@ctx = ClassContext.create(StopContext.new, [0, :Humungous])
|
43
|
+
30.times { |num| @ctx.record_method("method#{num}") }
|
44
|
+
@config = LargeClass.default_config
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should ignore first excepted name' do
|
48
|
+
@config[LargeClass::EXCLUDE_KEY] = ['Humungous']
|
49
|
+
lc = LargeClass.new(@config)
|
50
|
+
lc.examine(@ctx, @rpt).should == false
|
51
|
+
@rpt.length.should == 0
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should ignore second excepted name' do
|
55
|
+
@config[LargeClass::EXCLUDE_KEY] = ['Oversized', 'Humungous']
|
56
|
+
lc = LargeClass.new(@config)
|
57
|
+
lc.examine(@ctx, @rpt).should == false
|
58
|
+
@rpt.length.should == 0
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should report non-excepted name' do
|
62
|
+
@config[LargeClass::EXCLUDE_KEY] = ['SmellMe']
|
63
|
+
lc = LargeClass.new(@config)
|
64
|
+
lc.examine(@ctx, @rpt).should == true
|
65
|
+
@rpt.length.should == 1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe LargeClass, 'counting instance variables' do
|
70
|
+
it 'warns about class with 10 ivars' do
|
71
|
+
class ManyIvars
|
72
|
+
def method
|
73
|
+
@vara = @varb = @varc = @vard = @vare
|
74
|
+
@varf = @varg = @varh = @vari = @varj
|
75
|
+
end
|
76
|
+
end
|
77
|
+
ManyIvars.should reek_of(:LargeClass, /10/)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'ignores class with only a couple of ivars' do
|
81
|
+
LargeClass.should_not reek_of(:LargeClass)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'ignores fq class with only a couple of ivars' do
|
85
|
+
Reek::Smells::LargeClass.should_not reek_of(:LargeClass)
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/code_parser'
|
4
|
+
require 'reek/report'
|
5
|
+
require 'reek/smells/long_method'
|
6
|
+
|
7
|
+
include Reek
|
8
|
+
include Reek::Smells
|
9
|
+
|
10
|
+
def process_method(src)
|
11
|
+
source = Source.from_s(src)
|
12
|
+
CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe LongMethod do
|
16
|
+
it 'should not report short methods' do
|
17
|
+
'def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end'.should_not reek
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should report long methods' do
|
21
|
+
'def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should reek_only_of(:LongMethod, /6 statements/)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not report initialize' do
|
25
|
+
'def initialize(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should_not reek
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should only report a long method once' do
|
29
|
+
source =<<EOS
|
30
|
+
def standard_entries(rbconfig)
|
31
|
+
@abc = rbconfig
|
32
|
+
rubypath = File.join(@abc['bindir'], @abcf['ruby_install_name'] + cff['EXEEXT'])
|
33
|
+
major = yyy['MAJOR'].to_i
|
34
|
+
minor = zzz['MINOR'].to_i
|
35
|
+
teeny = ccc['TEENY'].to_i
|
36
|
+
version = ""
|
37
|
+
if c['rubylibdir']
|
38
|
+
@libruby = "/lib/ruby"
|
39
|
+
@librubyver = "/lib/ruby/"
|
40
|
+
@librubyverarch = "/lib/ruby/"
|
41
|
+
@siteruby = "lib/ruby/version/site_ruby"
|
42
|
+
@siterubyver = siteruby
|
43
|
+
@siterubyverarch = "$siterubyver/['arch']}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
EOS
|
47
|
+
source.should reek_only_of(:LongMethod)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should report long inner block' do
|
51
|
+
src = <<EOS
|
52
|
+
def long(arga)
|
53
|
+
f(3)
|
54
|
+
self.each do |xyzero|
|
55
|
+
xyzero = 1
|
56
|
+
xyzero = 2
|
57
|
+
xyzero = 3
|
58
|
+
xyzero = 4
|
59
|
+
xyzero = 5
|
60
|
+
xyzero = 6
|
61
|
+
end
|
62
|
+
end
|
63
|
+
EOS
|
64
|
+
src.should reek_only_of(:LongMethod)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe LongMethod do
|
69
|
+
it 'counts 1 assignment' do
|
70
|
+
method = process_method('def one() val = 4; end')
|
71
|
+
method.num_statements.should == 1
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'counts 3 assignments' do
|
75
|
+
method = process_method('def one() val = 4; val = 4; val = 4; end')
|
76
|
+
method.num_statements.should == 3
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'counts 1 attr assignment' do
|
80
|
+
method = process_method('def one() val[0] = 4; end')
|
81
|
+
method.num_statements.should == 1
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'counts 1 increment assignment' do
|
85
|
+
method = process_method('def one() val += 4; end')
|
86
|
+
method.num_statements.should == 1
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'counts 1 increment attr assignment' do
|
90
|
+
method = process_method('def one() val[0] += 4; end')
|
91
|
+
method.num_statements.should == 1
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'counts 1 nested assignment' do
|
95
|
+
method = process_method('def one() val = fred = 4; end')
|
96
|
+
method.num_statements.should == 1
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'counts returns' do
|
100
|
+
method = process_method('def one() val = 4; true; end')
|
101
|
+
method.num_statements.should == 2
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe LongMethod, 'does not count control statements' do
|
106
|
+
it 'counts 1 statement in a conditional expression' do
|
107
|
+
method = process_method('def one() if val == 4; callee(); end; end')
|
108
|
+
method.num_statements.should == 1
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'counts 3 statements in a conditional expression' do
|
112
|
+
method = process_method('def one() if val == 4; callee(); callee(); callee(); end; end')
|
113
|
+
method.num_statements.should == 3
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'does not count empty conditional expression' do
|
117
|
+
method = process_method('def one() if val == 4; ; end; end')
|
118
|
+
method.num_statements.should == 0
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'counts 1 statement in a while loop' do
|
122
|
+
method = process_method('def one() while val < 4; callee(); end; end')
|
123
|
+
method.num_statements.should == 1
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'counts 3 statements in a while loop' do
|
127
|
+
method = process_method('def one() while val < 4; callee(); callee(); callee(); end; end')
|
128
|
+
method.num_statements.should == 3
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'counts 1 statement in a until loop' do
|
132
|
+
method = process_method('def one() until val < 4; callee(); end; end')
|
133
|
+
method.num_statements.should == 1
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'counts 3 statements in a until loop' do
|
137
|
+
method = process_method('def one() until val < 4; callee(); callee(); callee(); end; end')
|
138
|
+
method.num_statements.should == 3
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'counts 1 statement in a for loop' do
|
142
|
+
method = process_method('def one() for i in 0..4; callee(); end; end')
|
143
|
+
method.num_statements.should == 1
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'counts 3 statements in a for loop' do
|
147
|
+
method = process_method('def one() for i in 0..4; callee(); callee(); callee(); end; end')
|
148
|
+
method.num_statements.should == 3
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'counts 1 statement in a rescue' do
|
152
|
+
method = process_method('def one() begin; callee(); rescue; callee(); end; end')
|
153
|
+
method.num_statements.should == 2
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'counts 3 statements in a rescue' do
|
157
|
+
method = process_method('def one() begin; callee(); callee(); callee(); rescue; callee(); callee(); callee(); end; end')
|
158
|
+
method.num_statements.should == 6
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'counts 1 statement in a when' do
|
162
|
+
method = process_method('def one() case fred; when "hi"; callee(); end; end')
|
163
|
+
method.num_statements.should == 1
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'counts 3 statements in a when' do
|
167
|
+
method = process_method('def one() case fred; when "hi"; callee(); callee(); when "lo"; callee(); end; end')
|
168
|
+
method.num_statements.should == 3
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'does not count empty case' do
|
172
|
+
method = process_method('def one() case fred; when "hi"; ; when "lo"; ; end; end')
|
173
|
+
method.num_statements.should == 0
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'counts else statement' do
|
177
|
+
src = <<EOS
|
178
|
+
def parse(arg, argv, &error)
|
179
|
+
if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
|
180
|
+
return nil, block, nil
|
181
|
+
end
|
182
|
+
opt = (val = parse_arg(val, &error))[1]
|
183
|
+
val = conv_arg(*val)
|
184
|
+
if opt and !arg
|
185
|
+
argv.shift
|
186
|
+
else
|
187
|
+
val[0] = nil
|
188
|
+
end
|
189
|
+
val
|
190
|
+
end
|
191
|
+
EOS
|
192
|
+
method = process_method(src)
|
193
|
+
method.num_statements.should == 6
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/code_parser'
|
4
|
+
require 'reek/smells/long_parameter_list'
|
5
|
+
require 'reek/report'
|
6
|
+
|
7
|
+
include Reek
|
8
|
+
include Reek::Smells
|
9
|
+
|
10
|
+
describe LongParameterList do
|
11
|
+
|
12
|
+
describe 'for methods with few parameters' do
|
13
|
+
it 'should report nothing for no parameters' do
|
14
|
+
'def simple; f(3);true; end'.should_not reek
|
15
|
+
end
|
16
|
+
it 'should report nothing for 1 parameter' do
|
17
|
+
'def simple(yep) f(3);true end'.should_not reek
|
18
|
+
end
|
19
|
+
it 'should report nothing for 2 parameters' do
|
20
|
+
'def simple(yep,zero) f(3);true end'.should_not reek
|
21
|
+
end
|
22
|
+
it 'should not count an optional block' do
|
23
|
+
'def simple(alpha, yep, zero, &opt) f(3);true end'.should_not reek
|
24
|
+
end
|
25
|
+
it 'should not report inner block with too many parameters' do
|
26
|
+
'def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end'.should_not reek
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'and default values' do
|
30
|
+
it 'should report nothing for 1 parameter' do
|
31
|
+
'def simple(zero=nil) f(3);false end'.should_not reek
|
32
|
+
end
|
33
|
+
it 'should report nothing for 2 parameters with 1 default' do
|
34
|
+
'def simple(yep, zero=nil) f(3);false end'.should_not reek
|
35
|
+
end
|
36
|
+
it 'should report nothing for 2 defaulted parameters' do
|
37
|
+
'def simple(yep=4, zero=nil) f(3);false end'.should_not reek
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'for methods with too many parameters' do
|
43
|
+
it 'should report 4 parameters' do
|
44
|
+
'def simple(arga, argb, argc, argd) f(3);true end'.should reek_only_of(:LongParameterList, /4 parameters/)
|
45
|
+
end
|
46
|
+
it 'should report 8 parameters' do
|
47
|
+
'def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end'.should reek_only_of(:LongParameterList, /8 parameters/)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'and default values' do
|
51
|
+
it 'should report 3 with 1 defaulted' do
|
52
|
+
'def simple(polly, queue, yep, zero=nil) f(3);false end'.should reek_only_of(:LongParameterList, /4 parameters/)
|
53
|
+
end
|
54
|
+
it 'should report with 3 defaulted' do
|
55
|
+
'def simple(aarg, polly=2, yep=true, zero=nil) f(3);false end'.should reek_only_of(:LongParameterList, /4 parameters/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'in a class' do
|
60
|
+
class InnerTest
|
61
|
+
def xyzero(arga,argb) f(3);true end
|
62
|
+
def abc(argx,yep,zero,argm) f(3);false end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should only report long param list' do
|
66
|
+
InnerTest.should reek_only_of(:LongParameterList, /abc/)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'yield' do
|
72
|
+
it 'should not report yield with no parameters' do
|
73
|
+
'def simple(arga, argb, &blk) f(3);yield; end'.should_not reek
|
74
|
+
end
|
75
|
+
it 'should not report yield with few parameters' do
|
76
|
+
'def simple(arga, argb, &blk) f(3);yield a,b; end'.should_not reek
|
77
|
+
end
|
78
|
+
it 'should report yield with many parameters' do
|
79
|
+
'def simple(arga, argb, &blk) f(3);yield arga,argb,arga,argb; end'.should reek_only_of(:LongYieldList, /simple/, /yields/, /4/)
|
80
|
+
end
|
81
|
+
it 'should not report yield of a long expression' do
|
82
|
+
'def simple(arga, argb, &blk) f(3);yield(if @dec then argb else 5+3 end); end'.should_not reek
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/nested_iterators'
|
4
|
+
|
5
|
+
include Reek::Smells
|
6
|
+
|
7
|
+
describe NestedIterators do
|
8
|
+
|
9
|
+
it 'should report nested iterators in a method' do
|
10
|
+
'def bad(fred) @fred.each {|item| item.each {|ting| ting.ting} } end'.should reek_only_of(:NestedIterators)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should not report method with successive iterators' do
|
14
|
+
'def bad(fred)
|
15
|
+
@fred.each {|item| item.each }
|
16
|
+
@jim.each {|ting| ting.each }
|
17
|
+
end'.should_not reek
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should not report method with chained iterators' do
|
21
|
+
'def chained
|
22
|
+
@sig.keys.sort_by { |xray| xray.to_s }.each { |min| md5 << min.to_s }
|
23
|
+
end'.should_not reek
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should report nested iterators only once per method' do
|
27
|
+
'def bad(fred)
|
28
|
+
@fred.each {|item| item.each {|part| @joe.send} }
|
29
|
+
@jim.each {|ting| ting.each {|piece| @hal.send} }
|
30
|
+
end'.should reek_only_of(:NestedIterators)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/smells'
|
4
|
+
|
5
|
+
include Reek
|
6
|
+
|
7
|
+
describe SmellWarning, ' in comparisons' do
|
8
|
+
before :each do
|
9
|
+
@first = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self")
|
10
|
+
@second = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self")
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should hash equal when the smell is the same' do
|
14
|
+
@first.hash.should == @second.hash
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should compare equal when the smell is the same' do
|
18
|
+
@first.should == @second
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should compare equal when using <=>' do
|
22
|
+
(@first <=> @second).should == 0
|
23
|
+
end
|
24
|
+
end
|