reek 1.0.0 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +56 -22
- data/config/defaults.reek +3 -5
- data/lib/reek.rb +1 -1
- data/lib/reek/block_context.rb +27 -5
- data/lib/reek/class_context.rb +5 -9
- data/lib/reek/code_parser.rb +23 -50
- data/lib/reek/method_context.rb +18 -12
- data/lib/reek/module_context.rb +1 -1
- data/lib/reek/name.rb +8 -1
- data/lib/reek/object_refs.rb +2 -3
- data/lib/reek/object_source.rb +53 -0
- data/lib/reek/report.rb +41 -2
- data/lib/reek/sexp_formatter.rb +4 -46
- data/lib/reek/smells/large_class.rb +27 -8
- data/lib/reek/smells/long_parameter_list.rb +1 -1
- data/lib/reek/smells/smells.rb +4 -8
- data/lib/reek/source.rb +19 -8
- data/lib/reek/stop_context.rb +4 -16
- data/lib/reek/yield_call_context.rb +1 -3
- data/reek.gemspec +11 -9
- data/spec/reek/block_context_spec.rb +40 -0
- data/spec/reek/class_context_spec.rb +11 -40
- data/spec/reek/code_context_spec.rb +2 -1
- data/spec/reek/code_parser_spec.rb +0 -10
- data/spec/reek/config_spec.rb +2 -2
- data/spec/reek/method_context_spec.rb +14 -0
- data/spec/reek/name_spec.rb +13 -0
- data/spec/reek/object_refs_spec.rb +11 -9
- data/spec/reek/report_spec.rb +1 -1
- data/spec/reek/singleton_method_context_spec.rb +1 -1
- data/spec/reek/smells/duplication_spec.rb +2 -2
- data/spec/reek/smells/feature_envy_spec.rb +132 -36
- data/spec/reek/smells/large_class_spec.rb +48 -47
- data/spec/reek/smells/long_method_spec.rb +1 -1
- data/spec/reek/smells/long_parameter_list_spec.rb +4 -11
- data/spec/reek/smells/uncommunicative_name_spec.rb +6 -1
- data/spec/reek/smells/utility_function_spec.rb +6 -9
- data/spec/{samples → slow}/inline_spec.rb +13 -10
- data/spec/{samples → slow}/optparse_spec.rb +20 -12
- data/spec/{samples → slow}/redcloth_spec.rb +16 -8
- data/spec/{integration → slow}/reek_source_spec.rb +0 -0
- data/spec/{samples → slow/samples}/inline.rb +0 -0
- data/spec/{samples → slow/samples}/optparse.rb +0 -0
- data/spec/{samples → slow/samples}/redcloth.rb +0 -0
- data/spec/{integration → slow}/script_spec.rb +0 -0
- data/spec/slow/source_list_spec.rb +40 -0
- data/spec/spec_helper.rb +2 -0
- data/tasks/rspec.rake +1 -1
- metadata +30 -15
- data/spec/reek/sexp_formatter_spec.rb +0 -31
data/History.txt
CHANGED
@@ -1,44 +1,78 @@
|
|
1
|
-
== 1.
|
1
|
+
== 1.1.3 2009-05-19
|
2
|
+
|
3
|
+
=== Minor Changes
|
4
|
+
* No longer depends directly on the sexp_processor gem
|
5
|
+
|
6
|
+
=== Fixes
|
7
|
+
* LargeClass now relies only on the given source code (#26)
|
8
|
+
|
9
|
+
== 1.1.2 2009-05-18
|
10
|
+
|
11
|
+
=== Major Enhancements
|
12
|
+
* Switched from ParseTree to ruby_parser for source code parsing
|
13
|
+
* 'MyClass.should_not reek' now only possible if ParseTree gem installed
|
14
|
+
|
15
|
+
== 1.1.1 2009-05-08
|
16
|
+
|
17
|
+
=== Minor enhancements
|
18
|
+
* LargeClass now also warns about any class with > 9 instance variables (#6)
|
19
|
+
* Now depends on ruby2ruby, to display code better
|
20
|
+
* Duplication notices more repeated method calls
|
21
|
+
* Smells within blocks are now reported better
|
22
|
+
|
23
|
+
== 1.1.0 2009-04-10
|
24
|
+
|
25
|
+
=== Minor enhancements
|
26
|
+
* Now possible to write 'MyClass.should_not reek' (#33)
|
27
|
+
|
28
|
+
=== Fixes
|
29
|
+
* Now counts attr assignments ([]= etc) in feature envy calculations
|
30
|
+
* Doesn't attempt to find *.reek files when reading code from stdin
|
2
31
|
|
3
|
-
|
32
|
+
== 1.0.1 2009-04-06
|
4
33
|
|
34
|
+
=== Fixes
|
35
|
+
* Dir[...].to_source now creates a Report that can be browsed (#36)
|
36
|
+
|
37
|
+
== 1.0.0 2009-04-05
|
38
|
+
|
39
|
+
=== Major enhancements
|
5
40
|
* Use *.reek files in source tree to configure Reek's behaviour
|
6
41
|
* Added -f option to configure report format
|
7
42
|
* --sort_order replaced by -f, -c and -s
|
8
43
|
* Matchers provided for rspec; eg. foo.should_not reek
|
9
44
|
|
10
|
-
=== Minor enhancements
|
11
|
-
|
45
|
+
=== Minor enhancements
|
12
46
|
* Smells in singleton methods are now analysed
|
13
47
|
* Uncommunicative parameter names in blocks now reported
|
14
48
|
* Modules and blocks now reflected in scope of smell reports
|
15
49
|
|
16
|
-
=== Fixes
|
17
|
-
|
50
|
+
=== Fixes
|
18
51
|
* Corrected false reports of long arg lists to yield
|
19
52
|
* A method can now be a UtilityFunction only when it includes a call
|
20
53
|
|
21
54
|
== 0.3.1 2008-11-17
|
22
55
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
56
|
+
=== Minor enhancements
|
57
|
+
* Uncommunicative Name now checks instance variables more thoroughly
|
58
|
+
* Uncommunicative Name now warns about names of the form 'x2'
|
59
|
+
* Added check for duplicated calls within a method
|
60
|
+
* Reduced scope of Feature Envy warnings to cover only overuse of lvars
|
61
|
+
* Added rdoc comments explaining what each smell is about
|
62
|
+
* Chained iterators are no longer mis-reported as nested
|
30
63
|
|
31
64
|
== 0.3.0 2008-11-02
|
32
65
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
66
|
+
=== Minor enhancements
|
67
|
+
* New smell: first naive checks for Control Couple
|
68
|
+
* reek now only checks sources passed on the command line
|
69
|
+
* Code snippets can be supplied on the commandline
|
70
|
+
* Added headings and warnings count when smells in multiple files
|
71
|
+
* Added Reek::RakeTask to run reek from rakefiles
|
72
|
+
|
73
|
+
=== Fixes
|
74
|
+
* Fixed: Returns exit status 2 when smells are reported
|
75
|
+
* Fixed: no longer claims an empty method is a Utility Function
|
42
76
|
|
43
77
|
== 0.2.3 2008-09-22
|
44
78
|
|
data/config/defaults.reek
CHANGED
data/lib/reek.rb
CHANGED
data/lib/reek/block_context.rb
CHANGED
@@ -1,13 +1,35 @@
|
|
1
|
+
require 'set'
|
1
2
|
require 'reek/code_context'
|
2
3
|
|
3
4
|
module Reek
|
5
|
+
|
6
|
+
module ParameterSet
|
7
|
+
def names
|
8
|
+
return @names if @names
|
9
|
+
return (@names = []) if empty?
|
10
|
+
arg = slice(1)
|
11
|
+
case slice(0)
|
12
|
+
when :masgn
|
13
|
+
@names = arg[1..-1].map {|lasgn| Name.new(lasgn[1]) }
|
14
|
+
when :lasgn
|
15
|
+
@names = [Name.new(arg)]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def include?(name)
|
20
|
+
names.include?(name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
4
24
|
class BlockContext < CodeContext
|
5
25
|
|
6
26
|
def initialize(outer, exp)
|
7
27
|
super
|
8
|
-
@parameters = []
|
9
|
-
@local_variables = []
|
10
28
|
@name = Name.new('block')
|
29
|
+
@parameters = exp[0] if exp
|
30
|
+
@parameters ||= []
|
31
|
+
@parameters.extend(ParameterSet)
|
32
|
+
@local_variables = Set.new
|
11
33
|
end
|
12
34
|
|
13
35
|
def inside_a_block?
|
@@ -22,8 +44,8 @@ module Reek
|
|
22
44
|
@outer.inside_a_block?
|
23
45
|
end
|
24
46
|
|
25
|
-
def
|
26
|
-
@
|
47
|
+
def record_local_variable(sym)
|
48
|
+
@local_variables << Name.new(sym)
|
27
49
|
end
|
28
50
|
|
29
51
|
def outer_name
|
@@ -31,7 +53,7 @@ module Reek
|
|
31
53
|
end
|
32
54
|
|
33
55
|
def variable_names
|
34
|
-
@parameters + @local_variables
|
56
|
+
@parameters.names + @local_variables.to_a
|
35
57
|
end
|
36
58
|
end
|
37
59
|
end
|
data/lib/reek/class_context.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
+
require 'set'
|
1
2
|
require 'reek/code_context'
|
2
3
|
|
3
4
|
class Class
|
4
|
-
def non_inherited_methods
|
5
|
-
instance_methods(false) + private_instance_methods(false)
|
6
|
-
end
|
7
|
-
|
8
5
|
def is_overriding_method?(sym)
|
9
6
|
instance_methods(false).include?(sym) and superclass.instance_methods(true).include?(sym)
|
10
7
|
end
|
@@ -23,7 +20,7 @@ module Reek
|
|
23
20
|
@name = name
|
24
21
|
@superclass = superclass
|
25
22
|
@parsed_methods = []
|
26
|
-
@instance_variables =
|
23
|
+
@instance_variables = Set.new
|
27
24
|
end
|
28
25
|
|
29
26
|
def myself
|
@@ -33,12 +30,12 @@ module Reek
|
|
33
30
|
def find_module(modname)
|
34
31
|
sym = modname.to_s
|
35
32
|
return nil unless myself
|
36
|
-
myself.const_defined?(sym) ? myself.const_get(sym) : nil
|
33
|
+
@myself.const_defined?(sym) ? @myself.const_get(sym) : nil
|
37
34
|
end
|
38
35
|
|
39
36
|
def is_overriding_method?(name)
|
40
37
|
return false unless myself
|
41
|
-
myself.is_overriding_method?(name.to_s)
|
38
|
+
@myself.is_overriding_method?(name.to_s)
|
42
39
|
end
|
43
40
|
|
44
41
|
def is_struct?
|
@@ -46,8 +43,7 @@ module Reek
|
|
46
43
|
end
|
47
44
|
|
48
45
|
def num_methods
|
49
|
-
|
50
|
-
meths.length
|
46
|
+
@parsed_methods.length
|
51
47
|
end
|
52
48
|
|
53
49
|
def record_instance_variable(sym)
|
data/lib/reek/code_parser.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
3
|
-
require 'sexp_processor'
|
2
|
+
require 'sexp'
|
4
3
|
require 'reek/block_context'
|
5
4
|
require 'reek/class_context'
|
6
5
|
require 'reek/module_context'
|
@@ -12,41 +11,24 @@ require 'reek/yield_call_context'
|
|
12
11
|
|
13
12
|
module Reek
|
14
13
|
|
15
|
-
class CodeParser
|
14
|
+
class CodeParser
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
# Creates a new Ruby code checker. Any smells discovered by
|
22
|
-
# +check_source+ or +check_object+ will be stored in +report+.
|
16
|
+
# Creates a new Ruby code checker. Any smells discovered
|
17
|
+
# will be stored in +report+.
|
23
18
|
def initialize(report, smells, ctx = StopContext.new)
|
24
|
-
super()
|
25
19
|
@report = report
|
26
20
|
@smells = smells
|
27
21
|
@element = ctx
|
28
|
-
@unsupported -= [:cfunc]
|
29
|
-
@default_method = :process_default
|
30
|
-
@require_empty = @warn_on_default = false
|
31
22
|
end
|
32
23
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
check_parse_tree(CodeParser.parse_tree_for(code))
|
38
|
-
end
|
39
|
-
|
40
|
-
# Analyses the given Ruby object +obj+ looking for smells.
|
41
|
-
# Any smells found are saved in the +Report+ object that
|
42
|
-
# was passed to this object's constructor.
|
43
|
-
def check_object(obj)
|
44
|
-
check_parse_tree(ParseTree.new.parse_tree(obj))
|
24
|
+
def process(exp)
|
25
|
+
meth = "process_#{exp[0]}"
|
26
|
+
meth = :process_default unless self.respond_to?(meth)
|
27
|
+
self.send(meth, exp)
|
45
28
|
end
|
46
29
|
|
47
30
|
def process_default(exp)
|
48
|
-
exp[
|
49
|
-
s(exp)
|
31
|
+
exp[0..-1].each { |sub| process(sub) if Array === sub }
|
50
32
|
end
|
51
33
|
|
52
34
|
def process_module(exp)
|
@@ -54,7 +36,6 @@ module Reek
|
|
54
36
|
process_default(exp)
|
55
37
|
check_smells(:module)
|
56
38
|
end
|
57
|
-
s(exp)
|
58
39
|
end
|
59
40
|
|
60
41
|
def process_class(exp)
|
@@ -62,7 +43,6 @@ module Reek
|
|
62
43
|
process_default(exp) unless @element.is_struct?
|
63
44
|
check_smells(:class)
|
64
45
|
end
|
65
|
-
s(exp)
|
66
46
|
end
|
67
47
|
|
68
48
|
def process_defn(exp)
|
@@ -75,23 +55,20 @@ module Reek
|
|
75
55
|
|
76
56
|
def process_args(exp)
|
77
57
|
exp[1..-1].each {|sym| @element.record_parameter(sym) }
|
78
|
-
s(exp)
|
79
58
|
end
|
80
59
|
|
81
60
|
def process_attrset(exp)
|
82
61
|
@element.record_depends_on_self if /^@/ === exp[1].to_s
|
83
|
-
s(exp)
|
84
62
|
end
|
85
63
|
|
86
64
|
def process_lit(exp)
|
87
65
|
val = exp[1]
|
88
66
|
@element.record_depends_on_self if val == :self
|
89
|
-
s(exp)
|
90
67
|
end
|
91
68
|
|
92
69
|
def process_iter(exp)
|
93
70
|
process(exp[1])
|
94
|
-
handle_context(BlockContext, :iter, exp[
|
71
|
+
handle_context(BlockContext, :iter, exp[2..-1])
|
95
72
|
end
|
96
73
|
|
97
74
|
def process_dasgn_curr(exp)
|
@@ -114,20 +91,24 @@ module Reek
|
|
114
91
|
end
|
115
92
|
|
116
93
|
def process_fcall(exp)
|
117
|
-
@element.
|
118
|
-
@element.refs.record_reference_to_self
|
94
|
+
@element.record_use_of_self
|
119
95
|
process_default(exp)
|
120
96
|
end
|
121
97
|
|
122
98
|
def process_cfunc(exp)
|
123
99
|
@element.record_depends_on_self
|
124
|
-
s(exp)
|
125
100
|
end
|
126
101
|
|
127
102
|
def process_vcall(exp)
|
128
|
-
@element.
|
129
|
-
|
130
|
-
|
103
|
+
@element.record_use_of_self
|
104
|
+
end
|
105
|
+
|
106
|
+
def process_attrasgn(exp)
|
107
|
+
process_call(exp)
|
108
|
+
end
|
109
|
+
|
110
|
+
def process_op_asgn1(exp)
|
111
|
+
process_call(exp)
|
131
112
|
end
|
132
113
|
|
133
114
|
def process_if(exp)
|
@@ -140,8 +121,7 @@ module Reek
|
|
140
121
|
|
141
122
|
def process_lasgn(exp)
|
142
123
|
@element.record_local_variable(exp[1])
|
143
|
-
|
144
|
-
s(exp)
|
124
|
+
process_default(exp)
|
145
125
|
end
|
146
126
|
|
147
127
|
def process_iasgn(exp)
|
@@ -152,11 +132,8 @@ module Reek
|
|
152
132
|
|
153
133
|
def process_self(exp)
|
154
134
|
@element.record_depends_on_self
|
155
|
-
s(exp)
|
156
135
|
end
|
157
136
|
|
158
|
-
private
|
159
|
-
|
160
137
|
def self.count_statements(exp)
|
161
138
|
stmts = exp[1..-1]
|
162
139
|
ignore = 0
|
@@ -165,6 +142,8 @@ module Reek
|
|
165
142
|
stmts.length - ignore
|
166
143
|
end
|
167
144
|
|
145
|
+
private
|
146
|
+
|
168
147
|
def self.is_expr?(exp, type)
|
169
148
|
Array === exp and exp[0] == type
|
170
149
|
end
|
@@ -178,7 +157,6 @@ module Reek
|
|
178
157
|
process_default(exp)
|
179
158
|
check_smells(type)
|
180
159
|
end
|
181
|
-
s(exp)
|
182
160
|
end
|
183
161
|
|
184
162
|
def check_smells(type)
|
@@ -194,11 +172,6 @@ module Reek
|
|
194
172
|
|
195
173
|
def pop(exp)
|
196
174
|
@element = @element.outer
|
197
|
-
s(exp)
|
198
|
-
end
|
199
|
-
|
200
|
-
def check_parse_tree(sexp) # :nodoc:
|
201
|
-
sexp.each { |exp| process(exp) }
|
202
175
|
end
|
203
176
|
end
|
204
177
|
end
|
data/lib/reek/method_context.rb
CHANGED
@@ -32,22 +32,28 @@ module Reek
|
|
32
32
|
def has_parameter(sym)
|
33
33
|
@parameters.include?(sym.to_s)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def record_call_to(exp)
|
37
37
|
@calls[exp] += 1
|
38
38
|
receiver, meth = exp[1..2]
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
when :ivar
|
46
|
-
record_depends_on_self
|
47
|
-
@refs.record_reference_to_self
|
48
|
-
end
|
39
|
+
receiver ||= [:self]
|
40
|
+
case receiver[0]
|
41
|
+
when :lvar
|
42
|
+
@refs.record_ref(receiver) unless meth == :new
|
43
|
+
when :self
|
44
|
+
record_use_of_self
|
49
45
|
end
|
50
46
|
end
|
47
|
+
|
48
|
+
def record_use_of_self
|
49
|
+
record_depends_on_self
|
50
|
+
@refs.record_reference_to_self
|
51
|
+
end
|
52
|
+
|
53
|
+
def record_instance_variable(sym)
|
54
|
+
record_use_of_self
|
55
|
+
@outer.record_instance_variable(sym)
|
56
|
+
end
|
51
57
|
|
52
58
|
def record_depends_on_self
|
53
59
|
@depends_on_self = true
|
@@ -58,7 +64,7 @@ module Reek
|
|
58
64
|
end
|
59
65
|
|
60
66
|
def self.is_block_arg?(param)
|
61
|
-
Array === param and param[0] == :block
|
67
|
+
(Array === param and param[0] == :block) or (param.to_s =~ /^\&/)
|
62
68
|
end
|
63
69
|
|
64
70
|
def record_parameter(param)
|