rubocop 1.76.2 → 1.78.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +23 -1
  4. data/lib/rubocop/cli.rb +12 -1
  5. data/lib/rubocop/config_loader.rb +1 -38
  6. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
  7. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  8. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +0 -22
  9. data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
  10. data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
  11. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
  12. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  13. data/lib/rubocop/cop/layout/line_length.rb +26 -5
  14. data/lib/rubocop/cop/layout/space_before_brackets.rb +2 -9
  15. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -2
  16. data/lib/rubocop/cop/lint/duplicate_methods.rb +25 -4
  17. data/lib/rubocop/cop/lint/float_comparison.rb +4 -4
  18. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -3
  19. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  20. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +4 -4
  21. data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
  22. data/lib/rubocop/cop/lint/useless_access_modifier.rb +8 -0
  23. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
  24. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  25. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  26. data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
  27. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  28. data/lib/rubocop/cop/naming/method_name.rb +87 -12
  29. data/lib/rubocop/cop/naming/predicate_method.rb +64 -6
  30. data/lib/rubocop/cop/naming/predicate_prefix.rb +2 -2
  31. data/lib/rubocop/cop/security/eval.rb +2 -1
  32. data/lib/rubocop/cop/security/open.rb +1 -0
  33. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  34. data/lib/rubocop/cop/style/collection_querying.rb +167 -0
  35. data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
  36. data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
  37. data/lib/rubocop/cop/style/hash_conversion.rb +16 -8
  38. data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -2
  39. data/lib/rubocop/cop/style/it_block_parameter.rb +1 -1
  40. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  41. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +16 -0
  42. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
  43. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  44. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -1
  45. data/lib/rubocop/cop/style/redundant_self.rb +3 -0
  46. data/lib/rubocop/cop/style/single_line_methods.rb +4 -1
  47. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -1
  48. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  49. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  50. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  51. data/lib/rubocop/lsp/diagnostic.rb +4 -4
  52. data/lib/rubocop/pending_cops_reporter.rb +56 -0
  53. data/lib/rubocop/server/cache.rb +4 -2
  54. data/lib/rubocop/server/client_command/base.rb +10 -0
  55. data/lib/rubocop/server/client_command/exec.rb +2 -1
  56. data/lib/rubocop/server/client_command/start.rb +11 -1
  57. data/lib/rubocop/version.rb +1 -1
  58. data/lib/rubocop.rb +3 -0
  59. data/lib/ruby_lsp/rubocop/addon.rb +2 -2
  60. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c98c6b67493a9eeb135c1e86846e068746676cd7caba305df7343f6da5a9307
4
- data.tar.gz: a5e75c620016505e918bc98e273a729f14388b6c3cf95358c4975d785ca7fa57
3
+ metadata.gz: 5b840814034fbb98e67e3bb60014f0f00f9387148ab85b8b66f3a7ca711efdd2
4
+ data.tar.gz: b223e62eeeef5effd425654bf869ea22935beb8955df6e6fb22f0ba2a623d0f3
5
5
  SHA512:
6
- metadata.gz: '08701aa9d2fa3f7a1cf2b950b8bdf8640c47965345c3572645dd04f73507142ebf08aa16d5e7ab829a9e74330d45b4280ef700a7974eb02d7cf29e5890f67bb8'
7
- data.tar.gz: 8d0f787edacfee68d6e6bc13db5c9f2247f137c3074fec0af47dae1b6b0b51403e9d071d1a40a81529271d35d1954a5848e16c489ebb175c9b2a24a4c1192a48
6
+ metadata.gz: 83f46c7462c956b9a37e61feb329b3dfdb96e631cab64ffa3d1485bdc2d36a3585dacc17fc0b546ca98a0ad1014e1818eabf328a367654ad0151eaea3eea7369
7
+ data.tar.gz: d7cd91419c2ff881ef14b5f4406c9b87e555d2948c2c20b98bf02e6007e44b3d20b0aa73f3b91a595c5613164e551ba5f728e0852d084d04fe37312a65fa2b96
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.76', require: false
56
+ gem 'rubocop', '~> 1.78', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -281,6 +281,13 @@ Gemspec/AddRuntimeDependency:
281
281
  Include:
282
282
  - '**/*.gemspec'
283
283
 
