rubocop 1.86.2 → 1.87.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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +7 -0
  3. data/lib/rubocop/cli.rb +2 -0
  4. data/lib/rubocop/config_loader.rb +17 -2
  5. data/lib/rubocop/config_loader_resolver.rb +11 -3
  6. data/lib/rubocop/config_store.rb +1 -1
  7. data/lib/rubocop/cop/base.rb +8 -2
  8. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
  9. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  10. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  11. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
  12. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  13. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  14. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +14 -5
  15. data/lib/rubocop/cop/layout/end_alignment.rb +2 -2
  16. data/lib/rubocop/cop/layout/indentation_width.rb +13 -1
  17. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
  18. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
  19. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  20. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  21. data/lib/rubocop/cop/lint/constant_reassignment.rb +36 -4
  22. data/lib/rubocop/cop/lint/constant_resolution.rb +5 -5
  23. data/lib/rubocop/cop/lint/deprecated_constants.rb +1 -1
  24. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  25. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  26. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  27. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  28. data/lib/rubocop/cop/lint/number_conversion.rb +5 -5
  29. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  30. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  31. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +2 -2
  32. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +3 -3
  33. data/lib/rubocop/cop/lint/require_relative_self_path.rb +1 -1
  34. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  35. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -1
  36. data/lib/rubocop/cop/lint/unreachable_code.rb +2 -2
  37. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
  38. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  39. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  40. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  41. data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
  42. data/lib/rubocop/cop/mixin.rb +1 -0
  43. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  44. data/lib/rubocop/cop/naming/predicate_method.rb +2 -2
  45. data/lib/rubocop/cop/naming/predicate_prefix.rb +1 -1
  46. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  47. data/lib/rubocop/cop/registry.rb +28 -6
  48. data/lib/rubocop/cop/security/io_methods.rb +1 -1
  49. data/lib/rubocop/cop/style/alias.rb +10 -1
  50. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  51. data/lib/rubocop/cop/style/class_and_module_children.rb +8 -0
  52. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
  53. data/lib/rubocop/cop/style/file_write.rb +18 -16
  54. data/lib/rubocop/cop/style/format_string.rb +4 -3
  55. data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
  56. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  57. data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
  58. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  59. data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
  60. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
  61. data/lib/rubocop/cop/style/regexp_literal.rb +2 -2
  62. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
  63. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  64. data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
  65. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
  66. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  67. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  68. data/lib/rubocop/file_patterns.rb +9 -1
  69. data/lib/rubocop/options.rb +18 -0
  70. data/lib/rubocop/project_index_loader.rb +66 -0
  71. data/lib/rubocop/runner.rb +47 -3
  72. data/lib/rubocop/version.rb +20 -2
  73. data/lib/rubocop.rb +1 -0
  74. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfb5d2d113d00eb380202a0e76f462318033838aa240febe88bd2861b1bf6609
4
- data.tar.gz: 9463407310a9babcc5869f9b1db0ca273ed036a3b440b5c27438cba855bee4ec
3
+ metadata.gz: 9386e7f8b3fc90e4096eb5436a4d35612586e27dd1ff46ba40e1051a7909fd52
4
+ data.tar.gz: 615ec2ec69759dce081efc1fddb8469a7ddf6a72223fea741368b501f333bce0
5
5
  SHA512:
6
- metadata.gz: 5084465b6aa455c8ecd75e8b8f1e52f92e966d64117d2d88ad343ca535eb6fdc02f05056e6f21ac86e2344ec52cc1db2d69f8bf14a76b76bdee86a2bd5971520
7
- data.tar.gz: 2101bc8bb5b392fa971f9a881e96b03321442b5067b4952413d806363bb89389cb2631671bfa6af0e30203800cff947d587ac0c68ef1651fdec455cc453faa18
6
+ metadata.gz: c07cb70ee9d4c997a85c079361624d43574b78e6c364e8d0ff939b4d826c19b0e1ef2aad9569aea4f2f247b9b792ae9b21a776f69161da1c9a193e2f3de74d40
7
+ data.tar.gz: f6b44267bdfeba1237e06af52009143f13a7c0419a5ccaddf47dc9701c328f2b2ef6d87811ae5c8f05ece533ca236425e599c77a5a283ba44c641de09fc1b7e6
data/config/default.yml CHANGED
@@ -104,6 +104,12 @@ AllCops:
104
104
  # When `NewCops` is `disable`, pending cops are disabled in bulk. Can be overridden by
