rubocop 1.84.2 → 1.85.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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +83 -4
  3. data/config/obsoletion.yml +5 -0
  4. data/lib/rubocop/cli/command/mcp.rb +19 -0
  5. data/lib/rubocop/cli.rb +6 -3
  6. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  7. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  8. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  9. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  10. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  11. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  12. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  13. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  14. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
  15. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  16. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  17. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
  18. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
  19. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  20. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  21. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  22. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  23. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  24. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  25. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  26. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  27. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  28. data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
  29. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  30. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -1
  31. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +0 -9
  32. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +7 -6
  33. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  34. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  35. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  36. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  37. data/lib/rubocop/cop/lint/void.rb +32 -12
  38. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  39. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  40. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  41. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
  42. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  43. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
  44. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  45. data/lib/rubocop/cop/security/eval.rb +15 -2
  46. data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
  47. data/lib/rubocop/cop/style/alias.rb +4 -1
  48. data/lib/rubocop/cop/style/array_join.rb +4 -2
  49. data/lib/rubocop/cop/style/ascii_comments.rb +5 -2
  50. data/lib/rubocop/cop/style/attr.rb +5 -2
  51. data/lib/rubocop/cop/style/bare_percent_literals.rb +3 -1
  52. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  53. data/lib/rubocop/cop/style/block_delimiters.rb +2 -2
  54. data/lib/rubocop/cop/style/case_equality.rb +4 -0
  55. data/lib/rubocop/cop/style/class_and_module_children.rb +10 -2
  56. data/lib/rubocop/cop/style/colon_method_call.rb +3 -1
  57. data/lib/rubocop/cop/style/copyright.rb +1 -1
  58. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  59. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  60. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  61. data/lib/rubocop/cop/style/empty_class_definition.rb +21 -20
  62. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  63. data/lib/rubocop/cop/style/encoding.rb +7 -1
  64. data/lib/rubocop/cop/style/end_block.rb +3 -1
  65. data/lib/rubocop/cop/style/endless_method.rb +8 -3
  66. data/lib/rubocop/cop/style/file_open.rb +63 -0
  67. data/lib/rubocop/cop/style/for.rb +3 -0
  68. data/lib/rubocop/cop/style/format_string_token.rb +29 -2
  69. data/lib/rubocop/cop/style/global_vars.rb +4 -1
  70. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +21 -5
  71. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  72. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  73. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  74. data/lib/rubocop/cop/style/inline_comment.rb +4 -1
  75. data/lib/rubocop/cop/style/map_join.rb +123 -0
  76. data/lib/rubocop/cop/style/multiline_if_then.rb +3 -1
  77. data/lib/rubocop/cop/style/nil_comparison.rb +2 -3
  78. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  79. data/lib/rubocop/cop/style/not.rb +2 -0
  80. data/lib/rubocop/cop/style/numeric_literals.rb +2 -1
  81. data/lib/rubocop/cop/style/one_class_per_file.rb +95 -0
  82. data/lib/rubocop/cop/style/one_line_conditional.rb +4 -3
  83. data/lib/rubocop/cop/style/parallel_assignment.rb +4 -0
  84. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  85. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
  86. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  87. data/lib/rubocop/cop/style/proc.rb +3 -2
  88. data/lib/rubocop/cop/style/reduce_to_hash.rb +169 -0
  89. data/lib/rubocop/cop/style/redundant_begin.rb +3 -3
  90. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  91. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  92. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  93. data/lib/rubocop/cop/style/redundant_parentheses.rb +6 -3
  94. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  95. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +104 -0
  96. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  97. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  98. data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
  99. data/lib/rubocop/cop/style/semicolon.rb +2 -0
  100. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  101. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
  102. data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
  103. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  104. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  105. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  106. data/lib/rubocop/cop/variable_force/branch.rb +2 -2
  107. data/lib/rubocop/directive_comment.rb +2 -1
  108. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  109. data/lib/rubocop/lsp/diagnostic.rb +1 -0
  110. data/lib/rubocop/mcp/server.rb +174 -0
  111. data/lib/rubocop/options.rb +10 -1
  112. data/lib/rubocop/server/cache.rb +5 -7
  113. data/lib/rubocop/target_ruby.rb +18 -12
  114. data/lib/rubocop/version.rb +1 -1
  115. data/lib/rubocop.rb +14 -0
  116. metadata +34 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f04de47751f13e6453b15f6114038e6c9ef89418cde47c8e8ce73abecc1664ee