284
+ Gemspec/AttributeAssignment:
285
+ Description: 'Use consistent style for Gemspec attributes assignment.'
286
+ Enabled: pending
287
+ VersionAdded: '1.77'
288
+ Include:
289
+ - '**/*.gemspec'
290
+
284
291
  Gemspec/DependencyVersion:
285
292
  Description: 'Requires or forbids specifying gem dependency versions.'
286
293
  Enabled: false
@@ -1095,6 +1102,7 @@ Layout/LineLength:
1095
1102
  # To make it possible to copy or click on URIs in the code, we allow lines
1096
1103
  # containing a URI to be longer than Max.
1097
1104
  AllowURI: true
1105
+ AllowQualifiedName: true
1098
1106
  URISchemes:
1099
1107
  - http
1100
1108
  - https
@@ -2400,6 +2408,7 @@ Lint/SelfAssignment:
2400
2408
  Description: 'Checks for self-assignments.'
2401
2409
  Enabled: true
2402
2410
  VersionAdded: '0.89'
2411
+ AllowRBSInlineAnnotation: false
2403
2412
 
2404
2413
  Lint/SendWithMixinArgument:
2405
2414
  Description: 'Checks for `send` method when using mixin.'
@@ -3063,7 +3072,7 @@ Naming/PredicateMethod:
3063
3072
  Description: 'Checks that predicate methods end with `?` and non-predicate methods do not.'
3064
3073
  Enabled: pending
3065
3074
  VersionAdded: '1.76'
3066
- VersionChanged: '1.76'
3075
+ VersionChanged: '1.78'
3067
3076
  # In `aggressive` mode, the cop will register an offense for predicate methods that
3068
3077
  # may return a non-boolean value.
3069
3078
  # In `conservative` mode, the cop will *not* register an offense for predicate methods
@@ -3073,6 +3082,9 @@ Naming/PredicateMethod:
3073
3082
  - call
3074
3083
  AllowedPatterns: []
3075
3084
  AllowBangMethods: false
3085
+ # Methods that are known to not return a boolean value, despite ending in `?`.
3086
+ WaywardPredicates:
3087
+ - nonzero?
3076
3088
 
3077
3089
  Naming/PredicatePrefix:
3078
3090
  Description: 'Predicate method names should not be prefixed and end with a `?`.'
@@ -3660,6 +3672,13 @@ Style/CollectionMethods:
3660
3672
  - inject
3661
3673
  - reduce
3662
3674
 
3675
+ Style/CollectionQuerying:
3676
+ Description: 'Prefer `Enumerable` predicate methods over expressions with `count`.'
3677
+ StyleGuide: '#collection-querying'
3678
+ Enabled: pending
3679
+ VersionAdded: '1.77'
3680
+ Safe: false
3681
+
3663
3682
  Style/ColonMethodCall:
3664
3683
  Description: 'Do not use :: for method call.'
3665
3684
  StyleGuide: '#double-colons'
@@ -4061,6 +4080,9 @@ Style/FetchEnvVar:
4061
4080
  VersionAdded: '1.28'
4062
4081
  # Environment variables to be excluded from the inspection.
4063
4082
  AllowedVars: []
4083
+ # When `true`, autocorrects `ENV["key"]` to `ENV.fetch("key", nil)`.
4084
+ # When `false`, autocorrects `ENV["key"]` to `ENV.fetch("key")`.
4085
+ DefaultToNil: true
4064
4086
 
4065
4087
  Style/FileEmpty:
4066
4088
  Description: >-
data/lib/rubocop/cli.rb CHANGED
@@ -12,7 +12,7 @@ module RuboCop
12
12
  STATUS_INTERRUPTED = Signal.list['INT'] + 128
13
13
  DEFAULT_PARALLEL_OPTIONS = %i[
14
14
  color config debug display_style_guide display_time display_only_fail_level_offenses
15
- display_only_failed editor_mode except extra_details fail_level fix_layout format
15
+ display_only_failed editor_mode except extra_details fail_level fix_layout format formatters
16
16
  ignore_disable_comments lint only only_guide_cops require safe
17
17
  autocorrect safe_autocorrect autocorrect_all
18
18
  ].freeze
@@ -48,6 +48,7 @@ module RuboCop
48
48
  validate_options_vs_config
49
49
  parallel_by_default!
50
50
  apply_default_formatter
