reek 3.2 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/reek/ast/ast_node_class_map.rb +1 -5
- data/lib/reek/ast/node.rb +2 -4
- data/lib/reek/ast/object_refs.rb +5 -9
- data/lib/reek/ast/reference_collector.rb +2 -4
- data/lib/reek/cli/application.rb +9 -12
- data/lib/reek/cli/command.rb +0 -4
- data/lib/reek/cli/input.rb +4 -4
- data/lib/reek/cli/option_interpreter.rb +7 -11
- data/lib/reek/cli/options.rb +40 -42
- data/lib/reek/cli/reek_command.rb +3 -3
- data/lib/reek/cli/warning_collector.rb +3 -7
- data/lib/reek/code_comment.rb +1 -5
- data/lib/reek/context/code_context.rb +17 -19
- data/lib/reek/examiner.rb +6 -8
- data/lib/reek/rake/task.rb +22 -12
- data/lib/reek/report/formatter.rb +1 -5
- data/lib/reek/report/report.rb +13 -22
- data/lib/reek/smells/attribute.rb +6 -9
- data/lib/reek/smells/control_parameter.rb +13 -21
- data/lib/reek/smells/data_clump.rb +9 -17
- data/lib/reek/smells/duplicate_method_call.rb +6 -12
- data/lib/reek/smells/long_parameter_list.rb +2 -2
- data/lib/reek/smells/long_yield_list.rb +4 -4
- data/lib/reek/smells/nested_iterators.rb +2 -4
- data/lib/reek/smells/nil_check.rb +2 -6
- data/lib/reek/smells/repeated_conditional.rb +2 -2
- data/lib/reek/smells/smell_configuration.rb +7 -15
- data/lib/reek/smells/smell_detector.rb +10 -23
- data/lib/reek/smells/smell_warning.rb +6 -6
- data/lib/reek/smells/too_many_instance_variables.rb +2 -2
- data/lib/reek/smells/too_many_methods.rb +2 -2
- data/lib/reek/smells/too_many_statements.rb +4 -4
- data/lib/reek/smells/uncommunicative_method_name.rb +5 -5
- data/lib/reek/smells/uncommunicative_module_name.rb +5 -5
- data/lib/reek/smells/uncommunicative_parameter_name.rb +4 -8
- data/lib/reek/smells/uncommunicative_variable_name.rb +4 -8
- data/lib/reek/source/source_code.rb +1 -5
- data/lib/reek/spec/should_reek.rb +4 -9
- data/lib/reek/spec/should_reek_of.rb +5 -8
- data/lib/reek/spec/should_reek_only_of.rb +8 -12
- data/lib/reek/tree_dresser.rb +2 -6
- data/lib/reek/tree_walker.rb +22 -28
- data/lib/reek/version.rb +1 -1
- metadata +1 -1
data/lib/reek/code_comment.rb
CHANGED
@@ -21,7 +21,7 @@ module Reek
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def descriptive?
|
24
|
-
text.split(/\s+/).length >= 2
|
24
|
+
@text.split(/\s+/).length >= 2
|
25
25
|
end
|
26
26
|
|
27
27
|
protected
|
@@ -32,9 +32,5 @@ module Reek
|
|
32
32
|
# TODO: extend this to all configs -------------------^
|
33
33
|
# TODO: extend to allow configuration of whole smell class, not just subclass
|
34
34
|
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
private_attr_reader :text
|
39
35
|
end
|
40
36
|
end
|
@@ -70,11 +70,11 @@ module Reek
|
|
70
70
|
# @param child [CodeContext] the child context to register
|
71
71
|
def append_child_context(child)
|
72
72
|
child.visibility = tracked_visibility
|
73
|
-
children << child
|
73
|
+
@children << child
|
74
74
|
end
|
75
75
|
|
76
76
|
def count_statements(num)
|
77
|
-
|
77
|
+
@num_statements += num
|
78
78
|
end
|
79
79
|
|
80
80
|
def record_call_to(exp)
|
@@ -83,19 +83,19 @@ module Reek
|
|
83
83
|
case type
|
84
84
|
when :lvar, :lvasgn
|
85
85
|
unless exp.object_creation_call?
|
86
|
-
refs.record_reference_to(receiver.name, line: exp.line)
|
86
|
+
@refs.record_reference_to(receiver.name, line: exp.line)
|
87
87
|
end
|
88
88
|
when :self
|
89
|
-
refs.record_reference_to(:self, line: exp.line)
|
89
|
+
@refs.record_reference_to(:self, line: exp.line)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
93
|
def record_use_of_self
|
94
|
-
refs.record_reference_to(:self)
|
94
|
+
@refs.record_reference_to(:self)
|
95
95
|
end
|
96
96
|
|
97
97
|
def name
|
98
|
-
exp.name
|
98
|
+
@exp.name
|
99
99
|
end
|
100
100
|
|
101
101
|
def local_nodes(type, &blk)
|
@@ -103,7 +103,7 @@ module Reek
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def each_node(type, ignoring, &blk)
|
106
|
-
exp.each_node(type, ignoring, &blk)
|
106
|
+
@exp.each_node(type, ignoring, &blk)
|
107
107
|
end
|
108
108
|
|
109
109
|
def matches?(candidates)
|
@@ -119,7 +119,8 @@ module Reek
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def full_name
|
122
|
-
|
122
|
+
context = @context ? @context.full_name : ''
|
123
|
+
exp.full_name(context)
|
123
124
|
end
|
124
125
|
|
125
126
|
def config_for(detector_class)
|
@@ -139,49 +140,46 @@ module Reek
|
|
139
140
|
# @param names [Array<Symbol>]
|
140
141
|
def track_visibility(visibility, names = [])
|
141
142
|
if names.any?
|
142
|
-
children.each do |child|
|
143
|
+
@children.each do |child|
|
143
144
|
child.visibility = visibility if names.include? child.name
|
144
145
|
end
|
145
146
|
else
|
146
|
-
|
147
|
+
@tracked_visibility = visibility
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
150
151
|
def type
|
151
|
-
exp.type
|
152
|
+
@exp.type
|
152
153
|
end
|
153
154
|
|
154
155
|
# Iterate over +self+ and child contexts.
|
155
156
|
def each(&block)
|
156
157
|
yield self
|
157
|
-
children.each do |child|
|
158
|
+
@children.each do |child|
|
158
159
|
child.each(&block)
|
159
160
|
end
|
160
161
|
end
|
161
162
|
|
162
163
|
protected
|
163
164
|
|
164
|
-
attr_writer :
|
165
|
+
attr_writer :visibility
|
165
166
|
|
166
167
|
private
|
167
168
|
|
168
|
-
private_attr_writer :tracked_visibility
|
169
|
-
private_attr_reader :context, :refs
|
170
|
-
|
171
169
|
def tracked_visibility
|
172
170
|
@tracked_visibility ||= :public
|
173
171
|
end
|
174
172
|
|
175
173
|
def config
|
176
|
-
@config ||= if exp
|
177
|
-
CodeComment.new(exp.full_comment || '').config
|
174
|
+
@config ||= if @exp
|
175
|
+
CodeComment.new(@exp.full_comment || '').config
|
178
176
|
else
|
179
177
|
{}
|
180
178
|
end
|
181
179
|
end
|
182
180
|
|
183
181
|
def context_config_for(detector_class)
|
184
|
-
context ? context.config_for(detector_class) : {}
|
182
|
+
@context ? @context.config_for(detector_class) : {}
|
185
183
|
end
|
186
184
|
end
|
187
185
|
end
|
data/lib/reek/examiner.rb
CHANGED
@@ -39,14 +39,14 @@ module Reek
|
|
39
39
|
# @return [String] description of the source being analysed
|
40
40
|
#
|
41
41
|
def description
|
42
|
-
@description ||= source.description
|
42
|
+
@description ||= @source.description
|
43
43
|
end
|
44
44
|
|
45
45
|
#
|
46
46
|
# @return [Array<SmellWarning>] the smells found in the source
|
47
47
|
#
|
48
48
|
def smells
|
49
|
-
@smells ||= collector.warnings
|
49
|
+
@smells ||= @collector.warnings
|
50
50
|
end
|
51
51
|
|
52
52
|
#
|
@@ -65,15 +65,13 @@ module Reek
|
|
65
65
|
|
66
66
|
private
|
67
67
|
|
68
|
-
private_attr_reader :configuration, :collector, :smell_types, :source
|
69
|
-
|
70
68
|
def run
|
71
69
|
smell_repository = Smells::SmellRepository.new(source_description: description,
|
72
|
-
smell_types: smell_types,
|
73
|
-
configuration: configuration)
|
74
|
-
syntax_tree = source.syntax_tree
|
70
|
+
smell_types: @smell_types,
|
71
|
+
configuration: @configuration)
|
72
|
+
syntax_tree = @source.syntax_tree
|
75
73
|
TreeWalker.new(smell_repository, syntax_tree).walk if syntax_tree
|
76
|
-
smell_repository.report_on(collector)
|
74
|
+
smell_repository.report_on(@collector)
|
77
75
|
end
|
78
76
|
|
79
77
|
def eligible_smell_types(filter_by_smells = [])
|
data/lib/reek/rake/task.rb
CHANGED
@@ -39,17 +39,17 @@ module Reek
|
|
39
39
|
|
40
40
|
# Path to reek's config file.
|
41
41
|
# Setting the REEK_CFG environment variable overrides this.
|
42
|
-
|
42
|
+
attr_writer :config_file
|
43
43
|
|
44
44
|
# Glob pattern to match source files.
|
45
45
|
# Setting the REEK_SRC environment variable overrides this.
|
46
46
|
# Defaults to 'lib/**/*.rb'.
|
47
|
-
|
47
|
+
attr_writer :source_files
|
48
48
|
|
49
49
|
# String containing commandline options to be passed to Reek.
|
50
50
|
# Setting the REEK_OPTS environment variable overrides this value.
|
51
51
|
# Defaults to ''.
|
52
|
-
|
52
|
+
attr_writer :reek_opts
|
53
53
|
|
54
54
|
# Whether or not to fail Rake when an error occurs (typically when smells are found).
|
55
55
|
# Defaults to true.
|
@@ -60,11 +60,10 @@ module Reek
|
|
60
60
|
attr_writer :verbose
|
61
61
|
|
62
62
|
def initialize(name = :reek)
|
63
|
-
@config_file = ENV['REEK_CFG']
|
64
63
|
@name = name
|
65
|
-
@reek_opts =
|
64
|
+
@reek_opts = ''
|
66
65
|
@fail_on_error = true
|
67
|
-
@source_files =
|
66
|
+
@source_files = 'lib/**/*.rb'
|
68
67
|
@verbose = false
|
69
68
|
|
70
69
|
yield self if block_given?
|
@@ -73,17 +72,15 @@ module Reek
|
|
73
72
|
|
74
73
|
private
|
75
74
|
|
76
|
-
private_attr_reader :fail_on_error, :name, :verbose
|
77
|
-
|
78
75
|
def define_task
|
79
76
|
desc 'Check for code smells'
|
80
|
-
task(name) { run_task }
|
77
|
+
task(@name) { run_task }
|
81
78
|
end
|
82
79
|
|
83
80
|
def run_task
|
84
|
-
puts "\n\n!!! Running 'reek' rake command: #{command}\n\n" if verbose
|
81
|
+
puts "\n\n!!! Running 'reek' rake command: #{command}\n\n" if @verbose
|
85
82
|
system(*command)
|
86
|
-
abort("\n\n!!! `reek` has found smells - exiting!") if sys_call_failed? && fail_on_error
|
83
|
+
abort("\n\n!!! `reek` has found smells - exiting!") if sys_call_failed? && @fail_on_error
|
87
84
|
end
|
88
85
|
|
89
86
|
def command
|
@@ -92,12 +89,25 @@ module Reek
|
|
92
89
|
reject(&:empty?)
|
93
90
|
end
|
94
91
|
|
92
|
+
def source_files
|
93
|
+
FileList[ENV['REEK_SRC'] || @source_files]
|
94
|
+
end
|
95
|
+
|
96
|
+
def reek_opts
|
97
|
+
ENV['REEK_OPTS'] || @reek_opts
|
98
|
+
end
|
99
|
+
|
100
|
+
def config_file
|
101
|
+
ENV['REEK_CFG'] || @config_file
|
102
|
+
end
|
103
|
+
|
95
104
|
def sys_call_failed?
|
96
105
|
!$CHILD_STATUS.success?
|
97
106
|
end
|
98
107
|
|
99
108
|
def config_file_as_argument
|
100
|
-
|
109
|
+
return [] unless @config_file
|
110
|
+
['-c', @config_file]
|
101
111
|
end
|
102
112
|
|
103
113
|
def reek_opts_as_arguments
|
@@ -35,7 +35,7 @@ module Reek
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def format(warning)
|
38
|
-
"#{location_formatter.format(warning)}#{base_format(warning)}"
|
38
|
+
"#{@location_formatter.format(warning)}#{base_format(warning)}"
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
@@ -43,10 +43,6 @@ module Reek
|
|
43
43
|
def base_format(warning)
|
44
44
|
"#{warning.context} #{warning.message} (#{warning.smell_type})"
|
45
45
|
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
private_attr_reader :location_formatter
|
50
46
|
end
|
51
47
|
|
52
48
|
#
|
data/lib/reek/report/report.rb
CHANGED
@@ -30,8 +30,8 @@ module Reek
|
|
30
30
|
#
|
31
31
|
# @param [Reek::Examiner] examiner object to report on
|
32
32
|
def add_examiner(examiner)
|
33
|
-
|
34
|
-
examiners << examiner
|
33
|
+
@total_smell_count += examiner.smells_count
|
34
|
+
@examiners << examiner
|
35
35
|
self
|
36
36
|
end
|
37
37
|
|
@@ -42,22 +42,13 @@ module Reek
|
|
42
42
|
|
43
43
|
# @api private
|
44
44
|
def smells?
|
45
|
-
total_smell_count > 0
|
45
|
+
@total_smell_count > 0
|
46
46
|
end
|
47
47
|
|
48
48
|
# @api private
|
49
49
|
def smells
|
50
|
-
examiners.map(&:smells).flatten
|
50
|
+
@examiners.map(&:smells).flatten
|
51
51
|
end
|
52
|
-
|
53
|
-
protected
|
54
|
-
|
55
|
-
attr_accessor :total_smell_count
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
private_attr_reader :examiners, :options, :report_formatter,
|
60
|
-
:sort_by_issue_count, :warning_formatter
|
61
52
|
end
|
62
53
|
|
63
54
|
#
|
@@ -73,7 +64,7 @@ module Reek
|
|
73
64
|
private
|
74
65
|
|
75
66
|
def smell_summaries
|
76
|
-
examiners.map { |ex| summarize_single_examiner(ex) }.reject(&:empty?)
|
67
|
+
@examiners.map { |ex| summarize_single_examiner(ex) }.reject(&:empty?)
|
77
68
|
end
|
78
69
|
|
79
70
|
def display_summary
|
@@ -81,33 +72,33 @@ module Reek
|
|
81
72
|
end
|
82
73
|
|
83
74
|
def display_total_smell_count
|
84
|
-
return unless examiners.size > 1
|
75
|
+
return unless @examiners.size > 1
|
85
76
|
print total_smell_count_message
|
86
77
|
end
|
87
78
|
|
88
79
|
def summarize_single_examiner(examiner)
|
89
80
|
result = heading_formatter.header(examiner)
|
90
81
|
if examiner.smelly?
|
91
|
-
formatted_list = report_formatter.format_list(examiner.smells,
|
92
|
-
|
82
|
+
formatted_list = @report_formatter.format_list(examiner.smells,
|
83
|
+
@warning_formatter)
|
93
84
|
result += ":\n#{formatted_list}"
|
94
85
|
end
|
95
86
|
result
|
96
87
|
end
|
97
88
|
|
98
89
|
def sort_examiners
|
99
|
-
examiners.sort_by!(&:smells_count).reverse! if sort_by_issue_count
|
90
|
+
@examiners.sort_by!(&:smells_count).reverse! if @sort_by_issue_count
|
100
91
|
end
|
101
92
|
|
102
93
|
def total_smell_count_message
|
103
94
|
colour = smells? ? WARNINGS_COLOR : NO_WARNINGS_COLOR
|
104
|
-
s = total_smell_count == 1 ? '' : 's'
|
105
|
-
Rainbow("#{total_smell_count} total warning#{s}\n").color(colour)
|
95
|
+
s = @total_smell_count == 1 ? '' : 's'
|
96
|
+
Rainbow("#{@total_smell_count} total warning#{s}\n").color(colour)
|
106
97
|
end
|
107
98
|
|
108
99
|
def heading_formatter
|
109
100
|
@heading_formatter ||=
|
110
|
-
options.fetch(:heading_formatter, HeadingFormatter::Quiet).new(report_formatter)
|
101
|
+
@options.fetch(:heading_formatter, HeadingFormatter::Quiet).new(@report_formatter)
|
111
102
|
end
|
112
103
|
end
|
113
104
|
|
@@ -127,7 +118,7 @@ module Reek
|
|
127
118
|
def show
|
128
119
|
print ::JSON.generate(
|
129
120
|
smells.map do |smell|
|
130
|
-
smell.yaml_hash(warning_formatter)
|
121
|
+
smell.yaml_hash(@warning_formatter)
|
131
122
|
end
|
132
123
|
)
|
133
124
|
end
|
@@ -34,8 +34,8 @@ module Reek
|
|
34
34
|
# @return [Array<SmellWarning>]
|
35
35
|
#
|
36
36
|
def examine_context(ctx)
|
37
|
-
|
38
|
-
|
37
|
+
@visiblity_tracker = {}
|
38
|
+
@visiblity_mode = :public
|
39
39
|
attributes_in(ctx).map do |attribute, line|
|
40
40
|
SmellWarning.new self,
|
41
41
|
context: ctx.full_name,
|
@@ -47,9 +47,6 @@ module Reek
|
|
47
47
|
|
48
48
|
private
|
49
49
|
|
50
|
-
private_attr_accessor :visiblity_mode, :visiblity_tracker
|
51
|
-
private_attr_reader :result
|
52
|
-
|
53
50
|
def attributes_in(module_ctx)
|
54
51
|
attributes = Set.new
|
55
52
|
module_ctx.local_nodes(:send) do |call_node|
|
@@ -81,7 +78,7 @@ module Reek
|
|
81
78
|
|
82
79
|
def track_argument(arg, line)
|
83
80
|
arg_name = arg.children.first
|
84
|
-
visiblity_tracker[arg_name] = visiblity_mode
|
81
|
+
@visiblity_tracker[arg_name] = @visiblity_mode
|
85
82
|
[arg_name, line]
|
86
83
|
end
|
87
84
|
|
@@ -91,14 +88,14 @@ module Reek
|
|
91
88
|
|
92
89
|
def track_visibility(call_node)
|
93
90
|
if call_node.arg_names.any?
|
94
|
-
call_node.arg_names.each { |arg| visiblity_tracker[arg] = call_node.method_name }
|
91
|
+
call_node.arg_names.each { |arg| @visiblity_tracker[arg] = call_node.method_name }
|
95
92
|
else
|
96
|
-
|
93
|
+
@visiblity_mode = call_node.method_name
|
97
94
|
end
|
98
95
|
end
|
99
96
|
|
100
97
|
def recorded_public_methods
|
101
|
-
visiblity_tracker.select { |_, visbility| visbility == :public }
|
98
|
+
@visiblity_tracker.select { |_, visbility| visbility == :public }
|
102
99
|
end
|
103
100
|
end
|
104
101
|
end
|
@@ -73,20 +73,16 @@ module Reek
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def smells?
|
76
|
-
occurences.any?
|
76
|
+
@occurences.any?
|
77
77
|
end
|
78
78
|
|
79
79
|
def lines
|
80
|
-
occurences.map(&:line)
|
80
|
+
@occurences.map(&:line)
|
81
81
|
end
|
82
82
|
|
83
83
|
def name
|
84
|
-
param.to_s
|
84
|
+
@param.to_s
|
85
85
|
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
private_attr_reader :occurences, :param
|
90
86
|
end
|
91
87
|
|
92
88
|
# Finds cases of ControlParameter in a particular node for a particular parameter
|
@@ -112,15 +108,13 @@ module Reek
|
|
112
108
|
|
113
109
|
private
|
114
110
|
|
115
|
-
private_attr_reader :node, :param
|
116
|
-
|
117
111
|
def conditional_nodes
|
118
|
-
node.body_nodes(CONDITIONAL_NODE_TYPES)
|
112
|
+
@node.body_nodes(CONDITIONAL_NODE_TYPES)
|
119
113
|
end
|
120
114
|
|
121
115
|
def nested_finders
|
122
116
|
@nested_finders ||= conditional_nodes.flat_map do |node|
|
123
|
-
self.class.new(node, param)
|
117
|
+
self.class.new(node, @param)
|
124
118
|
end
|
125
119
|
end
|
126
120
|
|
@@ -135,12 +129,12 @@ module Reek
|
|
135
129
|
|
136
130
|
def uses_of_param_in_condition
|
137
131
|
return [] unless condition
|
138
|
-
condition.each_node(:lvar).select { |inner| inner.var_name == param }
|
132
|
+
condition.each_node(:lvar).select { |inner| inner.var_name == @param }
|
139
133
|
end
|
140
134
|
|
141
135
|
def condition
|
142
|
-
return nil unless CONDITIONAL_NODE_TYPES.include? node.type
|
143
|
-
node.condition
|
136
|
+
return nil unless CONDITIONAL_NODE_TYPES.include? @node.type
|
137
|
+
@node.condition
|
144
138
|
end
|
145
139
|
|
146
140
|
def regular_call_involving_param?(call_node)
|
@@ -156,12 +150,12 @@ module Reek
|
|
156
150
|
end
|
157
151
|
|
158
152
|
def call_involving_param?(call_node)
|
159
|
-
call_node.each_node(:lvar).any? { |it| it.var_name == param }
|
153
|
+
call_node.each_node(:lvar).any? { |it| it.var_name == @param }
|
160
154
|
end
|
161
155
|
|
162
156
|
def uses_param_in_body?
|
163
|
-
nodes = node.body_nodes([:lvar], [:if, :case, :and, :or])
|
164
|
-
nodes.any? { |lvar_node| lvar_node.var_name == param }
|
157
|
+
nodes = @node.body_nodes([:lvar], [:if, :case, :and, :or])
|
158
|
+
nodes.any? { |lvar_node| lvar_node.var_name == @param }
|
165
159
|
end
|
166
160
|
end
|
167
161
|
|
@@ -181,14 +175,12 @@ module Reek
|
|
181
175
|
|
182
176
|
private
|
183
177
|
|
184
|
-
private_attr_reader :context
|
185
|
-
|
186
178
|
def potential_parameters
|
187
|
-
context.exp.parameter_names
|
179
|
+
@context.exp.parameter_names
|
188
180
|
end
|
189
181
|
|
190
182
|
def find_matches(param)
|
191
|
-
ControlParameterFinder.new(context.exp, param).find_matches
|
183
|
+
ControlParameterFinder.new(@context.exp, param).find_matches
|
192
184
|
end
|
193
185
|
end
|
194
186
|
end
|