rubocop 0.31.0 → 0.35.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +315 -0
- data/README.md +199 -38
- data/config/default.yml +91 -12
- data/config/disabled.yml +45 -4
- data/config/enabled.yml +107 -9
- data/lib/rubocop/ast_node.rb +48 -0
- data/lib/rubocop/cli.rb +11 -1
- data/lib/rubocop/comment_config.rb +4 -1
- data/lib/rubocop/config.rb +26 -17
- data/lib/rubocop/config_loader.rb +61 -14
- data/lib/rubocop/cop/commissioner.rb +7 -12
- data/lib/rubocop/cop/cop.rb +43 -20
- data/lib/rubocop/cop/lint/block_alignment.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +69 -0
- data/lib/rubocop/cop/lint/debugger.rb +9 -48
- data/lib/rubocop/cop/lint/def_end_alignment.rb +8 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +42 -23
- data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
- data/lib/rubocop/cop/lint/duplicated_key.rb +37 -0
- data/lib/rubocop/cop/lint/end_alignment.rb +33 -13
- data/lib/rubocop/cop/lint/eval.rb +6 -2
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +175 -0
- data/lib/rubocop/cop/lint/literal_in_condition.rb +0 -5
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +10 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +31 -0
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +19 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/lint/unneeded_disable.rb +72 -0
- data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +8 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +17 -6
- data/lib/rubocop/cop/metrics/class_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -3
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -2
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +28 -4
- data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +26 -3
- data/lib/rubocop/cop/mixin/check_assignment.rb +2 -3
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +59 -12
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_naming.rb +14 -3
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -3
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +10 -1
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +41 -0
- data/lib/rubocop/cop/mixin/if_node.rb +10 -0
- data/lib/rubocop/cop/mixin/method_preference.rb +28 -0
- data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
- data/lib/rubocop/cop/mixin/on_method_def.rb +4 -5
- data/lib/rubocop/cop/mixin/safe_assignment.rb +3 -14
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +8 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +8 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -7
- data/lib/rubocop/cop/mixin/string_help.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +5 -4
- data/lib/rubocop/cop/offense.rb +16 -3
- data/lib/rubocop/cop/performance/case_when_splat.rb +160 -0
- data/lib/rubocop/cop/performance/count.rb +35 -30
- data/lib/rubocop/cop/performance/detect.rb +16 -3
- data/lib/rubocop/cop/performance/fixed_size.rb +50 -0
- data/lib/rubocop/cop/performance/flat_map.rb +3 -3
- data/lib/rubocop/cop/performance/sample.rb +103 -59
- data/lib/rubocop/cop/performance/size.rb +2 -1
- data/lib/rubocop/cop/performance/string_replacement.rb +187 -0
- data/lib/rubocop/cop/rails/action_filter.rb +31 -5
- data/lib/rubocop/cop/rails/date.rb +15 -14
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +97 -0
- data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
- data/lib/rubocop/cop/rails/time_zone.rb +46 -18
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/align_hash.rb +8 -15
- data/lib/rubocop/cop/style/align_parameters.rb +19 -7
- data/lib/rubocop/cop/style/and_or.rb +42 -13
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -1
- data/lib/rubocop/cop/style/block_comments.rb +4 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +69 -24
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +40 -12
- data/lib/rubocop/cop/style/case_indentation.rb +18 -4
- data/lib/rubocop/cop/style/collection_methods.rb +2 -20
- data/lib/rubocop/cop/style/command_literal.rb +2 -10
- data/lib/rubocop/cop/style/comment_annotation.rb +29 -8
- data/lib/rubocop/cop/style/copyright.rb +5 -3
- data/lib/rubocop/cop/style/documentation.rb +21 -12
- data/lib/rubocop/cop/style/dot_position.rb +6 -0
- data/lib/rubocop/cop/style/double_negation.rb +4 -15
- data/lib/rubocop/cop/style/each_with_object.rb +17 -4
- data/lib/rubocop/cop/style/else_alignment.rb +2 -1
- data/lib/rubocop/cop/style/empty_else.rb +25 -0
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +39 -14
- data/lib/rubocop/cop/style/encoding.rb +10 -4
- data/lib/rubocop/cop/style/extra_spacing.rb +126 -5
- data/lib/rubocop/cop/style/first_array_element_line_break.rb +41 -0
- data/lib/rubocop/cop/style/first_hash_element_line_break.rb +35 -0
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +37 -0
- data/lib/rubocop/cop/style/first_method_parameter_line_break.rb +42 -0
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +5 -3
- data/lib/rubocop/cop/style/for.rb +2 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +32 -5
- data/lib/rubocop/cop/style/indent_hash.rb +67 -37
- data/lib/rubocop/cop/style/indentation_width.rb +36 -10
- data/lib/rubocop/cop/style/initial_indentation.rb +37 -0
- data/lib/rubocop/cop/style/leading_comment_space.rb +3 -2
- data/lib/rubocop/cop/style/method_call_parentheses.rb +28 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -7
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +21 -24
- data/lib/rubocop/cop/style/mutable_constant.rb +35 -0
- data/lib/rubocop/cop/style/nested_modifier.rb +97 -0
- data/lib/rubocop/cop/style/next.rb +50 -15
- data/lib/rubocop/cop/style/non_nil_check.rb +12 -8
- data/lib/rubocop/cop/style/one_line_conditional.rb +8 -4
- data/lib/rubocop/cop/style/option_hash.rb +64 -0
- data/lib/rubocop/cop/style/optional_arguments.rb +49 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +218 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -66
- data/lib/rubocop/cop/style/predicate_name.rb +7 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -13
- data/lib/rubocop/cop/style/redundant_freeze.rb +37 -0
- data/lib/rubocop/cop/style/redundant_return.rb +32 -3
- data/lib/rubocop/cop/style/regexp_literal.rb +2 -10
- data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +81 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +30 -22
- data/lib/rubocop/cop/style/send.rb +18 -0
- data/lib/rubocop/cop/style/signal_exception.rb +24 -11
- data/lib/rubocop/cop/style/single_line_methods.rb +8 -9
- data/lib/rubocop/cop/style/single_space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/style/space_around_operators.rb +2 -0
- data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +61 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +108 -0
- data/lib/rubocop/cop/style/string_methods.rb +32 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +11 -10
- data/lib/rubocop/cop/style/symbol_literal.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +62 -13
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +9 -1
- data/lib/rubocop/cop/style/trailing_comma.rb +17 -7
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -2
- data/lib/rubocop/cop/style/trivial_accessors.rb +10 -1
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +31 -20
- data/lib/rubocop/cop/style/variable_name.rb +5 -0
- data/lib/rubocop/cop/style/while_until_do.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +15 -2
- data/lib/rubocop/cop/team.rb +25 -5
- data/lib/rubocop/cop/util.rb +7 -2
- data/lib/rubocop/cop/variable_force/locatable.rb +6 -6
- data/lib/rubocop/cop/variable_force.rb +10 -10
- data/lib/rubocop/formatter/base_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +70 -8
- data/lib/rubocop/formatter/formatter_set.rb +27 -1
- data/lib/rubocop/formatter/progress_formatter.rb +10 -2
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
- data/lib/rubocop/node_pattern.rb +390 -0
- data/lib/rubocop/options.rb +148 -81
- data/lib/rubocop/processed_source.rb +7 -2
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +60 -0
- data/lib/rubocop/result_cache.rb +123 -0
- data/lib/rubocop/runner.rb +85 -22
- data/lib/rubocop/target_finder.rb +4 -4
- data/lib/rubocop/token.rb +2 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/warning.rb +11 -0
- data/lib/rubocop.rb +32 -3
- data/relnotes/v0.32.0.md +139 -0
- data/relnotes/v0.32.1.md +122 -0
- data/relnotes/v0.33.0.md +157 -0
- data/relnotes/v0.34.0.md +182 -0
- data/relnotes/v0.34.1.md +129 -0
- data/relnotes/v0.34.2.md +139 -0
- data/relnotes/v0.35.0.md +210 -0
- data/rubocop.gemspec +4 -4
- metadata +50 -12
- data/lib/rubocop/cop/performance/parallel_assignment.rb +0 -79
|
@@ -30,7 +30,7 @@ module RuboCop
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
callback_methods.each do |callback|
|
|
33
|
-
class_eval <<-EOS
|
|
33
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
34
34
|
def #{callback}(node)
|
|
35
35
|
@cops.each do |cop|
|
|
36
36
|
next unless cop.respond_to?(:#{callback})
|
|
@@ -46,15 +46,12 @@ module RuboCop
|
|
|
46
46
|
|
|
47
47
|
def investigate(processed_source)
|
|
48
48
|
reset_errors
|
|
49
|
+
remove_irrelevant_cops(processed_source.buffer.name)
|
|
49
50
|
prepare(processed_source)
|
|
50
51
|
invoke_custom_processing(@cops, processed_source)
|
|
51
52
|
invoke_custom_processing(@forces, processed_source)
|
|
52
53
|
process(processed_source.ast) if processed_source.ast
|
|
53
|
-
@cops.
|
|
54
|
-
filename = processed_source.buffer.name
|
|
55
|
-
# ignore files that are of no interest to the cop in question
|
|
56
|
-
offenses.concat(cop.offenses) if cop.relevant_file?(filename)
|
|
57
|
-
end
|
|
54
|
+
@cops.flat_map(&:offenses)
|
|
58
55
|
end
|
|
59
56
|
|
|
60
57
|
private
|
|
@@ -63,6 +60,10 @@ module RuboCop
|
|
|
63
60
|
@errors = Hash.new { |hash, k| hash[k] = [] }
|
|
64
61
|
end
|
|
65
62
|
|
|
63
|
+
def remove_irrelevant_cops(filename)
|
|
64
|
+
@cops.reject! { |cop| cop.excluded_file?(filename) }
|
|
65
|
+
end
|
|
66
|
+
|
|
66
67
|
# TODO: Bad design.
|
|
67
68
|
def prepare(processed_source)
|
|
68
69
|
@cops.each { |cop| cop.processed_source = processed_source }
|
|
@@ -76,12 +77,6 @@ module RuboCop
|
|
|
76
77
|
cops_or_forces.each do |cop|
|
|
77
78
|
next unless cop.respond_to?(:investigate)
|
|
78
79
|
|
|
79
|
-
if cop.respond_to?(:relevant_file?)
|
|
80
|
-
# ignore files that are of no interest to the cop in question
|
|
81
|
-
filename = processed_source.buffer.name
|
|
82
|
-
next unless cop.relevant_file?(filename)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
80
|
with_cop_error_handling(cop) do
|
|
86
81
|
cop.investigate(processed_source)
|
|
87
82
|
end
|
data/lib/rubocop/cop/cop.rb
CHANGED
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
|
49
49
|
#
|
|
50
50
|
# The Cop class is meant to be extended.
|
|
51
51
|
#
|
|
52
|
-
# Cops track offenses and can autocorrect them
|
|
52
|
+
# Cops track offenses and can autocorrect them on the fly.
|
|
53
53
|
#
|
|
54
54
|
# A commissioner object is responsible for traversing the AST and invoking
|
|
55
55
|
# the specific callbacks on each cop.
|
|
@@ -66,6 +66,7 @@ module RuboCop
|
|
|
66
66
|
# end
|
|
67
67
|
class Cop
|
|
68
68
|
extend AST::Sexp
|
|
69
|
+
extend NodePattern::Macros
|
|
69
70
|
include Util
|
|
70
71
|
include IgnoredNode
|
|
71
72
|
include AutocorrectLogic
|
|
@@ -133,11 +134,16 @@ module RuboCop
|
|
|
133
134
|
end
|
|
134
135
|
|
|
135
136
|
def display_style_guide?
|
|
136
|
-
style_guide_url &&
|
|
137
|
+
(style_guide_url || reference_url) &&
|
|
137
138
|
(@options[:display_style_guide] ||
|
|
138
139
|
config['AllCops'] && config['AllCops']['DisplayStyleGuide'])
|
|
139
140
|
end
|
|
140
141
|
|
|
142
|
+
def extra_details?
|
|
143
|
+
@options[:extra_details] ||
|
|
144
|
+
config['AllCops'] && config['AllCops']['ExtraDetails']
|
|
145
|
+
end
|
|
146
|
+
|
|
141
147
|
# Returns true if the cop name or the cop namespace matches any of the
|
|
142
148
|
# given names.
|
|
143
149
|
def self.match?(given_names)
|
|
@@ -154,34 +160,33 @@ module RuboCop
|
|
|
154
160
|
def add_offense(node, loc, message = nil, severity = nil)
|
|
155
161
|
location = loc.is_a?(Symbol) ? node.loc.send(loc) : loc
|
|
156
162
|
|
|
157
|
-
return unless enabled_line?(location.line)
|
|
158
|
-
|
|
159
163
|
# Don't include the same location twice for one cop.
|
|
160
|
-
return if @offenses.
|
|
164
|
+
return if @offenses.any? { |o| o.location == location }
|
|
161
165
|
|
|
162
166
|
severity = custom_severity || severity || default_severity
|
|
163
167
|
|
|
164
168
|
message ||= message(node)
|
|
165
169
|
message = annotate_message(message)
|
|
166
170
|
|
|
167
|
-
|
|
171
|
+
status = enabled_line?(location.line) ? correct(node) : :disabled
|
|
168
172
|
|
|
169
|
-
@offenses << Offense.new(severity, location, message, name,
|
|
170
|
-
yield if block_given?
|
|
173
|
+
@offenses << Offense.new(severity, location, message, name, status)
|
|
174
|
+
yield if block_given? && status != :disabled
|
|
171
175
|
end
|
|
172
176
|
|
|
173
177
|
def correct(node)
|
|
174
|
-
return
|
|
175
|
-
return
|
|
178
|
+
return :unsupported unless support_autocorrect?
|
|
179
|
+
return :uncorrected unless autocorrect?
|
|
176
180
|
|
|
177
181
|
correction = autocorrect(node)
|
|
178
|
-
return
|
|
182
|
+
return :uncorrected unless correction
|
|
179
183
|
@corrections << correction
|
|
180
|
-
|
|
184
|
+
:corrected
|
|
181
185
|
end
|
|
182
186
|
|
|
183
187
|
def config_to_allow_offenses
|
|
184
|
-
Formatter::DisabledConfigFormatter
|
|
188
|
+
Formatter::DisabledConfigFormatter
|
|
189
|
+
.config_to_allow_offenses[cop_name] ||= {}
|
|
185
190
|
end
|
|
186
191
|
|
|
187
192
|
def config_to_allow_offenses=(hash)
|
|
@@ -200,21 +205,39 @@ module RuboCop
|
|
|
200
205
|
!file_name_matches_any?(file, 'Exclude', false)
|
|
201
206
|
end
|
|
202
207
|
|
|
208
|
+
def excluded_file?(file)
|
|
209
|
+
!relevant_file?(file)
|
|
210
|
+
end
|
|
211
|
+
|
|
203
212
|
def style_guide_url
|
|
204
|
-
url = cop_config
|
|
213
|
+
url = cop_config['StyleGuide']
|
|
205
214
|
(url.nil? || url.empty?) ? nil : url
|
|
206
215
|
end
|
|
207
216
|
|
|
217
|
+
def reference_url
|
|
218
|
+
url = cop_config['Reference']
|
|
219
|
+
(url.nil? || url.empty?) ? nil : url
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def details
|
|
223
|
+
details = cop_config && cop_config['Details']
|
|
224
|
+
(details.nil? || details.empty?) ? nil : details
|
|
225
|
+
end
|
|
226
|
+
|
|
208
227
|
private
|
|
209
228
|
|
|
210
229
|
def annotate_message(message)
|
|
211
230
|
message = "#{name}: #{message}" if display_cop_names?
|
|
212
|
-
message
|
|
231
|
+
message += " #{details}" if extra_details?
|
|
232
|
+
if display_style_guide?
|
|
233
|
+
links = [style_guide_url, reference_url].compact.join(', ')
|
|
234
|
+
message = "#{message} (#{links})"
|
|
235
|
+
end
|
|
213
236
|
message
|
|
214
237
|
end
|
|
215
238
|
|
|
216
239
|
def file_name_matches_any?(file, parameter, default_result)
|
|
217
|
-
patterns = cop_config
|
|
240
|
+
patterns = cop_config[parameter]
|
|
218
241
|
return default_result unless patterns
|
|
219
242
|
path = nil
|
|
220
243
|
patterns.any? do |pattern|
|
|
@@ -237,15 +260,15 @@ module RuboCop
|
|
|
237
260
|
end
|
|
238
261
|
|
|
239
262
|
def custom_severity
|
|
240
|
-
severity = cop_config
|
|
263
|
+
severity = cop_config['Severity']
|
|
241
264
|
return unless severity
|
|
242
265
|
|
|
243
266
|
if Severity::NAMES.include?(severity.to_sym)
|
|
244
267
|
severity.to_sym
|
|
245
268
|
else
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
269
|
+
message = "Warning: Invalid severity '#{severity}'. " \
|
|
270
|
+
"Valid severities are #{Severity::NAMES.join(', ')}."
|
|
271
|
+
warn(Rainbow(message).red)
|
|
249
272
|
end
|
|
250
273
|
end
|
|
251
274
|
end
|
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
|
14
14
|
class BlockAlignment < Cop
|
|
15
15
|
include CheckAssignment
|
|
16
16
|
|
|
17
|
-
MSG = '`end` at %d, %d is not aligned with `%s` at %d, %d%s'
|
|
17
|
+
MSG = '`end` at %d, %d is not aligned with `%s` at %d, %d%s.'
|
|
18
18
|
|
|
19
19
|
def on_block(node)
|
|
20
20
|
return if ignored_node?(node)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Lint
|
|
6
|
+
# This cop checks for circular argument references in optional keyword
|
|
7
|
+
# arguments and optional ordinal arguments.
|
|
8
|
+
#
|
|
9
|
+
# This cop mirrors a warning produced by MRI since 2.2.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# # bad
|
|
13
|
+
# def bake(pie: pie)
|
|
14
|
+
# pie.heat_up
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# def bake(pie:)
|
|
19
|
+
# pie.refrigerate
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# # good
|
|
23
|
+
# def bake(pie: self.pie)
|
|
24
|
+
# pie.feed_to(user)
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# # bad
|
|
28
|
+
# def cook(dry_ingredients = dry_ingredients)
|
|
29
|
+
# dry_ingredients.reduce(&:+)
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# # good
|
|
33
|
+
# def cook(dry_ingredients = self.dry_ingredients)
|
|
34
|
+
# dry_ingredients.combine
|
|
35
|
+
# end
|
|
36
|
+
class CircularArgumentReference < Cop
|
|
37
|
+
MSG = 'Circular argument reference - `%s`.'
|
|
38
|
+
|
|
39
|
+
def on_kwoptarg(node)
|
|
40
|
+
check_for_circular_argument_references(*node)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def on_optarg(node)
|
|
44
|
+
check_for_circular_argument_references(*node)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def check_for_circular_argument_references(arg_name, arg_value)
|
|
50
|
+
case arg_value.type
|
|
51
|
+
when :send
|
|
52
|
+
# Ruby 2.0 will have type send every time, and "send nil" if it is
|
|
53
|
+
# calling itself with a specified "self" receiver
|
|
54
|
+
receiver, name = *arg_value
|
|
55
|
+
return unless name == arg_name && receiver.nil?
|
|
56
|
+
when :lvar
|
|
57
|
+
# Ruby 2.2.2 will have type lvar if it is calling its own method
|
|
58
|
+
# without a specified "self"
|
|
59
|
+
return unless arg_value.to_a == [arg_name]
|
|
60
|
+
else
|
|
61
|
+
return
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
add_offense(arg_value, :expression, format(MSG, arg_name))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -7,56 +7,17 @@ module RuboCop
|
|
|
7
7
|
class Debugger < Cop
|
|
8
8
|
MSG = 'Remove debugger entry point `%s`.'
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
BYEBUG_NODE = s(:send, nil, :byebug)
|
|
19
|
-
|
|
20
|
-
# binding.pry node
|
|
21
|
-
#
|
|
22
|
-
# (send
|
|
23
|
-
# (send nil :binding) :pry)
|
|
24
|
-
PRY_NODE = s(:send, s(:send, nil, :binding), :pry)
|
|
25
|
-
|
|
26
|
-
# binding.remote_pry node
|
|
27
|
-
#
|
|
28
|
-
# (send
|
|
29
|
-
# (send nil :binding) :remote_pry)
|
|
30
|
-
REMOTE_PRY_NODE = s(:send, s(:send, nil, :binding), :remote_pry)
|
|
31
|
-
|
|
32
|
-
# binding.pry_remote node
|
|
33
|
-
#
|
|
34
|
-
# (send
|
|
35
|
-
# (send nil :binding) :pry_remote)
|
|
36
|
-
PRY_REMOTE_NODE = s(:send, s(:send, nil, :binding), :pry_remote)
|
|
37
|
-
|
|
38
|
-
# save_and_open_page
|
|
39
|
-
#
|
|
40
|
-
# (send nil :save_and_open_page)
|
|
41
|
-
CAPYBARA_SAVE_PAGE = s(:send, nil, :save_and_open_page)
|
|
42
|
-
|
|
43
|
-
# save_and_open_screenshot
|
|
44
|
-
#
|
|
45
|
-
# (send nil :save_and_open_screenshot)
|
|
46
|
-
CAPYBARA_SAVE_SCREENSHOT = s(:send, nil, :save_and_open_screenshot)
|
|
47
|
-
|
|
48
|
-
DEBUGGER_NODES = [
|
|
49
|
-
DEBUGGER_NODE,
|
|
50
|
-
BYEBUG_NODE,
|
|
51
|
-
PRY_NODE,
|
|
52
|
-
REMOTE_PRY_NODE,
|
|
53
|
-
PRY_REMOTE_NODE,
|
|
54
|
-
CAPYBARA_SAVE_PAGE,
|
|
55
|
-
CAPYBARA_SAVE_SCREENSHOT
|
|
56
|
-
]
|
|
10
|
+
def_node_matcher :debugger_call?,
|
|
11
|
+
'{(send nil {:debugger :byebug} ...)
|
|
12
|
+
(send (send nil :binding)
|
|
13
|
+
{:pry :remote_pry :pry_remote} ...)
|
|
14
|
+
(send (const nil :Pry) :rescue ...)
|
|
15
|
+
(send nil {:save_and_open_page
|
|
16
|
+
:save_and_open_screenshot
|
|
17
|
+
:save_screenshot} ...)}'
|
|
57
18
|
|
|
58
19
|
def on_send(node)
|
|
59
|
-
return unless
|
|
20
|
+
return unless debugger_call?(node)
|
|
60
21
|
add_offense(node,
|
|
61
22
|
:expression,
|
|
62
23
|
format(MSG, node.loc.expression.source))
|
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
|
20
20
|
include OnMethodDef
|
|
21
21
|
include EndKeywordAlignment
|
|
22
22
|
|
|
23
|
-
MSG = '`end` at %d, %d is not aligned with `%s` at %d, %d'
|
|
23
|
+
MSG = '`end` at %d, %d is not aligned with `%s` at %d, %d.'
|
|
24
24
|
|
|
25
25
|
def on_method_def(node, _method_name, _args, _body)
|
|
26
26
|
check_offset_of_node(node)
|
|
@@ -28,8 +28,8 @@ module RuboCop
|
|
|
28
28
|
|
|
29
29
|
def on_send(node)
|
|
30
30
|
receiver, method_name, *args = *node
|
|
31
|
-
return unless
|
|
32
|
-
|
|
31
|
+
return unless modifier_and_def_on_same_line?(receiver, method_name,
|
|
32
|
+
args)
|
|
33
33
|
|
|
34
34
|
method_def = args.first
|
|
35
35
|
if style == :start_of_line
|
|
@@ -49,7 +49,11 @@ module RuboCop
|
|
|
49
49
|
private
|
|
50
50
|
|
|
51
51
|
def autocorrect(node)
|
|
52
|
-
|
|
52
|
+
if style == :start_of_line && node.parent && node.parent.send_type?
|
|
53
|
+
align(node, node.parent)
|
|
54
|
+
else
|
|
55
|
+
align(node, node)
|
|
56
|
+
end
|
|
53
57
|
end
|
|
54
58
|
end
|
|
55
59
|
end
|
|
@@ -5,22 +5,36 @@ module RuboCop
|
|
|
5
5
|
module Lint
|
|
6
6
|
# This cop checks for uses of the deprecated class method usages.
|
|
7
7
|
class DeprecatedClassMethods < Cop
|
|
8
|
-
|
|
8
|
+
# Inner class to DeprecatedClassMethods.
|
|
9
|
+
# This class exists to add abstraction and clean naming to the
|
|
10
|
+
# objects that are going to be operated on.
|
|
11
|
+
class DeprecatedClassMethod
|
|
12
|
+
include AST::Sexp
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
attr_reader :class_constant, :deprecated_method, :replacement_method
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
def initialize(class_constant, deprecated_method, replacement_method)
|
|
17
|
+
@class_constant = class_constant
|
|
18
|
+
@deprecated_method = deprecated_method
|
|
19
|
+
@replacement_method = replacement_method
|
|
20
|
+
end
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
def class_nodes
|
|
23
|
+
@class_nodes ||= [
|
|
24
|
+
s(:const, nil, class_constant),
|
|
25
|
+
s(:const, s(:cbase), class_constant)
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
MSG = '`%s` is deprecated in favor of `%s`.'
|
|
31
|
+
DEPRECATED_METHODS_OBJECT = [
|
|
32
|
+
DeprecatedClassMethod.new(:File, :exists?, :exist?),
|
|
33
|
+
DeprecatedClassMethod.new(:Dir, :exists?, :exist?)
|
|
34
|
+
]
|
|
23
35
|
|
|
36
|
+
def on_send(node)
|
|
37
|
+
check(node) do |data|
|
|
24
38
|
add_offense(node, :selector,
|
|
25
39
|
format(MSG,
|
|
26
40
|
deprecated_method(data),
|
|
@@ -30,31 +44,36 @@ module RuboCop
|
|
|
30
44
|
|
|
31
45
|
def autocorrect(node)
|
|
32
46
|
lambda do |corrector|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
DEPRECATED_METHODS.each do |data|
|
|
36
|
-
next unless class_nodes(data).include?(receiver)
|
|
37
|
-
next unless method_name == data[1]
|
|
38
|
-
|
|
47
|
+
check(node) do |data|
|
|
39
48
|
corrector.replace(node.loc.selector,
|
|
40
|
-
data
|
|
49
|
+
data.replacement_method.to_s)
|
|
41
50
|
end
|
|
42
51
|
end
|
|
43
52
|
end
|
|
44
53
|
|
|
45
54
|
private
|
|
46
55
|
|
|
47
|
-
def
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
def check(node, &block)
|
|
57
|
+
receiver, method_name, *_args = *node
|
|
58
|
+
|
|
59
|
+
DEPRECATED_METHODS_OBJECT.each do |data|
|
|
60
|
+
next unless data.class_nodes.include?(receiver)
|
|
61
|
+
next unless method_name == data.deprecated_method
|
|
62
|
+
|
|
63
|
+
block.call(data)
|
|
64
|
+
end
|
|
50
65
|
end
|
|
51
66
|
|
|
52
67
|
def deprecated_method(data)
|
|
53
|
-
|
|
68
|
+
method_call(data.class_constant, data.deprecated_method)
|
|
54
69
|
end
|
|
55
70
|
|
|
56
71
|
def replacement_method(data)
|
|
57
|
-
|
|
72
|
+
method_call(data.class_constant, data.replacement_method)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def method_call(class_constant, method)
|
|
76
|
+
format('%s.%s', class_constant, method)
|
|
58
77
|
end
|
|
59
78
|
end
|
|
60
79
|
end
|
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
|
65
65
|
|
|
66
66
|
def method_names(body)
|
|
67
67
|
body.child_nodes.map do |node|
|
|
68
|
-
_receiver, node, body
|
|
68
|
+
_receiver, node, body = *node if node.send_type?
|
|
69
69
|
|
|
70
70
|
if node.is_a? Symbol
|
|
71
71
|
next if body.nil?
|
|
@@ -76,7 +76,7 @@ module RuboCop
|
|
|
76
76
|
method, _args, _body = *node
|
|
77
77
|
elsif node.defs_type?
|
|
78
78
|
_receiver, method = *node
|
|
79
|
-
method = "self.#{
|
|
79
|
+
method = "self.#{method}"
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
method ? [method, node] : nil
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Lint
|
|
6
|
+
# This cop checks for duplicated keys in hash literals.
|
|
7
|
+
#
|
|
8
|
+
# This cop mirrors a warning in Ruby 2.2.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# hash = { food: 'apple', food: 'orange' }
|
|
12
|
+
class DuplicatedKey < Cop
|
|
13
|
+
MSG = 'Duplicated key in hash literal.'
|
|
14
|
+
|
|
15
|
+
LITERALS = [:sym, :str, :float, :int]
|
|
16
|
+
|
|
17
|
+
def on_hash(node)
|
|
18
|
+
keys = []
|
|
19
|
+
|
|
20
|
+
hash_pairs = *node
|
|
21
|
+
hash_pairs.each do |pair|
|
|
22
|
+
key, _value = *pair
|
|
23
|
+
if keys.include?(key) && LITERALS.include?(key.type)
|
|
24
|
+
add_offense(key, :expression)
|
|
25
|
+
elsif keys.include?(key) && key.type == :array
|
|
26
|
+
key.children.each do |child|
|
|
27
|
+
return false unless LITERALS.include?(child.type)
|
|
28
|
+
end
|
|
29
|
+
add_offense(key, :expression)
|
|
30
|
+
end
|
|
31
|
+
keys << key
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -40,6 +40,14 @@ module RuboCop
|
|
|
40
40
|
check_offset_of_node(node)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def on_case(node)
|
|
44
|
+
if argument_case?(node)
|
|
45
|
+
return check_alignment(node.ancestors.first, node)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
check_offset_of_node(node)
|
|
49
|
+
end
|
|
50
|
+
|
|
43
51
|
private
|
|
44
52
|
|
|
45
53
|
def check_assignment(node, rhs)
|
|
@@ -50,31 +58,43 @@ module RuboCop
|
|
|
50
58
|
|
|
51
59
|
return unless rhs
|
|
52
60
|
|
|
53
|
-
return unless [:if, :while, :until].include?(rhs.type)
|
|
61
|
+
return unless [:if, :while, :until, :case].include?(rhs.type)
|
|
54
62
|
return if ternary_op?(rhs)
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
check_alignment(node, rhs)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def check_alignment(outer_node, inner_node)
|
|
68
|
+
expr = outer_node.loc.expression
|
|
69
|
+
if variable_alignment?(expr, inner_node, style)
|
|
58
70
|
range = Parser::Source::Range.new(expr.source_buffer,
|
|
59
71
|
expr.begin_pos,
|
|
60
|
-
|
|
61
|
-
offset =
|
|
72
|
+
inner_node.loc.keyword.end_pos)
|
|
73
|
+
offset =
|
|
74
|
+
inner_node.loc.keyword.column - outer_node.loc.expression.column
|
|
62
75
|
else
|
|
63
|
-
range =
|
|
76
|
+
range = inner_node.loc.keyword
|
|
64
77
|
offset = 0
|
|
65
78
|
end
|
|
66
79
|
|
|
67
|
-
check_offset(
|
|
68
|
-
ignore_node(
|
|
80
|
+
check_offset(inner_node, range.source, offset)
|
|
81
|
+
ignore_node(inner_node) # Don't check again.
|
|
69
82
|
end
|
|
70
83
|
|
|
71
|
-
def
|
|
72
|
-
|
|
84
|
+
def autocorrect(node)
|
|
85
|
+
align(node, alignment_node(node))
|
|
73
86
|
end
|
|
74
87
|
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
def alignment_node(node)
|
|
89
|
+
return node unless style == :variable
|
|
90
|
+
return node.ancestors.first if argument_case?(node)
|
|
91
|
+
|
|
92
|
+
node.each_ancestor(:lvasgn).first
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def argument_case?(node)
|
|
96
|
+
node.case_type? && !node.ancestors.empty? &&
|
|
97
|
+
node.ancestors.first.send_type?
|
|
78
98
|
end
|
|
79
99
|
end
|
|
80
100
|
end
|
|
@@ -8,9 +8,13 @@ module RuboCop
|
|
|
8
8
|
MSG = 'The use of `eval` is a serious security risk.'
|
|
9
9
|
|
|
10
10
|
def on_send(node)
|
|
11
|
-
receiver, method_name, = *node
|
|
11
|
+
receiver, method_name, *args = *node
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
return unless receiver.nil? &&
|
|
14
|
+
method_name == :eval &&
|
|
15
|
+
!args.empty? &&
|
|
16
|
+
args.first.type != :str
|
|
17
|
+
add_offense(node, :selector)
|
|
14
18
|
end
|
|
15
19
|
end
|
|
16
20
|
end
|