105
105
  # the `--disable-pending-cops` command-line option.
106
106
  NewCops: pending
107
+ # When `true`, RuboCop builds a project index (a project-wide map of declarations and references)
108
+ # once per run and makes it available to cops that opt in.
109
+ # The project index is implemented by the optional `rubydex` gem; when `rubydex` is not installed,
110
+ # a warning is shown and the flag has no effect.
111
+ # The default `false` preserves RuboCop's traditional file-local analysis.
112
+ UseProjectIndex: false
107
113
  # Enables the result cache if `true`. Can be overridden by the `--cache` command
108
114
  # line option.
109
115
  UseCache: true
@@ -1703,6 +1709,7 @@ Lint/ConstantReassignment:
1703
1709
  Description: 'Checks for constant reassignments.'
1704
1710
  Enabled: pending
1705
1711
  VersionAdded: '1.70'
1712
+ VersionChanged: '1.87'
1706
1713
 
1707
1714
  Lint/ConstantResolution:
1708
1715
  Description: 'Checks that constants are fully qualified with `::`.'
data/lib/rubocop/cli.rb CHANGED
@@ -189,6 +189,8 @@ module RuboCop
189
189
  ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
190
190
  ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
191
191
  ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
192
+ ConfigLoader.enabled_by_default = @options[:enable_all_cops]
193
+ ConfigLoader.disabled_by_default = @options[:disable_all_cops]
192
194
  end
193
195
 
194
196
  def set_options_to_pending_cops_reporter
@@ -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
@@ -36,7 +36,7 @@ module RuboCop
36
36
  end
37
37
 
38
38
  def force_default_config!
39
- @options_config = ConfigLoader.default_configuration
39
+ @options_config = ConfigLoader.apply_default_overrides(ConfigLoader.default_configuration)
40
40
  end
41
41
 
42
42
  def unvalidated
