kevinrutherford-reek 1.1.3 → 1.1.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.1.4 (in git)
2
+
3
+ === Minor Changes
4
+ * LongMethod now counts statements deeper into each method (#25)
5
+ * LongMethod no longer counts control structures, only their contained stmts
6
+
1
7
  == 1.1.3 2009-05-19
2
8
 
3
9
  === Minor Changes
@@ -28,9 +28,8 @@ module Reek
28
28
  end
29
29
 
30
30
  def find_module(modname)
31
- sym = modname.to_s
32
31
  return nil unless myself
33
- @myself.const_defined?(sym) ? @myself.const_get(sym) : nil
32
+ @myself.const_or_nil(modname.to_s)
34
33
  end
35
34
 
36
35
  def is_overriding_method?(name)
@@ -1,3 +1,10 @@
1
+ class Module
2
+
3
+ def const_or_nil(sym)
4
+ const_defined?(sym) ? const_get(sym) : nil
5
+ end
6
+ end
7
+
1
8
  module Reek
2
9
 
3
10
  #
@@ -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
- push(klass.new(@element, exp)) do
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].each {|smell| smell.examine(@element, @report) }
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
@@ -19,8 +19,7 @@ module Reek
19
19
 
20
20
  def find_module(modname)
21
21
  return nil unless myself
22
- sym = modname.to_s
23
- @myself.const_defined?(sym) ? @myself.const_get(sym) : nil
22
+ @myself.const_or_nil(modname.to_s)
24
23
  end
25
24
 
26
25
  def outer_name
data/lib/reek/options.rb CHANGED
@@ -44,8 +44,8 @@ EOB
44
44
  def self.parse(args)
45
45
  begin
46
46
  @@opts = parse_args(args)
47
- if ARGV.length > 0
48
- return Source.from_pathlist(ARGV)
47
+ if args.length > 0
48
+ return Source.from_pathlist(args)
49
49
  else
50
50
  return Source.from_io($stdin, 'stdin')
51
51
  end
data/lib/reek.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
3
  module Reek # :doc:
4
- VERSION = '1.1.3'
4
+ VERSION = '1.1.3.1'
5
5
  end
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-05-19}
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"]
@@ -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.parse ['nosuchfile.rb']
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
- ov = other[key]
181
- if Array === ov and has_key?(key)
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.should reek_only_of(:LongMethod)
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
@@ -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(35).smells
38
+ ruby.report.should have_at_most(32).smells
42
39
  end
43
40
  end
@@ -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(116).smells
107
+ ruby.report.should have_at_most(117).smells
107
108
  end
108
109
  end
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  $:.unshift File.dirname(__FILE__) + '/../lib'
2
2
 
3
3
  begin
4
- require 'spec'
4
+ require 'spec/expectations'
5
5
  rescue LoadError
6
6
  require 'rubygems'
7
7
  gem 'rspec'
8
- require 'spec'
8
+ require 'spec/expectations'
9
9
  end
10
10
 
11
11
  require 'reek/spec'
data/tasks/rspec.rake CHANGED
@@ -13,7 +13,8 @@ namespace 'rspec' do
13
13
 
14
14
  Spec::Rake::SpecTask.new('all') do |t|
15
15
  t.spec_files = FAST + SLOW
16
- t.rcov = false
16
+ t.rcov = true
17
+ t.rcov_dir = 'build/coverage'
17
18
  end
18
19
  end
19
20
 
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-05-19 00:00:00 -07:00
12
+ date: 2009-06-04 00:00:00 -07:00
13
13
  default_executable: reek
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency