rubocop 1.69.2 → 1.70.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +19 -2
  5. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  6. data/lib/rubocop/config.rb +13 -4
  7. data/lib/rubocop/config_loader.rb +4 -0
  8. data/lib/rubocop/config_loader_resolver.rb +14 -3
  9. data/lib/rubocop/config_validator.rb +18 -8
  10. data/lib/rubocop/cop/base.rb +6 -0
  11. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  12. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  13. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  14. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  15. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -7
  16. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  17. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  18. data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -7
  19. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  20. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -6
  21. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  22. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
  23. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  24. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
  25. data/lib/rubocop/cop/layout/line_length.rb +1 -0
  26. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +24 -0
  27. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  28. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  29. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
  30. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  31. data/lib/rubocop/cop/lint/constant_reassignment.rb +152 -0
  32. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  33. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +11 -3
  34. data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -1
  35. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  36. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +6 -14
  37. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  38. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  39. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  40. data/lib/rubocop/cop/lint/void.rb +3 -2
  41. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  42. data/lib/rubocop/cop/mixin/check_line_breakable.rb +7 -7
  43. data/lib/rubocop/cop/mixin/comments_help.rb +2 -0
  44. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  45. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +26 -16
  46. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  47. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  48. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  49. data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
  50. data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -1
  51. data/lib/rubocop/cop/style/and_or.rb +1 -1
  52. data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -4
  53. data/lib/rubocop/cop/style/class_and_module_children.rb +5 -2
  54. data/lib/rubocop/cop/style/each_for_simple_loop.rb +3 -6
  55. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  56. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  57. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  58. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -9
  59. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  60. data/lib/rubocop/cop/style/float_division.rb +8 -4
  61. data/lib/rubocop/cop/style/hash_except.rb +54 -67
  62. data/lib/rubocop/cop/style/hash_syntax.rb +5 -2
  63. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  64. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -1
  65. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  66. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  67. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  68. data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
  69. data/lib/rubocop/cop/style/object_then.rb +13 -15
  70. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  71. data/lib/rubocop/cop/style/raise_args.rb +5 -3
  72. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  73. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  74. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  75. data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -3
  76. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -4
  77. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  78. data/lib/rubocop/cop/style/redundant_self_assignment.rb +6 -5
  79. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  80. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  81. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  82. data/lib/rubocop/cop/style/single_line_methods.rb +2 -3
  83. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  84. data/lib/rubocop/cop/style/super_arguments.rb +63 -15
  85. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  86. data/lib/rubocop/cop/style/yoda_expression.rb +1 -0
  87. data/lib/rubocop/cop/util.rb +9 -2
  88. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  89. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  90. data/lib/rubocop/lsp/logger.rb +2 -2
  91. data/lib/rubocop/lsp/routes.rb +7 -23
  92. data/lib/rubocop/lsp/runtime.rb +15 -49
  93. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  94. data/lib/rubocop/path_util.rb +11 -8
  95. data/lib/rubocop/rspec/shared_contexts.rb +4 -1
  96. data/lib/rubocop/runner.rb +5 -6
  97. data/lib/rubocop/target_ruby.rb +15 -0
  98. data/lib/rubocop/version.rb +1 -1
  99. data/lib/rubocop.rb +3 -0
  100. data/lib/ruby_lsp/rubocop/addon.rb +78 -0
  101. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
  102. metadata +12 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45af4a986637b8c3dacb16d942870c2138501ae834e79c0875b81bbf09644b54
4
- data.tar.gz: 65961fc4cb25730ad9528201e22a82427def59f6ad5f048cd01a0ca89a437c3c
3
+ metadata.gz: 55382302106a1f2c44166213aaa0c23bfccc3c0ebac5b1af95fa9073ddf59aa0
4
+ data.tar.gz: bb1a6e491c7750b3f4aff90fbe2590f289d5f85ca9bbc2d71e01bd35d420b38c
5
5
  SHA512:
