reek 1.2.7.3 → 1.2.8
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 +17 -0
- data/README.md +32 -48
- data/config/defaults.reek +7 -1
- data/features/api.feature +20 -0
- data/features/masking_smells.feature +41 -0
- data/features/options.feature +4 -0
- data/features/rake_task.feature +14 -0
- data/features/yaml.feature +8 -8
- data/lib/reek.rb +1 -1
- data/lib/reek/cli/command_line.rb +9 -2
- data/lib/reek/cli/reek_command.rb +5 -4
- data/lib/reek/cli/yaml_command.rb +2 -2
- data/lib/reek/core/code_context.rb +10 -1
- data/lib/reek/core/method_context.rb +2 -2
- data/lib/reek/core/sniffer.rb +3 -1
- data/lib/reek/core/stop_context.rb +4 -0
- data/lib/reek/examiner.rb +2 -2
- data/lib/reek/rake/task.rb +16 -0
- data/lib/reek/smell_warning.rb +3 -2
- data/lib/reek/smells/attribute.rb +13 -9
- data/lib/reek/smells/boolean_parameter.rb +14 -9
- data/lib/reek/smells/class_variable.rb +16 -5
- data/lib/reek/smells/control_couple.rb +11 -6
- data/lib/reek/smells/data_clump.rb +33 -30
- data/lib/reek/smells/duplication.rb +39 -8
- data/lib/reek/smells/feature_envy.rb +7 -8
- data/lib/reek/smells/irresponsible_module.rb +12 -3
- data/lib/reek/smells/large_class.rb +31 -15
- data/lib/reek/smells/long_method.rb +15 -5
- data/lib/reek/smells/long_parameter_list.rb +14 -7
- data/lib/reek/smells/long_yield_list.rb +12 -9
- data/lib/reek/smells/nested_iterators.rb +46 -11
- data/lib/reek/smells/simulated_polymorphism.rb +16 -8
- data/lib/reek/smells/smell_detector.rb +13 -13
- data/lib/reek/smells/uncommunicative_method_name.rb +12 -20
- data/lib/reek/smells/uncommunicative_module_name.rb +17 -19
- data/lib/reek/smells/uncommunicative_parameter_name.rb +22 -15
- data/lib/reek/smells/uncommunicative_variable_name.rb +24 -18
- data/lib/reek/smells/utility_function.rb +6 -6
- data/lib/reek/source/code_comment.rb +19 -1
- data/lib/reek/source/tree_dresser.rb +40 -22
- data/reek.gemspec +6 -4
- data/spec/matchers/smell_of_matcher.rb +58 -0
- data/spec/reek/core/code_context_spec.rb +4 -2
- data/spec/reek/core/code_parser_spec.rb +2 -1
- data/spec/reek/core/method_context_spec.rb +5 -5
- data/spec/reek/smells/attribute_spec.rb +2 -4
- data/spec/reek/smells/boolean_parameter_spec.rb +32 -42
- data/spec/reek/smells/class_variable_spec.rb +22 -6
- data/spec/reek/smells/control_couple_spec.rb +15 -14
- data/spec/reek/smells/data_clump_spec.rb +29 -111
- data/spec/reek/smells/duplication_spec.rb +79 -49
- data/spec/reek/smells/feature_envy_spec.rb +1 -2
- data/spec/reek/smells/irresponsible_module_spec.rb +43 -22
- data/spec/reek/smells/large_class_spec.rb +34 -59
- data/spec/reek/smells/long_method_spec.rb +15 -10
- data/spec/reek/smells/long_parameter_list_spec.rb +24 -24
- data/spec/reek/smells/long_yield_list_spec.rb +13 -14
- data/spec/reek/smells/nested_iterators_spec.rb +93 -76
- data/spec/reek/smells/smell_detector_shared.rb +4 -2
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +10 -27
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +22 -23
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +36 -26
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +45 -48
- data/spec/reek/smells/utility_function_spec.rb +14 -13
- data/spec/reek/source/code_comment_spec.rb +61 -3
- data/spec/reek/source/tree_dresser_spec.rb +96 -1
- data/spec/samples/config/allow_duplication.reek +3 -0
- data/spec/samples/config/deeper_nested_iterators.reek +3 -0
- data/spec/samples/demo/demo.rb +8 -0
- data/spec/samples/inline_config/dirty.rb +16 -0
- data/spec/samples/inline_config/masked.reek +7 -0
- data/spec/samples/mask_some/dirty.rb +8 -0
- data/spec/samples/mask_some/some.reek +8 -0
- data/spec/spec_helper.rb +2 -0
- metadata +15 -5
@@ -19,12 +19,16 @@ module Reek
|
|
19
19
|
#
|
20
20
|
class UncommunicativeParameterName < SmellDetector
|
21
21
|
|
22
|
+
SMELL_CLASS = 'UncommunicativeName'
|
23
|
+
SMELL_SUBCLASS = self.name.split(/::/)[-1]
|
24
|
+
PARAMETER_NAME_KEY = 'parameter_name'
|
25
|
+
|
22
26
|
# The name of the config field that lists the regexps of
|
23
27
|
# smelly names to be reported.
|
24
28
|
REJECT_KEY = 'reject'
|
25
29
|
|
26
30
|
DEFAULT_REJECT_SET = [/^.$/, /[0-9]$/, /[A-Z]/]
|
27
|
-
|
31
|
+
|
28
32
|
# The name of the config field that lists the specific names that are
|
29
33
|
# to be treated as exceptions; these names will not be reported as
|
30
34
|
# uncommunicative.
|
@@ -34,8 +38,8 @@ module Reek
|
|
34
38
|
|
35
39
|
def self.default_config
|
36
40
|
super.adopt(
|
37
|
-
|
38
|
-
|
41
|
+
REJECT_KEY => DEFAULT_REJECT_SET,
|
42
|
+
ACCEPT_KEY => DEFAULT_ACCEPT_SET
|
39
43
|
)
|
40
44
|
end
|
41
45
|
|
@@ -49,23 +53,26 @@ module Reek
|
|
49
53
|
|
50
54
|
#
|
51
55
|
# Checks the given +context+ for uncommunicative names.
|
52
|
-
# Remembers any smells found.
|
53
56
|
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
# @return [Array<SmellWarning>]
|
58
|
+
#
|
59
|
+
def examine_context(ctx)
|
60
|
+
@reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
|
61
|
+
@accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
|
62
|
+
ctx.exp.parameter_names.select do |name|
|
63
|
+
is_bad_name?(name, ctx)
|
64
|
+
end.map do |name|
|
65
|
+
smell = SmellWarning.new(SMELL_CLASS, ctx.full_name, [ctx.exp.line],
|
66
|
+
"has the parameter name '#{name}'",
|
67
|
+
@source, SMELL_SUBCLASS, {PARAMETER_NAME_KEY => name.to_s})
|
68
|
+
smell
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
65
|
-
def is_bad_name?(name,
|
72
|
+
def is_bad_name?(name, ctx)
|
66
73
|
var = name.to_s.gsub(/^[@\*\&]*/, '')
|
67
|
-
return false if var == '*' or
|
68
|
-
|
74
|
+
return false if var == '*' or @accept_names.include?(var)
|
75
|
+
@reject_names.detect {|patt| patt === var}
|
69
76
|
end
|
70
77
|
end
|
71
78
|
end
|
@@ -19,12 +19,16 @@ module Reek
|
|
19
19
|
#
|
20
20
|
class UncommunicativeVariableName < SmellDetector
|
21
21
|
|
22
|
+
SMELL_CLASS = 'UncommunicativeName'
|
23
|
+
SMELL_SUBCLASS = self.name.split(/::/)[-1]
|
24
|
+
VARIABLE_NAME_KEY = 'variable_name'
|
25
|
+
|
22
26
|
# The name of the config field that lists the regexps of
|
23
27
|
# smelly names to be reported.
|
24
28
|
REJECT_KEY = 'reject'
|
25
29
|
|
26
30
|
DEFAULT_REJECT_SET = [/^.$/, /[0-9]$/, /[A-Z]/]
|
27
|
-
|
31
|
+
|
28
32
|
# The name of the config field that lists the specific names that are
|
29
33
|
# to be treated as exceptions; these names will not be reported as
|
30
34
|
# uncommunicative.
|
@@ -34,8 +38,8 @@ module Reek
|
|
34
38
|
|
35
39
|
def self.default_config
|
36
40
|
super.adopt(
|
37
|
-
|
38
|
-
|
41
|
+
REJECT_KEY => DEFAULT_REJECT_SET,
|
42
|
+
ACCEPT_KEY => DEFAULT_ACCEPT_SET
|
39
43
|
)
|
40
44
|
end
|
41
45
|
|
@@ -49,32 +53,34 @@ module Reek
|
|
49
53
|
|
50
54
|
#
|
51
55
|
# Checks the given +context+ for uncommunicative names.
|
52
|
-
# Remembers any smells found.
|
53
56
|
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
# @return [Array<SmellWarning>]
|
58
|
+
#
|
59
|
+
def examine_context(ctx)
|
60
|
+
@reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
|
61
|
+
@accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
|
62
|
+
variable_names(ctx.exp).select do |name, lines|
|
63
|
+
is_bad_name?(name, ctx)
|
64
|
+
end.map do |name, lines|
|
65
|
+
SmellWarning.new(SMELL_CLASS, ctx.full_name, lines,
|
66
|
+
"has the variable name '#{name}'",
|
67
|
+
@source, SMELL_SUBCLASS, {VARIABLE_NAME_KEY => name.to_s})
|
62
68
|
end
|
63
69
|
end
|
64
70
|
|
65
|
-
def is_bad_name?(name,
|
71
|
+
def is_bad_name?(name, ctx)
|
66
72
|
var = name.to_s.gsub(/^[@\*\&]*/, '')
|
67
|
-
return false if
|
68
|
-
|
73
|
+
return false if @accept_names.include?(var)
|
74
|
+
@reject_names.detect {|patt| patt === var}
|
69
75
|
end
|
70
76
|
|
71
77
|
def variable_names(exp)
|
72
78
|
assignment_nodes = exp.each_node(:lasgn, [:class, :module, :defs, :defn])
|
73
79
|
case exp.first
|
74
|
-
|
75
|
-
|
80
|
+
when :class, :module
|
81
|
+
assignment_nodes += exp.each_node(:iasgn, [:class, :module])
|
76
82
|
end
|
77
|
-
result = Hash.new {|hash,key| hash[key] = []}
|
83
|
+
result = Hash.new {|hash, key| hash[key] = []}
|
78
84
|
assignment_nodes.each {|asgn| result[asgn[1]].push(asgn.line) }
|
79
85
|
result
|
80
86
|
end
|
@@ -61,18 +61,18 @@ module Reek
|
|
61
61
|
|
62
62
|
#
|
63
63
|
# Checks whether the given +method+ is a utility function.
|
64
|
-
#
|
64
|
+
#
|
65
|
+
# @return [Array<SmellWarning>]
|
65
66
|
#
|
66
67
|
def examine_context(method_ctx)
|
67
|
-
return
|
68
|
-
return
|
69
|
-
return
|
68
|
+
return [] if method_ctx.num_statements == 0
|
69
|
+
return [] if depends_on_instance?(method_ctx.exp)
|
70
|
+
return [] if num_helper_methods(method_ctx) <= value(HELPER_CALLS_LIMIT_KEY, method_ctx, DEFAULT_HELPER_CALLS_LIMIT)
|
70
71
|
# SMELL: loads of calls to value{} with the above pattern
|
71
72
|
smell = SmellWarning.new(SMELL_CLASS, method_ctx.full_name, [method_ctx.exp.line],
|
72
73
|
"doesn't depend on instance state",
|
73
74
|
@source, SMELL_SUBCLASS)
|
74
|
-
|
75
|
-
#SMELL: serious duplication
|
75
|
+
[smell]
|
76
76
|
end
|
77
77
|
|
78
78
|
private
|
@@ -7,13 +7,31 @@ module Reek
|
|
7
7
|
# module, class and method definitions.
|
8
8
|
#
|
9
9
|
class CodeComment
|
10
|
+
CONFIG_REGEX = /:reek:(\w+)(:\s*\{.*?\})?/
|
10
11
|
|
11
12
|
def initialize(text)
|
12
|
-
@
|
13
|
+
@config = Hash.new { |hash,key| hash[key] = {} }
|
14
|
+
@text = text.gsub(CONFIG_REGEX) do |m|
|
15
|
+
add_to_config($1, $2)
|
16
|
+
''
|
17
|
+
end.gsub(/#/, '').gsub(/\n/, '').strip
|
13
18
|
end
|
19
|
+
|
20
|
+
def config
|
21
|
+
@config
|
22
|
+
end
|
23
|
+
|
14
24
|
def is_descriptive?
|
15
25
|
@text.split(/\s+/).length >= 2
|
16
26
|
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def add_to_config(smell, options)
|
30
|
+
options ||= ': { enabled: false }'
|
31
|
+
@config.merge! YAML.load(smell.gsub(/(?:^|_)(.)/) { $1.upcase } + options)
|
32
|
+
# extend this to all configs --------------------------^
|
33
|
+
# extend to allow configuration of whole smell class, not just subclass
|
34
|
+
end
|
17
35
|
end
|
18
36
|
end
|
19
37
|
end
|
@@ -6,6 +6,17 @@ module Reek
|
|
6
6
|
# syntax tree more easily.
|
7
7
|
#
|
8
8
|
module SexpNode
|
9
|
+
def self.format(expr)
|
10
|
+
case expr
|
11
|
+
when Sexp then expr.format_ruby
|
12
|
+
else expr.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def hash
|
17
|
+
self.inspect.hash
|
18
|
+
end
|
19
|
+
|
9
20
|
def is_language_node?
|
10
21
|
first.class == Symbol
|
11
22
|
end
|
@@ -37,7 +48,7 @@ module Reek
|
|
37
48
|
end
|
38
49
|
blk.call(self) if first == target_type
|
39
50
|
end
|
40
|
-
def
|
51
|
+
def format_ruby
|
41
52
|
return self[0].to_s unless Array === self
|
42
53
|
Ruby2Ruby.new.process(deep_copy)
|
43
54
|
end
|
@@ -64,15 +75,6 @@ module Reek
|
|
64
75
|
end
|
65
76
|
end
|
66
77
|
|
67
|
-
module ClassNode
|
68
|
-
def name() self[1] end
|
69
|
-
def superclass() self[2] end
|
70
|
-
def full_name(outer)
|
71
|
-
prefix = outer == '' ? '' : "#{outer}::"
|
72
|
-
"#{prefix}#{name}"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
78
|
module CvarNode
|
77
79
|
def name() self[1] end
|
78
80
|
end
|
@@ -80,24 +82,29 @@ module Reek
|
|
80
82
|
CvasgnNode = CvarNode
|
81
83
|
CvdeclNode = CvarNode
|
82
84
|
|
83
|
-
module
|
84
|
-
def name() self[1] end
|
85
|
+
module MethodNode
|
85
86
|
def arg_names
|
86
87
|
unless @args
|
87
|
-
@args =
|
88
|
+
@args = argslist[1..-1].reject {|param| Sexp === param or param.to_s =~ /^&/}
|
88
89
|
end
|
89
90
|
@args
|
90
91
|
end
|
91
92
|
def parameters()
|
92
93
|
unless @params
|
93
|
-
@params =
|
94
|
+
@params = argslist.reject {|param| Sexp === param}
|
94
95
|
end
|
95
96
|
@params
|
96
97
|
end
|
97
98
|
def parameter_names
|
98
99
|
parameters[1..-1]
|
99
100
|
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module DefnNode
|
104
|
+
def name() self[1] end
|
105
|
+
def argslist() self[2] end
|
100
106
|
def body() self[3] end
|
107
|
+
include MethodNode
|
101
108
|
def full_name(outer)
|
102
109
|
prefix = outer == '' ? '' : "#{outer}#"
|
103
110
|
"#{prefix}#{name}"
|
@@ -107,16 +114,12 @@ module Reek
|
|
107
114
|
module DefsNode
|
108
115
|
def receiver() self[1] end
|
109
116
|
def name() self[2] end
|
110
|
-
def
|
111
|
-
self[3].reject {|param| Sexp === param}
|
112
|
-
end
|
113
|
-
def parameter_names
|
114
|
-
parameters[1..-1]
|
115
|
-
end
|
117
|
+
def argslist() self[3] end
|
116
118
|
def body() self[4] end
|
119
|
+
include MethodNode
|
117
120
|
def full_name(outer)
|
118
121
|
prefix = outer == '' ? '' : "#{outer}#"
|
119
|
-
"#{prefix}#{
|
122
|
+
"#{prefix}#{SexpNode.format(receiver)}.#{name}"
|
120
123
|
end
|
121
124
|
end
|
122
125
|
|
@@ -148,12 +151,27 @@ module Reek
|
|
148
151
|
|
149
152
|
module ModuleNode
|
150
153
|
def name() self[1] end
|
154
|
+
def simple_name
|
155
|
+
expr = name
|
156
|
+
while Sexp === expr and expr[0] == :colon2
|
157
|
+
expr = expr[2]
|
158
|
+
end
|
159
|
+
expr
|
160
|
+
end
|
151
161
|
def full_name(outer)
|
152
162
|
prefix = outer == '' ? '' : "#{outer}::"
|
153
|
-
"#{prefix}#{
|
163
|
+
"#{prefix}#{text_name}"
|
164
|
+
end
|
165
|
+
def text_name
|
166
|
+
SexpNode.format(name)
|
154
167
|
end
|
155
168
|
end
|
156
169
|
|
170
|
+
module ClassNode
|
171
|
+
include ModuleNode
|
172
|
+
def superclass() self[2] end
|
173
|
+
end
|
174
|
+
|
157
175
|
module YieldNode
|
158
176
|
def args() self[1..-1] end
|
159
177
|
def arg_names
|
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.2.
|
5
|
+
s.version = "1.2.8"
|
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{2010-
|
9
|
+
s.date = %q{2010-04-26}
|
10
10
|
s.default_executable = %q{reek}
|
11
11
|
s.description = %q{Reek is a tool that examines Ruby classes, modules and methods
|
12
12
|
and reports any code smells it finds.
|
@@ -14,10 +14,12 @@ and reports any code smells it finds.
|
|
14
14
|
s.email = ["kevin@rutherford-software.com"]
|
15
15
|
s.executables = ["reek"]
|
16
16
|
s.extra_rdoc_files = ["History.txt", "License.txt"]
|
17
|
-
s.files = [".yardopts", "History.txt", "License.txt", "README.md", "Rakefile", "bin/reek", "config/defaults.reek", "features/masking_smells.feature", "features/options.feature", "features/rake_task.feature", "features/reports.feature", "features/samples.feature", "features/stdin.feature", "features/step_definitions/reek_steps.rb", "features/support/env.rb", "features/yaml.feature", "lib/reek.rb", "lib/reek/cli/application.rb", "lib/reek/cli/command_line.rb", "lib/reek/cli/help_command.rb", "lib/reek/cli/reek_command.rb", "lib/reek/cli/report.rb", "lib/reek/cli/version_command.rb", "lib/reek/cli/yaml_command.rb", "lib/reek/core/code_context.rb", "lib/reek/core/code_parser.rb", "lib/reek/core/method_context.rb", "lib/reek/core/module_context.rb", "lib/reek/core/object_refs.rb", "lib/reek/core/singleton_method_context.rb", "lib/reek/core/smell_configuration.rb", "lib/reek/core/sniffer.rb", "lib/reek/core/stop_context.rb", "lib/reek/core/warning_collector.rb", "lib/reek/examiner.rb", "lib/reek/rake/task.rb", "lib/reek/smell_warning.rb", "lib/reek/smells.rb", "lib/reek/smells/attribute.rb", "lib/reek/smells/boolean_parameter.rb", "lib/reek/smells/class_variable.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/data_clump.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/irresponsible_module.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/simulated_polymorphism.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/uncommunicative_method_name.rb", "lib/reek/smells/uncommunicative_module_name.rb", "lib/reek/smells/uncommunicative_parameter_name.rb", "lib/reek/smells/uncommunicative_variable_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/source.rb", "lib/reek/source/code_comment.rb", "lib/reek/source/config_file.rb", "lib/reek/source/core_extras.rb", "lib/reek/source/reference_collector.rb", "lib/reek/source/sexp_formatter.rb", "lib/reek/source/source_code.rb", "lib/reek/source/source_file.rb", "lib/reek/source/source_locator.rb", "lib/reek/source/tree_dresser.rb", "lib/reek/spec.rb", "lib/reek/spec/should_reek.rb", "lib/reek/spec/should_reek_of.rb", "lib/reek/spec/should_reek_only_of.rb", "reek.gemspec", "spec/reek/cli/help_command_spec.rb", "spec/reek/cli/reek_command_spec.rb", "spec/reek/cli/report_spec.rb", "spec/reek/cli/version_command_spec.rb", "spec/reek/cli/yaml_command_spec.rb", "spec/reek/core/code_context_spec.rb", "spec/reek/core/code_parser_spec.rb", "spec/reek/core/config_spec.rb", "spec/reek/core/method_context_spec.rb", "spec/reek/core/module_context_spec.rb", "spec/reek/core/object_refs_spec.rb", "spec/reek/core/singleton_method_context_spec.rb", "spec/reek/core/smell_configuration_spec.rb", "spec/reek/core/stop_context_spec.rb", "spec/reek/core/warning_collector_spec.rb", "spec/reek/examiner_spec.rb", "spec/reek/smell_warning_spec.rb", "spec/reek/smells/attribute_spec.rb", "spec/reek/smells/behaves_like_variable_detector.rb", "spec/reek/smells/boolean_parameter_spec.rb", "spec/reek/smells/class_variable_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/data_clump_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/irresponsible_module_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/long_yield_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/simulated_polymorphism_spec.rb", "spec/reek/smells/smell_detector_shared.rb", "spec/reek/smells/uncommunicative_method_name_spec.rb", "spec/reek/smells/uncommunicative_module_name_spec.rb", "spec/reek/smells/uncommunicative_parameter_name_spec.rb", "spec/reek/smells/uncommunicative_variable_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/reek/source/code_comment_spec.rb", "spec/reek/source/object_source_spec.rb", "spec/reek/source/reference_collector_spec.rb", "spec/reek/source/source_code_spec.rb", "spec/reek/source/tree_dresser_spec.rb", "spec/reek/spec/should_reek_of_spec.rb", "spec/reek/spec/should_reek_only_of_spec.rb", "spec/reek/spec/should_reek_spec.rb", "spec/samples/all_but_one_masked/clean_one.rb", "spec/samples/all_but_one_masked/dirty.rb", "spec/samples/all_but_one_masked/masked.reek", "spec/samples/clean_due_to_masking/clean_one.rb", "spec/samples/clean_due_to_masking/clean_three.rb", "spec/samples/clean_due_to_masking/clean_two.rb", "spec/samples/clean_due_to_masking/dirty_one.rb", "spec/samples/clean_due_to_masking/dirty_two.rb", "spec/samples/clean_due_to_masking/masked.reek", "spec/samples/corrupt_config_file/corrupt.reek", "spec/samples/corrupt_config_file/dirty.rb", "spec/samples/empty_config_file/dirty.rb", "spec/samples/empty_config_file/empty.reek", "spec/samples/exceptions.reek", "spec/samples/inline.rb", "spec/samples/masked/dirty.rb", "spec/samples/masked/masked.reek", "spec/samples/mixed_results/clean_one.rb", "spec/samples/mixed_results/clean_three.rb", "spec/samples/mixed_results/clean_two.rb", "spec/samples/mixed_results/dirty_one.rb", "spec/samples/mixed_results/dirty_two.rb", "spec/samples/not_quite_masked/dirty.rb", "spec/samples/not_quite_masked/masked.reek", "spec/samples/optparse.rb", "spec/samples/overrides/masked/dirty.rb", "spec/samples/overrides/masked/lower.reek", "spec/samples/overrides/upper.reek", "spec/samples/redcloth.rb", "spec/samples/three_clean_files/clean_one.rb", "spec/samples/three_clean_files/clean_three.rb", "spec/samples/three_clean_files/clean_two.rb", "spec/samples/two_smelly_files/dirty_one.rb", "spec/samples/two_smelly_files/dirty_two.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/test.rake"]
|
17
|
+
s.files = [".yardopts", "History.txt", "License.txt", "README.md", "Rakefile", "bin/reek", "config/defaults.reek", "features/api.feature", "features/masking_smells.feature", "features/options.feature", "features/rake_task.feature", "features/reports.feature", "features/samples.feature", "features/stdin.feature", "features/step_definitions/reek_steps.rb", "features/support/env.rb", "features/yaml.feature", "lib/reek.rb", "lib/reek/cli/application.rb", "lib/reek/cli/command_line.rb", "lib/reek/cli/help_command.rb", "lib/reek/cli/reek_command.rb", "lib/reek/cli/report.rb", "lib/reek/cli/version_command.rb", "lib/reek/cli/yaml_command.rb", "lib/reek/core/code_context.rb", "lib/reek/core/code_parser.rb", "lib/reek/core/method_context.rb", "lib/reek/core/module_context.rb", "lib/reek/core/object_refs.rb", "lib/reek/core/singleton_method_context.rb", "lib/reek/core/smell_configuration.rb", "lib/reek/core/sniffer.rb", "lib/reek/core/stop_context.rb", "lib/reek/core/warning_collector.rb", "lib/reek/examiner.rb", "lib/reek/rake/task.rb", "lib/reek/smell_warning.rb", "lib/reek/smells.rb", "lib/reek/smells/attribute.rb", "lib/reek/smells/boolean_parameter.rb", "lib/reek/smells/class_variable.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/data_clump.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/irresponsible_module.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/simulated_polymorphism.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/uncommunicative_method_name.rb", "lib/reek/smells/uncommunicative_module_name.rb", "lib/reek/smells/uncommunicative_parameter_name.rb", "lib/reek/smells/uncommunicative_variable_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/source.rb", "lib/reek/source/code_comment.rb", "lib/reek/source/config_file.rb", "lib/reek/source/core_extras.rb", "lib/reek/source/reference_collector.rb", "lib/reek/source/sexp_formatter.rb", "lib/reek/source/source_code.rb", "lib/reek/source/source_file.rb", "lib/reek/source/source_locator.rb", "lib/reek/source/tree_dresser.rb", "lib/reek/spec.rb", "lib/reek/spec/should_reek.rb", "lib/reek/spec/should_reek_of.rb", "lib/reek/spec/should_reek_only_of.rb", "reek.gemspec", "spec/matchers/smell_of_matcher.rb", "spec/reek/cli/help_command_spec.rb", "spec/reek/cli/reek_command_spec.rb", "spec/reek/cli/report_spec.rb", "spec/reek/cli/version_command_spec.rb", "spec/reek/cli/yaml_command_spec.rb", "spec/reek/core/code_context_spec.rb", "spec/reek/core/code_parser_spec.rb", "spec/reek/core/config_spec.rb", "spec/reek/core/method_context_spec.rb", "spec/reek/core/module_context_spec.rb", "spec/reek/core/object_refs_spec.rb", "spec/reek/core/singleton_method_context_spec.rb", "spec/reek/core/smell_configuration_spec.rb", "spec/reek/core/stop_context_spec.rb", "spec/reek/core/warning_collector_spec.rb", "spec/reek/examiner_spec.rb", "spec/reek/smell_warning_spec.rb", "spec/reek/smells/attribute_spec.rb", "spec/reek/smells/behaves_like_variable_detector.rb", "spec/reek/smells/boolean_parameter_spec.rb", "spec/reek/smells/class_variable_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/data_clump_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/irresponsible_module_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/long_yield_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/simulated_polymorphism_spec.rb", "spec/reek/smells/smell_detector_shared.rb", "spec/reek/smells/uncommunicative_method_name_spec.rb", "spec/reek/smells/uncommunicative_module_name_spec.rb", "spec/reek/smells/uncommunicative_parameter_name_spec.rb", "spec/reek/smells/uncommunicative_variable_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/reek/source/code_comment_spec.rb", "spec/reek/source/object_source_spec.rb", "spec/reek/source/reference_collector_spec.rb", "spec/reek/source/source_code_spec.rb", "spec/reek/source/tree_dresser_spec.rb", "spec/reek/spec/should_reek_of_spec.rb", "spec/reek/spec/should_reek_only_of_spec.rb", "spec/reek/spec/should_reek_spec.rb", "spec/samples/all_but_one_masked/clean_one.rb", "spec/samples/all_but_one_masked/dirty.rb", "spec/samples/all_but_one_masked/masked.reek", "spec/samples/clean_due_to_masking/clean_one.rb", "spec/samples/clean_due_to_masking/clean_three.rb", "spec/samples/clean_due_to_masking/clean_two.rb", "spec/samples/clean_due_to_masking/dirty_one.rb", "spec/samples/clean_due_to_masking/dirty_two.rb", "spec/samples/clean_due_to_masking/masked.reek", "spec/samples/config/allow_duplication.reek", "spec/samples/config/deeper_nested_iterators.reek", "spec/samples/corrupt_config_file/corrupt.reek", "spec/samples/corrupt_config_file/dirty.rb", "spec/samples/demo/demo.rb", "spec/samples/empty_config_file/dirty.rb", "spec/samples/empty_config_file/empty.reek", "spec/samples/exceptions.reek", "spec/samples/inline_config/dirty.rb", "spec/samples/inline_config/masked.reek", "spec/samples/inline.rb", "spec/samples/mask_some/dirty.rb", "spec/samples/mask_some/some.reek", "spec/samples/masked/dirty.rb", "spec/samples/masked/masked.reek", "spec/samples/mixed_results/clean_one.rb", "spec/samples/mixed_results/clean_three.rb", "spec/samples/mixed_results/clean_two.rb", "spec/samples/mixed_results/dirty_one.rb", "spec/samples/mixed_results/dirty_two.rb", "spec/samples/not_quite_masked/dirty.rb", "spec/samples/not_quite_masked/masked.reek", "spec/samples/optparse.rb", "spec/samples/overrides/masked/dirty.rb", "spec/samples/overrides/masked/lower.reek", "spec/samples/overrides/upper.reek", "spec/samples/redcloth.rb", "spec/samples/three_clean_files/clean_one.rb", "spec/samples/three_clean_files/clean_three.rb", "spec/samples/three_clean_files/clean_two.rb", "spec/samples/two_smelly_files/dirty_one.rb", "spec/samples/two_smelly_files/dirty_two.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/test.rake"]
|
18
18
|
s.homepage = %q{http://wiki.github.com/kevinrutherford/reek}
|
19
19
|
s.post_install_message = %q{
|
20
|
-
|
20
|
+
Thank you for downloading Reek. For info:
|
21
|
+
- see the reek wiki http://wiki.github.com/kevinrutherford/reek
|
22
|
+
- follow @rubyreek on twitter
|
21
23
|
}
|
22
24
|
s.rdoc_options = ["--main", "README.md"]
|
23
25
|
s.require_paths = ["lib"]
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module SmellOfMatcher
|
2
|
+
class SmellOf
|
3
|
+
def initialize(klass, *expected_smells)
|
4
|
+
@klass = klass
|
5
|
+
@expected_smells = expected_smells
|
6
|
+
@config = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def failure_message_for_should
|
10
|
+
"Expected #{@source.desc} to smell of #{@klass}, but it didn't: #{@reason}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def failure_message_for_should_not
|
14
|
+
"Expected #{@source.desc} not to smell of #{@klass}, but it did"
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches?(src)
|
18
|
+
@source = src.to_reek_source
|
19
|
+
ctx = MethodContext.new(nil, @source.syntax_tree)
|
20
|
+
detector = @klass.new(@source.desc, @klass.default_config.merge(@config))
|
21
|
+
detector.examine(ctx)
|
22
|
+
actual_smells = detector.smells_found.to_a
|
23
|
+
if actual_smells.empty?
|
24
|
+
@reason = 'no smells found by detector'
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
return false if actual_smells.any? do |expected_smell|
|
28
|
+
@reason = "Found #{expected_smell.smell_class}/#{expected_smell.subclass}" &&
|
29
|
+
expected_smell.smell_class != @klass::SMELL_CLASS &&
|
30
|
+
expected_smell.subclass != @klass::SMELL_SUBCLASS
|
31
|
+
end
|
32
|
+
return actual_smells.length == 1 if @expected_smells.empty?
|
33
|
+
return false unless @expected_smells.length == actual_smells.length
|
34
|
+
@expected_smells.each_with_index do |expected_smell,index|
|
35
|
+
expected_smell.each do |(key,value)|
|
36
|
+
if actual_smells[index].smell[key] != value
|
37
|
+
@reason = "#{key} != #{value}"
|
38
|
+
return false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def with_config(options)
|
46
|
+
@config = options
|
47
|
+
self
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def smell_of(klass, *smells)
|
52
|
+
SmellOf.new(klass, *smells)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Spec::Runner.configure do |config|
|
57
|
+
config.include(SmellOfMatcher)
|
58
|
+
end
|
@@ -13,6 +13,7 @@ describe CodeContext do
|
|
13
13
|
@exp = mock('exp')
|
14
14
|
@exp.should_receive(:name).any_number_of_times.and_return(@exp_name)
|
15
15
|
@exp.should_receive(:full_name).any_number_of_times.and_return(@full_name)
|
16
|
+
@exp.should_receive(:comments).any_number_of_times.and_return('')
|
16
17
|
@ctx = CodeContext.new(nil, @exp)
|
17
18
|
end
|
18
19
|
it 'gets its short name from the exp' do
|
@@ -36,6 +37,7 @@ describe CodeContext do
|
|
36
37
|
@outer_name = 'another_random sting'
|
37
38
|
outer = mock('outer')
|
38
39
|
outer.should_receive(:full_name).at_least(:once).and_return(@outer_name)
|
40
|
+
outer.should_receive(:config).and_return({})
|
39
41
|
@ctx = CodeContext.new(outer, @exp)
|
40
42
|
end
|
41
43
|
it 'creates the correct full name' do
|
@@ -54,8 +56,8 @@ describe CodeContext do
|
|
54
56
|
it 'should pass unknown method calls down the stack' do
|
55
57
|
stop = StopContext.new
|
56
58
|
def stop.bananas(arg1, arg2) arg1 + arg2 + 43 end
|
57
|
-
element = ModuleContext.new(stop, 'mod',
|
58
|
-
element = MethodContext.new(element,
|
59
|
+
element = ModuleContext.new(stop, 'mod', ast(:module, :mod, nil))
|
60
|
+
element = MethodContext.new(element, ast(:defn, :bad))
|
59
61
|
element.bananas(17, -5).should == 55
|
60
62
|
end
|
61
63
|
end
|