kevinrutherford-reek 0.3.1.4
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.
- data/History.txt +92 -0
- data/README.txt +6 -0
- data/Rakefile +7 -0
- data/bin/reek +19 -0
- data/lib/reek/block_context.rb +37 -0
- data/lib/reek/class_context.rb +73 -0
- data/lib/reek/code_context.rb +47 -0
- data/lib/reek/code_parser.rb +204 -0
- data/lib/reek/exceptions.reek +13 -0
- data/lib/reek/if_context.rb +25 -0
- data/lib/reek/method_context.rb +85 -0
- data/lib/reek/module_context.rb +34 -0
- data/lib/reek/name.rb +42 -0
- data/lib/reek/object_refs.rb +53 -0
- data/lib/reek/options.rb +92 -0
- data/lib/reek/rake_task.rb +121 -0
- data/lib/reek/report.rb +42 -0
- data/lib/reek/sexp_formatter.rb +52 -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 +50 -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 +85 -0
- data/lib/reek/smells/uncommunicative_name.rb +80 -0
- data/lib/reek/smells/utility_function.rb +34 -0
- data/lib/reek/source.rb +116 -0
- data/lib/reek/spec.rb +130 -0
- data/lib/reek/stop_context.rb +62 -0
- data/lib/reek/yield_call_context.rb +14 -0
- data/lib/reek.rb +8 -0
- data/spec/integration/reek_source_spec.rb +20 -0
- data/spec/integration/script_spec.rb +55 -0
- data/spec/reek/class_context_spec.rb +198 -0
- data/spec/reek/code_context_spec.rb +92 -0
- data/spec/reek/code_parser_spec.rb +44 -0
- data/spec/reek/config_spec.rb +42 -0
- data/spec/reek/module_context_spec.rb +38 -0
- data/spec/reek/object_refs_spec.rb +129 -0
- data/spec/reek/options_spec.rb +13 -0
- data/spec/reek/report_spec.rb +48 -0
- data/spec/reek/sexp_formatter_spec.rb +31 -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 +129 -0
- data/spec/reek/smells/large_class_spec.rb +86 -0
- data/spec/reek/smells/long_method_spec.rb +59 -0
- data/spec/reek/smells/long_parameter_list_spec.rb +92 -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 +118 -0
- data/spec/reek/smells/utility_function_spec.rb +96 -0
- data/spec/samples/inline.rb +704 -0
- data/spec/samples/inline_spec.rb +40 -0
- data/spec/samples/optparse.rb +1788 -0
- data/spec/samples/optparse_spec.rb +100 -0
- data/spec/samples/redcloth.rb +1130 -0
- data/spec/samples/redcloth_spec.rb +93 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +15 -0
- data/tasks/reek.rake +20 -0
- data/tasks/rspec.rake +22 -0
- metadata +167 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/code_parser'
|
4
|
+
require 'reek/sexp_formatter'
|
5
|
+
|
6
|
+
include Reek
|
7
|
+
|
8
|
+
def should_print(example)
|
9
|
+
it "should format #{example} correctly" do
|
10
|
+
sexp = CodeParser.parse_tree_for(example)[0]
|
11
|
+
SexpFormatter.format(sexp).should == example
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe SexpFormatter do
|
16
|
+
should_print 'self'
|
17
|
+
should_print 'Alpha'
|
18
|
+
should_print 'Alpha::Beta'
|
19
|
+
should_print '@@fred'
|
20
|
+
should_print '`ls`'
|
21
|
+
should_print 'array[0]'
|
22
|
+
should_print 'array[0, 1, 2]'
|
23
|
+
should_print 'obj.method(arg1, arg2)'
|
24
|
+
should_print 'obj.method'
|
25
|
+
should_print '$1'
|
26
|
+
should_print 'o=q.downcase'
|
27
|
+
should_print 'true'
|
28
|
+
should_print '"-#{q}xxx#{z.size}"'
|
29
|
+
should_print '0..5'
|
30
|
+
should_print '0..temp'
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/module_context'
|
4
|
+
require 'reek/singleton_method_context'
|
5
|
+
require 'reek/stop_context'
|
6
|
+
|
7
|
+
include Reek
|
8
|
+
|
9
|
+
describe SingletonMethodContext, 'outer_name' do
|
10
|
+
|
11
|
+
it "should report full context" do
|
12
|
+
element = StopContext.new
|
13
|
+
element = ModuleContext.new(element, [0, :mod])
|
14
|
+
element = SingletonMethodContext.new(element, [:defs, [:vcall, :a], :b, nil])
|
15
|
+
element.outer_name.should match(/mod::a\.b/)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/control_couple'
|
4
|
+
|
5
|
+
include Reek::Smells
|
6
|
+
|
7
|
+
describe ControlCouple do
|
8
|
+
it 'should report a ternary check on a parameter' do
|
9
|
+
'def simple(arga) arga ? @ivar : 3 end'.should reek_of(:ControlCouple, /arga/)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should not report a ternary check on an ivar' do
|
13
|
+
'def simple(arga) @ivar ? arga : 3 end'.should_not reek
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not report a ternary check on a lvar' do
|
17
|
+
'def simple(arga) lvar = 27; lvar ? arga : @ivar end'.should_not reek
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should spot a couple inside a block' do
|
21
|
+
'def blocks(arg) @text.map { |blk| arg ? blk : "#{blk}" } end'.should reek_of(:ControlCouple, /arg/)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
require 'reek/report'
|
3
|
+
require 'reek/method_context'
|
4
|
+
require 'reek/stop_context'
|
5
|
+
require 'reek/smells/duplication'
|
6
|
+
|
7
|
+
include Reek
|
8
|
+
include Reek::Smells
|
9
|
+
|
10
|
+
describe Duplication, "repeated method calls" do
|
11
|
+
it 'should report repeated call' do
|
12
|
+
'def double_thing() @other.thing + @other.thing end'.should reek_only_of(:Duplication, /@other.thing/)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should report repeated call to lvar' do
|
16
|
+
'def double_thing() other[@thing] + other[@thing] end'.should reek_only_of(:Duplication, /other\[@thing\]/)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should report call parameters' do
|
20
|
+
'def double_thing() @other.thing(2,3) + @other.thing(2,3) end'.should reek_only_of(:Duplication, /@other.thing\(2, 3\)/)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should report nested calls' do
|
24
|
+
ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.to_source
|
25
|
+
ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
|
26
|
+
ruby.should reek_of(:Duplication, /@other.thing.foo/)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should ignore calls to new' do
|
30
|
+
'def double_thing() @other.new + @other.new end'.should_not reek
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Duplication, "non-repeated method calls" do
|
35
|
+
it 'should not report similar calls' do
|
36
|
+
'def equals(other) other.thing == self.thing end'.should_not reek
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should respect call parameters' do
|
40
|
+
'def double_thing() @other.thing(3) + @other.thing(2) end'.should_not reek
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
require 'ostruct'
|
45
|
+
|
46
|
+
describe Duplication, '#examine' do
|
47
|
+
before :each do
|
48
|
+
@mc = OpenStruct.new
|
49
|
+
@dup = Duplication.new
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should return true when reporting a smell' do
|
53
|
+
@mc.calls = {'x' => 47}
|
54
|
+
@dup.examine(@mc, []).should == true
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should return false when not reporting a smell' do
|
58
|
+
@mc.calls = []
|
59
|
+
@dup.examine(@mc, []).should == false
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should return false when not reporting calls to new' do
|
63
|
+
@mc.calls = {[:call, :Set, :new] => 4}
|
64
|
+
@dup.examine(@mc, []).should == false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe Duplication, 'when disabled' do
|
69
|
+
before :each do
|
70
|
+
@ctx = MethodContext.new(StopContext.new, [0, :double_thing])
|
71
|
+
@dup = Duplication.new({SmellDetector::ENABLED_KEY => false})
|
72
|
+
@rpt = Report.new
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should not report repeated call' do
|
76
|
+
@ctx.record_call_to([:fred])
|
77
|
+
@ctx.record_call_to([:fred])
|
78
|
+
@dup.examine(@ctx, @rpt).should == false
|
79
|
+
@rpt.length.should == 0
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,129 @@
|
|
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, 'with only messages to self' 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
|
+
end
|
22
|
+
|
23
|
+
describe FeatureEnvy, 'when the receiver is a parameter' do
|
24
|
+
it 'should not report single use' do
|
25
|
+
'def no_envy(arga) arga.barg(@item) end'.should_not reek
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should not report return value' do
|
29
|
+
'def no_envy(arga) arga.barg(@item); arga end'.should_not reek
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should report many calls to parameter' do
|
33
|
+
'def envy(arga) arga.b(arga) + arga.c(@fred) end'.should reek_only_of(:FeatureEnvy, /arga/)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe FeatureEnvy, 'when there are many possible receivers' do
|
38
|
+
it 'should report highest affinity' do
|
39
|
+
ruby = 'def total_envy
|
40
|
+
fred = @item
|
41
|
+
total = 0
|
42
|
+
total += fred.price
|
43
|
+
total += fred.tax
|
44
|
+
total *= 1.15
|
45
|
+
end'
|
46
|
+
ruby.should reek_only_of(:FeatureEnvy, /total/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should report multiple affinities' do
|
50
|
+
ruby = 'def total_envy
|
51
|
+
fred = @item
|
52
|
+
total = 0
|
53
|
+
total += fred.price
|
54
|
+
total += fred.tax
|
55
|
+
end'
|
56
|
+
ruby.should reek_of(:FeatureEnvy, /total/)
|
57
|
+
ruby.should reek_of(:FeatureEnvy, /fred/)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe FeatureEnvy, 'when the receiver is external' do
|
62
|
+
it 'should ignore global variables' do
|
63
|
+
'def no_envy() $s2.to_a; $s2[@item] end'.should_not reek
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should not report class methods' do
|
67
|
+
'def simple() self.class.new.flatten_merge(self) end'.should_not reek
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe FeatureEnvy, 'when the receiver is an ivar' do
|
72
|
+
it 'should not report single use of an ivar' do
|
73
|
+
'def no_envy() @item.to_a end'.should_not reek
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should not report returning an ivar' do
|
77
|
+
'def no_envy() @item.to_a; @item end'.should_not reek
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should not report ivar usage in a parameter' do
|
81
|
+
'def no_envy; @item.price + tax(@item) - savings(@item) end'.should_not reek
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should not be fooled by duplication' do
|
85
|
+
ruby = Source.from_s('def feed(thing); @cow.feed_to(thing.pig); @duck.feed_to(thing.pig); end')
|
86
|
+
ruby.should reek_only_of(:Duplication, /thing.pig/)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should count local calls' do
|
90
|
+
ruby = Source.from_s('def feed(thing); cow.feed_to(thing.pig); duck.feed_to(thing.pig); end')
|
91
|
+
ruby.should reek_only_of(:Duplication, /thing.pig/)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe FeatureEnvy, '#examine' do
|
96
|
+
|
97
|
+
before :each do
|
98
|
+
@context = MethodContext.new(StopContext.new, [:defn, :cool])
|
99
|
+
@fe = FeatureEnvy.new
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should return true when reporting a smell' do
|
103
|
+
@context.refs.record_ref([:lvar, :thing])
|
104
|
+
@context.refs.record_ref([:lvar, :thing])
|
105
|
+
@fe.examine(@context, []).should == true
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should return false when not reporting a smell' do
|
109
|
+
@fe.examine(@context, []).should == false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe FeatureEnvy, 'when the receiver is an lvar' do
|
114
|
+
it 'should not report single use of an lvar' do
|
115
|
+
'def no_envy() lv = @item; lv.to_a end'.should_not reek
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should not report returning an lvar' do
|
119
|
+
'def no_envy() lv = @item; lv.to_a; lv end'.should_not reek
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should report many calls to lvar' do
|
123
|
+
'def envy; lv = @item; lv.price + lv.tax end'.should reek_only_of(:FeatureEnvy, /lv/)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should not report lvar usage in a parameter' do
|
127
|
+
'def no_envy; lv = @item; lv.price + tax(lv) - savings(lv) end'.should_not reek
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,86 @@
|
|
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
|
+
class BigOne
|
12
|
+
26.times do |i|
|
13
|
+
define_method "method#{i}".to_sym do
|
14
|
+
@melting
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
before(:each) do
|
20
|
+
@rpt = Report.new
|
21
|
+
@cchk = CodeParser.new(@rpt, SmellConfig.new.smell_listeners)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not report short class' do
|
25
|
+
class ShortClass
|
26
|
+
def method1() @var1; end
|
27
|
+
def method2() @var2; end
|
28
|
+
def method3() @var3; end
|
29
|
+
def method4() @var4; end
|
30
|
+
def method5() @var5; end
|
31
|
+
def method6() @var6; end
|
32
|
+
end
|
33
|
+
@cchk.check_object(ShortClass)
|
34
|
+
@rpt.should be_empty
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should report large class' do
|
38
|
+
@cchk.check_object(BigOne)
|
39
|
+
@rpt.length.should == 1
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should report class name' do
|
43
|
+
@cchk.check_object(BigOne)
|
44
|
+
@rpt[0].report.should match(/BigOne/)
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'when exceptions are listed' do
|
48
|
+
before :each do
|
49
|
+
@ctx = ClassContext.create(StopContext.new, [0, :Humungous])
|
50
|
+
30.times { |num| @ctx.record_method("method#{num}") }
|
51
|
+
@config = LargeClass.default_config
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should ignore first excepted name' do
|
55
|
+
@config[LargeClass::EXCLUDE_KEY] = ['Humungous']
|
56
|
+
lc = LargeClass.new(@config)
|
57
|
+
lc.examine(@ctx, @rpt).should == false
|
58
|
+
@rpt.length.should == 0
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should ignore second excepted name' do
|
62
|
+
@config[LargeClass::EXCLUDE_KEY] = ['Oversized', 'Humungous']
|
63
|
+
lc = LargeClass.new(@config)
|
64
|
+
lc.examine(@ctx, @rpt).should == false
|
65
|
+
@rpt.length.should == 0
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should report non-excepted name' do
|
69
|
+
@config[LargeClass::EXCLUDE_KEY] = ['SmellMe']
|
70
|
+
lc = LargeClass.new(@config)
|
71
|
+
lc.examine(@ctx, @rpt).should == true
|
72
|
+
@rpt.length.should == 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe LargeClass do
|
78
|
+
it 'should not report empty class in another module' do
|
79
|
+
'class Treetop::Runtime::SyntaxNode; end'.should_not reek
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should deal with :: scoped names' do
|
83
|
+
element = ClassContext.create(StopContext.new, [:colon2, [:colon2, [:const, :Treetop], :Runtime], :SyntaxNode])
|
84
|
+
element.num_methods.should == 0
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/code_parser'
|
4
|
+
require 'reek/report'
|
5
|
+
|
6
|
+
include Reek
|
7
|
+
|
8
|
+
describe CodeParser, "(Long Method)" do
|
9
|
+
it 'should not report short methods' do
|
10
|
+
'def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end'.should_not reek
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should report long methods' do
|
14
|
+
'def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should reek_only_of(:LongMethod, /6 statements/)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should not report initialize' do
|
18
|
+
'def initialize(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should_not reek
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should only report a long method once' do
|
22
|
+
source =<<EOS
|
23
|
+
def standard_entries(rbconfig)
|
24
|
+
@abc = rbconfig
|
25
|
+
rubypath = File.join(@abc['bindir'], @abcf['ruby_install_name'] + cff['EXEEXT'])
|
26
|
+
major = yyy['MAJOR'].to_i
|
27
|
+
minor = zzz['MINOR'].to_i
|
28
|
+
teeny = ccc['TEENY'].to_i
|
29
|
+
version = ""
|
30
|
+
if c['rubylibdir']
|
31
|
+
@libruby = "/lib/ruby"
|
32
|
+
@librubyver = "/lib/ruby/"
|
33
|
+
@librubyverarch = "/lib/ruby/"
|
34
|
+
@siteruby = "lib/ruby/version/site_ruby"
|
35
|
+
@siterubyver = siteruby
|
36
|
+
@siterubyverarch = "$siterubyver/['arch']}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
EOS
|
40
|
+
source.should reek_only_of(:LongMethod)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should report long inner block' do
|
44
|
+
src = <<EOS
|
45
|
+
def long(arga)
|
46
|
+
f(3)
|
47
|
+
self.each do |xyzero|
|
48
|
+
xyzero = 1
|
49
|
+
xyzero = 2
|
50
|
+
xyzero = 3
|
51
|
+
xyzero = 4
|
52
|
+
xyzero = 5
|
53
|
+
xyzero = 6
|
54
|
+
end
|
55
|
+
end
|
56
|
+
EOS
|
57
|
+
src.should reek_only_of(:LongMethod)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,92 @@
|
|
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 CodeParser, "(Long Parameter List)" 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
|
+
before(:each) do
|
61
|
+
@rpt = Report.new
|
62
|
+
@cchk = CodeParser.new(@rpt, SmellConfig.new.smell_listeners)
|
63
|
+
end
|
64
|
+
|
65
|
+
class InnerTest
|
66
|
+
def xyzero(arga,argb) f(3);true end
|
67
|
+
def abc(argx,yep,zero,argm) f(3);false end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should only report long param list' do
|
71
|
+
@cchk.check_object(InnerTest)
|
72
|
+
@rpt.length.should == 1
|
73
|
+
@rpt[0].report.should match(/Long Parameter List/)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'yield' do
|
79
|
+
it 'should not report yield with no parameters' do
|
80
|
+
'def simple(arga, argb, &blk) f(3);yield; end'.should_not reek
|
81
|
+
end
|
82
|
+
it 'should not report yield with few parameters' do
|
83
|
+
'def simple(arga, argb, &blk) f(3);yield a,b; end'.should_not reek
|
84
|
+
end
|
85
|
+
it 'should report yield with many parameters' do
|
86
|
+
'def simple(arga, argb, &blk) f(3);yield a,b,a,b; end'.should reek_only_of(:LongYieldList, /simple/, /yields/, /4/)
|
87
|
+
end
|
88
|
+
it 'should not report yield of a long expression' do
|
89
|
+
'def simple(arga, argb, &blk) f(3);yield(if @dec then argb else 5+3 end); end'.should_not reek
|
90
|
+
end
|
91
|
+
end
|
92
|
+
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
|