4
- data.tar.gz: d1d9cd363db45392d753d24324b1828fe20834bfea01f5efcd2ee246352cbef1
3
+ metadata.gz: 540ad681621feef2b8ffb784afa823f9f03df707e480c371da9b95576c42a0c0
4
+ data.tar.gz: 2e346929c88929a4c923c3f4f5907b986580fbcd36de82687433ef22e5648f9b
5
5
  SHA512:
6
- metadata.gz: f28b74f272f302feb77cdf3053f1116c7b24e3b0c57b139c71fd315d3c38fa8b4f3c122691fd071af1990699f7b7a52d9de5296ac8bb257435ef612ca317ef11
7
- data.tar.gz: 82cba886044606ae3b12eb9ef3b2b706be63d1503e80a10a9b22df2b329ed318b8b286e1b110d64bce0c9f10d7f39f84ad48735ba8a6b2d2f259dd78f4592550
6
+ metadata.gz: 6c7d48381d4f7121e7e17303ad5ce20c74d24e04b71d9b6d57a89d9c8c435da93e1db46b2a9b574dcdd363dfaad4e568c02f24ad1c13bfc0481e73109b06c8a5
7
+ data.tar.gz: a04e081927cf6dca0c9775a741aa589ae5878cda28fbf8c7e69545970089a48908b56b82872416680acc4461b7ab6261191ea35190d994dc3f9bb3a3b57e0018
data/config/default.yml CHANGED
@@ -1720,6 +1720,11 @@ Lint/CopDirectiveSyntax:
1720
1720
  Enabled: pending
1721
1721
  VersionAdded: '1.72'
1722
1722
 
1723
+ Lint/DataDefineOverride:
1724
+ Description: 'Disallow overriding the `Data` built-in methods via `Data.define`.'
1725
+ Enabled: pending
1726
+ VersionAdded: '1.85'
1727
+
1723
1728
  Lint/Debugger:
1724
1729
  Description: 'Checks for debugger calls.'
1725
1730
  Enabled: true
@@ -2409,8 +2414,9 @@ Lint/SafeNavigationConsistency:
2409
2414
  consistent and appropriate safe navigation, without excess or deficiency,
2410
2415
  is used for all method calls on the same object.
2411
2416
  Enabled: true
2417
+ SafeAutoCorrect: false
2412
2418
  VersionAdded: '0.55'
2413
- VersionChanged: '0.77'
2419
+ VersionChanged: '1.85'
2414
2420
  AllowedMethods:
2415
2421
  - present?
2416
2422
  - blank?
@@ -2587,6 +2593,11 @@ Lint/UnreachableLoop:
2587
2593
  # eg. `exactly(2).times`
2588
2594
  - !ruby/regexp /(exactly|at_least|at_most)\(\d+\)\.times/
2589
2595
 
2596
+ Lint/UnreachablePatternBranch:
2597
+ Description: 'Checks for unreachable `in` pattern branches after an unconditional catch-all pattern.'
2598
+ Enabled: pending
2599
+ VersionAdded: '1.85'
2600
+
2590
2601
  Lint/UnusedBlockArgument:
2591
2602
  Description: 'Checks for unused block arguments.'
2592
2603
  StyleGuide: '#underscore-unused-vars'
@@ -3982,10 +3993,11 @@ Style/EmptyClassDefinition:
3982
3993
  Description: 'Enforces consistent style for empty class definitions.'
3983
3994
  Enabled: pending
3984
3995
  VersionAdded: '1.84'
3985
- EnforcedStyle: class_definition
3996
+ EnforcedStyle: class_keyword
3986
3997
  SupportedStyles:
3987
- - class_definition
3998
+ - class_keyword
3988
3999
  - class_new