6
- metadata.gz: aa6eb7a2cbf39d99cbda0faff3dfe690a61e9665847c21669bc9a005f9ac316e9404a8babc8cadf7f033bf82afcf317c8c503ede2306e8b3a8c211abaa878cb9
7
- data.tar.gz: 126f20d27ebf2e0098d0a1039230fea4178d2a196693db8c75326a7f3fdc797b1f030af3d116f2d74f69bb70cc033372ede6836962b2c47632a9ecf4f524dd56
6
+ metadata.gz: 6cff98184e513e6a57e5a82234f57a8130ef2e242eb3df675b677cfe5be8920d3cb732ce1f615385641731c328253fb65829922d371621d5e5148601f309ee51
7
+ data.tar.gz: 3c3d8e5fc22db6f9b1a1ca6f9e31a8a29467c4df358e12da099fcc528884832d00bc18842d846ee76300791c1cb76122a22b6eb079b5a713c6f7b827fbea71dc
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-24 Bozhidar Batsov
1
+ Copyright (c) 2012-25 Bozhidar Batsov
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -52,7 +52,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
52
52
  in your `Gemfile`:
53
53
 
54
54
  ```rb
55
- gem 'rubocop', '~> 1.69', require: false
55
+ gem 'rubocop', '~> 1.70', require: false
56
56
  ```
57
57
 
58
58
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
@@ -247,5 +247,5 @@ RuboCop's changelog is available [here](CHANGELOG.md).
247
247
 
248
248
  ## Copyright
249
249
 
250
- Copyright (c) 2012-2024 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for
250
+ Copyright (c) 2012-2025 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for
251
251
  further details.
data/config/default.yml CHANGED
@@ -1665,6 +1665,11 @@ Lint/ConstantOverwrittenInRescue:
1665
1665
  Enabled: pending
1666
1666
  VersionAdded: '1.31'
1667
1667
 
1668
+ Lint/ConstantReassignment:
1669
+ Description: 'Checks for constant reassignments.'
1670
+ Enabled: pending
1671
+ VersionAdded: '1.70'
1672
+
1668
1673
  Lint/ConstantResolution:
1669
1674
  Description: 'Check that constants are fully qualified with `::`.'
1670
1675
  Enabled: false
@@ -2402,6 +2407,12 @@ Lint/ShadowingOuterLocalVariable:
2402
2407
  Enabled: true
2403
2408
  VersionAdded: '0.9'
2404
2409
 
2410
+ Lint/SharedMutableDefault:
2411
+ Description: 'Checks for mutable literals used as default arguments during Hash initialization.'
2412
+ StyleGuide: '#no-mutable-defaults'
2413
+ Enabled: pending
2414
+ VersionAdded: '1.70'
2415
+
2405
2416
  Lint/StructNewOverride:
2406
2417
  Description: 'Disallow overriding the `Struct` built-in methods via `Struct.new`.'
2407
2418
  Enabled: true
@@ -3136,13 +3147,14 @@ Style/AccessModifierDeclarations:
3136
3147
  Description: 'Checks style of how access modifiers are used.'
3137
3148
  Enabled: true
3138
3149
  VersionAdded: '0.57'
3139
- VersionChanged: '0.81'
3150
+ VersionChanged: '1.70'
3140
3151
  EnforcedStyle: group
3141
3152
  SupportedStyles:
3142
3153
  - inline
3143
3154
  - group
3144
3155
  AllowModifiersOnSymbols: true
3145
3156
  AllowModifiersOnAttrs: true
3157
+ AllowModifiersOnAliasMethod: true
3146
3158
  SafeAutoCorrect: false
3147
3159
 
3148
3160
  Style/AccessorGrouping:
@@ -4316,6 +4328,11 @@ Style/IpAddresses:
4316
4328
  - '**/gems.rb'
4317
4329
  - '**/*.gemspec'
4318
4330
 
4331
+ Style/ItAssignment:
4332
+ Description: 'Checks for assignment to `it` inside a block.'
4333
+ Enabled: pending
4334
+ VersionAdded: '1.70'
4335
+
4319
4336
  Style/KeywordArgumentsMerging:
4320
4337
  Description: >-
4321
4338
  When passing an existing hash as keyword arguments, provide additional arguments
@@ -5059,7 +5076,7 @@ Style/RedundantConstantBase:
5059
5076
  VersionAdded: '1.40'
5060
5077
 
5061
5078
  Style/RedundantCurrentDirectoryInPath:
5062
- Description: 'Checks for uses a redundant current directory in path.'
5079
+ Description: 'Checks for a redundant current directory in a path given to `require_relative`.'
5063
5080
  Enabled: pending
