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,20 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'Reek source code:' do
|
4
|
+
Dir['lib/**/*.rb'].each do |path|
|
5
|
+
it "reports no smells in #{path}" do
|
6
|
+
File.new(path).should_not reek
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'reports no smells via the Dir matcher' do
|
11
|
+
Dir['lib/**/*.rb'].should_not reek
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'RakeTask' do
|
16
|
+
it 'should report no duplication' do
|
17
|
+
report = `rake reek`.split("\n")
|
18
|
+
report.length.should == 1
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'reek'
|
2
|
+
|
3
|
+
describe 'version number' do
|
4
|
+
it 'should report the correct value' do
|
5
|
+
actual = `ruby -Ilib bin/reek --version`.split
|
6
|
+
$?.exitstatus.should == 0
|
7
|
+
actual[0].should == 'reek'
|
8
|
+
actual[1].should == Reek::VERSION
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'exit status', 'when reek is used incorrectly' do
|
13
|
+
it 'should return non-zero status on bad option' do
|
14
|
+
`ruby -Ilib bin/reek --no-such-option`
|
15
|
+
$?.exitstatus.should == 1
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should complain about missing file' do
|
19
|
+
`ruby -Ilib bin/reek nosuchfile.rb`
|
20
|
+
$?.exitstatus.should == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should return non-zero status on missing argument' do
|
24
|
+
`ruby -Ilib bin/reek -f 2>/dev/null`
|
25
|
+
$?.exitstatus.should == 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'exit status', 'when reek is used correctly' do
|
30
|
+
it 'should return non-zero status when smells are reported' do
|
31
|
+
`echo "def x() 3; end" | ruby -Ilib bin/reek`
|
32
|
+
$?.exitstatus.should == 2
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should return zero status with no smells' do
|
36
|
+
`echo "def simple() @fred = 3 end" | ruby -Ilib bin/reek`
|
37
|
+
$?.exitstatus.should == 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'report format', 'with one source' do
|
42
|
+
it 'should output nothing with empty source' do
|
43
|
+
`echo "" | ruby -Ilib bin/reek`.should be_empty
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should output nothing when no smells' do
|
47
|
+
`echo "def simple() @fred = 3; end" | ruby -Ilib bin/reek`.should be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should not adorn the list of warnings' do
|
51
|
+
report = `echo "class Turn; def y() @x = 3; end end" | ruby -Ilib bin/reek`
|
52
|
+
report.split(/\n/).length.should == 2
|
53
|
+
report.should_not match(/\n\n/)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/class_context'
|
4
|
+
require 'reek/stop_context'
|
5
|
+
require 'reek/smells/feature_envy'
|
6
|
+
|
7
|
+
include Reek
|
8
|
+
include Reek::Smells
|
9
|
+
|
10
|
+
describe ClassContext do
|
11
|
+
it 'should report Long Parameter List' do
|
12
|
+
ruby = 'class Inner; def simple(arga, argb, argc, argd) f(3);true end end'
|
13
|
+
ruby.should reek_of(:LongParameterList, /Inner/, /simple/, /4 parameters/)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should report two different methods' do
|
17
|
+
src = <<EOEX
|
18
|
+
class Fred
|
19
|
+
def simple(arga, argb, argc, argd) f(3);true end
|
20
|
+
def simply(arga, argb, argc, argd) f(3);false end
|
21
|
+
end
|
22
|
+
EOEX
|
23
|
+
src.should reek_of(:LongParameterList, /Fred/, /simple/)
|
24
|
+
src.should reek_of(:LongParameterList, /Fred/, /simply/)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should report many different methods' do
|
28
|
+
src = <<EOEX
|
29
|
+
class Fred
|
30
|
+
def textile_bq(tag, atts, cite, content) f(3);end
|
31
|
+
def textile_p(tag, atts, cite, content) f(3);end
|
32
|
+
def textile_fn_(tag, num, atts, cite, content) f(3);end
|
33
|
+
def textile_popup_help(name, windowW, windowH) f(3);end
|
34
|
+
end
|
35
|
+
EOEX
|
36
|
+
src.should reek_of(:LongParameterList, /Fred/, /textile_bq/)
|
37
|
+
src.should reek_of(:LongParameterList, /Fred/, /textile_fn_/)
|
38
|
+
src.should reek_of(:LongParameterList, /Fred/, /textile_p/)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe Class do
|
43
|
+
|
44
|
+
module Insert
|
45
|
+
def meth_a() end
|
46
|
+
private
|
47
|
+
def meth_b() end
|
48
|
+
protected
|
49
|
+
def meth_c() end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Parent
|
53
|
+
def meth1() end
|
54
|
+
private
|
55
|
+
def meth2() end
|
56
|
+
protected
|
57
|
+
def meth3() end
|
58
|
+
end
|
59
|
+
|
60
|
+
class FullChild < Parent
|
61
|
+
include Insert
|
62
|
+
def meth7() end
|
63
|
+
private
|
64
|
+
def meth8() end
|
65
|
+
protected
|
66
|
+
def meth6() end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'with no superclass or modules' do
|
70
|
+
it 'should report correct number of methods' do
|
71
|
+
Parent.non_inherited_methods.length.should == 3
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'with superclass and modules' do
|
76
|
+
it 'should report correct number of methods' do
|
77
|
+
FullChild.non_inherited_methods.length.should == 3
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe ClassContext, 'overridden methods' do
|
83
|
+
class Above
|
84
|
+
def above() end
|
85
|
+
def both() end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Below < Above
|
89
|
+
def both() end
|
90
|
+
def below() end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'of loaded class' do
|
94
|
+
before :each do
|
95
|
+
@ctx = ClassContext.create(StopContext.new, [0, :Below])
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should recognise non-overridden method' do
|
99
|
+
@ctx.is_overriding_method?('below').should == false
|
100
|
+
@ctx.is_overriding_method?('above').should == false
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should recognise overridden method' do
|
104
|
+
@ctx.is_overriding_method?('both').should == true
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should recognise methods in current codebase' do
|
108
|
+
ctx = ClassContext.create(StopContext.new, [0, :FeatureEnvy])
|
109
|
+
ctx.is_overriding_method?('examine_context').should == true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'of non-loaded class' do
|
114
|
+
before :each do
|
115
|
+
@ctx = ClassContext.create(StopContext.new, [0, :Missing])
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should recognise non-overridden method' do
|
119
|
+
@ctx.is_overriding_method?('below').should == false
|
120
|
+
@ctx.is_overriding_method?('above').should == false
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should recognise overridden method' do
|
124
|
+
@ctx.is_overriding_method?('both').should == false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'Integration defect:' do
|
130
|
+
it 'should not report UtilityFunction for FeatureEnvy#examine_context' do
|
131
|
+
kelement = ClassContext.create(StopContext.new, [0, :FeatureEnvy, s(:const, :SmellDetector)])
|
132
|
+
meth = Name.new(:examine_context)
|
133
|
+
kelement.is_overriding_method?(meth).should == true
|
134
|
+
melement = MethodContext.new(kelement, [0, :examine_context])
|
135
|
+
melement.is_overriding_method?(meth).should == true
|
136
|
+
melement.depends_on_instance?.should == true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe CodeContext, 'find class' do
|
141
|
+
module Mod1
|
142
|
+
class Klass1
|
143
|
+
module Mod2
|
144
|
+
class Klass2
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
before :each do
|
151
|
+
@stop = StopContext.new
|
152
|
+
@mod1 = ModuleContext.create(@stop, [0, :Mod1])
|
153
|
+
@klass1 = ClassContext.create(@mod1, [0, :Klass1])
|
154
|
+
@mod2 = ModuleContext.create(@klass1, [0, :Mod2])
|
155
|
+
@klass2 = ClassContext.create(@mod2, [0, :Klass2])
|
156
|
+
end
|
157
|
+
|
158
|
+
describe StopContext do
|
159
|
+
it 'should not find unqualified class' do
|
160
|
+
@stop.find_module('Klass2').should == nil
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should find unqualified module' do
|
164
|
+
@stop.find_module('Mod1').name.should == 'Mod1'
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe ModuleContext do
|
169
|
+
it 'should find local name' do
|
170
|
+
@mod1.find_module('Klass1').name.should == 'Mod1::Klass1'
|
171
|
+
@mod2.find_module('Klass2').name.should == 'Mod1::Klass1::Mod2::Klass2'
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should not find deeper class' do
|
175
|
+
@mod1.find_module('Klass2').should == nil
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should find own Module' do
|
179
|
+
@mod1.myself.name.should == 'Mod1'
|
180
|
+
@mod2.myself.name.should == 'Mod1::Klass1::Mod2'
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe ClassContext do
|
185
|
+
it 'should find local module' do
|
186
|
+
@klass1.find_module('Mod2').name.should == 'Mod1::Klass1::Mod2'
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should not find deeper module' do
|
190
|
+
@klass1.find_module('Klass2').should == nil
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should find own Class' do
|
194
|
+
@klass1.myself.name.should == 'Mod1::Klass1'
|
195
|
+
@klass2.myself.name.should == 'Mod1::Klass1::Mod2::Klass2'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/block_context'
|
4
|
+
require 'reek/if_context'
|
5
|
+
require 'reek/class_context'
|
6
|
+
require 'reek/module_context'
|
7
|
+
require 'reek/method_context'
|
8
|
+
require 'reek/stop_context'
|
9
|
+
|
10
|
+
include Reek
|
11
|
+
|
12
|
+
describe CodeContext, 'to_s' do
|
13
|
+
|
14
|
+
it "should report full context" do
|
15
|
+
element = StopContext.new
|
16
|
+
element = ModuleContext.new(element, [0, :mod])
|
17
|
+
element = ClassContext.new(element, [0, :klass])
|
18
|
+
element = MethodContext.new(element, [0, :bad])
|
19
|
+
element = BlockContext.new(element, nil)
|
20
|
+
element.to_s.should match(/bad/)
|
21
|
+
element.to_s.should match(/klass/)
|
22
|
+
element.to_s.should match(/mod/)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should report method name via if context" do
|
26
|
+
element1 = StopContext.new
|
27
|
+
element2 = MethodContext.new(element1, [0, :bad])
|
28
|
+
element3 = IfContext.new(element2, [0,1])
|
29
|
+
BlockContext.new(element3, nil).to_s.should match(/bad/)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should report method name via nested blocks" do
|
33
|
+
element1 = StopContext.new
|
34
|
+
element2 = MethodContext.new(element1, [0, :bad])
|
35
|
+
element3 = BlockContext.new(element2, nil)
|
36
|
+
BlockContext.new(element3, nil).to_s.should match(/bad/)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe CodeContext, 'instance variables' do
|
41
|
+
it 'should pass instance variables down to the first class' do
|
42
|
+
element = StopContext.new
|
43
|
+
element = ModuleContext.new(element, [0, :mod])
|
44
|
+
class_element = ClassContext.new(element, [0, :klass])
|
45
|
+
element = MethodContext.new(class_element, [0, :bad])
|
46
|
+
element = BlockContext.new(element, nil)
|
47
|
+
element.record_instance_variable(:fred)
|
48
|
+
class_element.variable_names.should == [Name.new(:fred)]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe CodeContext, 'generics' do
|
53
|
+
it 'should pass unknown method calls down the stack' do
|
54
|
+
stop = StopContext.new
|
55
|
+
def stop.bananas(arg1, arg2) arg1 + arg2 + 43 end
|
56
|
+
element = ModuleContext.new(stop, [0, :mod])
|
57
|
+
class_element = ClassContext.new(element, [0, :klass])
|
58
|
+
element = MethodContext.new(class_element, [0, :bad])
|
59
|
+
element = BlockContext.new(element, nil)
|
60
|
+
element.bananas(17, -5).should == 55
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe CodeContext do
|
65
|
+
it 'should recognise itself in a collection of names' do
|
66
|
+
element = StopContext.new
|
67
|
+
element = ModuleContext.new(element, [0, :mod])
|
68
|
+
element.matches?(['banana', 'mod']).should == true
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should recognise itself in a collection of REs' do
|
72
|
+
element = StopContext.new
|
73
|
+
element = ModuleContext.new(element, [0, :mod])
|
74
|
+
element.matches?([/banana/, /mod/]).should == true
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should recognise its fq name in a collection of names' do
|
78
|
+
element = StopContext.new
|
79
|
+
element = ModuleContext.new(element, [0, :mod])
|
80
|
+
element = ClassContext.create(element, [0, :klass])
|
81
|
+
element.matches?(['banana', 'mod']).should == true
|
82
|
+
element.matches?(['banana', 'mod::klass']).should == true
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should recognise its fq name in a collection of names' do
|
86
|
+
element = StopContext.new
|
87
|
+
element = ModuleContext.new(element, [0, :mod])
|
88
|
+
element = ClassContext.create(element, [0, :klass])
|
89
|
+
element.matches?([/banana/, /mod/]).should == true
|
90
|
+
element.matches?([/banana/, /mod::klass/]).should == true
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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, "with no method definitions" do
|
9
|
+
it 'should report no problems for empty source code' do
|
10
|
+
''.should_not reek
|
11
|
+
end
|
12
|
+
it 'should report no problems for empty class' do
|
13
|
+
'class Fred; end'.should_not reek
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe CodeParser, 'with a global method definition' do
|
18
|
+
it 'should report no problems for simple method' do
|
19
|
+
'def Outermost::fred() true; end'.should_not reek
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe CodeParser, 'when given a C extension' do
|
24
|
+
before(:each) do
|
25
|
+
@cchk = CodeParser.new(Report.new, SmellConfig.new.smell_listeners)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should ignore :cfunc' do
|
29
|
+
@cchk.check_object(Enumerable)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe CodeParser, 'when a yield is the receiver' do
|
34
|
+
it 'should report no problems' do
|
35
|
+
source = 'def values(*args)
|
36
|
+
@to_sql += case
|
37
|
+
when block_given? then " #{yield.to_sql}"
|
38
|
+
else " values (#{args.to_sql})"
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end'
|
42
|
+
source.should_not reek
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/smells'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
include Reek
|
7
|
+
|
8
|
+
describe 'Config' do
|
9
|
+
before :each do
|
10
|
+
@first = {
|
11
|
+
'one' => {'two' => 3, 'three' => 4},
|
12
|
+
'two' => {'four' => true}
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should deep merge Hashes' do
|
17
|
+
other = Hash.new {|hash,key| hash[key] = {} }
|
18
|
+
other['one']['gunk'] = 45
|
19
|
+
other['two']['four'] = false
|
20
|
+
@first.value_merge!(other).to_yaml
|
21
|
+
@first['two']['four'].should == false
|
22
|
+
@first['one'].keys.length.should == 3
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should deep copy Hashes' do
|
26
|
+
second = @first.deep_copy
|
27
|
+
second['two'].object_id.should_not be_eql(@first['two'].object_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should merge array values' do
|
31
|
+
@first['three'] = [1,2,3]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Config, 'merging arrays' do
|
36
|
+
it 'should merge array values' do
|
37
|
+
first = {'key' => {'one' => [1,2,3]}}
|
38
|
+
second = {'key' => {'one' => [4,5]}}
|
39
|
+
first.value_merge!(second)
|
40
|
+
first['key']['one'].should == [1,2,3,4,5]
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require 'reek/module_context'
|
3
|
+
require 'reek/stop_context'
|
4
|
+
|
5
|
+
include Reek
|
6
|
+
|
7
|
+
describe ModuleContext do
|
8
|
+
it 'should report module name for smell in method' do
|
9
|
+
'module Fred; def simple(x) true; end; end'.should reek_of(:UncommunicativeName, /x/, /simple/, /Fred/)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should not report module with empty class' do
|
13
|
+
'module Fred; class Jim; end; end'.should_not reek
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should handle module with empty class' do
|
17
|
+
stop = StopContext.new
|
18
|
+
modctx = ModuleContext.create(stop, [:module, :Fred, []])
|
19
|
+
modctx.find_module(Name.new(:Jim)).should be_nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ModuleContext do
|
24
|
+
it 'should recognise global constant' do
|
25
|
+
'module ::Global class Inside; end; end'.should_not reek
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should not find missing global constant' do
|
29
|
+
element = ModuleContext.create(StopContext.new, [:module, [:colon3, :Global], nil])
|
30
|
+
element.myself.should be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should find global constant' do
|
34
|
+
module ::GlobalTestModule; end
|
35
|
+
element = ModuleContext.create(StopContext.new, [:module, [:colon3, :GlobalTestModule], nil])
|
36
|
+
element.myself.name.should == 'GlobalTestModule'
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/object_refs'
|
4
|
+
|
5
|
+
include Reek
|
6
|
+
|
7
|
+
describe ObjectRefs, 'when empty' do
|
8
|
+
before(:each) do
|
9
|
+
@refs = ObjectRefs.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should report one ref to self' do
|
13
|
+
@refs.refs_to_self.should == 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ObjectRefs, 'with no refs to self' do
|
18
|
+
before(:each) do
|
19
|
+
@refs = ObjectRefs.new
|
20
|
+
@refs.record_ref('a')
|
21
|
+
@refs.record_ref('b')
|
22
|
+
@refs.record_ref('a')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should report no refs to self' do
|
26
|
+
@refs.refs_to_self.should == 1
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should report :a as the max' do
|
30
|
+
@refs.max_keys.should == ['a']
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should not report self as the max' do
|
34
|
+
@refs.self_is_max?.should == false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ObjectRefs, 'with one ref to self' do
|
39
|
+
before(:each) do
|
40
|
+
@refs = ObjectRefs.new
|
41
|
+
@refs.record_ref('a')
|
42
|
+
@refs.record_ref('b')
|
43
|
+
@refs.record_ref('a')
|
44
|
+
@refs.record_reference_to_self
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should report 1 ref to self' do
|
48
|
+
@refs.refs_to_self.should == 2
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should report self among the max' do
|
52
|
+
@refs.max_keys.should be_include('a')
|
53
|
+
@refs.max_keys.should be_include(Sexp.from_array([:lit, :self]))
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should report self as the max' do
|
57
|
+
@refs.self_is_max?.should == true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe ObjectRefs, 'with many refs to self' do
|
62
|
+
before(:each) do
|
63
|
+
@refs = ObjectRefs.new
|
64
|
+
@refs.record_reference_to_self
|
65
|
+
@refs.record_ref('a')
|
66
|
+
@refs.record_reference_to_self
|
67
|
+
@refs.record_ref('b')
|
68
|
+
@refs.record_ref('a')
|
69
|
+
@refs.record_reference_to_self
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should report all refs to self' do
|
73
|
+
@refs.refs_to_self.should == 4
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should report self among the max' do
|
77
|
+
@refs.max_keys.should == [Sexp.from_array([:lit, :self])]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should report self as the max' do
|
81
|
+
@refs.self_is_max?.should == true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe ObjectRefs, 'when self is not the only max' do
|
86
|
+
before(:each) do
|
87
|
+
@refs = ObjectRefs.new
|
88
|
+
@refs.record_ref('a')
|
89
|
+
@refs.record_reference_to_self
|
90
|
+
@refs.record_ref('b')
|
91
|
+
@refs.record_ref('a')
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should report all refs to self' do
|
95
|
+
@refs.refs_to_self.should == 2
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should report self among the max' do
|
99
|
+
@refs.max_keys.should be_include('a')
|
100
|
+
@refs.max_keys.should be_include(Sexp.from_array([:lit, :self]))
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should report self as the max' do
|
104
|
+
@refs.self_is_max?.should == true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe ObjectRefs, 'when self is not among the max' do
|
109
|
+
before(:each) do
|
110
|
+
@refs = ObjectRefs.new
|
111
|
+
@refs.record_ref('a')
|
112
|
+
@refs.record_ref('b')
|
113
|
+
@refs.record_ref('a')
|
114
|
+
@refs.record_ref('b')
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should report all refs to self' do
|
118
|
+
@refs.refs_to_self.should == 1
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should not report self among the max' do
|
122
|
+
@refs.max_keys.should be_include('a')
|
123
|
+
@refs.max_keys.should be_include('b')
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should not report self as the max' do
|
127
|
+
@refs.self_is_max?.should == false
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/options'
|
4
|
+
|
5
|
+
include Reek
|
6
|
+
|
7
|
+
describe Options, ' when given no arguments' do
|
8
|
+
it "should retain the default sort order" do
|
9
|
+
default_order = Options[:format]
|
10
|
+
Options.parse ['nosuchfile.rb']
|
11
|
+
Options[:format].should == default_order
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
require 'reek/smells/smell_detector'
|
4
|
+
require 'reek/report'
|
5
|
+
require 'reek/source'
|
6
|
+
require 'reek/smells/feature_envy'
|
7
|
+
|
8
|
+
include Reek
|
9
|
+
|
10
|
+
describe Report, " when empty" do
|
11
|
+
before(:each) do
|
12
|
+
@rpt = Report.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should have zero length' do
|
16
|
+
@rpt.length.should == 0
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should claim to be empty' do
|
20
|
+
@rpt.should be_empty
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Report, "to_s" do
|
25
|
+
before(:each) do
|
26
|
+
rpt = Source.from_s('def simple(a) a[3] end').report
|
27
|
+
@report = rpt.to_s.split("\n")
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should place each detailed report on a separate line' do
|
31
|
+
@report.length.should == 2
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should mention every smell name' do
|
35
|
+
@report[0].should match(/[Utility Function]/)
|
36
|
+
@report[1].should match(/[Feature Envy]/)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe Report, " as a SortedSet" do
|
41
|
+
it 'should only add a smell once' do
|
42
|
+
rpt = Report.new
|
43
|
+
rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
|
44
|
+
rpt.length.should == 1
|
45
|
+
rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
|
46
|
+
rpt.length.should == 1
|
47
|
+
end
|
48
|
+
end
|