reek 1.3.8 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +11 -0
- data/README.md +22 -14
- data/Rakefile +2 -15
- data/assets/html_output.html.erb +103 -0
- data/features/command_line_interface/options.feature +3 -0
- data/features/command_line_interface/smell_selection.feature +19 -0
- data/features/rake_task/rake_task.feature +1 -1
- data/features/reports/reports.feature +16 -0
- data/features/reports/yaml.feature +26 -23
- data/features/samples.feature +2 -1
- data/features/step_definitions/reek_steps.rb +15 -15
- data/features/support/env.rb +7 -9
- data/lib/reek/cli/application.rb +2 -4
- data/lib/reek/cli/command.rb +12 -0
- data/lib/reek/cli/help_command.rb +3 -6
- data/lib/reek/cli/options.rb +147 -0
- data/lib/reek/cli/reek_command.rb +18 -14
- data/lib/reek/cli/report/formatter.rb +56 -0
- data/lib/reek/cli/report/report.rb +106 -0
- data/lib/reek/cli/report/strategy.rb +63 -0
- data/lib/reek/cli/version_command.rb +3 -6
- data/lib/reek/config_file_exception.rb +0 -1
- data/lib/reek/core/code_context.rb +1 -3
- data/lib/reek/core/code_parser.rb +13 -12
- data/lib/reek/core/method_context.rb +13 -2
- data/lib/reek/core/module_context.rb +0 -4
- data/lib/reek/core/object_refs.rb +2 -3
- data/lib/reek/core/singleton_method_context.rb +0 -2
- data/lib/reek/core/smell_configuration.rb +3 -5
- data/lib/reek/core/smell_repository.rb +7 -8
- data/lib/reek/core/sniffer.rb +4 -10
- data/lib/reek/core/stop_context.rb +2 -4
- data/lib/reek/core/warning_collector.rb +0 -1
- data/lib/reek/examiner.rb +19 -17
- data/lib/reek/rake/task.rb +7 -10
- data/lib/reek/smell_warning.rb +4 -8
- data/lib/reek/smells.rb +0 -1
- data/lib/reek/smells/attribute.rb +8 -11
- data/lib/reek/smells/boolean_parameter.rb +5 -7
- data/lib/reek/smells/class_variable.rb +6 -7
- data/lib/reek/smells/control_parameter.rb +78 -45
- data/lib/reek/smells/data_clump.rb +13 -16
- data/lib/reek/smells/duplicate_method_call.rb +13 -11
- data/lib/reek/smells/feature_envy.rb +6 -7
- data/lib/reek/smells/irresponsible_module.rb +4 -6
- data/lib/reek/smells/long_parameter_list.rb +5 -7
- data/lib/reek/smells/long_yield_list.rb +2 -4
- data/lib/reek/smells/nested_iterators.rb +12 -22
- data/lib/reek/smells/nil_check.rb +35 -46
- data/lib/reek/smells/prima_donna_method.rb +24 -16
- data/lib/reek/smells/repeated_conditional.rb +8 -10
- data/lib/reek/smells/smell_detector.rb +9 -7
- data/lib/reek/smells/too_many_instance_variables.rb +7 -9
- data/lib/reek/smells/too_many_methods.rb +6 -8
- data/lib/reek/smells/too_many_statements.rb +4 -6
- data/lib/reek/smells/uncommunicative_method_name.rb +5 -7
- data/lib/reek/smells/uncommunicative_module_name.rb +5 -7
- data/lib/reek/smells/uncommunicative_parameter_name.rb +7 -9
- data/lib/reek/smells/uncommunicative_variable_name.rb +15 -18
- data/lib/reek/smells/unused_parameters.rb +5 -45
- data/lib/reek/smells/utility_function.rb +9 -10
- data/lib/reek/source.rb +0 -1
- data/lib/reek/source/code_comment.rb +7 -8
- data/lib/reek/source/config_file.rb +2 -4
- data/lib/reek/source/core_extras.rb +1 -1
- data/lib/reek/source/reference_collector.rb +1 -2
- data/lib/reek/source/sexp_extensions.rb +93 -10
- data/lib/reek/source/sexp_formatter.rb +2 -3
- data/lib/reek/source/sexp_node.rb +19 -15
- data/lib/reek/source/source_code.rb +4 -14
- data/lib/reek/source/source_file.rb +3 -5
- data/lib/reek/source/source_locator.rb +5 -6
- data/lib/reek/source/source_repository.rb +3 -3
- data/lib/reek/source/tree_dresser.rb +2 -2
- data/lib/reek/spec.rb +1 -2
- data/lib/reek/spec/should_reek.rb +8 -5
- data/lib/reek/spec/should_reek_of.rb +6 -4
- data/lib/reek/spec/should_reek_only_of.rb +10 -6
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +34 -30
- data/spec/gem/updates_spec.rb +3 -4
- data/spec/gem/yard_spec.rb +1 -2
- data/spec/matchers/smell_of_matcher.rb +12 -14
- data/spec/quality/reek_source_spec.rb +42 -0
- data/spec/reek/cli/help_command_spec.rb +7 -5
- data/spec/reek/cli/report_spec.rb +89 -22
- data/spec/reek/cli/version_command_spec.rb +8 -6
- data/spec/reek/core/code_context_spec.rb +25 -26
- data/spec/reek/core/code_parser_spec.rb +6 -6
- data/spec/reek/core/method_context_spec.rb +18 -18
- data/spec/reek/core/module_context_spec.rb +5 -5
- data/spec/reek/core/object_refs_spec.rb +21 -22
- data/spec/reek/core/smell_configuration_spec.rb +22 -21
- data/spec/reek/core/stop_context_spec.rb +2 -2
- data/spec/reek/core/warning_collector_spec.rb +3 -3
- data/spec/reek/examiner_spec.rb +9 -9
- data/spec/reek/smell_warning_spec.rb +29 -29
- data/spec/reek/smells/attribute_spec.rb +6 -6
- data/spec/reek/smells/behaves_like_variable_detector.rb +6 -6
- data/spec/reek/smells/boolean_parameter_spec.rb +17 -17
- data/spec/reek/smells/class_variable_spec.rb +9 -9
- data/spec/reek/smells/control_parameter_spec.rb +161 -137
- data/spec/reek/smells/data_clump_spec.rb +22 -19
- data/spec/reek/smells/duplicate_method_call_spec.rb +71 -27
- data/spec/reek/smells/feature_envy_spec.rb +32 -32
- data/spec/reek/smells/irresponsible_module_spec.rb +21 -21
- data/spec/reek/smells/long_parameter_list_spec.rb +14 -14
- data/spec/reek/smells/long_yield_list_spec.rb +6 -6
- data/spec/reek/smells/nested_iterators_spec.rb +21 -21
- data/spec/reek/smells/nil_check_spec.rb +23 -15
- data/spec/reek/smells/prima_donna_method_spec.rb +5 -5
- data/spec/reek/smells/repeated_conditional_spec.rb +14 -14
- data/spec/reek/smells/smell_detector_shared.rb +9 -9
- data/spec/reek/smells/too_many_instance_variables_spec.rb +12 -12
- data/spec/reek/smells/too_many_methods_spec.rb +10 -10
- data/spec/reek/smells/too_many_statements_spec.rb +41 -41
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +4 -4
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +12 -12
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +21 -21
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +49 -49
- data/spec/reek/smells/unused_parameters_spec.rb +26 -16
- data/spec/reek/smells/utility_function_spec.rb +20 -20
- data/spec/reek/source/code_comment_spec.rb +37 -37
- data/spec/reek/source/object_source_spec.rb +5 -5
- data/spec/reek/source/reference_collector_spec.rb +9 -9
- data/spec/reek/source/sexp_extensions_spec.rb +73 -52
- data/spec/reek/source/sexp_formatter_spec.rb +3 -4
- data/spec/reek/source/sexp_node_spec.rb +3 -3
- data/spec/reek/source/source_code_spec.rb +16 -15
- data/spec/reek/source/tree_dresser_spec.rb +2 -2
- data/spec/reek/spec/should_reek_of_spec.rb +11 -11
- data/spec/reek/spec/should_reek_only_of_spec.rb +11 -11
- data/spec/reek/spec/should_reek_spec.rb +11 -11
- data/spec/samples/one_smelly_file/dirty.rb +3 -0
- data/spec/spec_helper.rb +0 -6
- data/tasks/develop.rake +8 -16
- data/tasks/reek.rake +5 -13
- data/tasks/test.rake +5 -22
- metadata +56 -34
- data/lib/reek/cli/command_line.rb +0 -126
- data/lib/reek/cli/report.rb +0 -138
@@ -4,13 +4,12 @@ require 'reek/source/reference_collector'
|
|
4
4
|
|
5
5
|
module Reek
|
6
6
|
module Smells
|
7
|
-
|
8
|
-
#
|
7
|
+
#
|
9
8
|
# A Utility Function is any instance method that has no
|
10
9
|
# dependency on the state of the instance.
|
11
|
-
#
|
10
|
+
#
|
12
11
|
# Currently +UtilityFunction+ will warn about any method that:
|
13
|
-
#
|
12
|
+
#
|
14
13
|
# * is non-empty, and
|
15
14
|
# * does not override an inherited method, and
|
16
15
|
# * calls at least one method on another object, and
|
@@ -34,8 +33,7 @@ module Reek
|
|
34
33
|
# likely belong there.
|
35
34
|
#
|
36
35
|
class UtilityFunction < SmellDetector
|
37
|
-
|
38
|
-
SMELL_SUBCLASS = self.name.split(/::/)[-1]
|
36
|
+
SMELL_SUBCLASS = name.split(/::/)[-1]
|
39
37
|
SMELL_CLASS = 'LowCohesion'
|
40
38
|
|
41
39
|
# The name of the config field that sets the maximum number of
|
@@ -50,6 +48,7 @@ module Reek
|
|
50
48
|
def contexts # :nodoc:
|
51
49
|
[:defn]
|
52
50
|
end
|
51
|
+
|
53
52
|
def default_config
|
54
53
|
super.merge(HELPER_CALLS_LIMIT_KEY => DEFAULT_HELPER_CALLS_LIMIT)
|
55
54
|
end
|
@@ -64,14 +63,14 @@ module Reek
|
|
64
63
|
return [] if method_ctx.num_statements == 0
|
65
64
|
return [] if depends_on_instance?(method_ctx.exp)
|
66
65
|
return [] if num_helper_methods(method_ctx) <= value(HELPER_CALLS_LIMIT_KEY, method_ctx, DEFAULT_HELPER_CALLS_LIMIT)
|
67
|
-
|
66
|
+
# SMELL: loads of calls to value{} with the above pattern
|
68
67
|
smell = SmellWarning.new(SMELL_CLASS, method_ctx.full_name, [method_ctx.exp.line],
|
69
|
-
|
70
|
-
|
68
|
+
"doesn't depend on instance state",
|
69
|
+
@source, SMELL_SUBCLASS)
|
71
70
|
[smell]
|
72
71
|
end
|
73
72
|
|
74
|
-
|
73
|
+
private
|
75
74
|
|
76
75
|
def depends_on_instance?(exp)
|
77
76
|
Reek::Source::ReferenceCollector.new(exp).num_refs_to_self > 0
|
data/lib/reek/source.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
2
|
module Reek
|
3
3
|
module Source
|
4
|
-
|
5
4
|
#
|
6
5
|
# A comment header from an abstract syntax tree; found directly above
|
7
6
|
# module, class and method definitions.
|
@@ -10,7 +9,6 @@ module Reek
|
|
10
9
|
CONFIG_REGEX = /:reek:(\w+)(:\s*\{.*?\})?/
|
11
10
|
|
12
11
|
def initialize(text)
|
13
|
-
@config = Hash.new { |hash,key| hash[key] = {} }
|
14
12
|
@text = text.gsub(CONFIG_REGEX) do
|
15
13
|
add_to_config($1, $2)
|
16
14
|
''
|
@@ -18,19 +16,20 @@ module Reek
|
|
18
16
|
end
|
19
17
|
|
20
18
|
def config
|
21
|
-
@config
|
19
|
+
@config ||= Hash.new { |hash, key| hash[key] = {} }
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
22
|
+
def descriptive?
|
25
23
|
@text.split(/\s+/).length >= 2
|
26
24
|
end
|
27
25
|
|
28
|
-
|
26
|
+
protected
|
27
|
+
|
29
28
|
def add_to_config(smell, options)
|
30
29
|
options ||= ': { enabled: false }'
|
31
|
-
|
32
|
-
# extend this to all configs
|
33
|
-
# extend to allow configuration of whole smell class, not just subclass
|
30
|
+
config.merge! YAML.load(smell.gsub(/(?:^|_)(.)/) { $1.upcase } + options)
|
31
|
+
# TODO: extend this to all configs -------------------^
|
32
|
+
# TODO: extend to allow configuration of whole smell class, not just subclass
|
34
33
|
end
|
35
34
|
end
|
36
35
|
end
|
@@ -3,13 +3,11 @@ require 'reek/config_file_exception'
|
|
3
3
|
|
4
4
|
module Reek
|
5
5
|
module Source
|
6
|
-
|
7
6
|
#
|
8
7
|
# A file called <something>.reek containing configuration settings for
|
9
8
|
# any or all of the smell detectors.
|
10
9
|
#
|
11
10
|
class ConfigFile
|
12
|
-
|
13
11
|
#
|
14
12
|
# Load the YAML config file from the supplied +file_path+.
|
15
13
|
#
|
@@ -59,7 +57,7 @@ module Reek
|
|
59
57
|
report_error(error.to_s)
|
60
58
|
end
|
61
59
|
|
62
|
-
report_error('Not a hash') unless Hash
|
60
|
+
report_error('Not a hash') unless result.is_a? Hash
|
63
61
|
|
64
62
|
result
|
65
63
|
end
|
@@ -79,7 +77,7 @@ module Reek
|
|
79
77
|
# Error.
|
80
78
|
#
|
81
79
|
def report_error(reason)
|
82
|
-
raise ConfigFileException
|
80
|
+
raise ConfigFileException, message(reason)
|
83
81
|
end
|
84
82
|
|
85
83
|
def message(reason)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
2
|
module Reek
|
3
3
|
module Source
|
4
|
-
|
5
4
|
#
|
6
5
|
# Locates references to the current object within a portion
|
7
6
|
# of an abstract syntax tree.
|
@@ -16,7 +15,7 @@ module Reek
|
|
16
15
|
def num_refs_to_self
|
17
16
|
result = 0
|
18
17
|
[:self, :zsuper, :ivar, :iasgn].each do |node_type|
|
19
|
-
@ast.look_for(node_type, STOP_NODES) { result += 1}
|
18
|
+
@ast.look_for(node_type, STOP_NODES) { result += 1 }
|
20
19
|
end
|
21
20
|
@ast.look_for(:call, STOP_NODES) do |call|
|
22
21
|
result += 1 unless call.receiver
|
@@ -3,28 +3,83 @@ require 'reek/source/sexp_node'
|
|
3
3
|
module Reek
|
4
4
|
module Source
|
5
5
|
module SexpExtensions
|
6
|
+
class MethodParameter
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
@name == other
|
15
|
+
end
|
16
|
+
|
17
|
+
def block?
|
18
|
+
@name.to_s =~ /^&/
|
19
|
+
end
|
20
|
+
|
21
|
+
def anonymous_splat?
|
22
|
+
@name == :*
|
23
|
+
end
|
24
|
+
|
25
|
+
def marked_unused?
|
26
|
+
plain_name.start_with?('_')
|
27
|
+
end
|
28
|
+
|
29
|
+
def plain_name
|
30
|
+
@plain_name ||= @name.to_s.sub(/^[*&]+/, '')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
6
34
|
module AndNode
|
7
|
-
def condition() self[1
|
35
|
+
def condition() self[1] end
|
36
|
+
|
37
|
+
def body
|
38
|
+
self[2]
|
39
|
+
end
|
8
40
|
end
|
9
41
|
|
42
|
+
# Utility methods for :or nodes
|
10
43
|
module OrNode
|
11
|
-
def condition() self[1
|
44
|
+
def condition() self[1] end
|
45
|
+
|
46
|
+
def body
|
47
|
+
self[2]
|
48
|
+
end
|
12
49
|
end
|
13
50
|
|
14
51
|
module AttrasgnNode
|
15
52
|
def args() self[3] end
|
16
53
|
end
|
17
54
|
|
55
|
+
# Utility methods for :case nodes
|
18
56
|
module CaseNode
|
19
57
|
def condition() self[1] end
|
58
|
+
|
59
|
+
def body
|
60
|
+
self[2..-1].extend SexpNode
|
61
|
+
end
|
20
62
|
end
|
21
63
|
|
64
|
+
# Utility methods for :when nodes
|
65
|
+
module WhenNode
|
66
|
+
def condition_list
|
67
|
+
self[1][1..-1]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Utility methods for :call nodes
|
22
72
|
module CallNode
|
23
73
|
def receiver() self[1] end
|
24
74
|
def method_name() self[2] end
|
25
75
|
def args() self[3..-1] end
|
76
|
+
|
77
|
+
def participants
|
78
|
+
([receiver] + args).compact
|
79
|
+
end
|
80
|
+
|
26
81
|
def arg_names
|
27
|
-
args.map {|arg| arg[1]}
|
82
|
+
args.map { |arg| arg[1] }
|
28
83
|
end
|
29
84
|
end
|
30
85
|
|
@@ -36,15 +91,26 @@ module Reek
|
|
36
91
|
CvdeclNode = CvarNode
|
37
92
|
|
38
93
|
module LvarNode
|
39
|
-
def
|
94
|
+
def var_name() self[1] end
|
40
95
|
end
|
41
96
|
|
42
97
|
module MethodNode
|
98
|
+
def arguments
|
99
|
+
@arguments ||= parameters.reject(&:block?)
|
100
|
+
end
|
101
|
+
|
43
102
|
def arg_names
|
44
|
-
@
|
103
|
+
@arg_names ||= arguments.map(&:name)
|
104
|
+
end
|
105
|
+
|
106
|
+
def parameters
|
107
|
+
@parameters ||= argslist[1..-1].map do |param|
|
108
|
+
MethodParameter.new(param.is_a?(Sexp) ? param[1] : param)
|
109
|
+
end
|
45
110
|
end
|
111
|
+
|
46
112
|
def parameter_names
|
47
|
-
@
|
113
|
+
@parameter_names ||= parameters.map(&:name)
|
48
114
|
end
|
49
115
|
|
50
116
|
def name_without_bang
|
@@ -59,7 +125,8 @@ module Reek
|
|
59
125
|
module DefnNode
|
60
126
|
def name() self[1] end
|
61
127
|
def argslist() self[2] end
|
62
|
-
|
128
|
+
|
129
|
+
def body
|
63
130
|
self[3..-1].extend SexpNode
|
64
131
|
end
|
65
132
|
include MethodNode
|
@@ -73,7 +140,8 @@ module Reek
|
|
73
140
|
def receiver() self[1] end
|
74
141
|
def name() self[2] end
|
75
142
|
def argslist() self[3] end
|
76
|
-
|
143
|
+
|
144
|
+
def body
|
77
145
|
self[4..-1].extend SexpNode
|
78
146
|
end
|
79
147
|
include MethodNode
|
@@ -83,8 +151,13 @@ module Reek
|
|
83
151
|
end
|
84
152
|
end
|
85
153
|
|
154
|
+
# Utility methods for :if nodes
|
86
155
|
module IfNode
|
87
156
|
def condition() self[1] end
|
157
|
+
|
158
|
+
def body
|
159
|
+
self[2..-1].extend SexpNode
|
160
|
+
end
|
88
161
|
end
|
89
162
|
|
90
163
|
module IterNode
|
@@ -92,11 +165,19 @@ module Reek
|
|
92
165
|
def args() self[2] end
|
93
166
|
def block() self[3] end
|
94
167
|
def parameters() self[2] || [] end
|
168
|
+
|
95
169
|
def parameter_names
|
96
170
|
parameters[1..-1].to_a
|
97
171
|
end
|
98
172
|
end
|
99
173
|
|
174
|
+
# Utility methods for :nil nodes
|
175
|
+
module NilNode
|
176
|
+
def nil_node?
|
177
|
+
true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
100
181
|
module LitNode
|
101
182
|
def value() self[1] end
|
102
183
|
end
|
@@ -119,13 +200,14 @@ module Reek
|
|
119
200
|
def name() self[1] end
|
120
201
|
|
121
202
|
def simple_name
|
122
|
-
Sexp
|
203
|
+
name.is_a?(Sexp) ? name.simple_name : name
|
123
204
|
end
|
124
205
|
|
125
206
|
def full_name(outer)
|
126
207
|
prefix = outer == '' ? '' : "#{outer}::"
|
127
208
|
"#{prefix}#{text_name}"
|
128
209
|
end
|
210
|
+
|
129
211
|
def text_name
|
130
212
|
SexpNode.format(name)
|
131
213
|
end
|
@@ -138,8 +220,9 @@ module Reek
|
|
138
220
|
|
139
221
|
module YieldNode
|
140
222
|
def args() self[1..-1] end
|
223
|
+
|
141
224
|
def arg_names
|
142
|
-
args.map {|arg| arg[1]}
|
225
|
+
args.map { |arg| arg[1] }
|
143
226
|
end
|
144
227
|
end
|
145
228
|
end
|
@@ -2,14 +2,13 @@ require 'ruby2ruby'
|
|
2
2
|
|
3
3
|
module Reek
|
4
4
|
module Source
|
5
|
-
|
6
5
|
#
|
7
6
|
# Formats snippets of syntax tree back into Ruby source code.
|
8
7
|
#
|
9
8
|
class SexpFormatter
|
10
9
|
def self.format(sexp)
|
11
|
-
return sexp.to_s unless Array
|
12
|
-
sexp = Sexp.from_array(YAML
|
10
|
+
return sexp.to_s unless sexp.is_a? Array
|
11
|
+
sexp = Sexp.from_array(YAML.load(YAML.dump(sexp)))
|
13
12
|
Ruby2Ruby.new.process(sexp)
|
14
13
|
end
|
15
14
|
end
|
@@ -13,29 +13,33 @@ module Reek
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def hash
|
16
|
-
|
16
|
+
inspect.hash
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
Symbol === first
|
21
|
-
end
|
22
|
-
|
23
|
-
def has_type?(type)
|
24
|
-
is_language_node? and first == type
|
25
|
-
end
|
26
|
-
|
27
|
-
def each_node(type, ignoring, &blk)
|
19
|
+
def each_node(type, ignoring = [], &blk)
|
28
20
|
if block_given?
|
29
21
|
look_for(type, ignoring, &blk)
|
30
22
|
else
|
31
23
|
result = []
|
32
|
-
look_for(type, ignoring) {|exp| result << exp}
|
24
|
+
look_for(type, ignoring) { |exp| result << exp }
|
33
25
|
result
|
34
26
|
end
|
35
27
|
end
|
36
28
|
|
29
|
+
def unnested_nodes(types)
|
30
|
+
result = []
|
31
|
+
if types.include? first
|
32
|
+
result << self
|
33
|
+
else
|
34
|
+
each_sexp do |elem|
|
35
|
+
result += elem.unnested_nodes(types)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
37
41
|
def each_sexp
|
38
|
-
each { |elem| yield elem if Sexp
|
42
|
+
each { |elem| yield elem if elem.is_a? Sexp }
|
39
43
|
end
|
40
44
|
|
41
45
|
#
|
@@ -50,8 +54,8 @@ module Reek
|
|
50
54
|
blk.call(self) if first == target_type
|
51
55
|
end
|
52
56
|
|
53
|
-
def
|
54
|
-
look_for(target_type) { |
|
57
|
+
def contains_nested_node?(target_type)
|
58
|
+
look_for(target_type) { |_elem| return true }
|
55
59
|
false
|
56
60
|
end
|
57
61
|
|
@@ -60,7 +64,7 @@ module Reek
|
|
60
64
|
end
|
61
65
|
|
62
66
|
def deep_copy
|
63
|
-
Sexp.new(*map { |elem| Sexp
|
67
|
+
Sexp.new(*map { |elem| elem.is_a?(Sexp) ? elem.deep_copy : elem })
|
64
68
|
end
|
65
69
|
end
|
66
70
|
end
|
@@ -4,22 +4,10 @@ require 'reek/source/tree_dresser'
|
|
4
4
|
|
5
5
|
module Reek
|
6
6
|
module Source
|
7
|
-
|
8
7
|
#
|
9
8
|
# A +Source+ object represents a chunk of Ruby source code.
|
10
9
|
#
|
11
10
|
class SourceCode
|
12
|
-
|
13
|
-
@@err_io = $stderr
|
14
|
-
|
15
|
-
class << self
|
16
|
-
def err_io=(io)
|
17
|
-
original = @@err_io
|
18
|
-
@@err_io = io
|
19
|
-
original
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
11
|
attr_reader :desc
|
24
12
|
|
25
13
|
def initialize(code, desc, parser = RubyParser.new)
|
@@ -28,13 +16,15 @@ module Reek
|
|
28
16
|
@parser = parser
|
29
17
|
end
|
30
18
|
|
31
|
-
def
|
19
|
+
def relevant_config_files
|
20
|
+
[]
|
21
|
+
end
|
32
22
|
|
33
23
|
def syntax_tree
|
34
24
|
begin
|
35
25
|
ast = @parser.parse(@source, @desc)
|
36
26
|
rescue Racc::ParseError, RubyParser::SyntaxError => error
|
37
|
-
|
27
|
+
$stderr.puts "#{desc}: #{error.class.name}: #{error}"
|
38
28
|
end
|
39
29
|
ast ||= s()
|
40
30
|
TreeDresser.new.dress(ast)
|