51
+ report_pending_cops
51
52
  execute_runners
52
53
  end
53
54
  end
@@ -155,6 +156,7 @@ module RuboCop
155
156
 
156
157
  def act_on_options
157
158
  set_options_to_config_loader
159
+ set_options_to_pending_cops_reporter
158
160
  handle_editor_mode
159
161
 
160
162
  @config_store.options_config = @options[:config] if @options[:config]
@@ -179,6 +181,11 @@ module RuboCop
179
181
  ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
180
182
  end
181
183
 
184
+ def set_options_to_pending_cops_reporter
185
+ PendingCopsReporter.disable_pending_cops = @options[:disable_pending_cops]
186
+ PendingCopsReporter.enable_pending_cops = @options[:enable_pending_cops]
187
+ end
188
+
182
189
  def handle_editor_mode
183
190
  RuboCop::LSP.enable if @options[:editor_mode]
184
191
  end
@@ -208,5 +215,9 @@ module RuboCop
208
215
  [[formatter, @options[:output_path]]]
209
216
  end
210
217
  end
218
+
219
+ def report_pending_cops
220
+ PendingCopsReporter.warn_if_needed(@config_store.for_pwd)
221
+ end
211
222
  end
212
223
  end
@@ -22,14 +22,6 @@ module RuboCop
22
22
  class << self
23
23
  include FileFinder
24
24
 
25
- PENDING_BANNER = <<~BANNER
26
- The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
27
-
28
- Please also note that you can opt-in to new cops by default by adding this to your config:
29
- AllCops:
30
- NewCops: enable
31
- BANNER
32
-
33
25
  attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
34
26
  :ignore_unrecognized_cops
35
27
  attr_writer :default_configuration
@@ -132,21 +124,7 @@ module RuboCop
132
124
  add_excludes_from_files(config, config_file)
133
125
  end
134
126
 
135
- merge_with_default(config, config_file).tap do |merged_config|
136
- unless possible_new_cops?(merged_config)
137
- pending_cops = pending_cops_only_qualified(merged_config.pending_cops)
138
- warn_on_pending_cops(pending_cops) unless pending_cops.empty?
139
- end
140
- end
141
- end
142
-
143
- def pending_cops_only_qualified(pending_cops)
144
- pending_cops.select { |cop| Cop::Registry.qualified_cop?(cop.name) }
145
- end
146
-
147
- def possible_new_cops?(config)
148
- disable_pending_cops || enable_pending_cops ||
149
- config.disabled_new_cops? || config.enabled_new_cops?
127
+ merge_with_default(config, config_file)
150
128
  end
151
129
 
152
130
  def add_excludes_from_files(config, config_file)
@@ -208,21 +186,6 @@ module RuboCop
208
186
  ConfigFinder.project_root
209
187
  end
210
188
 
211
- def warn_on_pending_cops(pending_cops)
212
- warn Rainbow(PENDING_BANNER).yellow
213
-
214
- pending_cops.each { |cop| warn_pending_cop cop }
215
-
216
- warn Rainbow('For more information: https://docs.rubocop.org/rubocop/versioning.html').yellow
217
- end
218
-
219
- def warn_pending_cop(cop)
220
- version = cop.metadata['VersionAdded'] || 'N/A'
221
-
222
- warn Rainbow("#{cop.name}: # new in #{version}").yellow
223
- warn Rainbow(' Enabled: true').yellow
224
- end
225
-
226
189
  # Merges the given configuration with the default one.
227
190
  def merge_with_default(config, config_file, unset_nil: true)
228
191
  resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
@@ -10,8 +10,11 @@ module RuboCop
10
10
  COMMA_REGEXP = /(?<=\))\s*,/.freeze
11
11
 
12
12
  def correct(corrector, node)
13
- corrector.remove(node.loc.begin)
14
- corrector.remove(node.loc.end)
13
+ buffer = node.source_range.source_buffer
14
+ corrector.remove(range_with_surrounding_space(range: node.loc.begin, buffer: buffer,
15
+ side: :right, whitespace: true))
16
+ corrector.remove(range_with_surrounding_space(range: node.loc.end, buffer: buffer,
17
+ side: :left))
15
18
  handle_orphaned_comma(corrector, node)
16
19
 