4000
+ - class_definition # Deprecated.
3989
4001
 
3990
4002
  Style/EmptyElse:
3991
4003
  Description: 'Avoid empty else-clauses.'
@@ -4145,6 +4157,12 @@ Style/FileNull:
4145
4157
  SafeAutoCorrect: false
4146
4158
  VersionAdded: '1.69'
4147
4159
 
4160
+ Style/FileOpen:
4161
+ Description: 'Checks for `File.open` without a block, which can leak file descriptors.'
4162
+ Enabled: pending
4163
+ Safe: false
4164
+ VersionAdded: '1.85'
4165
+
4148
4166
  Style/FileRead:
4149
4167
  Description: 'Favor `File.(bin)read` convenience methods.'
4150
4168
  StyleGuide: '#file-read'
@@ -4642,6 +4660,12 @@ Style/MapIntoArray:
4642
4660
  VersionChanged: '1.67'
4643
4661
  Safe: false
4644
4662
 
4663
+ Style/MapJoin:
4664
+ Description: 'Checks for redundant `map(&:to_s)` before `join`.'
4665
+ Enabled: pending
4666
+ Safe: false
4667
+ VersionAdded: '1.85'
4668
+
4645
4669
  Style/MapToHash:
4646
4670
  Description: 'Prefer `to_h` with a block over `map.to_h`.'
4647
4671
  Enabled: pending
@@ -5091,6 +5115,12 @@ Style/ObjectThen:
5091
5115
  - then
5092
5116
  - yield_self
5093
5117
 
5118
+ Style/OneClassPerFile:
5119
+ Description: 'Checks that each source file defines at most one top-level class or module.'
5120
+ Enabled: pending
5121
+ VersionAdded: '1.85'
5122
+ AllowedClasses: []
5123
+
5094
5124
  Style/OneLineConditional:
5095
5125
  Description: >-
5096
5126
  Favor the ternary operator (?:) or multi-line constructs over
@@ -5179,6 +5209,14 @@ Style/ParenthesesAroundCondition:
5179
5209
  AllowSafeAssignment: true
5180
5210
  AllowInMultilineConditions: false
5181
5211
 
5212
+ Style/PartitionInsteadOfDoubleSelect:
5213
+ Description: >-
5214
+ Checks for consecutive `select`/`filter`/`find_all` and `reject` calls
5215
+ on the same receiver with the same block body.
5216
+ Enabled: pending
5217
+ Safe: false
5218
+ VersionAdded: '1.85'
5219
+
5182
5220
  Style/PercentLiteralDelimiters:
5183
5221
  Description: 'Use `%`-literal delimiters consistently.'
5184
5222
  StyleGuide: '#percent-literal-braces'
@@ -5211,6 +5249,12 @@ Style/PerlBackrefs:
5211
5249
  Enabled: true
5212
5250
  VersionAdded: '0.13'
5213
5251
 
5252
+ Style/PredicateWithKind:
5253
+ Description: 'Prefer `any?(Klass)` to `any? { |x| x.is_a?(Klass) }`.'
5254
+ Enabled: pending
5255
+ SafeAutoCorrect: false
5256
+ VersionAdded: '1.85'
5257
+
5214
5258
  Style/PreferredHashMethods:
5215
5259
  Description: 'Checks use of `has_key?` and `has_value?` Hash methods.'
5216
5260
  StyleGuide: '#hash-key'
@@ -5261,6 +5305,12 @@ Style/RandomWithOffset:
5261
5305
  Enabled: true
5262
5306
  VersionAdded: '0.52'
5263
5307
 
5308
+ Style/ReduceToHash:
5309
+ Description: 'Use `to_h { ... }` instead of `each_with_object`, `inject`, or `reduce` to build a hash.'
5310
+ Enabled: pending
5311
+ Safe: false
5312
+ VersionAdded: '1.85'
5313
+
5264
5314
  Style/RedundantArgument:
5265
5315
  Description: 'Checks for a redundant argument passed to certain methods.'
5266
5316
  Enabled: pending
