rubocop 1.86.2 → 1.88.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/config/default.yml +82 -71
- data/config/obsoletion.yml +21 -1
- data/lib/rubocop/cli/command/auto_generate_config.rb +6 -0
- data/lib/rubocop/cli.rb +2 -0
- data/lib/rubocop/config_loader.rb +17 -2
- data/lib/rubocop/config_loader_resolver.rb +11 -3
- data/lib/rubocop/config_store.rb +1 -1
- data/lib/rubocop/cop/base.rb +25 -4
- data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +41 -4
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +14 -5
- data/lib/rubocop/cop/layout/end_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +13 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +1 -11
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +1 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/constant_reassignment.rb +36 -4
- data/lib/rubocop/cop/lint/constant_resolution.rb +5 -5
- data/lib/rubocop/cop/lint/debugger.rb +0 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
- data/lib/rubocop/cop/lint/empty_block.rb +3 -3
- data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -2
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -0
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +18 -3
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +5 -5
- data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +16 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +18 -9
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +3 -0
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
- data/lib/rubocop/cop/lint/rand_one.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +4 -1
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -3
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -7
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +10 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_object.rb +5 -0
- data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
- data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +2 -1
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +6 -6
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -0
- data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
- data/lib/rubocop/cop/lint/script_permission.rb +5 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +24 -1
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +14 -0
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +12 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +28 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +4 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +4 -2
- data/lib/rubocop/cop/lint/unreachable_code.rb +2 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +10 -5
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +8 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
- data/lib/rubocop/cop/lint/useless_times.rb +22 -1
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
- data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
- data/lib/rubocop/cop/mixin.rb +1 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_prefix.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/registry.rb +28 -6
- data/lib/rubocop/cop/security/io_methods.rb +1 -1
- data/lib/rubocop/cop/style/alias.rb +11 -2
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/array_first_last.rb +12 -1
- data/lib/rubocop/cop/style/array_intersect.rb +4 -0
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +3 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +16 -2
- data/lib/rubocop/cop/style/case_equality.rb +14 -2
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +8 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +21 -13
- data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
- data/lib/rubocop/cop/style/colon_method_call.rb +13 -6
- data/lib/rubocop/cop/style/combinable_loops.rb +5 -0
- data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +5 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -1
- data/lib/rubocop/cop/style/constant_visibility.rb +4 -1
- data/lib/rubocop/cop/style/date_time.rb +2 -2
- data/lib/rubocop/cop/style/dig_chain.rb +5 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
- data/lib/rubocop/cop/style/file_write.rb +21 -16
- data/lib/rubocop/cop/style/format_string.rb +4 -3
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +105 -11
- data/lib/rubocop/cop/style/parallel_assignment.rb +8 -1
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
- data/lib/rubocop/cop/style/redundant_format.rb +1 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
- data/lib/rubocop/cop/style/regexp_literal.rb +2 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +16 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
- data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
- data/lib/rubocop/cop/style/while_until_do.rb +7 -0
- data/lib/rubocop/cop/style/word_array.rb +1 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
- data/lib/rubocop/file_patterns.rb +9 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +14 -7
- data/lib/rubocop/options.rb +18 -0
- data/lib/rubocop/project_index_loader.rb +66 -0
- data/lib/rubocop/runner.rb +47 -3
- data/lib/rubocop/server/core.rb +6 -0
- data/lib/rubocop/version.rb +20 -2
- data/lib/rubocop.rb +1 -0
- metadata +5 -3
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
|
24
24
|
include FileFinder
|
|
25
25
|
|
|
26
26
|
attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
|
|
27
|
-
:ignore_unrecognized_cops
|
|
27
|
+
:enabled_by_default, :disabled_by_default, :ignore_unrecognized_cops
|
|
28
28
|
attr_writer :default_configuration, :cache_root
|
|
29
29
|
attr_reader :loaded_plugins, :loaded_features
|
|
30
30
|
|
|
@@ -41,6 +41,8 @@ module RuboCop
|
|
|
41
41
|
@loaded_features = Set.new
|
|
42
42
|
@disable_pending_cops = nil
|
|
43
43
|
@enable_pending_cops = nil
|
|
44
|
+
@enabled_by_default = nil
|
|
45
|
+
@disabled_by_default = nil
|
|
44
46
|
@ignore_parent_exclusion = nil
|
|
45
47
|
@ignore_unrecognized_cops = nil
|
|
46
48
|
@cache_root = nil
|
|
@@ -121,7 +123,7 @@ module RuboCop
|
|
|
121
123
|
end
|
|
122
124
|
|
|
123
125
|
def configuration_from_file(config_file, check: true)
|
|
124
|
-
return default_configuration if config_file == DEFAULT_FILE
|
|
126
|
+
return apply_default_overrides(default_configuration) if config_file == DEFAULT_FILE
|
|
125
127
|
|
|
126
128
|
config = load_file(config_file, check: check)
|
|
127
129
|
config.validate_after_resolution if check
|
|
@@ -190,6 +192,19 @@ module RuboCop
|
|
|
190
192
|
resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
|
|
191
193
|
end
|
|
192
194
|
|
|
195
|
+
# Applies CLI overrides for `AllCops/EnabledByDefault` and
|
|
196
|
+
# `AllCops/DisabledByDefault` to the given configuration. Used when the
|
|
197
|
+
# configuration would otherwise be returned without going through
|
|
198
|
+
# `merge_with_default` (e.g. there is no user-supplied `.rubocop.yml`).
|
|
199
|
+
def apply_default_overrides(config)
|
|
200
|
+
return config if @enabled_by_default.nil? && @disabled_by_default.nil?
|
|
201
|
+
|
|
202
|
+
hash = config.transform_values do |params|
|
|
203
|
+
params.is_a?(Hash) ? params.merge('Enabled' => !@disabled_by_default) : params
|
|
204
|
+
end
|
|
205
|
+
Config.new(hash, config.loaded_path)
|
|
206
|
+
end
|
|
207
|
+
|
|
193
208
|
# @api private
|
|
194
209
|
# Used to add plugins that were required inside a config or from
|
|
195
210
|
# the CLI using `--plugin`.
|
|
@@ -92,11 +92,11 @@ module RuboCop
|
|
|
92
92
|
# only cops from user configuration are enabled. If
|
|
93
93
|
# AllCops:EnabledByDefault is true, it changes the Enabled params so that
|
|
94
94
|
# only cops explicitly disabled in user configuration are disabled.
|
|
95
|
+
# When the `--disable-all-cops` or `--enable-all-cops` CLI option is given,
|
|
96
|
+
# it takes precedence over the configuration values.
|
|
95
97
|
def merge_with_default(config, config_file, unset_nil:)
|
|
96
98
|
default_configuration = ConfigLoader.default_configuration
|
|
97
|
-
|
|
98
|
-
disabled_by_default = config.for_all_cops['DisabledByDefault']
|
|
99
|
-
enabled_by_default = config.for_all_cops['EnabledByDefault']
|
|
99
|
+
disabled_by_default, enabled_by_default = resolve_default_overrides(config)
|
|
100
100
|
|
|
101
101
|
if disabled_by_default || enabled_by_default
|
|
102
102
|
default_configuration = transform(default_configuration) do |params|
|
|
@@ -169,6 +169,14 @@ module RuboCop
|
|
|
169
169
|
|
|
170
170
|
private
|
|
171
171
|
|
|
172
|
+
def resolve_default_overrides(config)
|
|
173
|
+
if ConfigLoader.disabled_by_default || ConfigLoader.enabled_by_default
|
|
174
|
+
[ConfigLoader.disabled_by_default, ConfigLoader.enabled_by_default]
|
|
175
|
+
else
|
|
176
|
+
[config.for_all_cops['DisabledByDefault'], config.for_all_cops['EnabledByDefault']]
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
172
180
|
def disabled?(hash, department)
|
|
173
181
|
hash[department].is_a?(Hash) && hash[department]['Enabled'] == false
|
|
174
182
|
end
|
data/lib/rubocop/config_store.rb
CHANGED
data/lib/rubocop/cop/base.rb
CHANGED
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
|
41
41
|
include AutocorrectLogic
|
|
42
42
|
|
|
43
43
|
attr_reader :config, :processed_source
|
|
44
|
+
attr_accessor :project_index
|
|
44
45
|
|
|
45
46
|
# Reports of an investigation.
|
|
46
47
|
# Immutable
|
|
@@ -306,7 +307,9 @@ module RuboCop
|
|
|
306
307
|
def ready
|
|
307
308
|
return self if self.class.support_multiple_source?
|
|
308
309
|
|
|
309
|
-
self.class.new(@config, @options)
|
|
310
|
+
self.class.new(@config, @options).tap do |fresh|
|
|
311
|
+
fresh.project_index = @project_index
|
|
312
|
+
end
|
|
310
313
|
end
|
|
311
314
|
|
|
312
315
|
### Reserved for Cop::Cop
|
|
@@ -416,7 +419,10 @@ module RuboCop
|
|
|
416
419
|
### Actually private methods
|
|
417
420
|
|
|
418
421
|
def reset_investigation
|
|
419
|
-
@currently_disabled_lines =
|
|
422
|
+
@currently_disabled_lines = nil
|
|
423
|
+
@current_offenses = nil
|
|
424
|
+
@processed_source = nil
|
|
425
|
+
@current_corrector = nil
|
|
420
426
|
end
|
|
421
427
|
|
|
422
428
|
# @return [Symbol, Corrector] offense status
|
|
@@ -492,8 +498,23 @@ module RuboCop
|
|
|
492
498
|
patterns = cop_config[parameter]
|
|
493
499
|
return default_result unless patterns
|
|
494
500
|
|
|
495
|
-
|
|
496
|
-
|
|
501
|
+
file_patterns = FilePatterns.from(patterns)
|
|
502
|
+
relative_file_path = config.path_relative_to_config(file)
|
|
503
|
+
return true if file_patterns.match?(relative_file_path)
|
|
504
|
+
|
|
505
|
+
if parameter == 'Include' && !relative_file_path.start_with?('..')
|
|
506
|
+
matches_absolute_include_pattern?(patterns, file)
|
|
507
|
+
else
|
|
508
|
+
file_patterns.match?(file)
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def matches_absolute_include_pattern?(patterns, file)
|
|
513
|
+
absolute_file_path = absolute?(file) ? file : File.expand_path(file)
|
|
514
|
+
patterns.any? do |pattern|
|
|
515
|
+
(absolute?(pattern.to_s) || pattern.to_s.start_with?('..')) &&
|
|
516
|
+
match_path?(pattern, absolute_file_path)
|
|
517
|
+
end
|
|
497
518
|
end
|
|
498
519
|
|
|
499
520
|
def enabled_line?(line_number)
|
|
@@ -128,8 +128,8 @@ module RuboCop
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
def ignored_gem?(node)
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
allowed_gems = Array(cop_config['AllowedGems'])
|
|
132
|
+
allowed_gems.include?(node.first_argument.value)
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
def checked_options_present?(node)
|
|
@@ -13,8 +13,7 @@ module RuboCop
|
|
|
13
13
|
buffer = node.source_range.source_buffer
|
|
14
14
|
corrector.remove(range_with_surrounding_space(range: node.loc.begin, buffer: buffer,
|
|
15
15
|
side: :right, whitespace: true))
|
|
16
|
-
corrector
|
|
17
|
-
side: :left))
|
|
16
|
+
remove_close_paren(corrector, node, buffer)
|
|
18
17
|
handle_orphaned_comma(corrector, node)
|
|
19
18
|
|
|
20
19
|
return unless ternary_condition?(node) && next_char_is_question_mark?(node)
|
|
@@ -24,6 +23,38 @@ module RuboCop
|
|
|
24
23
|
|
|
25
24
|
private
|
|
26
25
|
|
|
26
|
+
# When the line above `)` ends with a comment and a chained call follows `)`,
|
|
27
|
+
# crossing the newline would pull the chain into the comment. Preserve the newline.
|
|
28
|
+
def remove_close_paren(corrector, node, buffer)
|
|
29
|
+
newlines = !comment_above_close_paren_swallows_chain?(node, buffer)
|
|
30
|
+
corrector.remove(range_with_surrounding_space(range: node.loc.end, buffer: buffer,
|
|
31
|
+
side: :left, newlines: newlines))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def comment_above_close_paren_swallows_chain?(node, buffer)
|
|
35
|
+
last_child = node.children.last
|
|
36
|
+
return false unless last_child
|
|
37
|
+
|
|
38
|
+
body_end = last_child.source_range.end_pos
|
|
39
|
+
close_paren_begin = node.loc.end.begin_pos
|
|
40
|
+
return false if body_end >= close_paren_begin
|
|
41
|
+
|
|
42
|
+
source_between = buffer.source[body_end...close_paren_begin]
|
|
43
|
+
return false unless source_between.match?(/#[^\n]*\n/)
|
|
44
|
+
|
|
45
|
+
chained_after_close_paren?(node)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def chained_after_close_paren?(node)
|
|
49
|
+
close_paren = node.loc.end
|
|
50
|
+
line_text = close_paren.source_line
|
|
51
|
+
after_paren = line_text[(close_paren.column + 1)..]
|
|
52
|
+
return false if after_paren.nil?
|
|
53
|
+
|
|
54
|
+
trimmed = after_paren.lstrip
|
|
55
|
+
!trimmed.empty? && !trimmed.start_with?('#')
|
|
56
|
+
end
|
|
57
|
+
|
|
27
58
|
def ternary_condition?(node)
|
|
28
59
|
node.parent&.if_type? && node.parent.ternary?
|
|
29
60
|
end
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Gemspec
|
|
6
|
-
# An attribute assignment method
|
|
6
|
+
# An attribute assignment method call should be listed only once
|
|
7
7
|
# in a gemspec.
|
|
8
8
|
#
|
|
9
9
|
# Assigning to an attribute with the same name using `spec.foo =` or
|
|
10
10
|
# `spec.attribute#[]=` will be an unintended usage. On the other hand,
|
|
11
|
-
# duplication of methods such
|
|
11
|
+
# duplication of methods such as `spec.requirements`,
|
|
12
12
|
# `spec.add_runtime_dependency`, and others are permitted because it is
|
|
13
13
|
# the intended use of appending values.
|
|
14
14
|
#
|
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
|
6
6
|
# Requires a gemspec to have `rubygems_mfa_required` metadata set.
|
|
7
7
|
#
|
|
8
8
|
# This setting tells RubyGems that MFA (Multi-Factor Authentication) is
|
|
9
|
-
# required for accounts to be able perform privileged operations, such as
|
|
9
|
+
# required for accounts to be able to perform privileged operations, such as
|
|
10
10
|
# (see RubyGems' documentation for the full list of privileged
|
|
11
11
|
# operations):
|
|
12
12
|
#
|
|
@@ -4,10 +4,10 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Gemspec
|
|
6
6
|
# Checks that `RUBY_VERSION` and `Ruby::VERSION` constants are not used in gemspec.
|
|
7
|
-
# Using `RUBY_VERSION` and `Ruby::VERSION`
|
|
7
|
+
# Using `RUBY_VERSION` and `Ruby::VERSION` is dangerous because the value of the
|
|
8
8
|
# constant is determined by `rake release`.
|
|
9
|
-
# It's possible to have dependency based on
|
|
10
|
-
# to execute `rake release` and not user's
|
|
9
|
+
# It's possible to have a dependency based on the Ruby version used
|
|
10
|
+
# to execute `rake release` and not the user's Ruby version.
|
|
11
11
|
#
|
|
12
12
|
# @example
|
|
13
13
|
#
|
|
@@ -46,8 +46,7 @@ module RuboCop
|
|
|
46
46
|
|
|
47
47
|
def on_block(node)
|
|
48
48
|
return unless let_rubocop_config_new?(node)
|
|
49
|
-
|
|
50
|
-
describe = find_describe_method_node(node)
|
|
49
|
+
return unless (describe = find_describe_method_node(node))
|
|
51
50
|
|
|
52
51
|
unless (exist_config = describe.last_argument.source == ':config')
|
|
53
52
|
additional_message = ' and specify `:config` in `describe`'
|
|
@@ -65,7 +64,10 @@ module RuboCop
|
|
|
65
64
|
private
|
|
66
65
|
|
|
67
66
|
def find_describe_method_node(block_node)
|
|
68
|
-
block_node.ancestors.find
|
|
67
|
+
describe = block_node.ancestors.find do |ancestor|
|
|
68
|
+
ancestor.block_type? && ancestor.method?(:describe)
|
|
69
|
+
end
|
|
70
|
+
describe&.send_node
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
end
|
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
|
14
14
|
# `Layout/EndAlignment` cop aligns with keywords (e.g. `if`, `while`, `case`)
|
|
15
15
|
# by default. On the other hand, `||= begin` that this cop targets tends to
|
|
16
16
|
# align with the start of the line, it defaults to `EnforcedStyleAlignWith: start_of_line`.
|
|
17
|
-
# These
|
|
17
|
+
# These styles can be configured by each cop.
|
|
18
18
|
#
|
|
19
19
|
# @example EnforcedStyleAlignWith: start_of_line (default)
|
|
20
20
|
# # bad
|
|
@@ -18,6 +18,10 @@ module RuboCop
|
|
|
18
18
|
# `either` (which is the default) : the `end` is allowed to be in either
|
|
19
19
|
# location. The autocorrect will default to `start_of_line`.
|
|
20
20
|
#
|
|
21
|
+
# When the `do` or `{` appears on a continuation line of multiline
|
|
22
|
+
# method arguments, the start of the line where the method is called
|
|
23
|
+
# is used as the alignment target instead of that continuation line.
|
|
24
|
+
#
|
|
21
25
|
# @example EnforcedStyleAlignWith: either (default)
|
|
22
26
|
# # bad
|
|
23
27
|
#
|
|
@@ -116,6 +120,7 @@ module RuboCop
|
|
|
116
120
|
end_loc = block_node.loc.end
|
|
117
121
|
return unless begins_its_line?(end_loc)
|
|
118
122
|
|
|
123
|
+
start_node = start_for_line_node(block_node) if style == :start_of_line
|
|
119
124
|
start_loc = start_node.source_range
|
|
120
125
|
return unless start_loc.column != end_loc.column || style == :start_of_block
|
|
121
126
|
|
|
@@ -196,23 +201,34 @@ module RuboCop
|
|
|
196
201
|
|
|
197
202
|
def compute_do_source_line_column(node, end_loc)
|
|
198
203
|
do_loc = node.loc.begin # Actually it's either do or {.
|
|
204
|
+
anchor_loc = do_line_anchor_loc(node, do_loc)
|
|
199
205
|
|
|
200
206
|
# We've found that "end" is not aligned with the start node (which
|
|
201
207
|
# can be a block, a variable assignment, etc). But we also allow
|
|
202
208
|
# the "end" to be aligned with the start of the line where the "do"
|
|
203
209
|
# is, which is a style some people use in multi-line chains of
|
|
204
210
|
# blocks.
|
|
205
|
-
match = /\S.*/.match(
|
|
211
|
+
match = /\S.*/.match(anchor_loc.source_line)
|
|
206
212
|
indentation_of_do_line = match.begin(0)
|
|
207
|
-
|
|
213
|
+
permitted_columns = permitted_do_line_columns(do_loc, indentation_of_do_line)
|
|
214
|
+
return if permitted_columns.include?(end_loc.column) && style != :start_of_line
|
|
208
215
|
|
|
209
216
|
{
|
|
210
217
|
source: match[0],
|
|
211
|
-
line:
|
|
218
|
+
line: anchor_loc.line,
|
|
212
219
|
column: indentation_of_do_line
|
|
213
220
|
}
|
|
214
221
|
end
|
|
215
222
|
|
|
223
|
+
# `end` aligned with an argument continuation line that holds the `do`
|
|
224
|
+
# was accepted before the anchor moved to the method dispatch line;
|
|
225
|
+
# keep accepting it so that such code does not become an offense.
|
|
226
|
+
def permitted_do_line_columns(do_loc, indentation_of_do_line)
|
|
227
|
+
columns = [indentation_of_do_line]
|
|
228
|
+
columns << (do_loc.source_line =~ /\S/) if style == :either
|
|
229
|
+
columns
|
|
230
|
+
end
|
|
231
|
+
|
|
216
232
|
def loc_to_source_line_column(loc)
|
|
217
233
|
{
|
|
218
234
|
source: loc.source.lines.to_a.first.chomp,
|
|
@@ -239,7 +255,7 @@ module RuboCop
|
|
|
239
255
|
def compute_start_col(ancestor_node, node)
|
|
240
256
|
if style == :start_of_block
|
|
241
257
|
do_loc = node.loc.begin
|
|
242
|
-
return do_loc.source_line =~ /\S/
|
|
258
|
+
return do_line_anchor_loc(node, do_loc).source_line =~ /\S/
|
|
243
259
|
end
|
|
244
260
|
(ancestor_node || node).source_range.column
|
|
245
261
|
end
|
|
@@ -253,6 +269,27 @@ module RuboCop
|
|
|
253
269
|
|
|
254
270
|
corrector.remove(range)
|
|
255
271
|
end
|
|
272
|
+
|
|
273
|
+
# When the `do` or `{` is on a continuation line of multiline method
|
|
274
|
+
# arguments, the indentation of that line is not a meaningful
|
|
275
|
+
# alignment target; anchor on the method dispatch position instead.
|
|
276
|
+
def do_line_anchor_loc(node, do_loc)
|
|
277
|
+
if do_line_begins_inside_argument?(node, do_loc)
|
|
278
|
+
node.send_node.selector || node.send_node.source_range
|
|
279
|
+
else
|
|
280
|
+
do_loc
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def do_line_begins_inside_argument?(node, do_loc)
|
|
285
|
+
line_begin_pos = do_loc.begin_pos - do_loc.column
|
|
286
|
+
first_char_pos = line_begin_pos + (do_loc.source_line =~ /\S/)
|
|
287
|
+
|
|
288
|
+
(node.send_node.arguments + node.arguments).any? do |argument|
|
|
289
|
+
argument.source_range.begin_pos <= first_char_pos &&
|
|
290
|
+
first_char_pos < argument.source_range.end_pos
|
|
291
|
+
end
|
|
292
|
+
end
|
|
256
293
|
end
|
|
257
294
|
end
|
|
258
295
|
end
|
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
|
49
49
|
# - private_methods
|
|
50
50
|
# ----
|
|
51
51
|
#
|
|
52
|
-
# Instead of putting all literals in the expected order, is also
|
|
52
|
+
# Instead of putting all literals in the expected order, it is also
|
|
53
53
|
# possible to group categories of macros. Visibility levels are handled
|
|
54
54
|
# automatically.
|
|
55
55
|
#
|
|
@@ -5,8 +5,10 @@ module RuboCop
|
|
|
5
5
|
module Layout
|
|
6
6
|
# Enforces empty line after guard clause.
|
|
7
7
|
#
|
|
8
|
-
# This cop allows
|
|
9
|
-
# SimpleCov excludes code from the coverage report by wrapping it in
|
|
8
|
+
# This cop allows a SimpleCov directive comment after guard clause because
|
|
9
|
+
# SimpleCov excludes code from the coverage report by wrapping it in such directives.
|
|
10
|
+
# Both the legacy `# :nocov:` comment and the newer `# simplecov:disable` /
|
|
11
|
+
# `# simplecov:enable` comments are recognized:
|
|
10
12
|
#
|
|
11
13
|
# [source,ruby]
|
|
12
14
|
# ----
|
|
@@ -16,6 +18,13 @@ module RuboCop
|
|
|
16
18
|
# # :nocov:
|
|
17
19
|
# bar
|
|
18
20
|
# end
|
|
21
|
+
#
|
|
22
|
+
# def foo
|
|
23
|
+
# # simplecov:disable
|
|
24
|
+
# return if condition
|
|
25
|
+
# # simplecov:enable
|
|
26
|
+
# bar
|
|
27
|
+
# end
|
|
19
28
|
# ----
|
|
20
29
|
#
|
|
21
30
|
# Refer to SimpleCov's documentation for more details:
|
|
@@ -58,7 +67,7 @@ module RuboCop
|
|
|
58
67
|
|
|
59
68
|
MSG = 'Add empty line after guard clause.'
|
|
60
69
|
END_OF_HEREDOC_LINE = 1
|
|
61
|
-
|
|
70
|
+
SIMPLECOV_COMMENT_PATTERN = /\A#\s*(?::nocov:|simplecov\s*:\s*(?:disable|enable)\b)/.freeze
|
|
62
71
|
|
|
63
72
|
# @!method guard_clause_branch?(node)
|
|
64
73
|
def_node_matcher :guard_clause_branch?, <<~PATTERN
|
|
@@ -213,10 +222,10 @@ module RuboCop
|
|
|
213
222
|
parent.begin_type? && same_line?(node, node.right_sibling)
|
|
214
223
|
end
|
|
215
224
|
|
|
216
|
-
# SimpleCov excludes code from the coverage report by wrapping it in
|
|
225
|
+
# SimpleCov excludes code from the coverage report by wrapping it in directive comments:
|
|
217
226
|
# https://github.com/simplecov-ruby/simplecov#ignoringskipping-code
|
|
218
227
|
def simplecov_directive_comment?(comment)
|
|
219
|
-
|
|
228
|
+
SIMPLECOV_COMMENT_PATTERN.match?(comment.text)
|
|
220
229
|
end
|
|
221
230
|
end
|
|
222
231
|
end
|
|
@@ -19,10 +19,10 @@ module RuboCop
|
|
|
19
19
|
#
|
|
20
20
|
# This `Layout/EndAlignment` cop aligns with keywords (e.g. `if`, `while`, `case`)
|
|
21
21
|
# by default. On the other hand, `Layout/BeginEndAlignment` cop aligns with
|
|
22
|
-
# `EnforcedStyleAlignWith: start_of_line` by default
|
|
22
|
+
# `EnforcedStyleAlignWith: start_of_line` by default because `||= begin` tends
|
|
23
23
|
# to align with the start of the line. `Layout/DefEndAlignment` cop also aligns with
|
|
24
24
|
# `EnforcedStyleAlignWith: start_of_line` by default.
|
|
25
|
-
# These
|
|
25
|
+
# These styles can be configured by each cop.
|
|
26
26
|
#
|
|
27
27
|
# @example EnforcedStyleAlignWith: keyword (default)
|
|
28
28
|
# # bad
|
|
@@ -473,8 +473,12 @@ module RuboCop
|
|
|
473
473
|
end
|
|
474
474
|
|
|
475
475
|
def block_body_indentation_base(node, end_loc)
|
|
476
|
-
|
|
476
|
+
return end_loc unless style == :relative_to_receiver
|
|
477
|
+
|
|
478
|
+
if dot_on_new_line?(node)
|
|
477
479
|
node.send_node.loc.dot
|
|
480
|
+
elsif selector_on_new_line?(node)
|
|
481
|
+
node.send_node.loc.selector
|
|
478
482
|
else
|
|
479
483
|
end_loc
|
|
480
484
|
end
|
|
@@ -487,6 +491,14 @@ module RuboCop
|
|
|
487
491
|
receiver = send_node.receiver
|
|
488
492
|
receiver && receiver.last_line < send_node.loc.dot.line
|
|
489
493
|
end
|
|
494
|
+
|
|
495
|
+
def selector_on_new_line?(node)
|
|
496
|
+
send_node = node.send_node
|
|
497
|
+
return false unless send_node.loc?(:dot) && send_node.loc?(:selector)
|
|
498
|
+
|
|
499
|
+
receiver = send_node.receiver
|
|
500
|
+
receiver && receiver.last_line < send_node.loc.selector.line
|
|
501
|
+
end
|
|
490
502
|
end
|
|
491
503
|
end
|
|
492
504
|
end
|
|
@@ -114,7 +114,9 @@ module RuboCop
|
|
|
114
114
|
|
|
115
115
|
def other_cop_takes_precedence?(node)
|
|
116
116
|
single_line_block_chain_enabled? && any_descendant?(node, :any_block) do |block_node|
|
|
117
|
-
|
|
117
|
+
next unless (parent = block_node.parent)
|
|
118
|
+
|
|
119
|
+
parent.call_type? && parent.loc.dot && block_node.single_line?
|
|
118
120
|
end
|
|
119
121
|
end
|
|
120
122
|
|
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
|
28
28
|
MISTAKES = { '=-' => '-=', '=+' => '+=', '=*' => '*=', '=!' => '!=' }.freeze
|
|
29
29
|
|
|
30
30
|
def on_asgn(node)
|
|
31
|
-
return unless (rhs =
|
|
31
|
+
return unless (rhs = node.expression)
|
|
32
32
|
|
|
33
33
|
range = range_between(node.loc.operator.end_pos - 1, rhs.source_range.begin_pos + 1)
|
|
34
34
|
source = range.source
|
|
@@ -38,16 +38,6 @@ module RuboCop
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
SIMPLE_ASSIGNMENT_TYPES.each { |asgn_type| alias_method :"on_#{asgn_type}", :on_asgn }
|
|
41
|
-
|
|
42
|
-
private
|
|
43
|
-
|
|
44
|
-
def rhs(node)
|
|
45
|
-
if node.casgn_type?
|
|
46
|
-
node.children[2]
|
|
47
|
-
else
|
|
48
|
-
node.children[1]
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
41
|
end
|
|
52
42
|
end
|
|
53
43
|
end
|
|
@@ -44,13 +44,6 @@ module RuboCop
|
|
|
44
44
|
RESTRICT_ON_SEND = PRECEDENCE.flatten.freeze
|
|
45
45
|
MSG = 'Wrap expressions with varying precedence with parentheses to avoid ambiguity.'
|
|
46
46
|
|
|
47
|
-
def on_new_investigation
|
|
48
|
-
# Cache the precedence of each node being investigated
|
|
49
|
-
# so that we only need to calculate it once
|
|
50
|
-
@node_precedences = {}
|
|
51
|
-
super
|
|
52
|
-
end
|
|
53
|
-
|
|
54
47
|
def on_and(node)
|
|
55
48
|
return unless (parent = node.parent)
|
|
56
49
|
|
|
@@ -77,9 +70,7 @@ module RuboCop
|
|
|
77
70
|
private
|
|
78
71
|
|
|
79
72
|
def precedence(node)
|
|
80
|
-
|
|
81
|
-
PRECEDENCE.index { |operators| operators.include?(operator_name(node)) }
|
|
82
|
-
end
|
|
73
|
+
PRECEDENCE.index { |operators| operators.include?(operator_name(node)) }
|
|
83
74
|
end
|
|
84
75
|
|
|
85
76
|
def operator?(node)
|
|
@@ -80,7 +80,6 @@ module RuboCop
|
|
|
80
80
|
check_assignment_chain(arg_name, arg_value)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
# rubocop:disable Metrics/AbcSize
|
|
84
83
|
def check_assignment_chain(arg_name, node)
|
|
85
84
|
return unless node.lvasgn_type?
|
|
86
85
|
|
|
@@ -88,7 +87,7 @@ module RuboCop
|
|
|
88
87
|
current_node = node
|
|
89
88
|
|
|
90
89
|
while current_node.lvasgn_type?
|
|
91
|
-
seen_variables << current_node.children.first
|
|
90
|
+
seen_variables << current_node.children.first
|
|
92
91
|
current_node = current_node.children.last
|
|
93
92
|
end
|
|
94
93
|
|
|
@@ -99,7 +98,6 @@ module RuboCop
|
|
|
99
98
|
|
|
100
99
|
add_offense(current_node, message: format(MSG, arg_name: arg_name))
|
|
101
100
|
end
|
|
102
|
-
# rubocop:enable Metrics/AbcSize
|
|
103
101
|
end
|
|
104
102
|
end
|
|
105
103
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Checks for overwriting an exception with an exception result by
|
|
6
|
+
# Checks for overwriting an exception with an exception result by using ``rescue =>``.
|
|
7
7
|
#
|
|
8
8
|
# You intended to write as `rescue StandardError`.
|
|
9
9
|
# However, you have written `rescue => StandardError`.
|
|
@@ -12,8 +12,13 @@ module RuboCop
|
|
|
12
12
|
# class/module keyword definitions. It detects reassignment when a constant
|
|
13
13
|
# is first defined one way and then redefined using the `NAME = value` syntax.
|
|
14
14
|
#
|
|
15
|
-
# The cop cannot catch all offenses, like, for example, when
|
|
16
|
-
#
|
|
15
|
+
# The cop cannot catch all offenses, like, for example, when using metaprogramming
|
|
16
|
+
# (`Module#const_set`).
|
|
17
|
+
#
|
|
18
|
+
# By default the cop also cannot detect reassignment across files.
|
|
19
|
+
# When `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed,
|
|
20
|
+
# the cop additionally consults the project-wide index and reports reassignments
|
|
21
|
+
# whose previous definition lives in another file.
|
|
17
22
|
#
|
|
18
23
|
# The cop only takes into account constants assigned in a "simple" way: directly
|
|
19
24
|
# inside class/module definition, or within another constant. Other type of assignments
|
|
@@ -74,7 +79,10 @@ module RuboCop
|
|
|
74
79
|
# end
|
|
75
80
|
#
|
|
76
81
|
class ConstantReassignment < Base
|
|
82
|
+
include ProjectIndexHelp
|
|
83
|
+
|
|
77
84
|
MSG = 'Constant `%<constant>s` is already assigned in this namespace.'
|
|
85
|
+
CROSS_FILE_MSG = 'Constant `%<constant>s` is already assigned in `%<path>s`.'
|
|
78
86
|
|
|
79
87
|
RESTRICT_ON_SEND = %i[remove_const].freeze
|
|
80
88
|
|
|
@@ -101,9 +109,14 @@ module RuboCop
|
|
|
101
109
|
return unless simple_assignment?(node)
|
|
102
110
|
|
|
103
111
|
name = fully_qualified_constant_name(node)
|
|
104
|
-
return constant_definitions[name] = :casgn unless constant_definitions.key?(name)
|
|
105
112
|
|
|
106
|
-
|
|
113
|
+
if constant_definitions.key?(name)
|
|
114
|
+
add_offense(node, message: format(MSG, constant: constant_display_name(node)))
|
|
115
|
+
return
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
constant_definitions[name] = :casgn
|
|
119
|
+
report_cross_file_collision(node, name, constant_display_name(node))
|
|
107
120
|
end
|
|
108
121
|
|
|
109
122
|
def on_send(node)
|
|
@@ -192,6 +205,25 @@ module RuboCop
|
|
|
192
205
|
def constant_definitions
|
|
193
206
|
@constant_definitions ||= {}
|
|
194
207
|
end
|
|
208
|
+
|
|
209
|
+
def report_cross_file_collision(node, fully_qualified_name, display_name)
|
|
210
|
+
return unless project_index
|
|
211
|
+
return unless (declaration = project_index[fully_qualified_name.delete_prefix('::')])
|
|
212
|
+
return unless (prior = prior_definition_in_other_file(declaration))
|
|
213
|
+
|
|
214
|
+
msg = format(CROSS_FILE_MSG, constant: display_name, path: prior.location.to_file_path)
|
|
215
|
+
|
|
216
|
+
add_offense(node, message: msg)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def prior_definition_in_other_file(declaration)
|
|
220
|
+
current = processed_source.file_path
|
|
221
|
+
|
|
222
|
+
declaration.definitions.find do |definition|
|
|
223
|
+
other = definition.location.to_file_path
|
|
224
|
+
!File.identical?(other, current)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
195
227
|
end
|
|
196
228
|
end
|
|
197
229
|
end
|