17
20
  return unless ternary_condition?(node) && next_char_is_question_mark?(node)
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Gemspec
6
+ # Use consistent style for Gemspec attributes assignment.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # # This example uses two styles for assignment of metadata attribute.
12
+ # Gem::Specification.new do |spec|
13
+ # spec.metadata = { 'key' => 'value' }
14
+ # spec.metadata['another-key'] = 'another-value'
15
+ # end
16
+ #
17
+ # # good
18
+ # Gem::Specification.new do |spec|
19
+ # spec.metadata['key'] = 'value'
20
+ # spec.metadata['another-key'] = 'another-value'
21
+ # end
22
+ #
23
+ # # good
24
+ # Gem::Specification.new do |spec|
25
+ # spec.metadata = { 'key' => 'value', 'another-key' => 'another-value' }
26
+ # end
27
+ #
28
+ # # bad
29
+ # # This example uses two styles for assignment of authors attribute.
30
+ # Gem::Specification.new do |spec|
31
+ # spec.authors = %w[author-0 author-1]
32
+ # spec.authors[2] = 'author-2'
33
+ # end
34
+ #
35
+ # # good
36
+ # Gem::Specification.new do |spec|
37
+ # spec.authors = %w[author-0 author-1 author-2]
38
+ # end
39
+ #
40
+ # # good
41
+ # Gem::Specification.new do |spec|
42
+ # spec.authors[0] = 'author-0'
43
+ # spec.authors[1] = 'author-1'
44
+ # spec.authors[2] = 'author-2'
45
+ # end
46
+ #
47
+ # # good
48
+ # # This example uses consistent assignment per attribute,
49
+ # # even though two different styles are used overall.
50
+ # Gem::Specification.new do |spec|
51
+ # spec.metadata = { 'key' => 'value' }
52
+ # spec.authors[0] = 'author-0'
53
+ # spec.authors[1] = 'author-1'
54
+ # spec.authors[2] = 'author-2'
55
+ # end
56
+ #
57
+ class AttributeAssignment < Base
58
+ include GemspecHelp
59
+
60
+ MSG = 'Use consistent style for Gemspec attributes assignment.'
61
+
62
+ def on_new_investigation
63
+ return if processed_source.blank?
64
+
65
+ assignments = source_assignments(processed_source.ast)
66
+ indexed_assignments = source_indexed_assignments(processed_source.ast)
67
+
68
+ assignments.keys.intersection(indexed_assignments.keys).each do |attribute|
69
+ indexed_assignments[attribute].each do |node|
70
+ add_offense(node)
71
+ end
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def source_assignments(ast)
78
+ assignment_method_declarations(ast)
79
+ .select(&:assignment_method?)
80
+ .group_by(&:method_name)
81
+ .transform_keys { |method_name| method_name.to_s.delete_suffix('=').to_sym }
82
+ end
83
+
84
+ def source_indexed_assignments(ast)
85
+ indexed_assignment_method_declarations(ast)
86
+ .group_by { |node| node.children.first.method_name }
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -54,22 +54,6 @@ module RuboCop
54
54
  MSG = '`%<assignment>s` method calls already given on line ' \
55
55
  '%<line_of_first_occurrence>d of the gemspec.'
56
56
 