@@ -5430,6 +5480,11 @@ Style/RedundantLineContinuation:
5430
5480
  Enabled: pending
5431
5481
  VersionAdded: '1.49'
5432
5482
 
5483
+ Style/RedundantMinMaxBy:
5484
+ Description: 'Identifies places where `max_by`/`min_by` can be replaced by `max`/`min`.'
5485
+ Enabled: pending
5486
+ VersionAdded: '1.85'
5487
+
5433
5488
  Style/RedundantParentheses:
5434
5489
  Description: "Checks for parentheses that seem not to serve any purpose."
5435
5490
  Enabled: true
@@ -5507,6 +5562,12 @@ Style/RedundantStringEscape:
5507
5562
  Enabled: pending
5508
5563
  VersionAdded: '1.37'
5509
5564
 
5565
+ Style/RedundantStructKeywordInit:
5566
+ Description: 'Checks for redundant `keyword_init` option for `Struct.new`.'
5567
+ Enabled: pending
5568
+ SafeAutoCorrect: false
5569
+ VersionAdded: '1.85'
5570
+
5510
5571
  Style/RegexpLiteral:
5511
5572
  Description: 'Use / or %r around regular expressions.'
5512
5573
  StyleGuide: '#percent-r'
@@ -5613,8 +5674,20 @@ Style/Sample:
5613
5674
  Enabled: true
5614
5675
  VersionAdded: '0.30'
5615
5676
 
5677
+ Style/SelectByKind:
5678
+ Description: 'Prefer grep/grep_v to select/reject/find/detect with a kind check.'
5679
+ Enabled: pending
5680
+ SafeAutoCorrect: false
5681
+ VersionAdded: '1.85'
5682
+
5683
+ Style/SelectByRange:
5684
+ Description: 'Prefer grep/grep_v to select/reject/find/detect with a range check.'
5685
+ Enabled: pending
5686
+ SafeAutoCorrect: false
5687
+ VersionAdded: '1.85'
5688
+
5616
5689
  Style/SelectByRegexp:
5617
- Description: 'Prefer grep/grep_v to select/reject with a regexp match.'
5690
+ Description: 'Prefer grep/grep_v to select/reject/find/detect with a regexp match.'
5618
5691
  Enabled: pending
5619
5692
  SafeAutoCorrect: false
5620
5693
  VersionAdded: '1.22'
@@ -5873,6 +5946,12 @@ Style/SymbolProc:
5873
5946
  AllowedPatterns: []
5874
5947
  AllowComments: false
5875
5948
 
5949
+ Style/TallyMethod:
5950
+ Description: 'Prefer `Enumerable#tally` over manual counting patterns.'
5951
+ Enabled: pending
5952
+ Safe: false
5953
+ VersionAdded: '1.85'
5954
+
5876
5955
  Style/TernaryParentheses:
5877
5956
  Description: 'Checks for use of parentheses around ternary conditions.'
5878
5957
  Enabled: true
@@ -245,3 +245,8 @@ changed_enforced_styles:
245
245
  parameters: EnforcedStyle
246
246
  value: rails
247
247
  alternative: indented_internal_methods
248
+ - cops: Style/EmptyClassDefinition
249
+ parameters: EnforcedStyle
250
+ value: class_definition
251
+ alternative: class_keyword
252
+ severity: warning
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Start Model Context Protocol of RuboCop.
7
+ # @api private
8
+ class MCP < Base
9
+ self.command_name = :mcp
10
+
11
+ def run
12
+ require_relative '../../mcp/server'
13
+
14
+ RuboCop::MCP::Server.new(@config_store).start
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/rubocop/cli.rb CHANGED
@@ -76,7 +76,9 @@ module RuboCop
76
76
  STATUS_ERROR
77
77
  ensure
78
78
  elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_start
79
- puts "Finished in #{elapsed_time} seconds" if @options[:debug] || @options[:display_time]
79
+ if @options[:debug] || @options[:display_time]
80
+ puts "Finished in #{elapsed_time.round(5)} seconds"
81
+ end
80
82
  end
81
83
  # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
82
84
 