5064
5081
  VersionAdded: '1.53'
5065
5082
 
@@ -71,11 +71,11 @@ module RuboCop
71
71
 
72
72
  warn Rainbow("\n#{pluralize(errors.size, 'error')} occurred:").red
73
73
 
74
- errors.each { |error| warn error }
74
+ errors.each { |error| warn Rainbow(error).red }
75
75
 
76
- warn <<~WARNING
76
+ warn Rainbow(<<~WARNING.strip).yellow
77
77
  Errors are usually caused by RuboCop bugs.
78
- Please, report your problems to RuboCop's issue tracker.
78
+ Please, update to the latest RuboCop version if not already in use, and report a bug if the issue still occurs on this version.
79
79
  #{bug_tracker_uri}
80
80
  Mention the following information in the issue report:
81
81
  #{RuboCop::Version.verbose}
@@ -16,6 +16,7 @@ module RuboCop
16
16
 
17
17
  CopConfig = Struct.new(:name, :metadata)
18
18
 
19
+ EMPTY_CONFIG = {}.freeze
19
20
  DEFAULT_RAILS_VERSION = 5.0
20
21
  attr_reader :loaded_path
21
22
 
@@ -80,10 +81,7 @@ module RuboCop
80
81
 
81
82
  def make_excludes_absolute
82
83
  each_key do |key|
83
- @validator.validate_section_presence(key)
84
- next unless self[key]['Exclude']
85
-
86
- self[key]['Exclude'].map! do |exclude_elem|
84
+ dig(key, 'Exclude')&.map! do |exclude_elem|
87
85
  if exclude_elem.is_a?(String) && !absolute?(exclude_elem)
88
86
  File.expand_path(File.join(base_dir_for_path_parameters, exclude_elem))
89
87
  else
@@ -123,6 +121,13 @@ module RuboCop
123
121
  @for_cop[cop]
124
122
  end
125
123
 
124
+ # @return [Config, Hash] for the given cop / cop name.
125
+ # If the given cop is enabled, returns its configuration hash.
126
+ # Otherwise, returns an empty hash.
127
+ def for_enabled_cop(cop)
128
+ cop_enabled?(cop) ? for_cop(cop) : EMPTY_CONFIG
129
+ end
130
+
126
131
  # @return [Config] for the given cop merged with that of its department (if any)
127
132
  # Note: the 'Enabled' attribute is same as that returned by `for_cop`
128
133
  def for_badge(badge)
@@ -159,6 +164,10 @@ module RuboCop
159
164
  @for_all_cops ||= self['AllCops'] || {}
160
165
  end
161
166
 
167
+ def cop_enabled?(name)
168
+ !!for_cop(name)['Enabled']
169
+ end
170
+
162
171
  def disabled_new_cops?
163
172
  for_all_cops['NewCops'] == 'disable'
164
173
  end
@@ -41,6 +41,10 @@ module RuboCop
41
41
  def clear_options
42
42
  @debug = nil
43
43
  @loaded_features = Set.new
44
+ @disable_pending_cops = nil
45
+ @enable_pending_cops = nil
46
+ @ignore_parent_exclusion = nil
47
+ @ignore_unrecognized_cops = nil
44
48
  FileFinder.root_level = nil
45
49
  end
46
50
 
@@ -163,14 +163,21 @@ module RuboCop
163
163
  end
164
164
 
165
165
  def warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
166
+ # If the file being considered is remote, don't bother checking for duplicates
167
+ return if remote_config?(opts[:file])
168
+
166
169
  return unless duplicate_setting?(base_hash, derived_hash, key, opts[:inherited_file])
167
170
 
168
171
  inherit_mode = opts[:inherit_mode]['merge'] || opts[:inherit_mode]['override']
169
172
  return if base_hash[key].is_a?(Array) && inherit_mode&.include?(key)
170
173
 
171
- puts "#{PathUtil.smart_path(opts[:file])}: " \
172
- "#{opts[:cop_name]}:#{key} overrides " \
173
- "the same parameter in #{opts[:inherited_file]}"
174
+ puts duplicate_setting_warning(opts, key)
175
+ end
176
+
177
+ def duplicate_setting_warning(opts, key)
178
+ "#{PathUtil.smart_path(opts[:file])}: " \
179
+ "#{opts[:cop_name]}:#{key} overrides " \
180
+ "the same parameter in #{opts[:inherited_file]}"
174
181
  end