57
- # @!method assignment_method_declarations(node)
58
- def_node_search :assignment_method_declarations, <<~PATTERN
59
- (send
60
- (lvar {#match_block_variable_name? :_1 :it}) _ ...)
61
- PATTERN
62
-
63
- # @!method indexed_assignment_method_declarations(node)
64
- def_node_search :indexed_assignment_method_declarations, <<~PATTERN
65
- (send
66
- (send (lvar {#match_block_variable_name? :_1 :it}) _)
67
- :[]=
68
- literal?
69
- _
70
- )
71
- PATTERN
72
-
73
57
  def on_new_investigation
74
58
  return if processed_source.blank?
75
59
 
@@ -96,12 +80,6 @@ module RuboCop
96
80
  end
97
81
  end
98
82
 
99
- def match_block_variable_name?(receiver_name)
100
- gem_specification(processed_source.ast) do |block_variable_name|
101
- return block_variable_name == receiver_name
102
- end
103
- end
104
-
105
83
  def duplicated_assignment_method_nodes
106
84
  assignment_method_declarations(processed_source.ast)
107
85
  .select(&:assignment_method?)
@@ -74,6 +74,14 @@ module RuboCop
74
74
  }
75
75
  PATTERN
76
76
 
77
+ # @!method metadata_assignment(node)
78
+ def_node_search :metadata_assignment, <<~PATTERN
79
+ `{
80
+ (send _ :metadata= _)
81
+ (send (send _ :metadata) :[]= (str _) _)
82
+ }
83
+ PATTERN
84
+
77
85
  # @!method rubygems_mfa_required(node)
78
86
  def_node_search :rubygems_mfa_required, <<~PATTERN
79
87
  (pair (str "rubygems_mfa_required") $_)
@@ -131,9 +139,15 @@ module RuboCop
131
139
  end
132
140
 
133
141
  def insert_mfa_required(corrector, node, block_var)
134
- corrector.insert_before(node.loc.end, <<~RUBY)
142
+ require_mfa_directive = <<~RUBY.strip
135
143
  #{block_var}.metadata['rubygems_mfa_required'] = 'true'
136
144
  RUBY
145
+
146
+ if (last_assignment = metadata_assignment(processed_source.ast).to_a.last)
147
+ corrector.insert_after(last_assignment, "\n#{require_mfa_directive}")
148
+ else
149
+ corrector.insert_before(node.loc.end, "#{require_mfa_directive}\n")
150
+ end
137
151
  end
138
152
 
139
153
  def change_value(corrector, value)
@@ -46,7 +46,7 @@ module RuboCop
46
46
  /\A(does not|doesn't) (register|find|flag|report)/ => 'registers',
47
47
  /\A(does not|doesn't) add (a|an|any )?offense/ => 'registers an offense',
48
48
  /\Aregisters no offense/ => 'registers an offense',
49
- /\A(accepts|register)\b/ => 'registers'
49
+ /\A(accepts|allows|register)\b/ => 'registers'
50
50
  }.freeze
51
51
 
52
52
  EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
@@ -110,8 +110,8 @@ module RuboCop
110
110
  def directive_offense_type(directive, actual_name)
111
111
  return :missing_directive unless directive
112
112
 
113
- return :wrong_scope if wrong_scope(directive, actual_name)
114
- return :no_scope if no_scope(directive, actual_name)
113
+ return :wrong_scope if wrong_scope?(directive, actual_name)
114
+ return :no_scope if no_scope?(directive, actual_name)
115
115
 
116
116
  # The method directive being prefixed by 'self.' is always an offense.
117
117
  # The matched method_name does not contain the receiver but the
@@ -121,11 +121,11 @@ module RuboCop
121
121
  end
122
122
  end
123
123
 
124
- def wrong_scope(directive, actual_name)
124
+ def wrong_scope?(directive, actual_name)
125
125
  !actual_name.start_with?('self.') && directive[:has_scope_directive]
126
126
  end
127
127
 
128
- def no_scope(directive, actual_name)
128
+ def no_scope?(directive, actual_name)
129
129
  actual_name.start_with?('self.') && !directive[:has_scope_directive]
130
130
  end
131
131
 
@@ -161,7 +161,7 @@ module RuboCop
161
161
  elements.flat_map do |e|
162
162
  e.loc.column
163
163
  end
164
- end.uniq.count == 1
164
+ end.uniq.one?
165
165
  end
166
166
 
167
167
  def first_argument_line(elements)
@@ -258,7 +258,7 @@ module RuboCop
258
258
  if ignore_cop_directives? && directive_on_source_line?(line_index)
259
259
  return check_directive_line(line, line_index)
260
260
  end
261
- return check_uri_line(line, line_index) if allow_uri?
261
+ return check_line_for_exemptions(line, line_index) if allow_uri? || allow_qualified_name?
262
262
 
263
263
  register_offense(excess_range(nil, line, line_index), line, line_index)
264
264
  end
@@ -358,11 +358,32 @@ module RuboCop
358
358
  )
359
359
  end
360
360
 
361
- def check_uri_line(line, line_index)
362
- uri_range = find_excessive_uri_range(line)
363
- return if uri_range && allowed_uri_position?(line, uri_range)
361
+ def check_line_for_exemptions(line, line_index)
362
+ uri_range = range_if_applicable(line, :uri)
363
+ qualified_name_range = range_if_applicable(line, :qualified_name)
364
364
 
365
- register_offense(excess_range(uri_range, line, line_index), line, line_index)
365
+ return if allowed_combination?(line, uri_range, qualified_name_range)
366
+
367
+ range = uri_range || qualified_name_range
368
+ register_offense(excess_range(range, line, line_index), line, line_index)
369
+ end
370
+
371
+ def range_if_applicable(line, type)
372
+ return unless type == :uri ? allow_uri? : allow_qualified_name?
373
+
374
+ find_excessive_range(line, type)
375
+ end
376
+
377
+ def allowed_combination?(line, uri_range, qualified_name_range)
378
+ if uri_range && qualified_name_range
379
+ allowed_position?(line, uri_range) && allowed_position?(line, qualified_name_range)
380
+ elsif uri_range
381
+ allowed_position?(line, uri_range)
382
+ elsif qualified_name_range
383
+ allowed_position?(line, qualified_name_range)
384
+ else
385
+ false
386
+ end
366
387
  end
367
388
 
368
389
  def breakable_dstr?(node)
@@ -22,10 +22,11 @@ module RuboCop
22
22
  RESTRICT_ON_SEND = %i[[] []=].freeze
23
23
 
24
24
  def on_send(node)
25
+ return if node.loc.dot
26
+
25
27
  receiver_end_pos = node.receiver.source_range.end_pos
26
28
  selector_begin_pos = node.loc.selector.begin_pos
27
29
  return if receiver_end_pos >= selector_begin_pos
28
- return if dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
29
30
 
30
31
  range = range_between(receiver_end_pos, selector_begin_pos)
31
32
 
@@ -33,14 +34,6 @@ module RuboCop
33
34
  corrector.remove(range)
34
35
  end
35
36
  end
36
-
37
- private
38
-
39
- def dot_before_brackets?(node, receiver_end_pos, selector_begin_pos)
40
- return false unless node.loc.respond_to?(:dot) && (dot = node.loc.dot)
41
-
42
- dot.begin_pos == receiver_end_pos && dot.end_pos == selector_begin_pos
43
- end
44
37
  end
45
38
  end
46
39
  end
@@ -86,6 +86,7 @@ module RuboCop
86
86
  def on_array(node)
87
87
  return if node.array_type? && !node.square_brackets?
88
88
 
89
+ node = find_node_with_brackets(node)
89
90
  tokens, left, right = array_brackets(node)
90
91
  return unless left && right
91
92
 
@@ -102,6 +103,10 @@ module RuboCop
102
103
 
103
104
  private
104
105
 
106
+ def find_node_with_brackets(node)
107
+ node.ancestors.find(&:const_pattern_type?) || node
108
+ end
109
+
105
110
  def autocorrect(corrector, node)
106
111
  tokens, left, right = array_brackets(node)
107
112
 
@@ -119,7 +124,7 @@ module RuboCop
119
124
  def array_brackets(node)
120
125
  tokens = processed_source.tokens_within(node)
121
126
 
122
- left = tokens.find(&:left_array_bracket?)
127
+ left = tokens.find(&:left_bracket?)
123
128
  right = tokens.reverse_each.find(&:right_bracket?)
124
129
 
125
130
  [tokens, left, right]
@@ -192,7 +197,7 @@ module RuboCop
192
197
  if side == :right
193
198
  processed_source.tokens_within(node)[i].right_bracket?
194
199
  else
195
- processed_source.tokens_within(node)[i].left_array_bracket?
200
+ processed_source.tokens_within(node)[i].left_bracket?
196
201
  end
197
202
  end
198
203
 
@@ -6,6 +6,10 @@ module RuboCop
6
6
  # Checks for duplicated instance (or singleton) method
7
7
  # definitions.
8
8
  #
9
+ # NOTE: Aliasing a method to itself is allowed, as it indicates that
10
+ # the developer intends to suppress Ruby's method redefinition warnings.
11
+ # See https://bugs.ruby-lang.org/issues/13574.
12
+ #
9
13
  # @example
10
14
  #
11
15
  # # bad
@@ -40,6 +44,18 @@ module RuboCop
40
44
  #
41
45
  # alias bar foo
42
46
  #
47
+ # # good
48
+ # alias foo foo
49
+ # def foo
50
+ # 1
51
+ # end
52
+ #
53
+ # # good
54
+ # alias_method :foo, :foo
55
+ # def foo
56
+ # 1
57
+ # end
58
+ #
43
59
  # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
44
60
  #
45
61
  # # good
@@ -113,11 +129,13 @@ module RuboCop
113
129
 
114
130
  # @!method method_alias?(node)
115
131
  def_node_matcher :method_alias?, <<~PATTERN
116
- (alias (sym $_name) sym)
132
+ (alias (sym $_name) (sym $_original_name))
117
133
  PATTERN
118
134
 
119
135
  def on_alias(node)
120
- return unless (name = method_alias?(node))
136
+ name, original_name = method_alias?(node)
137
+ return unless name && original_name
138
+ return if name == original_name
121
139
  return if node.ancestors.any?(&:if_type?)
122
140
 
123
141
  found_instance_method(node, name)
@@ -125,7 +143,7 @@ module RuboCop
125
143
 
126
144
  # @!method alias_method?(node)
127
145
  def_node_matcher :alias_method?, <<~PATTERN
128
- (send nil? :alias_method (sym $_name) _)
146
+ (send nil? :alias_method (sym $_name) (sym $_original_name))
129
147
  PATTERN
130
148
 
131
149
  # @!method delegate_method?(node)
@@ -140,7 +158,10 @@ module RuboCop
140
158
  def_node_matcher :sym_name, '(sym $_name)'
141
159
 
142
160
  def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
143
- if (name = alias_method?(node))
161
+ name, original_name = alias_method?(node)
162
+
163
+ if name && original_name
164
+ return if name == original_name
144
165
  return if node.ancestors.any?(&:if_type?)
145
166
 
146
167
  found_instance_method(node, name)
@@ -94,7 +94,7 @@ module RuboCop
94
94
  when :float
95
95
  true
96
96
  when :send
97
- check_send(node)
97
+ float_send?(node)
98
98
  when :begin
99
99
  float?(node.children.first)
100
100
  else
@@ -108,18 +108,18 @@ module RuboCop
108
108
  (node.numeric_type? && node.value.zero?) || node.nil_type?
109
109
  end
110
110
 
111
- def check_send(node)
111
+ def float_send?(node)
112
112
  if node.arithmetic_operation?
113
113
  float?(node.receiver) || float?(node.first_argument)
114
114
  elsif FLOAT_RETURNING_METHODS.include?(node.method_name)
115
115
  true
116
116
  elsif node.receiver&.float_type?
117
117
  FLOAT_INSTANCE_METHODS.include?(node.method_name) ||
118
- check_numeric_returning_method(node)
118
+ numeric_returning_method?(node)
119
119
  end
120
120
  end
121
121
 
122
- def check_numeric_returning_method(node)
122
+ def numeric_returning_method?(node)
123
123
  return false unless node.receiver
124
124
 
125
125
  case node.method_name
@@ -123,7 +123,9 @@ module RuboCop
123
123
  # rubocop:enable Metrics/AbcSize
124
124
 
125
125
  def on_case(case_node)
126
- if case_node.condition
126
+ if (cond = case_node.condition)
127
+ return if !cond.falsey_literal? && !cond.truthy_literal?
128
+
127
129
  check_case(case_node)
128
130
  else
129
131
  case_node.when_branches.each do |when_node|
@@ -228,7 +230,7 @@ module RuboCop
228
230
  )
229
231
  end
230
232
 
231
- def condition_evaluation(node, cond)
233
+ def condition_evaluation?(node, cond)
232
234
  if node.unless?
233
235
  cond.falsey_literal?
234
236
  else
@@ -238,7 +240,7 @@ module RuboCop
238
240
 
239
241
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
240
242
  def correct_if_node(node, cond)
241
- result = condition_evaluation(node, cond)
243
+ result = condition_evaluation?(node, cond)
242
244
 
243
245
  new_node = if node.elsif? && result
244
246
  "else\n #{range_with_comments(node.if_branch).source}"
@@ -73,7 +73,7 @@ module RuboCop
73
73
  end
74
74
 
75
75
  def redundant_group?(expr)
76
- expr.is?(:passive, :group) && expr.count { |child| child.type != :free_space } == 1
76
+ expr.is?(:passive, :group) && expr.one? { |child| child.type != :free_space }
77
77
  end
78
78
 
79
79
  def redundantly_quantifiable?(node)