reek 1.0.0 → 1.1.3
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 +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)
|