175
182
 
176
183
  def determine_inherit_mode(hash, key)
@@ -242,6 +249,10 @@ module RuboCop
242
249
  uri.start_with?('http://', 'https://')
243
250
  end
244
251
 
252
+ def remote_config?(file)
253
+ file.is_a?(RemoteConfig)
254
+ end
255
+
245
256
  def handle_disabled_by_default(config, new_default_configuration)
246
257
  department_config = config.to_hash.reject { |cop| cop.include?('/') }
247
258
  department_config.each do |dept, dept_params|
@@ -3,6 +3,7 @@
3
3
  module RuboCop
4
4
  # Handles validation of configuration, for example cop names, parameter
5
5
  # names, and Ruby versions.
6
+ # rubocop:disable Metrics/ClassLength
6
7
  class ConfigValidator
7
8
  extend SimpleForwardable
8
9
 
@@ -41,8 +42,9 @@ module RuboCop
41
42
  ConfigLoader.default_configuration.key?(key)
42
43
  end
43
44
 
44
- check_obsoletions
45
+ validate_parameter_shape(valid_cop_names)
45
46
 
47
+ check_obsoletions
46
48
  alert_about_unrecognized_cops(invalid_cop_names)
47
49
  validate_new_cops_parameter
48
50
  validate_parameter_names(valid_cop_names)
@@ -64,12 +66,6 @@ module RuboCop
64
66
  target_ruby.version
65
67
  end
66
68
 
67
- def validate_section_presence(name)
68
- return unless @config.key?(name) && @config[name].nil?
69
-
70
- raise ValidationError, "empty section #{name} found in #{smart_loaded_path}"
71
- end
72
-
73
69
  private
74
70
 
75
71
  attr_reader :target_ruby
@@ -177,9 +173,22 @@ module RuboCop
177
173
  raise ValidationError, message
178
174
  end
179
175
 
176
+ def validate_parameter_shape(valid_cop_names)
177
+ valid_cop_names.each do |name|
178
+ if @config[name].nil?
179
+ raise ValidationError, "empty section #{name.inspect} found in #{smart_loaded_path}"
180
+ elsif !@config[name].is_a?(Hash)
181
+ raise ValidationError, <<~MESSAGE
182
+ The configuration for #{name.inspect} in #{smart_loaded_path} is not a Hash.
183
+
184
+ Found: #{@config[name].inspect}
185
+ MESSAGE
186
+ end
187
+ end
188
+ end
189
+
180
190
  def validate_parameter_names(valid_cop_names)
181
191
  valid_cop_names.each do |name|
182
- validate_section_presence(name)
183
192
  each_invalid_parameter(name) do |param, supported_params|
184
193
  warn Rainbow(<<~MESSAGE).yellow
185
194
  Warning: #{name} does not support #{param} parameter.
@@ -277,4 +286,5 @@ module RuboCop
277
286
  "is supposed to be #{supposed_values} and #{Rainbow(value).yellow} is not."
278
287
  end
279
288
  end
289
+ # rubocop:enable Metrics/ClassLength
280
290
  end
@@ -261,6 +261,12 @@ module RuboCop
261
261
  @config.target_ruby_version
262
262
  end
263
263
 
264
+ # Returns a gems locked versions (i.e. from Gemfile.lock or gems.locked)
265
+ # @returns [Gem::Version | nil] The locked gem version, or nil if the gem is not present.
266
+ def target_gem_version(gem_name)
267
+ @config.gem_versions_in_target && @config.gem_versions_in_target[gem_name]
268
+ end
269
+
264
270
  def parser_engine
265
271
  @config.parser_engine
266
272
  end
@@ -161,7 +161,7 @@ module RuboCop
161
161
  end
162
162
 
163
163
  def gem_options(node)
164
- return [] unless node.last_argument&.type == :hash
164
+ return [] unless node.last_argument&.hash_type?
165
165
 
166
166
  node.last_argument.keys.map(&:value)