@@ -198,7 +200,7 @@ module RuboCop
198
200
  RuboCop::LSP.enable if @options[:editor_mode]
199
201
  end
200
202
 
201
- # rubocop:disable Metrics/CyclomaticComplexity
203
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
202
204
  def handle_exiting_options
203
205
  return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
204
206
 
@@ -206,9 +208,10 @@ module RuboCop
206
208
  run_command(:show_cops) if @options[:show_cops]
207
209
  run_command(:show_docs_url) if @options[:show_docs_url]
208
210
  run_command(:lsp) if @options[:lsp]
211
+ run_command(:mcp) if @options[:mcp]
209
212
  raise Finished
210
213
  end
211
- # rubocop:enable Metrics/CyclomaticComplexity
214
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
212
215
 
213
216
  def apply_default_formatter
214
217
  # This must be done after the options have already been processed,
@@ -39,8 +39,10 @@ module RuboCop
39
39
  end
40
40
 
41
41
  def plugin_loaded?
42
- # Plugins loaded via `require` are included in `loaded_features`.
43
- config.loaded_plugins.include?(gem) || config.loaded_features.include?(gem)
42
+ # Plugins loaded via `plugins` are Plugin objects with an `about.name` attribute.
43
+ # Plugins loaded via `require` are included in `loaded_features` as strings.
44
+ config.loaded_plugins.any? { |plugin| plugin.about.name == gem } ||
45
+ config.loaded_features.include?(gem)
44
46
  end
45
47
  end
46
48
  end
@@ -16,7 +16,7 @@ module RuboCop
16
16
 
17
17
  def negated_condition(node)
18
18
  condition = node.condition
19
- condition = condition.children.first while condition.begin_type?
19
+ condition = condition.children.last while condition.begin_type?
20
20
  condition
21
21
  end
22
22
  end
@@ -97,8 +97,8 @@ module RuboCop
97
97
  if delimiters.first != delimiters.last
98
98
  # With different delimiters (eg. `[]`, `()`), if there are the same
99
99
  # number of each, escaping is not necessary
100
- delimiter_counts = delimiters.each_with_object({}) do |delimiter, counts|
101
- counts[delimiter] = content.count(delimiter)
100
+ delimiter_counts = delimiters.to_h do |delimiter|
101
+ [delimiter, content.count(delimiter)]
102
102
  end
103
103
 
104
104
  return content if delimiter_counts[delimiters.first] == delimiter_counts[delimiters.last]
@@ -92,7 +92,7 @@ module RuboCop
92
92
  (str "true")
93
93
  PATTERN
94
94
 
95
- def on_block(node) # rubocop:disable Metrics/MethodLength, InternalAffairs/NumblockHandler
95
+ def on_block(node) # rubocop:disable Metrics/MethodLength, InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
96
96
  gem_specification(node) do |block_var|
97
97
  metadata_value = metadata(node)
