kevinrutherford-reek 1.1.3 → 1.1.3.1
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 +6 -0
- data/lib/reek/class_context.rb +1 -2
- data/lib/reek/code_context.rb +7 -0
- data/lib/reek/code_parser.rb +68 -24
- data/lib/reek/module_context.rb +1 -2
- data/lib/reek/options.rb +2 -2
- data/lib/reek.rb +1 -1
- data/reek.gemspec +2 -2
- data/spec/reek/options_spec.rb +1 -1
- data/spec/reek/smells/feature_envy_spec.rb +3 -7
- data/spec/reek/smells/long_method_spec.rb +174 -0
- data/spec/slow/inline_spec.rb +1 -4
- data/spec/slow/optparse_spec.rb +2 -1
- data/spec/spec_helper.rb +2 -2
- data/tasks/rspec.rake +2 -1
- metadata +2 -2
data/History.txt
CHANGED
data/lib/reek/class_context.rb
CHANGED
data/lib/reek/code_context.rb
CHANGED
data/lib/reek/code_parser.rb
CHANGED
@@ -9,6 +9,20 @@ require 'reek/method_context'
|
|
9
9
|
require 'reek/singleton_method_context'
|
10
10
|
require 'reek/yield_call_context'
|
11
11
|
|
12
|
+
class Sexp
|
13
|
+
def children
|
14
|
+
find_all { |item| Sexp === item }
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_language_node?
|
18
|
+
first.class == Symbol
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_type?(type)
|
22
|
+
is_language_node? and first == type
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
12
26
|
module Reek
|
13
27
|
|
14
28
|
class CodeParser
|
@@ -25,6 +39,7 @@ module Reek
|
|
25
39
|
meth = "process_#{exp[0]}"
|
26
40
|
meth = :process_default unless self.respond_to?(meth)
|
27
41
|
self.send(meth, exp)
|
42
|
+
@element
|
28
43
|
end
|
29
44
|
|
30
45
|
def process_default(exp)
|
@@ -90,19 +105,10 @@ module Reek
|
|
90
105
|
process_default(exp)
|
91
106
|
end
|
92
107
|
|
93
|
-
def process_fcall(exp)
|
94
|
-
@element.record_use_of_self
|
95
|
-
process_default(exp)
|
96
|
-
end
|
97
|
-
|
98
108
|
def process_cfunc(exp)
|
99
109
|
@element.record_depends_on_self
|
100
110
|
end
|
101
111
|
|
102
|
-
def process_vcall(exp)
|
103
|
-
@element.record_use_of_self
|
104
|
-
end
|
105
|
-
|
106
112
|
def process_attrasgn(exp)
|
107
113
|
process_call(exp)
|
108
114
|
end
|
@@ -112,7 +118,49 @@ module Reek
|
|
112
118
|
end
|
113
119
|
|
114
120
|
def process_if(exp)
|
121
|
+
count_clause(exp[2])
|
122
|
+
count_clause(exp[3])
|
115
123
|
handle_context(IfContext, :if, exp)
|
124
|
+
@element.count_statements(-1)
|
125
|
+
end
|
126
|
+
|
127
|
+
def process_while(exp)
|
128
|
+
count_clause(exp[2])
|
129
|
+
process_default(exp)
|
130
|
+
@element.count_statements(-1)
|
131
|
+
end
|
132
|
+
|
133
|
+
def process_until(exp)
|
134
|
+
count_clause(exp[2])
|
135
|
+
process_default(exp)
|
136
|
+
@element.count_statements(-1)
|
137
|
+
end
|
138
|
+
|
139
|
+
def process_for(exp)
|
140
|
+
count_clause(exp[3])
|
141
|
+
process_default(exp)
|
142
|
+
@element.count_statements(-1)
|
143
|
+
end
|
144
|
+
|
145
|
+
def process_rescue(exp)
|
146
|
+
count_clause(exp[1])
|
147
|
+
process_default(exp)
|
148
|
+
@element.count_statements(-1)
|
149
|
+
end
|
150
|
+
|
151
|
+
def process_resbody(exp)
|
152
|
+
count_clause(exp[2])
|
153
|
+
process_default(exp)
|
154
|
+
end
|
155
|
+
|
156
|
+
def process_case(exp)
|
157
|
+
process_default(exp)
|
158
|
+
@element.count_statements(-1)
|
159
|
+
end
|
160
|
+
|
161
|
+
def process_when(exp)
|
162
|
+
count_clause(exp[2])
|
163
|
+
process_default(exp)
|
116
164
|
end
|
117
165
|
|
118
166
|
def process_ivar(exp)
|
@@ -134,33 +182,33 @@ module Reek
|
|
134
182
|
@element.record_depends_on_self
|
135
183
|
end
|
136
184
|
|
185
|
+
def count_clause(sexp)
|
186
|
+
if sexp and !sexp.has_type?(:block)
|
187
|
+
@element.count_statements(1)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
137
191
|
def self.count_statements(exp)
|
138
192
|
stmts = exp[1..-1]
|
139
193
|
ignore = 0
|
140
|
-
ignore = 1 if is_expr?(stmts[0], :args)
|
141
194
|
ignore += 1 if stmts[1] == s(:nil)
|
142
195
|
stmts.length - ignore
|
143
196
|
end
|
144
197
|
|
145
198
|
private
|
146
199
|
|
147
|
-
def self.is_expr?(exp, type)
|
148
|
-
Array === exp and exp[0] == type
|
149
|
-
end
|
150
|
-
|
151
|
-
def self.is_global_variable?(exp)
|
152
|
-
is_expr?(exp, :gvar)
|
153
|
-
end
|
154
|
-
|
155
200
|
def handle_context(klass, type, exp)
|
156
|
-
|
201
|
+
scope = klass.new(@element, exp)
|
202
|
+
push(scope) do
|
157
203
|
process_default(exp)
|
158
204
|
check_smells(type)
|
159
205
|
end
|
206
|
+
scope
|
160
207
|
end
|
161
208
|
|
162
209
|
def check_smells(type)
|
163
|
-
@smells[type]
|
210
|
+
listeners = @smells[type]
|
211
|
+
listeners.each {|smell| smell.examine(@element, @report) } if listeners
|
164
212
|
end
|
165
213
|
|
166
214
|
def push(context)
|
@@ -169,9 +217,5 @@ module Reek
|
|
169
217
|
yield
|
170
218
|
@element = orig
|
171
219
|
end
|
172
|
-
|
173
|
-
def pop(exp)
|
174
|
-
@element = @element.outer
|
175
|
-
end
|
176
220
|
end
|
177
221
|
end
|
data/lib/reek/module_context.rb
CHANGED
data/lib/reek/options.rb
CHANGED
data/lib/reek.rb
CHANGED
data/reek.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{reek}
|
5
|
-
s.version = "1.1.3"
|
5
|
+
s.version = "1.1.3.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Kevin Rutherford"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-06-04}
|
10
10
|
s.default_executable = %q{reek}
|
11
11
|
s.description = %q{Code smell detector for Ruby}
|
12
12
|
s.email = ["kevin@rutherford-software.com"]
|
data/spec/reek/options_spec.rb
CHANGED
@@ -7,7 +7,7 @@ include Reek
|
|
7
7
|
describe Options, ' when given no arguments' do
|
8
8
|
it "should retain the default sort order" do
|
9
9
|
default_order = Options[:format]
|
10
|
-
Options.
|
10
|
+
Options.parse_args(['nosuchfile.rb'])
|
11
11
|
Options[:format].should == default_order
|
12
12
|
end
|
13
13
|
end
|
@@ -177,12 +177,8 @@ describe FeatureEnvy do
|
|
177
177
|
it 'counts self references correctly' do
|
178
178
|
'def adopt!(other)
|
179
179
|
other.keys.each do |key|
|
180
|
-
|
181
|
-
|
182
|
-
self[key] += ov
|
183
|
-
else
|
184
|
-
self[key] = ov
|
185
|
-
end
|
180
|
+
self[key] += 3
|
181
|
+
self[key] = o4
|
186
182
|
end
|
187
183
|
self
|
188
184
|
end'.should_not reek
|
@@ -202,7 +198,7 @@ def report
|
|
202
198
|
@report
|
203
199
|
end
|
204
200
|
EOS
|
205
|
-
ruby.
|
201
|
+
ruby.should_not reek
|
206
202
|
end
|
207
203
|
end
|
208
204
|
|
@@ -2,8 +2,10 @@ require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
|
2
2
|
|
3
3
|
require 'reek/code_parser'
|
4
4
|
require 'reek/report'
|
5
|
+
require 'reek/smells/long_method'
|
5
6
|
|
6
7
|
include Reek
|
8
|
+
include Reek::Smells
|
7
9
|
|
8
10
|
describe LongMethod do
|
9
11
|
it 'should not report short methods' do
|
@@ -57,3 +59,175 @@ EOS
|
|
57
59
|
src.should reek_only_of(:LongMethod)
|
58
60
|
end
|
59
61
|
end
|
62
|
+
|
63
|
+
describe LongMethod do
|
64
|
+
it 'counts 1 assignment' do
|
65
|
+
src = 'def one() val = 4; end'
|
66
|
+
source = Source.from_s(src)
|
67
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
68
|
+
method.num_statements.should == 1
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'counts 3 assignments' do
|
72
|
+
src = 'def one() val = 4; val = 4; val = 4; end'
|
73
|
+
source = Source.from_s(src)
|
74
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
75
|
+
method.num_statements.should == 3
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'counts 1 attr assignment' do
|
79
|
+
src = 'def one() val[0] = 4; end'
|
80
|
+
source = Source.from_s(src)
|
81
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
82
|
+
method.num_statements.should == 1
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'counts 1 increment assignment' do
|
86
|
+
src = 'def one() val += 4; end'
|
87
|
+
source = Source.from_s(src)
|
88
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
89
|
+
method.num_statements.should == 1
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'counts 1 increment attr assignment' do
|
93
|
+
src = 'def one() val[0] += 4; end'
|
94
|
+
source = Source.from_s(src)
|
95
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
96
|
+
method.num_statements.should == 1
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'counts 1 nested assignment' do
|
100
|
+
src = 'def one() val = fred = 4; end'
|
101
|
+
source = Source.from_s(src)
|
102
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
103
|
+
method.num_statements.should == 1
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'counts returns' do
|
107
|
+
src = 'def one() val = 4; true; end'
|
108
|
+
source = Source.from_s(src)
|
109
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
110
|
+
method.num_statements.should == 2
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe LongMethod, 'does not count control statements' do
|
115
|
+
it 'counts 1 statement in a conditional expression' do
|
116
|
+
src = 'def one() if val == 4; callee(); end; end'
|
117
|
+
source = Source.from_s(src)
|
118
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
119
|
+
method.num_statements.should == 1
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'counts 3 statements in a conditional expression' do
|
123
|
+
src = 'def one() if val == 4; callee(); callee(); callee(); end; end'
|
124
|
+
source = Source.from_s(src)
|
125
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
126
|
+
method.num_statements.should == 3
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'does not count empty conditional expression' do
|
130
|
+
src = 'def one() if val == 4; ; end; end'
|
131
|
+
source = Source.from_s(src)
|
132
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
133
|
+
method.num_statements.should == 0
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'counts 1 statement in a while loop' do
|
137
|
+
src = 'def one() while val < 4; callee(); end; end'
|
138
|
+
source = Source.from_s(src)
|
139
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
140
|
+
method.num_statements.should == 1
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'counts 3 statements in a while loop' do
|
144
|
+
src = 'def one() while val < 4; callee(); callee(); callee(); end; end'
|
145
|
+
source = Source.from_s(src)
|
146
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
147
|
+
method.num_statements.should == 3
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'counts 1 statement in a until loop' do
|
151
|
+
src = 'def one() until val < 4; callee(); end; end'
|
152
|
+
source = Source.from_s(src)
|
153
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
154
|
+
method.num_statements.should == 1
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'counts 3 statements in a until loop' do
|
158
|
+
src = 'def one() until val < 4; callee(); callee(); callee(); end; end'
|
159
|
+
source = Source.from_s(src)
|
160
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
161
|
+
method.num_statements.should == 3
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'counts 1 statement in a for loop' do
|
165
|
+
src = 'def one() for i in 0..4; callee(); end; end'
|
166
|
+
source = Source.from_s(src)
|
167
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
168
|
+
method.num_statements.should == 1
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'counts 3 statements in a for loop' do
|
172
|
+
src = 'def one() for i in 0..4; callee(); callee(); callee(); end; end'
|
173
|
+
source = Source.from_s(src)
|
174
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
175
|
+
method.num_statements.should == 3
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'counts 1 statement in a rescue' do
|
179
|
+
src = 'def one() begin; callee(); rescue; callee(); end; end'
|
180
|
+
source = Source.from_s(src)
|
181
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
182
|
+
method.num_statements.should == 2
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'counts 3 statements in a rescue' do
|
186
|
+
src = 'def one() begin; callee(); callee(); callee(); rescue; callee(); callee(); callee(); end; end'
|
187
|
+
source = Source.from_s(src)
|
188
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
189
|
+
method.num_statements.should == 6
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'counts 1 statement in a when' do
|
193
|
+
src = 'def one() case fred; when "hi"; callee(); end; end'
|
194
|
+
source = Source.from_s(src)
|
195
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
196
|
+
method.num_statements.should == 1
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'counts 3 statements in a when' do
|
200
|
+
src = 'def one() case fred; when "hi"; callee(); callee(); when "lo"; callee(); end; end'
|
201
|
+
source = Source.from_s(src)
|
202
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
203
|
+
method.num_statements.should == 3
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'does not count empty case' do
|
207
|
+
src = 'def one() case fred; when "hi"; ; when "lo"; ; end; end'
|
208
|
+
source = Source.from_s(src)
|
209
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
210
|
+
method.num_statements.should == 0
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'counts else statement' do
|
214
|
+
src = <<EOS
|
215
|
+
def parse(arg, argv, &error)
|
216
|
+
if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
|
217
|
+
return nil, block, nil
|
218
|
+
end
|
219
|
+
opt = (val = parse_arg(val, &error))[1]
|
220
|
+
val = conv_arg(*val)
|
221
|
+
if opt and !arg
|
222
|
+
argv.shift
|
223
|
+
else
|
224
|
+
val[0] = nil
|
225
|
+
end
|
226
|
+
val
|
227
|
+
end
|
228
|
+
EOS
|
229
|
+
source = Source.from_s(src)
|
230
|
+
method = CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
|
231
|
+
method.num_statements.should == 6
|
232
|
+
end
|
233
|
+
end
|
data/spec/slow/inline_spec.rb
CHANGED
@@ -22,11 +22,8 @@ describe 'sample gem source code' do
|
|
22
22
|
ruby.should reek_of(:Duplication, /Module#inline/, /Inline.const_get\(lang\)/)
|
23
23
|
ruby.should reek_of(:FeatureEnvy, /Inline::C#strip_comments/, /src/)
|
24
24
|
ruby.should reek_of(:LargeClass, /Inline::C/, /instance variables/)
|
25
|
-
ruby.should reek_of(:LongMethod, /File#self.write_with_backup/)
|
26
25
|
ruby.should reek_of(:LongMethod, /Inline::C#build/)
|
27
26
|
ruby.should reek_of(:LongMethod, /Inline::C#generate/)
|
28
|
-
ruby.should reek_of(:LongMethod, /Inline::C#load_cache/)
|
29
|
-
ruby.should reek_of(:LongMethod, /Inline::C#module_name/)
|
30
27
|
ruby.should reek_of(:LongMethod, /Inline::C#parse_signature/)
|
31
28
|
ruby.should reek_of(:LongMethod, /Inline::self.rootdir/)
|
32
29
|
ruby.should reek_of(:LongMethod, /Module#inline/)
|
@@ -38,6 +35,6 @@ describe 'sample gem source code' do
|
|
38
35
|
ruby.should reek_of(:UncommunicativeName, /Inline::C#module_name/, /'x'/)
|
39
36
|
ruby.should reek_of(:UncommunicativeName, /Inline::C#parse_signature/, /'x'/)
|
40
37
|
ruby.should reek_of(:UtilityFunction, /Inline::C#strip_comments/)
|
41
|
-
ruby.report.should have_at_most(
|
38
|
+
ruby.report.should have_at_most(32).smells
|
42
39
|
end
|
43
40
|
end
|
data/spec/slow/optparse_spec.rb
CHANGED
@@ -54,6 +54,7 @@ describe 'sample gem source code' do
|
|
54
54
|
ruby.should reek_of(:LargeClass, /OptionParser/)
|
55
55
|
ruby.should reek_of(:LongMethod, /OptionParser#Completion::complete/)
|
56
56
|
ruby.should reek_of(:LongMethod, /OptionParser#List#update/)
|
57
|
+
ruby.should reek_of(:LongMethod, /OptionParser#Switch#PlacedArgument#parse/)
|
57
58
|
ruby.should reek_of(:LongMethod, /OptionParser#Switch#parse_arg/)
|
58
59
|
ruby.should reek_of(:LongMethod, /OptionParser#Switch#summarize/)
|
59
60
|
ruby.should reek_of(:LongMethod, /OptionParser#getopts/)
|
@@ -103,6 +104,6 @@ describe 'sample gem source code' do
|
|
103
104
|
ruby.should reek_of(:UncommunicativeName, /OptionParser#summarize/, /'l'/)
|
104
105
|
ruby.should reek_of(:UncommunicativeName, /OptionParser#ver/, /'v'/)
|
105
106
|
ruby.should reek_of(:UncommunicativeName, /block/, /'q'/)
|
106
|
-
ruby.report.should have_at_most(
|
107
|
+
ruby.report.should have_at_most(117).smells
|
107
108
|
end
|
108
109
|
end
|
data/spec/spec_helper.rb
CHANGED
data/tasks/rspec.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kevinrutherford-reek
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.3
|
4
|
+
version: 1.1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Rutherford
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-06-04 00:00:00 -07:00
|
13
13
|
default_executable: reek
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|