167
167
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Use `config.cop_enabled?('Department/CopName')` instead of
7
+ # traversing the config hash.
8
+ #
9
+ # @example
10
+ # # `for_cop(...)['Enabled']
11
+ #
12
+ # # bad
13
+ # config.for_cop('Department/CopName')['Enabled']
14
+ #
15
+ # # good
16
+ # config.cop_enabled?('Department/CopName')
17
+ #
18
+ # @example
19
+ # # when keeping a cop's config in a local and then checking the `Enabled` key
20
+ #
21
+ # # bad
22
+ # cop_config = config.for_cop('Department/CopName')
23
+ # cop_config['Enabled'] && cop_config['Foo']
24
+ #
25
+ # # good
26
+ # config.for_enabled_cop('Department/CopName')['Foo']
27
+ #
28
+ class CopEnabled < Base
29
+ extend AutoCorrector
30
+
31
+ MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
32
+ MSG_HASH = 'Consider replacing uses of `%<hash_name>s` with `config.for_enabled_cop`.'
33
+
34
+ RESTRICT_ON_SEND = [:[]].freeze
35
+
36
+ # @!method for_cop_enabled?(node)
37
+ def_node_matcher :for_cop_enabled?, <<~PATTERN
38
+ (send
39
+ (send
40
+ ${(send nil? :config) (ivar :@config)} :for_cop
41
+ $(str _)) :[]
42
+ (str "Enabled"))
43
+ PATTERN
44
+
45
+ # @!method config_enabled_lookup?(node)
46
+ def_node_matcher :config_enabled_lookup?, <<~PATTERN
47
+ (send
48
+ {(lvar $_) (ivar $_) (send nil? $_)} :[]
49
+ (str "Enabled"))
50
+ PATTERN
51
+
52
+ def on_send(node)
53
+ if (config_var, cop_name = for_cop_enabled?(node))
54
+ handle_for_cop(node, config_var, cop_name)
55
+ elsif (config_var = config_enabled_lookup?(node))
56
+ return unless config_var.end_with?('_config')
57
+
58
+ handle_hash(node, config_var)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def handle_for_cop(node, config_var, cop_name)
65
+ source = node.source
66
+ quote = cop_name.loc.begin.source
67
+ cop_name = cop_name.value
68
+
69
+ replacement = "#{config_var.source}.cop_enabled?(#{quote}#{cop_name}#{quote})"
70
+ message = format(MSG, source: source, replacement: replacement)
71
+
72
+ add_offense(node, message: message) do |corrector|
73
+ corrector.replace(node, replacement)
74
+ end
75
+ end
76
+
77
+ def handle_hash(node, config_var)
78
+ message = format(MSG_HASH, hash_name: config_var)
79
+
80
+ add_offense(node, message: message)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -21,16 +21,17 @@ module RuboCop
21
21
 
22
22
  # @!method node_type_check(node)
23
23
  def_node_matcher :node_type_check, <<~PATTERN
24
- (send (send $_ :type) :== (sym $_))
24
+ (send (call _ :type) :== (sym $_))
25
25
  PATTERN
26
26
 
27
27
  def on_send(node)
28
- node_type_check(node) do |receiver, node_type|
28
+ node_type_check(node) do |node_type|
29
29
  return unless Parser::Meta::NODE_TYPES.include?(node_type)
30
30
 
31
31
  message = format(MSG, type: node_type)
32
32
  add_offense(node, message: message) do |corrector|
33
- range = node.source_range.with(begin_pos: receiver.source_range.end_pos + 1)
33
+ range = node.receiver.loc.selector.join(node.source_range.end)
34
+
34
35
  corrector.replace(range, "#{node_type}_type?")
35
36
  end
36
37
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'internal_affairs/cop_description'
4
+ require_relative 'internal_affairs/cop_enabled'
4
5
  require_relative 'internal_affairs/create_empty_file'
5
6
  require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
6
7
  require_relative 'internal_affairs/example_description'
@@ -141,16 +141,10 @@ module RuboCop
141
141
  end
142
142
 
143
143
  def enforce_hash_argument_with_separator?
144
- return false unless hash_argument_config['Enabled']
145
-
146
144
  RuboCop::Cop::Layout::HashAlignment::SEPARATOR_ALIGNMENT_STYLES.any? do |style|
