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 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