rubocop 1.39.0 → 1.42.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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +91 -10
- data/exe/rubocop +1 -1
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/comment_config.rb +5 -0
- data/lib/rubocop/config.rb +39 -15
- data/lib/rubocop/config_loader.rb +14 -5
- data/lib/rubocop/config_loader_resolver.rb +6 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/badge.rb +9 -4
- data/lib/rubocop/cop/base.rb +84 -74
- data/lib/rubocop/cop/commissioner.rb +8 -3
- data/lib/rubocop/cop/cop.rb +29 -29
- data/lib/rubocop/cop/corrector.rb +23 -11
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
- data/lib/rubocop/cop/gemspec/dependency_version.rb +16 -18
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +32 -11
- data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
- data/lib/rubocop/cop/layout/empty_lines.rb +2 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +10 -6
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +38 -2
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +49 -2
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +61 -2
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -2
- data/lib/rubocop/cop/layout/indentation_style.rb +7 -2
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -5
- data/lib/rubocop/cop/layout/line_length.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +51 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +49 -2
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +53 -2
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +58 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +11 -4
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +19 -8
- data/lib/rubocop/cop/lint/empty_block.rb +1 -5
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +19 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +15 -3
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +10 -12
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +5 -3
- data/lib/rubocop/cop/lint/void.rb +6 -6
- data/lib/rubocop/cop/metrics/block_length.rb +9 -4
- data/lib/rubocop/cop/metrics/class_length.rb +10 -5
- data/lib/rubocop/cop/metrics/method_length.rb +9 -4
- data/lib/rubocop/cop/metrics/module_length.rb +10 -5
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -4
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -3
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/annotation_comment.rb +13 -6
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +28 -5
- data/lib/rubocop/cop/mixin/line_length_help.rb +8 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -3
- data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/require_library.rb +2 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -0
- data/lib/rubocop/cop/naming/inclusive_language.rb +4 -1
- data/lib/rubocop/cop/registry.rb +51 -36
- data/lib/rubocop/cop/security/compound_hash.rb +2 -1
- data/lib/rubocop/cop/style/alias.rb +9 -1
- data/lib/rubocop/cop/style/array_intersect.rb +111 -0
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +86 -0
- data/lib/rubocop/cop/style/documentation.rb +11 -5
- data/lib/rubocop/cop/style/guard_clause.rb +44 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +10 -7
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
- data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
- data/lib/rubocop/cop/style/map_to_set.rb +61 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
- data/lib/rubocop/cop/style/min_max_comparison.rb +73 -0
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +39 -0
- data/lib/rubocop/cop/style/redundant_return.rb +7 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +6 -3
- data/lib/rubocop/cop/style/require_order.rb +142 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +13 -5
- data/lib/rubocop/cop/style/semicolon.rb +2 -1
- data/lib/rubocop/cop/style/signal_exception.rb +8 -6
- data/lib/rubocop/cop/style/string_literals.rb +1 -5
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
- data/lib/rubocop/cop/style/word_array.rb +41 -0
- data/lib/rubocop/cop/style/yoda_expression.rb +74 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +31 -14
- data/lib/rubocop/cop/team.rb +30 -30
- data/lib/rubocop/cop/util.rb +32 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +17 -29
- data/lib/rubocop/cops_documentation_generator.rb +33 -11
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/file_patterns.rb +43 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +5 -1
- data/lib/rubocop/options.rb +8 -0
- data/lib/rubocop/path_util.rb +39 -16
- data/lib/rubocop/result_cache.rb +2 -2
- data/lib/rubocop/rspec/cop_helper.rb +4 -1
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/runner.rb +10 -3
- data/lib/rubocop/server/core.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +19 -6
- metadata +19 -9
data/lib/rubocop/cop/base.rb
CHANGED
@@ -68,6 +68,64 @@ module RuboCop
|
|
68
68
|
Documentation.url_for(self) if builtin?
|
69
69
|
end
|
70
70
|
|
71
|
+
def self.inherited(subclass)
|
72
|
+
super
|
73
|
+
Registry.global.enlist(subclass)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Call for abstract Cop classes
|
77
|
+
def self.exclude_from_registry
|
78
|
+
Registry.global.dismiss(self)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns if class supports autocorrect.
|
82
|
+
# It is recommended to extend AutoCorrector instead of overriding
|
83
|
+
def self.support_autocorrect?
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
### Naming
|
88
|
+
|
89
|
+
def self.badge
|
90
|
+
@badge ||= Badge.for(name)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.cop_name
|
94
|
+
badge.to_s
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.department
|
98
|
+
badge.department
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.lint?
|
102
|
+
department == :Lint
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns true if the cop name or the cop namespace matches any of the
|
106
|
+
# given names.
|
107
|
+
def self.match?(given_names)
|
108
|
+
return false unless given_names
|
109
|
+
|
110
|
+
given_names.include?(cop_name) || given_names.include?(badge.department_name)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Override and return the Force class(es) you need to join
|
114
|
+
def self.joining_forces; end
|
115
|
+
|
116
|
+
### Persistence
|
117
|
+
|
118
|
+
# Override if your cop should be called repeatedly for multiple investigations
|
119
|
+
# Between calls to `on_new_investigation` and `on_investigation_end`,
|
120
|
+
# the result of `processed_source` will remain constant.
|
121
|
+
# You should invalidate any caches that depend on the current `processed_source`
|
122
|
+
# in the `on_new_investigation` callback.
|
123
|
+
# If your cop does autocorrections, be aware that your instance may be called
|
124
|
+
# multiple times with the same `processed_source.path` but different content.
|
125
|
+
def self.support_multiple_source?
|
126
|
+
false
|
127
|
+
end
|
128
|
+
|
71
129
|
def initialize(config = nil, options = nil)
|
72
130
|
@config = config || Config.new
|
73
131
|
@options = options || { debug: false }
|
@@ -92,9 +150,6 @@ module RuboCop
|
|
92
150
|
# Typically do nothing here
|
93
151
|
end
|
94
152
|
|
95
|
-
# Override and return the Force class(es) you need to join
|
96
|
-
def self.joining_forces; end
|
97
|
-
|
98
153
|
# Gets called if no message is specified when calling `add_offense` or
|
99
154
|
# `add_global_offense`
|
100
155
|
# Cops are discouraged to override this; instead pass your message directly
|
@@ -107,8 +162,7 @@ module RuboCop
|
|
107
162
|
def add_global_offense(message = nil, severity: nil)
|
108
163
|
severity = find_severity(nil, severity)
|
109
164
|
message = find_message(nil, message)
|
110
|
-
|
111
|
-
Offense.new(severity, Offense::NO_LOCATION, message, name, :unsupported)
|
165
|
+
current_offenses << Offense.new(severity, Offense::NO_LOCATION, message, name, :unsupported)
|
112
166
|
end
|
113
167
|
|
114
168
|
# Adds an offense on the specified range (or node with an expression)
|
@@ -126,7 +180,7 @@ module RuboCop
|
|
126
180
|
|
127
181
|
status, corrector = enabled_line?(range.line) ? correct(range, &block) : :disabled
|
128
182
|
|
129
|
-
|
183
|
+
current_offenses << Offense.new(severity, range, message, name, status, corrector)
|
130
184
|
end
|
131
185
|
|
132
186
|
# This method should be overridden when a cop's behavior depends
|
@@ -148,48 +202,6 @@ module RuboCop
|
|
148
202
|
nil
|
149
203
|
end
|
150
204
|
|
151
|
-
def self.inherited(subclass)
|
152
|
-
super
|
153
|
-
Registry.global.enlist(subclass)
|
154
|
-
end
|
155
|
-
|
156
|
-
# Call for abstract Cop classes
|
157
|
-
def self.exclude_from_registry
|
158
|
-
Registry.global.dismiss(self)
|
159
|
-
end
|
160
|
-
|
161
|
-
# Returns if class supports autocorrect.
|
162
|
-
# It is recommended to extend AutoCorrector instead of overriding
|
163
|
-
def self.support_autocorrect?
|
164
|
-
false
|
165
|
-
end
|
166
|
-
|
167
|
-
### Naming
|
168
|
-
|
169
|
-
def self.badge
|
170
|
-
@badge ||= Badge.for(name)
|
171
|
-
end
|
172
|
-
|
173
|
-
def self.cop_name
|
174
|
-
badge.to_s
|
175
|
-
end
|
176
|
-
|
177
|
-
def self.department
|
178
|
-
badge.department
|
179
|
-
end
|
180
|
-
|
181
|
-
def self.lint?
|
182
|
-
department == :Lint
|
183
|
-
end
|
184
|
-
|
185
|
-
# Returns true if the cop name or the cop namespace matches any of the
|
186
|
-
# given names.
|
187
|
-
def self.match?(given_names)
|
188
|
-
return false unless given_names
|
189
|
-
|
190
|
-
given_names.include?(cop_name) || given_names.include?(department.to_s)
|
191
|
-
end
|
192
|
-
|
193
205
|
def cop_name
|
194
206
|
@cop_name ||= self.class.cop_name
|
195
207
|
end
|
@@ -225,6 +237,8 @@ module RuboCop
|
|
225
237
|
end
|
226
238
|
|
227
239
|
def relevant_file?(file)
|
240
|
+
return true unless @config.clusivity_config_for_badge?(self.class.badge)
|
241
|
+
|
228
242
|
file == RuboCop::AST::ProcessedSource::STRING_SOURCE_NAME ||
|
229
243
|
(file_name_matches_any?(file, 'Include', true) &&
|
230
244
|
!file_name_matches_any?(file, 'Exclude', false))
|
@@ -239,19 +253,6 @@ module RuboCop
|
|
239
253
|
ProcessedSource.new(source, target_ruby_version, path)
|
240
254
|
end
|
241
255
|
|
242
|
-
### Persistence
|
243
|
-
|
244
|
-
# Override if your cop should be called repeatedly for multiple investigations
|
245
|
-
# Between calls to `on_new_investigation` and `on_investigation_end`,
|
246
|
-
# the result of `processed_source` will remain constant.
|
247
|
-
# You should invalidate any caches that depend on the current `processed_source`
|
248
|
-
# in the `on_new_investigation` callback.
|
249
|
-
# If your cop does autocorrections, be aware that your instance may be called
|
250
|
-
# multiple times with the same `processed_source.path` but different content.
|
251
|
-
def self.support_multiple_source?
|
252
|
-
false
|
253
|
-
end
|
254
|
-
|
255
256
|
# @api private
|
256
257
|
# Called between investigations
|
257
258
|
def ready
|
@@ -270,6 +271,7 @@ module RuboCop
|
|
270
271
|
|
271
272
|
### Reserved for Commissioner
|
272
273
|
|
274
|
+
# rubocop:disable Layout/ClassStructure
|
273
275
|
# @api private
|
274
276
|
def callbacks_needed
|
275
277
|
self.class.callbacks_needed
|
@@ -282,6 +284,7 @@ module RuboCop
|
|
282
284
|
!Base.method_defined?(m) # exclude standard "callbacks" like 'on_begin_investigation'
|
283
285
|
end
|
284
286
|
end
|
287
|
+
# rubocop:enable Layout/ClassStructure
|
285
288
|
|
286
289
|
private
|
287
290
|
|
@@ -292,7 +295,7 @@ module RuboCop
|
|
292
295
|
end
|
293
296
|
|
294
297
|
def apply_correction(corrector)
|
295
|
-
|
298
|
+
current_corrector&.merge!(corrector) if corrector
|
296
299
|
end
|
297
300
|
|
298
301
|
### Reserved for Commissioner:
|
@@ -305,28 +308,41 @@ module RuboCop
|
|
305
308
|
@currently_disabled_lines ||= Set.new
|
306
309
|
end
|
307
310
|
|
311
|
+
def current_corrector
|
312
|
+
@current_corrector ||= Corrector.new(@processed_source) if @processed_source.valid_syntax?
|
313
|
+
end
|
314
|
+
|
315
|
+
def current_offenses
|
316
|
+
@current_offenses ||= []
|
317
|
+
end
|
318
|
+
|
308
319
|
private_class_method def self.restrict_on_send
|
309
320
|
@restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
|
310
321
|
end
|
311
322
|
|
312
323
|
# Called before any investigation
|
313
324
|
def begin_investigation(processed_source)
|
314
|
-
@current_offenses =
|
325
|
+
@current_offenses = nil
|
315
326
|
@current_offense_locations = nil
|
316
327
|
@currently_disabled_lines = nil
|
317
328
|
@processed_source = processed_source
|
318
|
-
@current_corrector =
|
329
|
+
@current_corrector = nil
|
319
330
|
end
|
320
331
|
|
332
|
+
EMPTY_OFFENSES = [].freeze
|
333
|
+
private_constant :EMPTY_OFFENSES
|
321
334
|
# Called to complete an investigation
|
322
335
|
def complete_investigation
|
323
|
-
InvestigationReport.new(
|
336
|
+
InvestigationReport.new(
|
337
|
+
self, processed_source, @current_offenses || EMPTY_OFFENSES, @current_corrector
|
338
|
+
)
|
324
339
|
ensure
|
325
340
|
reset_investigation
|
326
341
|
end
|
327
342
|
|
328
343
|
### Actually private methods
|
329
344
|
|
345
|
+
# rubocop:disable Layout/ClassStructure
|
330
346
|
def self.builtin?
|
331
347
|
return false unless (m = instance_methods(false).first) # any custom method will do
|
332
348
|
|
@@ -334,6 +350,7 @@ module RuboCop
|
|
334
350
|
path.start_with?(__dir__)
|
335
351
|
end
|
336
352
|
private_class_method :builtin?
|
353
|
+
# rubocop:enable Layout/ClassStructure
|
337
354
|
|
338
355
|
def reset_investigation
|
339
356
|
@currently_disabled_lines = @current_offenses = @processed_source = @current_corrector = nil
|
@@ -412,15 +429,8 @@ module RuboCop
|
|
412
429
|
patterns = cop_config[parameter]
|
413
430
|
return default_result unless patterns
|
414
431
|
|
415
|
-
|
416
|
-
patterns.
|
417
|
-
# Try to match the absolute path, as Exclude properties are absolute.
|
418
|
-
next true if match_path?(pattern, file)
|
419
|
-
|
420
|
-
# Try with relative path.
|
421
|
-
path ||= config.path_relative_to_config(file)
|
422
|
-
match_path?(pattern, path)
|
423
|
-
end
|
432
|
+
patterns = FilePatterns.from(patterns)
|
433
|
+
patterns.match?(config.path_relative_to_config(file)) || patterns.match?(file)
|
424
434
|
end
|
425
435
|
|
426
436
|
def enabled_line?(line_number)
|
@@ -82,7 +82,8 @@ module RuboCop
|
|
82
82
|
@cops.each { |cop| cop.send :begin_investigation, processed_source }
|
83
83
|
if processed_source.valid_syntax?
|
84
84
|
invoke(:on_new_investigation, @cops)
|
85
|
-
|
85
|
+
invoke_with_argument(:investigate, @forces, processed_source)
|
86
|
+
|
86
87
|
walk(processed_source.ast) unless @cops.empty?
|
87
88
|
invoke(:on_investigation_end, @cops)
|
88
89
|
else
|
@@ -149,8 +150,12 @@ module RuboCop
|
|
149
150
|
map
|
150
151
|
end
|
151
152
|
|
152
|
-
def invoke(callback, cops
|
153
|
-
cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback
|
153
|
+
def invoke(callback, cops)
|
154
|
+
cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback) } }
|
155
|
+
end
|
156
|
+
|
157
|
+
def invoke_with_argument(callback, cops, arg)
|
158
|
+
cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback, arg) } }
|
154
159
|
end
|
155
160
|
|
156
161
|
# Allow blind rescues here, since we're absorbing and packaging or
|
data/lib/rubocop/cop/cop.rb
CHANGED
@@ -22,6 +22,34 @@ module RuboCop
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def self.support_autocorrect?
|
26
|
+
method_defined?(:autocorrect)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.joining_forces
|
30
|
+
return unless method_defined?(:join_force?)
|
31
|
+
|
32
|
+
cop = new
|
33
|
+
Force.all.select { |force_class| cop.join_force?(force_class) }
|
34
|
+
end
|
35
|
+
|
36
|
+
### Deprecated registry access
|
37
|
+
|
38
|
+
# @deprecated Use Registry.global
|
39
|
+
def self.registry
|
40
|
+
Registry.global
|
41
|
+
end
|
42
|
+
|
43
|
+
# @deprecated Use Registry.all
|
44
|
+
def self.all
|
45
|
+
Registry.all
|
46
|
+
end
|
47
|
+
|
48
|
+
# @deprecated Use Registry.qualified_cop_name
|
49
|
+
def self.qualified_cop_name(name, origin)
|
50
|
+
Registry.qualified_cop_name(name, origin)
|
51
|
+
end
|
52
|
+
|
25
53
|
def add_offense(node_or_range, location: :expression, message: nil, severity: nil, &block)
|
26
54
|
@v0_argument = node_or_range
|
27
55
|
range = find_location(node_or_range, location)
|
@@ -45,17 +73,6 @@ module RuboCop
|
|
45
73
|
self.class.support_autocorrect?
|
46
74
|
end
|
47
75
|
|
48
|
-
def self.support_autocorrect?
|
49
|
-
method_defined?(:autocorrect)
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.joining_forces
|
53
|
-
return unless method_defined?(:join_force?)
|
54
|
-
|
55
|
-
cop = new
|
56
|
-
Force.all.select { |force_class| cop.join_force?(force_class) }
|
57
|
-
end
|
58
|
-
|
59
76
|
# @deprecated
|
60
77
|
def corrections
|
61
78
|
# warn 'Cop#corrections is deprecated' TODO
|
@@ -76,28 +93,11 @@ module RuboCop
|
|
76
93
|
super
|
77
94
|
end
|
78
95
|
|
79
|
-
### Deprecated registry access
|
80
|
-
|
81
|
-
# @deprecated Use Registry.global
|
82
|
-
def self.registry
|
83
|
-
Registry.global
|
84
|
-
end
|
85
|
-
|
86
|
-
# @deprecated Use Registry.all
|
87
|
-
def self.all
|
88
|
-
Registry.all
|
89
|
-
end
|
90
|
-
|
91
|
-
# @deprecated Use Registry.qualified_cop_name
|
92
|
-
def self.qualified_cop_name(name, origin)
|
93
|
-
Registry.qualified_cop_name(name, origin)
|
94
|
-
end
|
95
|
-
|
96
96
|
private
|
97
97
|
|
98
98
|
def begin_investigation(processed_source)
|
99
99
|
super
|
100
|
-
@offenses =
|
100
|
+
@offenses = current_offenses
|
101
101
|
@last_corrector = @current_corrector
|
102
102
|
end
|
103
103
|
|
@@ -11,6 +11,20 @@ module RuboCop
|
|
11
11
|
class Corrector < ::Parser::Source::TreeRewriter
|
12
12
|
NOOP_CONSUMER = ->(diagnostic) {} # noop
|
13
13
|
|
14
|
+
# Duck typing for get to a ::Parser::Source::Buffer
|
15
|
+
def self.source_buffer(source)
|
16
|
+
source = source.processed_source if source.respond_to?(:processed_source)
|
17
|
+
source = source.buffer if source.respond_to?(:buffer)
|
18
|
+
source = source.source_buffer if source.respond_to?(:source_buffer)
|
19
|
+
|
20
|
+
unless source.is_a? ::Parser::Source::Buffer
|
21
|
+
raise TypeError, 'Expected argument to lead to a Parser::Source::Buffer ' \
|
22
|
+
"but got #{source.inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
source
|
26
|
+
end
|
27
|
+
|
14
28
|
# @param source [Parser::Source::Buffer, or anything
|
15
29
|
# leading to one via `(processed_source.)buffer`]
|
16
30
|
#
|
@@ -64,18 +78,16 @@ module RuboCop
|
|
64
78
|
remove(to_remove)
|
65
79
|
end
|
66
80
|
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
raise TypeError, 'Expected argument to lead to a Parser::Source::Buffer ' \
|
75
|
-
"but got #{source.inspect}"
|
76
|
-
end
|
81
|
+
# Swaps sources at the given ranges.
|
82
|
+
#
|
83
|
+
# @param [Parser::Source::Range, RuboCop::AST::Node] node_or_range1
|
84
|
+
# @param [Parser::Source::Range, RuboCop::AST::Node] node_or_range2
|
85
|
+
def swap(node_or_range1, node_or_range2)
|
86
|
+
range1 = to_range(node_or_range1)
|
87
|
+
range2 = to_range(node_or_range2)
|
77
88
|
|
78
|
-
source
|
89
|
+
replace(range1, range2.source)
|
90
|
+
replace(range2, range1.source)
|
79
91
|
end
|
80
92
|
|
81
93
|
private
|
@@ -28,7 +28,10 @@ module RuboCop
|
|
28
28
|
# put the comment.
|
29
29
|
return if new_line_needed_before_closing_brace?(node)
|
30
30
|
|
31
|
-
|
31
|
+
end_range = last_element_range_with_trailing_comma(node).end
|
32
|
+
|
33
|
+
correct_next_line_brace(corrector, end_range)
|
34
|
+
correct_heredoc_argument_method_chain(corrector, end_range)
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
@@ -40,13 +43,19 @@ module RuboCop
|
|
40
43
|
corrector.insert_before(node.loc.end, "\n")
|
41
44
|
end
|
42
45
|
|
43
|
-
def correct_next_line_brace(corrector)
|
46
|
+
def correct_next_line_brace(corrector, end_range)
|
44
47
|
corrector.remove(range_with_surrounding_space(node.loc.end, side: :left))
|
48
|
+
corrector.insert_before(end_range, content_if_comment_present(corrector, node))
|
49
|
+
end
|
45
50
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
def correct_heredoc_argument_method_chain(corrector, end_range)
|
52
|
+
return unless (parent = node.parent)
|
53
|
+
return unless use_heredoc_argument_method_chain?(parent)
|
54
|
+
|
55
|
+
chained_method = range_between(parent.loc.dot.begin_pos, parent.loc.expression.end_pos)
|
56
|
+
|
57
|
+
corrector.remove(chained_method)
|
58
|
+
corrector.insert_after(end_range, chained_method.source)
|
50
59
|
end
|
51
60
|
|
52
61
|
def content_if_comment_present(corrector, node)
|
@@ -61,6 +70,13 @@ module RuboCop
|
|
61
70
|
end
|
62
71
|
end
|
63
72
|
|
73
|
+
def use_heredoc_argument_method_chain?(parent)
|
74
|
+
return false unless node.respond_to?(:first_argument)
|
75
|
+
return false unless (first_argument = node.first_argument)
|
76
|
+
|
77
|
+
parent.call_type? && first_argument.str_type? && first_argument.heredoc?
|
78
|
+
end
|
79
|
+
|
64
80
|
def select_content_to_be_inserted_after_last_element(corrector, node)
|
65
81
|
range = range_between(
|
66
82
|
node.loc.end.begin_pos,
|
@@ -58,8 +58,13 @@ module RuboCop
|
|
58
58
|
FORBIDDEN_MSG = 'Dependency version specification is forbidden.'
|
59
59
|
VERSION_SPECIFICATION_REGEX = /^\s*[~<>=]*\s*[0-9.]+/.freeze
|
60
60
|
|
61
|
-
|
62
|
-
|
61
|
+
ADD_DEPENDENCY_METHODS = %i[
|
62
|
+
add_dependency add_runtime_dependency add_development_dependency
|
63
|
+
].freeze
|
64
|
+
RESTRICT_ON_SEND = ADD_DEPENDENCY_METHODS
|
65
|
+
|
66
|
+
# @!method add_dependency_method_declaration?(node)
|
67
|
+
def_node_matcher :add_dependency_method_declaration?, <<~PATTERN
|
63
68
|
(send
|
64
69
|
(lvar #match_block_variable_name?) #add_dependency_method? ...)
|
65
70
|
PATTERN
|
@@ -74,18 +79,15 @@ module RuboCop
|
|
74
79
|
(send _ #add_dependency_method? <(hash <(pair (sym {:branch :ref :tag}) (str _)) ...>) ...>)
|
75
80
|
PATTERN
|
76
81
|
|
77
|
-
def
|
78
|
-
return
|
79
|
-
|
80
|
-
add_dependency_method_nodes.each do |node|
|
81
|
-
next if allowed_gem?(node)
|
82
|
+
def on_send(node)
|
83
|
+
return unless add_dependency_method_declaration?(node)
|
84
|
+
return if allowed_gem?(node)
|
82
85
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
86
|
+
if offense?(node)
|
87
|
+
add_offense(node)
|
88
|
+
opposite_style_detected
|
89
|
+
else
|
90
|
+
correct_style_detected
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
@@ -116,11 +118,7 @@ module RuboCop
|
|
116
118
|
end
|
117
119
|
|
118
120
|
def add_dependency_method?(method_name)
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
def add_dependency_method_nodes
|
123
|
-
add_dependency_method_declarations(processed_source.ast)
|
121
|
+
ADD_DEPENDENCY_METHODS.include?(method_name)
|
124
122
|
end
|
125
123
|
|
126
124
|
def offense?(node)
|
@@ -28,8 +28,9 @@ module RuboCop
|
|
28
28
|
/^\s+# This cop (?<special>#{SPECIAL_WORDS.join('|')})?\s*(?<word>.+?) .*/.freeze
|
29
29
|
REPLACEMENT_REGEX = /^\s+# This cop (#{SPECIAL_WORDS.join('|')})?\s*(.+?) /.freeze
|
30
30
|
|
31
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
31
32
|
def on_class(node)
|
32
|
-
return unless (module_node = node.parent)
|
33
|
+
return unless (module_node = node.parent) && node.parent_class
|
33
34
|
|
34
35
|
description_beginning = first_comment_line(module_node)
|
35
36
|
return unless description_beginning
|
@@ -48,6 +49,7 @@ module RuboCop
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
52
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
51
53
|
|
52
54
|
private
|
53
55
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Enforces the use of `node.lambda_or_proc?` instead of `node.lambda? || node.proc?`.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# node.lambda? || node.proc?
|
11
|
+
# node.proc? || node.lambda?
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# node.lambda_or_proc?
|
15
|
+
#
|
16
|
+
class LambdaOrProc < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
19
|
+
MSG = 'Use `%<prefer>s`.'
|
20
|
+
|
21
|
+
# @!method lambda_or_proc(node)
|
22
|
+
def_node_matcher :lambda_or_proc, <<~PATTERN
|
23
|
+
{
|
24
|
+
(or $(send _node :lambda?) $(send _node :proc?))
|
25
|
+
(or $(send _node :proc?) $(send _node :lambda?))
|
26
|
+
(or
|
27
|
+
(or _ $(send _node :lambda?)) $(send _node :proc?))
|
28
|
+
(or
|
29
|
+
(or _ $(send _node :proc?)) $(send _node :lambda?))
|
30
|
+
}
|
31
|
+
PATTERN
|
32
|
+
|
33
|
+
def on_or(node)
|
34
|
+
return unless (lhs, rhs = lambda_or_proc(node))
|
35
|
+
|
36
|
+
offense = lhs.receiver.source_range.join(rhs.source_range.end)
|
37
|
+
prefer = "#{lhs.receiver.source}.lambda_or_proc?"
|
38
|
+
|
39
|
+
add_offense(offense, message: format(MSG, prefer: prefer)) do |corrector|
|
40
|
+
corrector.replace(offense, prefer)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -6,6 +6,7 @@ require_relative 'internal_affairs/empty_line_between_expect_offense_and_correct
|
|
6
6
|
require_relative 'internal_affairs/example_description'
|
7
7
|
require_relative 'internal_affairs/example_heredoc_delimiter'
|
8
8
|
require_relative 'internal_affairs/inherit_deprecated_cop_class'
|
9
|
+
require_relative 'internal_affairs/lambda_or_proc'
|
9
10
|
require_relative 'internal_affairs/location_line_equality_comparison'
|
10
11
|
require_relative 'internal_affairs/method_name_end_with'
|
11
12
|
require_relative 'internal_affairs/method_name_equal'
|
@@ -132,25 +132,19 @@ module RuboCop
|
|
132
132
|
# end
|
133
133
|
# end
|
134
134
|
#
|
135
|
-
# @see https://rubystyle.guide#consistent-classes
|
136
135
|
class ClassStructure < Base
|
137
136
|
include VisibilityHelp
|
138
137
|
extend AutoCorrector
|
139
138
|
|
140
139
|
HUMANIZED_NODE_TYPE = {
|
141
140
|
casgn: :constants,
|
142
|
-
defs: :
|
141
|
+
defs: :public_class_methods,
|
143
142
|
def: :public_methods,
|
144
143
|
sclass: :class_singleton
|
145
144
|
}.freeze
|
146
145
|
|
147
146
|
MSG = '`%<category>s` is supposed to appear before `%<previous>s`.'
|
148
147
|
|
149
|
-
# @!method dynamic_constant?(node)
|
150
|
-
def_node_matcher :dynamic_constant?, <<~PATTERN
|
151
|
-
(casgn nil? _ (send ...))
|
152
|
-
PATTERN
|
153
|
-
|
154
148
|
# Validates code style on class declaration.
|
155
149
|
# Add offense when find a node out of expected order.
|
156
150
|
def on_class(class_node)
|
@@ -222,7 +216,7 @@ module RuboCop
|
|
222
216
|
def walk_over_nested_class_definition(class_node)
|
223
217
|
class_elements(class_node).each do |node|
|
224
218
|
classification = classify(node)
|
225
|
-
next if ignore?(classification)
|
219
|
+
next if ignore?(node, classification)
|
226
220
|
|
227
221
|
yield node, classification
|
228
222
|
end
|
@@ -240,17 +234,20 @@ module RuboCop
|
|
240
234
|
end
|
241
235
|
end
|
242
236
|
|
243
|
-
def ignore?(classification)
|
237
|
+
def ignore?(node, classification)
|
244
238
|
classification.nil? ||
|
245
239
|
classification.to_s.end_with?('=') ||
|
246
|
-
expected_order.index(classification).nil?
|
240
|
+
expected_order.index(classification).nil? ||
|
241
|
+
private_constant?(node)
|
247
242
|
end
|
248
243
|
|
249
244
|
def ignore_for_autocorrect?(node, sibling)
|
250
245
|
classification = classify(node)
|
251
246
|
sibling_class = classify(sibling)
|
252
247
|
|
253
|
-
ignore?(sibling_class) ||
|
248
|
+
ignore?(sibling, sibling_class) ||
|
249
|
+
classification == sibling_class ||
|
250
|
+
dynamic_constant?(node)
|
254
251
|
end
|
255
252
|
|
256
253
|
def humanize_node(node)
|
@@ -262,6 +259,30 @@ module RuboCop
|
|
262
259
|
HUMANIZED_NODE_TYPE[node.type] || node.type
|
263
260
|
end
|
264
261
|
|
262
|
+
def dynamic_constant?(node)
|
263
|
+
return false unless node.casgn_type? && node.namespace.nil?
|
264
|
+
|
265
|
+
expression = node.expression
|
266
|
+
expression.send_type? &&
|
267
|
+
!(expression.method?(:freeze) && expression.receiver&.recursive_basic_literal?)
|
268
|
+
end
|
269
|
+
|
270
|
+
def private_constant?(node)
|
271
|
+
return false unless node.casgn_type? && node.namespace.nil?
|
272
|
+
return false unless (parent = node.parent)
|
273
|
+
|
274
|
+
parent.each_child_node(:send) do |child_node|
|
275
|
+
return true if marked_as_private_constant?(child_node, node.name)
|
276
|
+
end
|
277
|
+
false
|
278
|
+
end
|
279
|
+
|
280
|
+
def marked_as_private_constant?(node, name)
|
281
|
+
return false unless node.method?(:private_constant)
|
282
|
+
|
283
|
+
node.arguments.any? { |arg| (arg.sym_type? || arg.str_type?) && arg.value == name }
|
284
|
+
end
|
285
|
+
|
265
286
|
def source_range_with_comment(node)
|
266
287
|
begin_pos, end_pos =
|
267
288
|
if (node.def_type? && !node.method?(:initialize)) ||
|