147
- hash_argument_config[style]&.include?('separator')
145
+ config.for_enabled_cop('Layout/HashAlignment')[style]&.include?('separator')
148
146
  end
149
147
  end
150
-
151
- def hash_argument_config
152
- config.for_cop('Layout/HashAlignment')
153
- end
154
148
  end
155
149
  end
156
150
  end
@@ -86,6 +86,7 @@ module RuboCop
86
86
 
87
87
  def on_send(node)
88
88
  return unless node.bare_access_modifier? && !node.block_literal?
89
+ return if same_line?(node, node.right_sibling)
89
90
  return if expected_empty_lines?(node)
90
91
 
91
92
  message = message(node)
@@ -70,7 +70,7 @@ module RuboCop
70
70
  end
71
71
 
72
72
  def check_assignment(token)
73
- return unless aligned_with_preceding_assignment(token) == :no
73
+ return unless aligned_with_preceding_equals_operator(token) == :no
74
74
 
75
75
  message = format(MSG_UNALIGNED_ASGN, location: 'preceding')
76
76
  add_offense(token.pos, message: message) do |corrector|
@@ -269,17 +269,12 @@ module RuboCop
269
269
  end
270
270
 
271
271
  def enforce_first_argument_with_fixed_indentation?
272
- return false unless argument_alignment_config['Enabled']
273
-
272
+ argument_alignment_config = config.for_enabled_cop('Layout/ArgumentAlignment')
274
273
  argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
275
274
  end
276
275
 
277
276
  def enable_layout_first_method_argument_line_break?
278
- config.for_cop('Layout/FirstMethodArgumentLineBreak')['Enabled']
279
- end
280
-
281
- def argument_alignment_config
282
- config.for_cop('Layout/ArgumentAlignment')
277
+ config.cop_enabled?('Layout/FirstMethodArgumentLineBreak')
283
278
  end
284
279
  end
285
280
  end
@@ -180,13 +180,8 @@ module RuboCop
180
180
  end
181
181
 
182
182
  def enforce_first_argument_with_fixed_indentation?
183
- return false unless array_alignment_config['Enabled']
184
-
185
- array_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
186
- end
187
-
188
- def array_alignment_config
189
- config.for_cop('Layout/ArrayAlignment')
183
+ argument_alignment_config = config.for_enabled_cop('Layout/ArrayAlignment')
184
+ argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
190
185
  end
191
186
  end
192
187
  end
@@ -225,14 +225,9 @@ module RuboCop
225
225
  end
226
226
 
227
227
  def enforce_first_argument_with_fixed_indentation?
228
- return false unless argument_alignment_config['Enabled']
229
-
228
+ argument_alignment_config = config.for_enabled_cop('Layout/ArgumentAlignment')
230
229
  argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
231
230
  end
232
-
233
- def argument_alignment_config
234
- config.for_cop('Layout/ArgumentAlignment')
235
- end
236
231
  end
237
232
  end
238
233
  end
@@ -202,6 +202,7 @@ module RuboCop
202
202
 
203
203
  ignore_node(last_argument)
204
204
  end
205
+ alias on_csend on_send
205
206
  alias on_super on_send
206
207
  alias on_yield on_send
207
208
 
@@ -227,6 +228,7 @@ module RuboCop
227
228
  left_sibling = argument_before_hash(node)
228
229
  parent_loc = node.parent.loc
229
230
  selector = left_sibling || parent_loc.selector || parent_loc.expression
231
+
230
232
  same_line?(selector, node.pairs.first)
231
233
  end
232
234
 
@@ -382,13 +384,13 @@ module RuboCop
382
384
  end
383
385
 
384
386
  def enforce_first_argument_with_fixed_indentation?
385
- return false unless argument_alignment_config['Enabled']
386
-
387
+ argument_alignment_config = config.for_enabled_cop('Layout/ArgumentAlignment')
387
388
  argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
388
389
  end
389
390
 
390
- def argument_alignment_config
391
- config.for_cop('Layout/ArgumentAlignment')
391
+ def same_line?(node1, node2)
392
+ # Override `Util#same_line?`
393
+ super || node1.last_line == line(node2)
392
394
  end
393
395
  end
394
396
  end
@@ -75,6 +75,7 @@ module RuboCop
75
75
  autocorrect(corrector, outermost_send)
