rubocop 1.60.2 → 1.62.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/output.css.erb +159 -0
  4. data/assets/output.html.erb +1 -160
  5. data/config/default.yml +41 -12
  6. data/lib/rubocop/cli/command/lsp.rb +2 -2
  7. data/lib/rubocop/cli.rb +6 -1
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_finder.rb +12 -2
  10. data/lib/rubocop/config_validator.rb +14 -5
  11. data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
  12. data/lib/rubocop/cop/base.rb +17 -8
  13. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  14. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
  16. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  17. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  18. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  19. data/lib/rubocop/cop/layout/end_alignment.rb +3 -1
  20. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
  21. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  22. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  23. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  24. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
  25. data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
  26. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  27. data/lib/rubocop/cop/lint/syntax.rb +1 -1
  28. data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -2
  29. data/lib/rubocop/cop/lint/void.rb +6 -1
  30. data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
  31. data/lib/rubocop/cop/registry.rb +1 -1
  32. data/lib/rubocop/cop/style/arguments_forwarding.rb +29 -8
  33. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  34. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  35. data/lib/rubocop/cop/style/conditional_assignment.rb +4 -5
  36. data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
  37. data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
  38. data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -5
  39. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +5 -8
  40. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  41. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +4 -0
  42. data/lib/rubocop/cop/style/object_then.rb +5 -3
  43. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
  44. data/lib/rubocop/cop/style/raise_args.rb +3 -0
  45. data/lib/rubocop/cop/style/redundant_argument.rb +2 -2
  46. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  47. data/lib/rubocop/cop/style/redundant_line_continuation.rb +17 -6
  48. data/lib/rubocop/cop/style/redundant_return.rb +6 -0
  49. data/lib/rubocop/cop/style/sample.rb +1 -3
  50. data/lib/rubocop/cops_documentation_generator.rb +4 -2
  51. data/lib/rubocop/formatter/html_formatter.rb +30 -10
  52. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  53. data/lib/rubocop/lsp/logger.rb +1 -1
  54. data/lib/rubocop/lsp/routes.rb +1 -1
  55. data/lib/rubocop/lsp/runtime.rb +1 -1
  56. data/lib/rubocop/lsp/server.rb +5 -2
  57. data/lib/rubocop/lsp/severity.rb +1 -1
  58. data/lib/rubocop/lsp.rb +29 -0
  59. data/lib/rubocop/magic_comment.rb +1 -1
  60. data/lib/rubocop/options.rb +11 -0
  61. data/lib/rubocop/path_util.rb +6 -2
  62. data/lib/rubocop/rspec/cop_helper.rb +8 -2
  63. data/lib/rubocop/rspec/expect_offense.rb +1 -1
  64. data/lib/rubocop/rspec/shared_contexts.rb +36 -17
  65. data/lib/rubocop/rspec/support.rb +2 -1
  66. data/lib/rubocop/runner.rb +9 -2
  67. data/lib/rubocop/target_finder.rb +84 -78
  68. data/lib/rubocop/target_ruby.rb +82 -80
  69. data/lib/rubocop/version.rb +18 -3
  70. metadata +9 -6
@@ -232,6 +232,10 @@ module RuboCop
232
232
  @config.target_ruby_version
233
233
  end
234
234
 
235
+ def parser_engine
236
+ @config.parser_engine
237
+ end
238
+
235
239
  def target_rails_version
236
240
  @config.target_rails_version
237
241
  end
@@ -254,7 +258,7 @@ module RuboCop
254
258
 
255
259
  # There should be very limited reasons for a Cop to do it's own parsing
256
260
  def parse(source, path = nil)
257
- ProcessedSource.new(source, target_ruby_version, path)
261
+ ProcessedSource.new(source, target_ruby_version, path, parser_engine: parser_engine)
258
262
  end
259
263
 
260
264
  # @api private
@@ -305,6 +309,17 @@ module RuboCop
305
309
  @current_original = original
306
310
  end
307
311
 