98
98
  mfa_value = mfa_value(metadata_value)
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for missing `itblock` handlers. The blocks with the `it`
7
+ # parameter introduced in Ruby 3.4 are parsed with a node type of
8
+ # `itblock` instead of block. Cops that define `block` handlers
9
+ # need to define `itblock` handlers or disable this cop for them.
10
+ #
11
+ # @example
12
+ #
13
+ # # bad
14
+ # class BlockRelatedCop < Base
15
+ # def on_block(node)
16
+ # end
17
+ # end
18
+ #
19
+ # # good
20
+ # class BlockRelatedCop < Base
21
+ # def on_block(node)
22
+ # end
23
+ #
24
+ # alias on_itblock on_block
25
+ # end
26
+ #
27
+ # class BlockRelatedCop < Base
28
+ # def on_block(node)
29
+ # end
30
+ #
31
+ # alias_method :on_itblock, :on_block
32
+ # end
33
+ #
34
+ # class BlockRelatedCop < Base
35
+ # def on_block(node)
36
+ # end
37
+ #
38
+ # def on_itblock(node)
39
+ # end
40
+ # end
41
+ class ItblockHandler < Base
42
+ MSG = 'Define on_itblock to handle blocks with the `it` parameter.'
43
+
44
+ def on_def(node)
45
+ return unless block_handler?(node)
46
+ return unless node.parent
47
+
48
+ add_offense(node) unless itblock_handler?(node.parent)
49
+ end
50
+
51
+ private
52
+
53
+ # @!method block_handler?(node)
54
+ def_node_matcher :block_handler?, <<~PATTERN
55
+ (def :on_block (args (arg :node)) ...)
56
+ PATTERN
57
+
58
+ # @!method itblock_handler?(node)
59
+ def_node_matcher :itblock_handler?, <<~PATTERN
60
+ {
61
+ `(def :on_itblock (args (arg :node)) ...)
62
+ `(alias (sym :on_itblock) (sym :on_block))
63
+ `(send nil? :alias_method (sym :on_itblock) (sym :on_block))
64
+ }
65
+ PATTERN
66
+ end
67
+ end
68
+ end
69
+ end
@@ -7,6 +7,7 @@ require_relative 'internal_affairs/empty_line_between_expect_offense_and_correct
7
7
  require_relative 'internal_affairs/example_description'
8
8
  require_relative 'internal_affairs/example_heredoc_delimiter'
9
9
  require_relative 'internal_affairs/inherit_deprecated_cop_class'
10
+ require_relative 'internal_affairs/itblock_handler'
10
11
  require_relative 'internal_affairs/lambda_or_proc'
11
12
  require_relative 'internal_affairs/location_exists'
12
13
  require_relative 'internal_affairs/location_expression'
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Check that the arguments on a multi-line method call are aligned.
6
+ # Checks that the arguments on a multi-line method call are aligned.
7
7
  #
8
8
  # @example EnforcedStyle: with_first_argument (default)
9
9
  # # good
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Check that the elements of a multi-line array literal are
6
+ # Checks that the elements of a multi-line array literal are
7
7
  # aligned.
8
8
  #
9
9
  # @example EnforcedStyle: with_first_element (default)
@@ -7,15 +7,25 @@ module RuboCop
7
7
  # the configuration.
8
8
  #
9
9
  # @example EnforcedStyle: no_empty_lines (default)
10
- # # good
10
+ # # bad
11
+ # foo do |bar|
12
+ #
13
+ # # ...
14
+ #
15
+ # end
11
16
  #
17
+ # # good
12
18
  # foo do |bar|
13
19
  # # ...
14
20
  # end
15
21
  #
16
22
  # @example EnforcedStyle: empty_lines
17
- # # good
23
+ # # bad
24
+ # foo do |bar|
25
+ # # ...
26
+ # end
18
27
  #
28
+ # # good
19
29
  # foo do |bar|
20
30
  #
21
31
  # # ...
@@ -7,8 +7,16 @@ module RuboCop
7
7
  # the configuration.
8
8
  #
9
9
  # @example EnforcedStyle: no_empty_lines (default)
10
- # # good
10
+ # # bad
11
+ # class Foo
12
+ #
13
+ # def bar
14
+ # # ...
15
+ # end
16
+ #
17
+ # end
11
18
  #
19
+ # # good
12
20
  # class Foo
13
21
  # def bar
14
22
  # # ...
@@ -16,8 +24,14 @@ module RuboCop
16
24
  # end
17
25
  #
18
26
  # @example EnforcedStyle: empty_lines
19
- # # good
27
+ # # bad
28
+ # class Foo
29
+ # def bar
30
+ # # ...
31
+ # end
32
+ # end
20
33
  #
34
+ # # good
21
35
  # class Foo
22
36
  #
23
37
  # def bar
@@ -7,8 +7,16 @@ module RuboCop
7
7
  # the configuration.
8
8
  #
9
9
  # @example EnforcedStyle: no_empty_lines (default)
10
- # # good
10
+ # # bad
11
+ # module Foo
12
+ #
13
+ # def bar
14
+ # # ...
15
+ # end
16
+ #
17
+ # end
11
18
  #
19
+ # # good
12
20
  # module Foo
13
21
  # def bar
14
22
  # # ...
@@ -16,8 +24,14 @@ module RuboCop
16
24
  # end
17
25
  #
18
26
  # @example EnforcedStyle: empty_lines
19
- # # good
27
+ # # bad
28
+ # module Foo
29
+ # def bar
30
+ # # ...
31
+ # end
32
+ # end
20
33
  #
34
+ # # good
21
35
  # module Foo
22
36
  #
23
37
  # def bar
@@ -135,7 +135,13 @@ module RuboCop
135
135
  private
136
136
 
137
137
  def autocorrect(corrector, node)
138
- AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
138
+ line_range = if !node.is_a?(AST::Node) || node.value.first_line <= node.key.first_line
139
+ node
140
+ else
141
+ processed_source.buffer.line_range(node.loc.line)
142
+ end
143
+
144
+ AlignmentCorrector.correct(corrector, processed_source, line_range, @column_delta)
139
145
  end
140
146
 
141
147
  def brace_alignment_style
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Check that the keys, separators, and values of a multi-line hash
6
+ # Checks that the keys, separators, and values of a multi-line hash
7
7
  # literal are aligned according to configuration. The configuration
8
8
  # options are:
9
9
  #
@@ -473,7 +473,7 @@ module RuboCop
473
473
  end
474
474
 
475
475
  def block_body_indentation_base(node, end_loc)
476
- if dot_on_new_line?(node)
476
+ if style == :relative_to_receiver && dot_on_new_line?(node)
477
477
  node.send_node.loc.dot
478
478
  else
479
479
  end_loc
@@ -69,14 +69,18 @@ module RuboCop
69
69
  SAME_LINE_OFFENSE = 'Right hand side of multi-line assignment is not ' \
70
70
  'on the same line as the assignment operator `=`.'
71
71
 
72
+ BLOCK_TYPES = %i[block numblock itblock].freeze
73
+
74
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
72
75
  def check_assignment(node, rhs)
73
76
  return if node.send_type? && node.loc.operator&.source != '='
74
77
  return unless rhs
75
78
  return unless supported_types.include?(rhs.type)
76
- return if rhs.single_line?
79
+ return if rhs.single_line? && (!rhs.block_type? || same_line?(node, rhs.loc.begin))
77
80
 
78
81
  check_by_enforced_style(node, rhs)
79
82
  end
83
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
80
84
 
81
85
  def check_by_enforced_style(node, rhs)
82
86
  case style
@@ -109,7 +113,10 @@ module RuboCop
109
113
  private
110
114
 
111
115
  def supported_types
112
- @supported_types ||= cop_config['SupportedTypes'].map(&:to_sym)
116
+ @supported_types ||= cop_config['SupportedTypes'].flat_map do |type|
117
+ sym = type.to_sym
118
+ sym == :block ? BLOCK_TYPES : sym
119
+ end
113
120
  end
114
121
  end
115
122
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Check that the parameters on a multi-line method call or definition are aligned.
6
+ # Checks that the parameters on a multi-line method call or definition are aligned.
7
7
  #
8
8
  # To set the alignment of the first argument, use the
9
9
  # `Layout/FirstParameterIndentation` cop.
@@ -114,7 +114,7 @@ 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.multiline?
117
+ block_node.parent.send_type? && block_node.parent.loc.dot && block_node.single_line?
118
118
  end
119
119
  end
120
120
 
@@ -29,7 +29,7 @@ module RuboCop
29
29
  include RangeHelp
30
30
  extend AutoCorrector
31
31
 
32
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
32
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
33
33
  arguments = node.arguments
34
34
 
35
35
  return unless node.arguments? && pipes?(arguments)
@@ -47,7 +47,7 @@ module RuboCop
47
47
  check(node, [:operator].freeze) if node.keyword?
48
48
  end
49
49
 
50
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
50
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
51
51
  check(node, %i[begin end].freeze)
52
52
  end
53
53
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Check that certain constants are fully qualified.
6
+ # Checks that certain constants are fully qualified.
7
7
  #
8
8
  # This is not enabled by default because it would mark a lot of offenses
9
9
  # unnecessarily.