@@ -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 = @current_offenses = @processed_source = @current_corrector = nil
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
@@ -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.remove(range_with_surrounding_space(range: node.loc.end, buffer: buffer,
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 calls should be listed only once
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 # as `spec.requirements`,
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` are dangerous because value of the
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 ruby version used
10
- # to execute `rake release` and not user's ruby version.
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
  #
@@ -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 style can be configured by each cop.
17
+ # These styles can be configured by each cop.
18
18
  #
19
19
  # @example EnforcedStyleAlignWith: start_of_line (default)
20
20
  # # bad
@@ -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 `# :nocov:` directive after guard clause because
9
- # SimpleCov excludes code from the coverage report by wrapping it in `# :nocov:`:
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
- SIMPLE_DIRECTIVE_COMMENT_PATTERN = /\A# *:nocov:\z/.freeze
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 `# :nocov:`:
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
- SIMPLE_DIRECTIVE_COMMENT_PATTERN.match?(comment.text)
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 due to `||= begin` tends
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 style can be configured by each cop.
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
- if style == :relative_to_receiver && dot_on_new_line?(node)
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
- block_node.parent.send_type? && block_node.parent.loc.dot && block_node.single_line?
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
 
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Layout
6
6
  # Checks for space between the name of a receiver and a left
7
- # brackets.
7
+ # bracket.
8
8
  #
9
9
  # @example
10
10
  #
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # when param passed without parentheses.
8
8
  #
9
9
  # This cop can customize allowed methods with `AllowedMethods`.
10
- # By default, there are no methods to allowed.
10
+ # By default, there are no allowed methods.
11
11
  #
12
12
  # @example
13
13
  #
@@ -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 use ``rescue =>``.
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 a constant
16
- # is reassigned in another file, or when using metaprogramming (`Module#const_set`).
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
- add_offense(node, message: format(MSG, constant: constant_display_name(node)))
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
@@ -13,12 +13,12 @@ module RuboCop
13
13
  #
14
14
  # Large projects will over time end up with one or two constant names that
15
15
  # are problematic because of a conflict with a library or just internally
16
- # using the same name a namespace and a class. To avoid too many unnecessary
17
- # offenses, Enable this cop with `Only: [The, Constant, Names, Causing, Issues]`
16
+ # using the same name for a namespace and a class. To avoid too many unnecessary
17
+ # offenses, enable this cop with `Only: [The, Constant, Names, Causing, Issues]`
18
18
  #
19
- # NOTE: `Style/RedundantConstantBase` cop is disabled if this cop is enabled to prevent
20
- # conflicting rules. Because it respects user configurations that want to enable
21
- # this cop which is disabled by default.
19
+ # NOTE: `Style/RedundantConstantBase` cop is disabled if this cop is enabled,
20
+ # to prevent conflicting rules. This is because it respects user configurations
21
+ # that want to enable this cop which is disabled by default.
22
22
  #
23
23
  # @example
24
24
  # # By default checks every constant
@@ -14,7 +14,7 @@ module RuboCop
14
14
  # Alternative: 'alternative_value'
15
15
  # DeprecatedVersion: 'deprecated_version'
16
16
  #
17
- # By default, `NIL`, `TRUE`, `FALSE`, `Net::HTTPServerException, `Random::DEFAULT`,
17
+ # By default, `NIL`, `TRUE`, `FALSE`, `Net::HTTPServerException`, `Random::DEFAULT`,
18
18
  # `Struct::Group`, and `Struct::Passwd` are configured.
19
19
  #
20
20
  # @example
@@ -23,7 +23,7 @@ module RuboCop
23
23
  # `ERB.new` with non-keyword arguments is deprecated since ERB 2.2.0.
24
24
  # Use `:trim_mode` and `:eoutvar` keyword arguments to `ERB.new`.
25
25
  # This cop identifies places where `ERB.new(str, trim_mode, eoutvar)` can
26
- # be replaced by `ERB.new(str, :trim_mode: trim_mode, eoutvar: eoutvar)`.
26
+ # be replaced by `ERB.new(str, trim_mode: trim_mode, eoutvar: eoutvar)`.
27
27
  #
28
28
  # @example
29
29
  # # Target codes supports Ruby 2.6 and higher only
@@ -6,7 +6,7 @@ module RuboCop
6
6
  module Lint
7
7
  # Checks that there is an `# rubocop:enable ...` statement
8
8
  # after a `# rubocop:disable ...` statement. This will prevent leaving
9
- # cop disables on wide ranges of code, that latter contributors to
9
+ # cop disables on wide ranges of code, that later contributors to
10
10
  # a file wouldn't be aware of.
11
11
  #
12
12
  # You can set `MaximumRangeSize` to define the maximum number of
@@ -4,8 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Lint
6
6
  # In math and Python, we can use `x < y < z` style comparison to compare
7
- # multiple value. However, we can't use the comparison in Ruby. However,
8
- # the comparison is not syntax error. This cop checks the bad usage of
7
+ # multiple values. However, we can't use the comparison in Ruby. However,
8
+ # the comparison is not a syntax error. This cop checks the bad usage of
9
9
  # comparison operators.
10
10
  #
11
11
  # @example
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # always sort the list.
13
13
  #
14
14
  # `Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
15
- # So all bad cases are acceptable when Ruby 3.0 or higher are used.
15
+ # So all bad cases are acceptable when Ruby 3.0 or higher is used.
16
16
  #
17
17
  # NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
18
18
  #
@@ -3,9 +3,9 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Warns the usage of unsafe number conversions. Unsafe
7
- # number conversion can cause unexpected error if auto type conversion
8
- # fails. Cop prefer parsing with number class instead.
6
+ # Warns against the usage of unsafe number conversions. Unsafe
7
+ # number conversion can cause an unexpected error if auto type conversion
8
+ # fails. The cop prefers parsing with a number class instead.
9
9
  #
10
10
  # Conversion with `Integer`, `Float`, etc. will raise an `ArgumentError`
11
11
  # if given input that is not numeric (eg. an empty string), whereas
@@ -14,10 +14,10 @@ module RuboCop
14
14
  # always correct to raise if a value is not numeric.
15
15
  #
16
16
  # NOTE: Some values cannot be converted properly using one of the `Kernel`
17
- # method (for instance, `Time` and `DateTime` values are allowed by this
17
+ # methods (for instance, `Time` and `DateTime` values are allowed by this
18
18
  # cop by default). Similarly, Rails' duration methods do not work well
19
19
  # with `Integer()` and can be allowed with `AllowedMethods`. By default,
20
- # there are no methods to allowed.
20
+ # there are no allowed methods.
21
21
  #
22
22
  # @safety
23
23
  # Autocorrection is unsafe because it is not guaranteed that the
@@ -16,7 +16,7 @@ module RuboCop
16
16
  # ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
17
17
  # -e:1: _1 is reserved for numbered parameter
18
18
  #
19
- # NOTE: The parametered parameters are from `_1` to `_9`. This cop checks `_0`, and over `_10`
19
+ # NOTE: The numbered parameters are from `_1` to `_9`. This cop checks `_0`, and over `_10`
20
20
  # as well to prevent confusion.
21
21
  #
22
22
  # @example
@@ -63,7 +63,7 @@ module RuboCop
63
63
  end
64
64
 
65
65
  def spaces_before_left_parenthesis(node)
66
- return 0 if node.parenthesized?
66
+ return 0 if node.parenthesized? || !node.first_argument.source.start_with?('(')
67
67
 
68
68
  node.first_argument.source_range.begin_pos - node.loc.selector.end_pos
69
69
  end
@@ -6,8 +6,8 @@ module RuboCop
6
6
  # Detects instances of rubocop:enable comments that can be
7
7
  # removed.
8
8
  #
9
- # When comment enables all cops at once `rubocop:enable all`
10
- # that cop checks whether any cop was actually enabled.
9
+ # When a comment enables all cops at once `rubocop:enable all`
10
+ # the cop checks whether any cop was actually enabled.
11
11
  #
12
12
  # @example
13
13
  #
@@ -17,14 +17,14 @@ module RuboCop
17
17
  # or with `String.new` or `String()`.
18
18
  # * `to_sym` when called on a symbol literal or interpolated symbol.
19
19
  # * `to_i` when called on an integer literal or with `Integer()`.
20
- # * `to_f` when called on a float literal of with `Float()`.
20
+ # * `to_f` when called on a float literal or with `Float()`.
21
21
  # * `to_r` when called on a rational literal or with `Rational()`.
22
- # * `to_c` when called on a complex literal of with `Complex()`.
22
+ # * `to_c` when called on a complex literal or with `Complex()`.
23
23
  # * `to_a` when called on an array literal, or with `Array.new`, `Array()` or `Array[]`.
24
24
  # * `to_h` when called on a hash literal, or with `Hash.new`, `Hash()` or `Hash[]`.
25
25
  # * `to_set` when called on `Set.new` or `Set[]`.
26
26
  #
27
- # In all cases, chaining one same `to_*` conversion methods listed above is redundant.
27
+ # In all cases, chaining one of the same `to_*` conversion methods listed above is redundant.
28
28
  #
29
29
  # The cop can also register an offense for chaining conversion methods on methods that are
30
30
  # expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for uses a file requiring itself with `require_relative`.
6
+ # Checks for a file requiring itself with `require_relative`.
7
7
  #
8
8
  # @example
9
9
  #
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for a rescued exception that get shadowed by a
6
+ # Checks for a rescued exception that gets shadowed by a
7
7
  # less specific exception being rescued before a more specific
8
8
  # exception is rescued.
9
9
  #