312
+ # @api private
313
+ def always_autocorrect?
314
+ # `true` is the same as `'always'` for backward compatibility.
315
+ ['always', true].include?(cop_config.fetch('AutoCorrect', 'always'))
316
+ end
317
+
318
+ # @api private
319
+ def contextual_autocorrect?
320
+ cop_config.fetch('AutoCorrect', 'always') == 'contextual'
321
+ end
322
+
308
323
  def inspect # :nodoc:
309
324
  "#<#{self.class.name}:#{object_id} @config=#{@config} @options=#{@options}>"
310
325
  end
@@ -389,7 +404,7 @@ module RuboCop
389
404
  def use_corrector(range, corrector)
390
405
  if autocorrect?
391
406
  attempt_correction(range, corrector)
392
- elsif corrector && cop_config.fetch('AutoCorrect', true)
407
+ elsif corrector && (always_autocorrect? || (contextual_autocorrect? && !LSP.enabled?))
393
408
  :uncorrected
394
409
  else
395
410
  :unsupported
@@ -481,12 +496,6 @@ module RuboCop
481
496
  range.end_pos + @current_offset
482
497
  )
483
498
  end
484
-
485
- # This experimental feature has been under consideration for a while.
486
- # @api private
487
- def lsp_mode?
488
- ARGV.include?('--lsp')
489
- end
490
499
  end
491
500
  end
492
501
  end
@@ -34,18 +34,14 @@ module RuboCop
34
34
  end
35
35
 
36
36
  def offending_range
37
+ begin_range = block_node.source_range.begin
38
+
37
39
  if block_node.arguments?
38
- replacement_range(argument_node.source_range.end_pos)
40
+ begin_range.join(argument_node.source_range.end)
39
41
  else
40
- replacement_range(block_node.loc.begin.end_pos)
42
+ begin_range.join(block_node.loc.begin.end)
41
43
  end
42
44
  end
43
-
44
- def replacement_range(end_pos)
45
- Parser::Source::Range.new(block_node.source_range.source_buffer,
46
- block_node.source_range.begin_pos,
47
- end_pos)
48
- end
49
45
  end
50
46
  end
51
47
  end
@@ -15,6 +15,8 @@ module RuboCop
15
15
  end
16
16
 
17
17
  def call(corrector)
18
+ offending_range = for_node.source_range.begin.join(end_range)
19
+
18
20
  corrector.replace(offending_range, correction)
19
21
  end
20
22
 
@@ -40,11 +42,11 @@ module RuboCop
40
42
  collection_node.range_type? || collection_node.or_type? || collection_node.and_type?
41
43
  end
42
44
 
43
- def end_position
45
+ def end_range
44
46
  if for_node.do?
45
- keyword_begin.end_pos
47
+ keyword_begin.end
46
48
  else
47
- collection_end.end_pos
49
+ collection_end.end
48
50
  end
49
51
  end
50
52
 
@@ -59,16 +61,6 @@ module RuboCop
59
61
  collection_node.source_range
60
62
  end
61
63
  end
62
-
63
- def offending_range
64
- replacement_range(end_position)
65
- end
66
-
67
- def replacement_range(end_pos)
68
- Parser::Source::Range.new(for_node.source_range.source_buffer,
69
- for_node.source_range.begin_pos,
70
- end_pos)
71
- end
72
64
  end
73
65
  end
74
66
  end
@@ -110,6 +110,8 @@ module RuboCop
110
110
  end
111
111
  end
112
112
 
113
+ return unless required_ruby_version
114
+
113
115
  required_ruby_version.str_content.scan(/\d/).first(2).join('.')
114
116
  end
115
117
 
@@ -30,6 +30,7 @@ module RuboCop
30
30
  extend AutoCorrector
31
31
 
32
32
  MSG = 'Use `%<method_name>s` instead of `%<method_suffix>s`.'