76
76
  end
77
77
  end
78
+ alias on_csend on_send
78
79
 
79
80
  private
80
81
 
@@ -101,7 +101,7 @@ module RuboCop
101
101
  ranges << loc.expression
102
102
  elsif literal.heredoc?
103
103
  ranges << loc.heredoc_body
104
- elsif loc.respond_to?(:begin) && loc.begin
104
+ elsif (loc.respond_to?(:begin) && loc.begin) || ignored_parent?(literal)
105
105
  ranges << loc.expression
106
106
  end
107
107
  end
@@ -127,6 +127,12 @@ module RuboCop
127
127
  comment_ranges(processed_source.comments)
128
128
  end
129
129
 
130
+ def ignored_parent?(node)
131
+ return false unless node.parent
132
+
133
+ node.parent.type?(:regexp, :xstr)
134
+ end
135
+
130
136
  def no_space_style?
131
137
  cop_config['EnforcedStyle'] == 'no_space'
132
138
  end
@@ -127,7 +127,7 @@ module RuboCop
127
127
 
128
128
  def base_column(child)
129
129
  grandparent = child.parent.parent
130
- if grandparent&.type == :pair
130
+ if grandparent&.pair_type?
131
131
  grandparent.loc.column
132
132
  else
133
133
  child.source_range.source_line =~ /\S/
@@ -90,6 +90,7 @@ module RuboCop
90
90
  alias on_array on_potential_breakable_node
91
91
  alias on_hash on_potential_breakable_node
92
92
  alias on_send on_potential_breakable_node
93
+ alias on_csend on_potential_breakable_node
93
94
  alias on_def on_potential_breakable_node
94
95
 
95
96
  def on_new_investigation
@@ -33,6 +33,18 @@ module RuboCop
33
33
  #
34
34
  # @example AllowMultilineFinalElement: false (default)
35
35
  #
36
+ # # bad
37
+ # foo(a, b,
38
+ # c
39
+ # )
40
+ #
41
+ # # bad
42
+ # foo(
43
+ # a, b, {
44
+ # foo: "bar",
45
+ # }
46
+ # )
47
+ #
36
48
  # # good
37
49
  # foo(
38
50
  # a,
@@ -44,6 +56,18 @@ module RuboCop
44
56
  #
45
57
  # @example AllowMultilineFinalElement: true
46
58
  #
59
+ # # bad
60
+ # foo(a, b,
61
+ # c
62
+ # )
63
+ #
64
+ # # good
65
+ # foo(
66
+ # a, b, {
67
+ # foo: "bar",
68
+ # }
69
+ # )
70
+ #
47
71
  # # good
48
72
  # foo(
49
73
  # a,
@@ -115,7 +115,7 @@ module RuboCop
115
115
  end
116
116
 
117
117
  def single_line_block_chain_enabled?
118
- @config.for_cop('Layout/SingleLineBlockChain')['Enabled']
118
+ @config.cop_enabled?('Layout/SingleLineBlockChain')
119
119
  end
120
120
 
121
121
  def convertible_block?(node)
@@ -22,7 +22,7 @@ module RuboCop
22
22
 
23
23
  def on_def(node)
24
24
  args = node.arguments
25
- return unless args.loc.begin&.is?('(')
25
+ return unless args.parenthesized_call?
26
26
 
27
27
  expr = args.source_range
28
28
  pos_before_left_paren = range_between(expr.begin_pos - 1, expr.begin_pos)
@@ -242,12 +242,12 @@ module RuboCop
242
242
  return !aligned_with_operator?(operator) unless type == :assignment
243
243
 
244
244
  token = Token.new(operator, nil, operator.source)
245
- align_preceding = aligned_with_preceding_assignment(token)
245
+ align_preceding = aligned_with_preceding_equals_operator(token)
246
246
 
247
247
  return false if align_preceding == :yes ||
248
- aligned_with_subsequent_assignment(token) == :none
248
+ aligned_with_subsequent_equals_operator(token) == :none
249
249
 
250
- aligned_with_subsequent_assignment(token) != :yes
250
+ aligned_with_subsequent_equals_operator(token) != :yes
251
251
  end
252
252
 
253
253
  def excess_trailing_space?(right_operand, with_space)