33
+ RESTRICT_ON_SEND = %i[end_with?].freeze
33
34
  SUGGEST_METHOD_FOR_SUFFIX = {
34
35
  '=' => 'assignment_method?',
35
36
  '!' => 'bang_method?',
@@ -51,14 +52,15 @@ module RuboCop
51
52
 
52
53
  def on_send(node)
53
54
  method_name_end_with?(node) do |method_name_node, end_with_arg|
55
+ next unless method_name_node.receiver
56
+
57
+ preferred_method = SUGGEST_METHOD_FOR_SUFFIX[end_with_arg.value]
54
58
  range = range(method_name_node, node)
55
- message = format(
56
- MSG,
57
- method_name: SUGGEST_METHOD_FOR_SUFFIX[end_with_arg.value],
58
- method_suffix: range.source
59
- )
59
+ message = format(MSG, method_name: preferred_method, method_suffix: range.source)
60
60
 
61
- add_offense(range, message: message)
61
+ add_offense(range, message: message) do |corrector|
62
+ corrector.replace(range, preferred_method)
63
+ end
62
64
  end
63
65
  end
64
66
  alias on_csend on_send
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for redundant arguments of `RuboCop::RSpec::ExpectOffense`'s methods.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # expect_no_offenses('code', keyword: keyword)
12
+ #
13
+ # # good
14
+ # expect_no_offenses('code')
15
+ #
16
+ class RedundantExpectOffenseArguments < Base
17
+ extend AutoCorrector
18
+
19
+ MSG = 'Remove the redundant arguments.'
20
+ RESTRICT_ON_SEND = %i[expect_no_offenses].freeze
21
+
22
+ def on_send(node)
23
+ return if node.arguments.one? || !node.arguments[1]&.hash_type?
24
+
25
+ range = node.first_argument.source_range.end.join(node.last_argument.source_range.end)
26
+
27
+ add_offense(range) do |corrector|
28
+ corrector.remove(range)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -20,6 +20,7 @@ require_relative 'internal_affairs/offense_location_keyword'
20
20
  require_relative 'internal_affairs/processed_source_buffer_name'
21
21
  require_relative 'internal_affairs/redundant_context_config_parameter'
22
22
  require_relative 'internal_affairs/redundant_described_class_as_subject'
23
+ require_relative 'internal_affairs/redundant_expect_offense_arguments'
23
24
  require_relative 'internal_affairs/redundant_let_rubocop_config_new'
24
25
  require_relative 'internal_affairs/redundant_location_argument'
25
26
  require_relative 'internal_affairs/redundant_message_argument'
@@ -20,7 +20,9 @@ module RuboCop
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
22
  # `EnforcedStyleAlignWith: start_of_line` by default due to `||= begin` tends
23
- # to align with the start of the line. These style can be configured by each cop.
23
+ # to align with the start of the line. `Layout/DefEndAlignment` cop also aligns with
24
+ # `EnforcedStyleAlignWith: start_of_line` by default.
25
+ # These style can be configured by each cop.
24
26
  #
25
27
  # @example EnforcedStyleAlignWith: keyword (default)
26
28
  # # bad
@@ -89,7 +89,9 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def index_access_call_chained?(node)
92
- node.send_type? && node.method?(:[]) && node.children.first.method?(:[])
92
+ return false unless node.send_type? && node.method?(:[])
93
+
94
+ node.children.first.send_type? && node.children.first.method?(:[])
93
95
  end
94
96
 
95
97
  def configured_to_not_be_inspected?(node)
@@ -81,19 +81,28 @@ module RuboCop
81
81
  private
82
82
 
83
83
  def check_empty(left_brace, space_plus_brace, used_style)
84
- return if style_for_empty_braces == used_style
85
-
86
- config_to_allow_offenses['EnforcedStyleForEmptyBraces'] = used_style.to_s
84
+ if style_for_empty_braces == used_style
85
+ handle_different_styles_for_empty_braces(used_style)
86
+ return
87
+ elsif !config_to_allow_offenses.key?('Enabled')
88
+ config_to_allow_offenses['EnforcedStyleForEmptyBraces'] = used_style.to_s
89
+ end
87
90
 
88
91
  if style_for_empty_braces == :space
89
- add_offense(left_brace, message: MISSING_MSG) do |corrector|
90
- autocorrect(corrector, left_brace)
91
- end
92
+ range = left_brace
93
+ msg = MISSING_MSG
92
94
  else
93
- space = range_between(space_plus_brace.begin_pos, left_brace.begin_pos)
94
- add_offense(space, message: DETECTED_MSG) do |corrector|
95
- autocorrect(corrector, space)
96
- end
95
+ range = range_between(space_plus_brace.begin_pos, left_brace.begin_pos)
96
+ msg = DETECTED_MSG
97
+ end
98
+ add_offense(range, message: msg) { |corrector| autocorrect(corrector, range) }
99
+ end
100
+
101
+ def handle_different_styles_for_empty_braces(used_style)
102
+ if config_to_allow_offenses['EnforcedStyleForEmptyBraces'] &&
103
+ config_to_allow_offenses['EnforcedStyleForEmptyBraces'].to_sym != used_style
104
+ config_to_allow_offenses.clear
105
+ config_to_allow_offenses['Enabled'] = false
97
106
  end
98
107
  end
99
108
 
@@ -116,7 +116,7 @@ module RuboCop
116
116
 
117
117
  def incorrect_style_detected(token1, token2,
118
118
  expect_space, is_empty_braces)
119
- brace = (token1.text == '{' ? token1 : token2).pos
119
+ brace = (token1.left_brace? ? token1 : token2).pos
120
120
  range = expect_space ? brace : space_range(brace)
121
121
  detected_style = expect_space ? 'no_space' : 'space'
122
122
 
@@ -104,7 +104,7 @@ module RuboCop
104
104
  def correct_other_branches(corrector, node)
105
105
  return unless require_other_branches_correction?(node)
106
106
 
107
- if node.else_branch&.if_type?
107
+ if node.else_branch&.if_type? && !node.else_branch.modifier_form?
108
108
  # Replace an orphaned `elsif` with `if`
109
109
  corrector.replace(node.else_branch.loc.keyword, 'if')
110
110
  else
@@ -5,7 +5,8 @@ module RuboCop
5
5
  module Lint
6
6
  # Checks for redundant safe navigation calls.
7
7
  # Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
8
- # and an offense is not detected when the receiver is a snake case constant.
8
+ # and an offense is not detected when the receiver is a constant. The detection also applies
9
+ # to literal receivers, except for `nil`.
9
10
  #
10
11
  # For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
11
12
  # and `equal?` methods are checked by default.
@@ -76,10 +77,9 @@ module RuboCop
76
77
  #
77
78
  class RedundantSafeNavigation < Base
78
79
  include AllowedMethods
79
- include RangeHelp
80
80
  extend AutoCorrector
81
81
 
82
- MSG = 'Redundant safe navigation detected.'
82
+ MSG = 'Redundant safe navigation detected, use `.` instead.'
83
83
  MSG_LITERAL = 'Redundant safe navigation with default literal detected.'
84
84
 
85
85
  NIL_SPECIFIC_METHODS = (nil.methods - Object.new.methods).to_set.freeze
@@ -105,24 +105,23 @@ module RuboCop
105
105
 
106
106
  # rubocop:disable Metrics/AbcSize
107
107
  def on_csend(node)
108
- unless node.receiver.const_type? && !node.receiver.source.match?(SNAKE_CASE)
108
+ unless assume_receiver_instance_exists?(node.receiver)
109
109
  return unless check?(node) && allowed_method?(node.method_name)
110
110
  return if respond_to_nil_specific_method?(node)
111
111
  end
112
112
 
113
- range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
114
- add_offense(range) { |corrector| corrector.replace(node.loc.dot, '.') }
113
+ range = node.loc.dot
114
+ add_offense(range) { |corrector| corrector.replace(range, '.') }
115
115
  end
116
116
 
117
117
  def on_or(node)
118
118
  conversion_with_default?(node) do |send_node|
119
- range = range_between(send_node.loc.dot.begin_pos, node.source_range.end_pos)
119
+ range = send_node.loc.dot.begin.join(node.source_range.end)
120
120
 
121
121
  add_offense(range, message: MSG_LITERAL) do |corrector|
122
122
  corrector.replace(send_node.loc.dot, '.')
123
123
 
124
- range_with_default = range_between(node.lhs.source_range.end.begin_pos,
125
- node.source_range.end.end_pos)
124
+ range_with_default = node.lhs.source_range.end.begin.join(node.source_range.end)
126
125
  corrector.remove(range_with_default)
127
126
  end
128
127
  end
@@ -131,6 +130,12 @@ module RuboCop
131
130
 
132
131
  private
133
132
 
133
+ def assume_receiver_instance_exists?(receiver)
134
+ return true if receiver.const_type? && !receiver.source.match?(SNAKE_CASE)
135
+
136
+ receiver.literal? && !receiver.nil_type?
137
+ end
138
+
134
139
  def check?(node)
135
140
  parent = node.parent
136
141
  return false unless parent
@@ -59,9 +59,7 @@ module RuboCop
59
59
 
60
60
  def autocorrect(corrector, node)
61
61
  rescued, _, _body = *node
62
- range = Parser::Source::Range.new(node.source_range.source_buffer,
63
- node.loc.keyword.end_pos,
64
- rescued.source_range.end_pos)
62
+ range = node.loc.keyword.end.join(rescued.source_range.end)
65
63
 
66
64
  corrector.replace(range, correction(*rescued))
67
65
  end
@@ -46,14 +46,14 @@ module RuboCop
46
46
  message = format_message_from(processed_source)
47
47
 
48
48
  add_offense(comment, message: message) do
49
- autocorrect(comment) if autocorrect_requested?
49
+ autocorrect if autocorrect_requested?
50
50
  end
51
51
  end
52
52
 
53
53
  private
54
54
 
55
- def autocorrect(comment)
56
- FileUtils.chmod('+x', comment.source_range.source_buffer.name)
55
+ def autocorrect
56
+ FileUtils.chmod('+x', processed_source.file_path)
57
57
  end
58
58
 
59
59
  def executable?(processed_source)
@@ -17,7 +17,7 @@ module RuboCop
17
17
  private
18
18
 
19
19
  def add_offense_from_diagnostic(diagnostic, ruby_version)
20
- message = if lsp_mode?
20
+ message = if LSP.enabled?
21
21
  diagnostic.message
22
22
  else
23
23
  "#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
@@ -51,8 +51,13 @@ module RuboCop
51
51
  enum_conversion_call?(node) do |method_node, arguments|
52
52
  next if method_node.call_type? &&
53
53
  !method_node.method?(:__method__) && !method_node.method?(:__callee__)
54
- next if method_name?(method_node, def_node.method_name) &&
55
- arguments_match?(arguments, def_node)
54
+
55
+ valid = if method_name?(method_node, def_node.method_name)
56
+ arguments_match?(arguments, def_node)
57
+ else
58
+ def_node.arguments.empty?
59
+ end
60
+ return if valid
56
61
 
57
62
  add_offense(node)
58
63
  end
@@ -100,7 +100,12 @@ module RuboCop
100
100
  expressions = *node
101
101
  expressions.pop unless in_void_context?(node)
102
102
  expressions.each do |expr|
103
- check_void_op(expr)
103
+ check_void_op(expr) do
104
+ block_node = node.each_ancestor(:block).first
105
+
106
+ block_node&.method?(:each)
107
+ end
108
+
104
109
  check_expression(expr)
105
110
  end
106
111
  end
@@ -99,7 +99,7 @@ module RuboCop
99
99
  !(method_name.start_with?(prefix) && # cheap check to avoid allocating Regexp
100
100
  method_name.match?(/^#{prefix}[^0-9]/)) ||
101
101
  method_name == expected_name(method_name, prefix) ||
102
- method_name.end_with?('=') || # rubocop:todo InternalAffairs/MethodNameEndWith
102
+ method_name.end_with?('=') ||
103
103
  allowed_method?(method_name)
104
104
  end
105
105
 
@@ -109,7 +109,7 @@ module RuboCop
109
109
  else
110
110
  method_name.dup
111
111
  end
112
- new_name << '?' unless method_name.end_with?('?') # rubocop:todo InternalAffairs/MethodNameEndWith
112
+ new_name << '?' unless method_name.end_with?('?')
113
113
  new_name
114
114
  end
115
115
 
@@ -300,7 +300,7 @@ module RuboCop
300
300
  unless given_badge.match?(real_badge)
301
301
  path = PathUtil.smart_path(source_path)
302
302
  warn "#{path}: #{given_badge} has the wrong namespace - " \
303
- "should be #{real_badge.department}"
303
+ "replace it with #{given_badge.with_department(real_badge.department)}"
304
304
  end
305
305
 
306
306
  real_badge.to_s
@@ -8,6 +8,12 @@ module RuboCop
8
8
  # This cop identifies places where `do_something(*args, &block)`
9
9
  # can be replaced by `do_something(...)`.
10
10
  #
11
+ # In Ruby 3.1, anonymous block forwarding has been added.
12
+ #
13
+ # This cop identifies places where `do_something(&block)` can be replaced
14
+ # by `do_something(&)`; if desired, this functionality can be disabled
15
+ # by setting `UseAnonymousForwarding: false`.
16
+ #
11
17
  # In Ruby 3.2, anonymous args/kwargs forwarding has been added.
12
18
  #
13
19
  # This cop also identifies places where `use_args(*args)`/`use_kwargs(**kwargs)` can be
@@ -41,22 +47,25 @@ module RuboCop
41
47
  #
42
48
  # @example UseAnonymousForwarding: true (default, only relevant for Ruby >= 3.2)
43
49
  # # bad
44
- # def foo(*args, **kwargs)
50
+ # def foo(*args, **kwargs, &block)
45
51
  # args_only(*args)
46
52
  # kwargs_only(**kwargs)
53
+ # block_only(&block)
47
54
  # end
48
55
  #
49
56
  # # good
50
- # def foo(*, **)
57
+ # def foo(*, **, &)
51
58
  # args_only(*)
52
59
  # kwargs_only(**)
60
+ # block_only(&)
53
61
  # end
54
62
  #
55
63
  # @example UseAnonymousForwarding: false (only relevant for Ruby >= 3.2)
56
64
  # # good
57
- # def foo(*args, **kwargs)
65
+ # def foo(*args, **kwargs, &block)
58
66
  # args_only(*args)
59
67
  # kwargs_only(**kwargs)
68
+ # block_only(&block)
60
69
  # end
61
70
  #
62
71
  # @example AllowOnlyRestArgument: true (default, only relevant for Ruby < 3.2)
@@ -179,9 +188,12 @@ module RuboCop
179
188
 
180
189
  send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
181
190
  if !forward_rest && !forward_kwrest
182
- register_forward_block_arg_offense(!forward_rest, node.arguments, block_arg)
183
- register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
184
-
191
+ # Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
192
+ # in Ruby 3.3.0.
193
+ if outside_block?(forward_block_arg)
194
+ register_forward_block_arg_offense(!forward_rest, node.arguments, block_arg)
195
+ register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
196
+ end
185
197
  registered_block_arg_offense = true
186
198
  break
187
199
  else
@@ -196,12 +208,13 @@ module RuboCop
196
208
  end
197
209
  # rubocop:enable Metrics/MethodLength
198
210
 
211
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
199
212
  def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
200
213
  return unless use_anonymous_forwarding?
201
214
 
202
- rest_arg, kwrest_arg, _block_arg = *forwardable_args
215
+ rest_arg, kwrest_arg, block_arg = *forwardable_args
203
216
 
204
- send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, _forward_block_arg| # rubocop:disable Layout/LineLength
217
+ send_classifications.each do |send_node, _c, forward_rest, forward_kwrest, forward_block_arg| # rubocop:disable Layout/LineLength
205
218
  if outside_block?(forward_rest)
206
219
  register_forward_args_offense(def_node.arguments, rest_arg)
207
220
  register_forward_args_offense(send_node, forward_rest)
@@ -211,8 +224,16 @@ module RuboCop
211
224
  register_forward_kwargs_offense(!forward_rest, def_node.arguments, kwrest_arg)
212
225
  register_forward_kwargs_offense(!forward_rest, send_node, forward_kwrest)
213
226
  end
227
+
228
+ # Prevents `anonymous block parameter is also used within block (SyntaxError)` occurs
229
+ # in Ruby 3.3.0.
230
+ if outside_block?(forward_block_arg)
231
+ register_forward_block_arg_offense(!forward_rest, def_node.arguments, block_arg)
232
+ register_forward_block_arg_offense(!forward_rest, send_node, forward_block_arg)
233
+ end
214
234
  end
215
235
  end
236
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
216
237
 
217
238
  def non_splat_or_block_pass_lvar_references(body)
218
239
  body.each_descendant(:lvar, :lvasgn).filter_map do |lvar|
@@ -230,7 +230,7 @@ module RuboCop
230
230
 
231
231
  def branch_conditions(node)
232
232
  conditions = []
233
- while node&.if_type?
233
+ while node&.if_type? && !node.ternary?
234
234
  conditions << node.condition
235
235
  node = node.else_branch
236
236
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../directive_comment'
4
+
3
5
  module RuboCop
4
6
  module Cop
5
7
  module Style
@@ -49,8 +51,9 @@ module RuboCop
49
51
  KEYWORDS = %w[begin class def end module].freeze
50
52
  KEYWORD_REGEXES = KEYWORDS.map { |w| /^\s*#{w}\s/ }.freeze
51
53
 
52
- ALLOWED_COMMENTS = %w[:nodoc: :yields: rubocop:disable rubocop:todo].freeze
53
- ALLOWED_COMMENT_REGEXES = ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ }.freeze
54
+ ALLOWED_COMMENTS = %w[:nodoc: :yields:].freeze
55
+ ALLOWED_COMMENT_REGEXES = (ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ } +
56
+ [DirectiveComment::DIRECTIVE_COMMENT_REGEXP]).freeze
54
57
 
55
58
  REGEXP = /(?<keyword>\S+).*#/.freeze
56
59
 
@@ -115,8 +115,8 @@ module RuboCop
115
115
  end
116
116
 
117
117
  # Check for `if` and `case` statements where each branch is used for
118
- # assignment to the same variable when using the return of the
119
- # condition can be used instead.
118
+ # both the assignment and comparison of the same variable
119
+ # when using the return of the condition can be used instead.
120
120
  #
121
121
  # @example EnforcedStyle: assign_to_condition (default)
122
122
  # # bad
@@ -460,9 +460,8 @@ module RuboCop
460
460
 
461
461
  def assignment(node)
462
462
  *_, condition = *node
463
- Parser::Source::Range.new(node.source_range.source_buffer,
464
- node.source_range.begin_pos,
465
- condition.source_range.begin_pos)
463
+
464
+ node.source_range.begin.join(condition.source_range.begin)
466
465
  end
467
466
 
468
467
  def correct_if_branches(corrector, cop, node)
@@ -195,6 +195,7 @@ module RuboCop
195
195
  acceptable_19_syntax_symbol?(pair.key.source)
196
196
  end
197
197
 
198
+ # rubocop:disable Metrics/CyclomaticComplexity
198
199
  def acceptable_19_syntax_symbol?(sym_name)
199
200
  sym_name.delete_prefix!(':')
200
201
 
@@ -209,9 +210,12 @@ module RuboCop
209
210
  # Most hash keys can be matched against a simple regex.
210
211
  return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
211
212
 
212
- # For more complicated hash keys, let the parser validate the syntax.
213
- parse("{ #{sym_name}: :foo }").valid_syntax?
213
+ return false if target_ruby_version <= 2.1
214
+
215
+ (sym_name.start_with?("'") && sym_name.end_with?("'")) ||
216
+ (sym_name.start_with?('"') && sym_name.end_with?('"'))
214
217
  end
218
+ # rubocop:enable Metrics/CyclomaticComplexity
215
219
 
216
220
  def check(pairs, delim, msg)
217
221
  pairs.each do |pair|