rubocop 0.92.0 → 1.2.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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -7
  3. data/config/default.yml +169 -59
  4. data/exe/rubocop +1 -1
  5. data/lib/rubocop.rb +15 -3
  6. data/lib/rubocop/cached_data.rb +2 -1
  7. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  8. data/lib/rubocop/cli/command/version.rb +1 -1
  9. data/lib/rubocop/comment_config.rb +1 -1
  10. data/lib/rubocop/config.rb +4 -0
  11. data/lib/rubocop/config_loader.rb +19 -2
  12. data/lib/rubocop/config_loader_resolver.rb +7 -5
  13. data/lib/rubocop/config_validator.rb +7 -6
  14. data/lib/rubocop/cop/badge.rb +9 -24
  15. data/lib/rubocop/cop/base.rb +16 -1
  16. data/lib/rubocop/cop/bundler/duplicated_gem.rb +23 -3
  17. data/lib/rubocop/cop/commissioner.rb +36 -22
  18. data/lib/rubocop/cop/corrector.rb +3 -1
  19. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
  20. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  21. data/lib/rubocop/cop/force.rb +1 -1
  22. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
  23. data/lib/rubocop/cop/layout/class_structure.rb +7 -0
  24. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  25. data/lib/rubocop/cop/layout/dot_position.rb +6 -9
  26. data/lib/rubocop/cop/layout/else_alignment.rb +15 -2
  27. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -7
  28. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
  29. data/lib/rubocop/cop/layout/end_alignment.rb +3 -3
  30. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
  31. data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
  32. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
  33. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -11
  34. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
  35. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
  36. data/lib/rubocop/cop/layout/space_inside_parens.rb +35 -13
  37. data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
  38. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
  39. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
  40. data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
  41. data/lib/rubocop/cop/lint/debugger.rb +2 -3
  42. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
  43. data/lib/rubocop/cop/lint/else_layout.rb +29 -3
  44. data/lib/rubocop/cop/lint/empty_block.rb +59 -0
  45. data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
  46. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
  47. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +17 -3
  48. data/lib/rubocop/cop/lint/loop.rb +0 -4
  49. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  50. data/lib/rubocop/cop/lint/nested_percent_literal.rb +14 -0
  51. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +58 -0
  52. data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
  53. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
  54. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  55. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
  56. data/lib/rubocop/cop/lint/to_enum_arguments.rb +95 -0
  57. data/lib/rubocop/cop/lint/to_json.rb +1 -1
  58. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +185 -0
  59. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  60. data/lib/rubocop/cop/lint/useless_setter_call.rb +6 -1
  61. data/lib/rubocop/cop/metrics/block_length.rb +3 -1
  62. data/lib/rubocop/cop/metrics/class_length.rb +14 -6
  63. data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -1
  64. data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
  65. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  66. data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
  67. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +12 -2
  68. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +11 -5
  69. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +67 -18
  70. data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
  71. data/lib/rubocop/cop/naming/variable_number.rb +82 -8
  72. data/lib/rubocop/cop/offense.rb +18 -5
  73. data/lib/rubocop/cop/security/open.rb +12 -10
  74. data/lib/rubocop/cop/style/access_modifier_declarations.rb +6 -2
  75. data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
  76. data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
  77. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +0 -4
  78. data/lib/rubocop/cop/style/case_like_if.rb +18 -6
  79. data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
  80. data/lib/rubocop/cop/style/collection_compact.rb +85 -0
  81. data/lib/rubocop/cop/style/combinable_loops.rb +8 -1
  82. data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
  83. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +67 -0
  84. data/lib/rubocop/cop/style/double_negation.rb +6 -1
  85. data/lib/rubocop/cop/style/explicit_block_argument.rb +6 -2
  86. data/lib/rubocop/cop/style/for.rb +0 -4
  87. data/lib/rubocop/cop/style/format_string_token.rb +48 -3
  88. data/lib/rubocop/cop/style/hash_syntax.rb +3 -3
  89. data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -0
  90. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
  91. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -11
  92. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
  93. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  94. data/lib/rubocop/cop/style/mixin_grouping.rb +0 -4
  95. data/lib/rubocop/cop/style/multiple_comparison.rb +54 -7
  96. data/lib/rubocop/cop/style/negated_if_else_condition.rb +99 -0
  97. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
  98. data/lib/rubocop/cop/style/raise_args.rb +21 -9
  99. data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
  100. data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
  101. data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
  102. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
  103. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +45 -24
  104. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
  105. data/lib/rubocop/cop/style/redundant_self.rb +3 -0
  106. data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
  107. data/lib/rubocop/cop/style/semicolon.rb +3 -0
  108. data/lib/rubocop/cop/style/string_concatenation.rb +14 -2
  109. data/lib/rubocop/cop/style/swap_values.rb +108 -0
  110. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  111. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
  112. data/lib/rubocop/cop/team.rb +6 -1
  113. data/lib/rubocop/cop/util.rb +5 -1
  114. data/lib/rubocop/cop/variable_force/branch.rb +0 -4
  115. data/lib/rubocop/ext/regexp_node.rb +35 -11
  116. data/lib/rubocop/ext/regexp_parser.rb +84 -0
  117. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  118. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +47 -0
  119. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  120. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  121. data/lib/rubocop/magic_comment.rb +2 -2
  122. data/lib/rubocop/options.rb +6 -1
  123. data/lib/rubocop/result_cache.rb +8 -2
  124. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  125. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  126. data/lib/rubocop/runner.rb +4 -4
  127. data/lib/rubocop/target_finder.rb +23 -25
  128. data/lib/rubocop/version.rb +56 -6
  129. metadata +22 -8
  130. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
@@ -67,7 +67,8 @@ module RuboCop
67
67
  private
68
68
 
69
69
  def allowed_method_name?(method_name, prefix)
70
- !method_name.match?(/^#{prefix}[^0-9]/) ||
70
+ !(method_name.start_with?(prefix) && # cheap check to avoid allocating Regexp
71
+ method_name.match?(/^#{prefix}[^0-9]/)) ||
71
72
  method_name == expected_name(method_name, prefix) ||
72
73
  method_name.end_with?('=') ||
73
74
  allowed_method?(method_name)
@@ -7,42 +7,98 @@ module RuboCop
7
7
  # configured style, snake_case, normalcase, or non_integer,
8
8
  # for their numbering.
9
9
  #
10
+ # Additionally, `CheckMethodNames` and `CheckSymbols` configuration options
11
+ # can be used to specify whether method names and symbols should be checked.
12
+ # Both are enabled by default.
13
+ #
10
14
  # @example EnforcedStyle: snake_case
11
15
  # # bad
12
- #
16
+ # :some_sym1
13
17
  # variable1 = 1
14
18
  #
15
- # # good
19
+ # def some_method1; end
16
20
  #
21
+ # def some_method_1(arg1); end
22
+ #
23
+ # # good
24
+ # :some_sym_1
17
25
  # variable_1 = 1
18
26
  #
27
+ # def some_method_1; end
28
+ #
29
+ # def some_method_1(arg_1); end
30
+ #
19
31
  # @example EnforcedStyle: normalcase (default)
20
32
  # # bad
21
- #
33
+ # :some_sym_1
22
34
  # variable_1 = 1
23
35
  #
24
- # # good
36
+ # def some_method_1; end
25
37
  #
38
+ # def some_method1(arg_1); end
39
+ #
40
+ # # good
41
+ # :some_sym1
26
42
  # variable1 = 1
27
43
  #
44
+ # def some_method1; end
45
+ #
46
+ # def some_method1(arg1); end
47
+ #
28
48
  # @example EnforcedStyle: non_integer
29
49
  # # bad
50
+ # :some_sym1
51
+ # :some_sym_1
30
52
  #
31
53
  # variable1 = 1
32
- #
33
54
  # variable_1 = 1
34
55
  #
56
+ # def some_method1; end
57
+ #
58
+ # def some_method_1; end
59
+ #
60
+ # def some_methodone(arg1); end
61
+ # def some_methodone(arg_1); end
62
+ #
35
63
  # # good
64
+ # :some_symone
65
+ # :some_sym_one
36
66
  #
37
67
  # variableone = 1
38
- #
39
68
  # variable_one = 1
69
+ #
70
+ # def some_methodone; end
71
+ #
72
+ # def some_method_one; end
73
+ #
74
+ # def some_methodone(argone); end
75
+ # def some_methodone(arg_one); end
76
+ #
77
+ # # In the following examples, we assume `EnforcedStyle: normalcase` (default).
78
+ #
79
+ # @example CheckMethodNames: true (default)
80
+ # # bad
81
+ # def some_method_1; end
82
+ #
83
+ # @example CheckMethodNames: false
84
+ # # good
85
+ # def some_method_1; end
86
+ #
87
+ # @example CheckSymbols: true (default)
88
+ # # bad
89
+ # :some_sym_1
90
+ #
91
+ # @example CheckSymbols: false
92
+ # # good
93
+ # :some_sym_1
94
+ #
40
95
  class VariableNumber < Base
41
96
  include ConfigurableNumbering
42
97
 
43
- MSG = 'Use %<style>s for variable numbers.'
98
+ MSG = 'Use %<style>s for %<identifier_type>s numbers.'
44
99
 
45
100
  def on_arg(node)
101
+ @node = node
46
102
  name, = *node
47
103
  check_name(node, name, node.loc.name)
48
104
  end
@@ -50,10 +106,28 @@ module RuboCop
50
106
  alias on_ivasgn on_arg
51
107
  alias on_cvasgn on_arg
52
108
 
109
+ def on_def(node)
110
+ @node = node
111
+ check_name(node, node.method_name, node.loc.name) if cop_config['CheckMethodNames']
112
+ end
113
+ alias on_defs on_def
114
+
115
+ def on_sym(node)
116
+ @node = node
117
+ check_name(node, node.value, node) if cop_config['CheckSymbols']
118
+ end
119
+
53
120
  private
54
121
 
55
122
  def message(style)
56
- format(MSG, style: style)
123
+ identifier_type =
124
+ case @node.type
125
+ when :def, :defs then 'method name'
126
+ when :sym then 'symbol'
127
+ else 'variable'
128
+ end
129
+
130
+ format(MSG, style: style, identifier_type: identifier_type)
57
131
  end
58
132
  end
59
133
  end
@@ -63,10 +63,23 @@ module RuboCop
63
63
  attr_reader :corrector
64
64
 
65
65
  PseudoSourceRange = Struct.new(:line, :column, :source_line, :begin_pos,
66
- :end_pos)
66
+ :end_pos) do
67
+ alias_method :first_line, :line
68
+ alias_method :last_line, :line
69
+ alias_method :last_column, :column
70
+
71
+ def column_range
72
+ column...last_column
73
+ end
74
+
75
+ def size
76
+ end_pos - begin_pos
77
+ end
78
+ alias_method :length, :size
79
+ end
67
80
  private_constant :PseudoSourceRange
68
81
 
69
- NO_LOCATION = PseudoSourceRange.new(1, 0, '', 0, 1).freeze
82
+ NO_LOCATION = PseudoSourceRange.new(1, 0, '', 0, 0).freeze
70
83
 
71
84
  # @api private
72
85
  def initialize(severity, location, message, cop_name, # rubocop:disable Metrics/ParameterLists
@@ -200,7 +213,7 @@ module RuboCop
200
213
  # returns `true` if two offenses contain same attributes
201
214
  def ==(other)
202
215
  COMPARISON_ATTRIBUTES.all? do |attribute|
203
- send(attribute) == other.send(attribute)
216
+ public_send(attribute) == other.public_send(attribute)
204
217
  end
205
218
  end
206
219
 
@@ -208,7 +221,7 @@ module RuboCop
208
221
 
209
222
  def hash
210
223
  COMPARISON_ATTRIBUTES.reduce(0) do |hash, attribute|
211
- hash ^ send(attribute).hash
224
+ hash ^ public_send(attribute).hash
212
225
  end
213
226
  end
214
227
 
@@ -221,7 +234,7 @@ module RuboCop
221
234
  # comparison result
222
235
  def <=>(other)
223
236
  COMPARISON_ATTRIBUTES.each do |attribute|
224
- result = send(attribute) <=> other.send(attribute)
237
+ result = public_send(attribute) <=> other.public_send(attribute)
225
238
  return result unless result.zero?
226
239
  end
227
240
  0
@@ -3,35 +3,37 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Security
6
- # This cop checks for the use of `Kernel#open`.
6
+ # This cop checks for the use of `Kernel#open` and `URI.open`.
7
7
  #
8
- # `Kernel#open` enables not only file access but also process invocation
9
- # by prefixing a pipe symbol (e.g., `open("| ls")`). So, it may lead to
10
- # a serious security risk by using variable input to the argument of
11
- # `Kernel#open`. It would be better to use `File.open`, `IO.popen` or
12
- # `URI#open` explicitly.
8
+ # `Kernel#open` and `URI.open` enable not only file access but also process
9
+ # invocation by prefixing a pipe symbol (e.g., `open("| ls")`).
10
+ # So, it may lead to a serious security risk by using variable input to
11
+ # the argument of `Kernel#open` and `URI.open`. It would be better to use
12
+ # `File.open`, `IO.popen` or `URI.parse#open` explicitly.
13
13
  #
14
14
  # @example
15
15
  # # bad
16
16
  # open(something)
17
+ # URI.open(something)
17
18
  #
18
19
  # # good
19
20
  # File.open(something)
20
21
  # IO.popen(something)
21
22
  # URI.parse(something).open
22
23
  class Open < Base
23
- MSG = 'The use of `Kernel#open` is a serious security risk.'
24
+ MSG = 'The use of `%<receiver>sopen` is a serious security risk.'
24
25
  RESTRICT_ON_SEND = %i[open].freeze
25
26
 
26
27
  def_node_matcher :open?, <<~PATTERN
27
- (send nil? :open $!str ...)
28
+ (send ${nil? (const {nil? cbase} :URI)} :open $!str ...)
28
29
  PATTERN
29
30
 
30
31
  def on_send(node)
31
- open?(node) do |code|
32
+ open?(node) do |receiver, code|
32
33
  return if safe?(code)
33
34
 
34
- add_offense(node.loc.selector)
35
+ message = format(MSG, receiver: receiver ? "#{receiver.source}." : 'Kernel#')
36
+ add_offense(node.loc.selector, message: message)
35
37
  end
36
38
  end
37
39
 
@@ -83,8 +83,8 @@ module RuboCop
83
83
 
84
84
  def on_send(node)
85
85
  return unless node.access_modifier?
86
- return if node.parent.pair_type?
87
- return if cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node)
86
+ return if node.parent&.pair_type?
87
+ return if allow_modifiers_on_symbols?(node)
88
88
 
89
89
  if offense?(node)
90
90
  add_offense(node.loc.selector) if opposite_style_detected
@@ -95,6 +95,10 @@ module RuboCop
95
95
 
96
96
  private
97
97
 
98
+ def allow_modifiers_on_symbols?(node)
99
+ cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node)
100
+ end
101
+
98
102
  def offense?(node)
99
103
  (group_style? && access_modifier_is_inlined?(node)) ||
100
104
  (inline_style? && access_modifier_is_not_inlined?(node))
@@ -7,6 +7,9 @@ module RuboCop
7
7
  # By default it enforces accessors to be placed in grouped declarations,
8
8
  # but it can be configured to enforce separating them in multiple declarations.
9
9
  #
10
+ # NOTE: `Sorbet` is not compatible with "grouped" style. Consider "separated" style
11
+ # or disabling this cop.
12
+ #
10
13
  # @example EnforcedStyle: grouped (default)
11
14
  # # bad
12
15
  # class Foo
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # In Ruby 2.7, arguments forwarding has been added.
7
+ #
8
+ # This cop identifies places where `do_something(*args, &block)`
9
+ # can be replaced by `do_something(...)`.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # def foo(*args, &block)
14
+ # bar(*args, &block)
15
+ # end
16
+ #
17
+ # # bad
18
+ # def foo(*args, **kwargs, &block)
19
+ # bar(*args, **kwargs, &block)
20
+ # end
21
+ #
22
+ # # good
23
+ # def foo(...)
24
+ # bar(...)
25
+ # end
26
+ #
27
+ # @example AllowOnlyRestArgument: true (default)
28
+ # # good
29
+ # def foo(*args)
30
+ # bar(*args)
31
+ # end
32
+ #
33
+ # @example AllowOnlyRestArgument: false
34
+ # # bad
35
+ # # The following code can replace the arguments with `...`,
36
+ # # but it will change the behavior. Because `...` forwards block also.
37
+ # def foo(*args)
38
+ # bar(*args)
39
+ # end
40
+ #
41
+ class ArgumentsForwarding < Base
42
+ include RangeHelp
43
+ extend AutoCorrector
44
+ extend TargetRubyVersion
45
+
46
+ minimum_target_ruby_version 2.7
47
+
48
+ MSG = 'Use arguments forwarding.'
49
+
50
+ def_node_matcher :use_rest_arguments?, <<~PATTERN
51
+ (args (restarg $_) $...)
52
+ PATTERN
53
+
54
+ def_node_matcher :only_rest_arguments?, <<~PATTERN
55
+ (send _ _ (splat (lvar %1)))
56
+ PATTERN
57
+
58
+ def_node_matcher :forwarding_method_arguments?, <<~PATTERN
59
+ {
60
+ (send _ _
61
+ (splat (lvar %1))
62
+ (block-pass (lvar %2)))
63
+ (send _ _
64
+ (splat (lvar %1))
65
+ (hash (kwsplat (lvar %3)))
66
+ (block-pass (lvar %2)))
67
+ }
68
+ PATTERN
69
+
70
+ def on_def(node)
71
+ return unless node.body
72
+ return unless (rest_args_name, args = use_rest_arguments?(node.arguments))
73
+
74
+ node.each_descendant(:send) do |send_node|
75
+ kwargs_name, block_name = extract_argument_names_from(args)
76
+
77
+ next unless forwarding_method?(send_node, rest_args_name, kwargs_name, block_name) &&
78
+ all_lvars_as_forwarding_method_arguments?(node, send_node)
79
+
80
+ register_offense_to_forwarding_method_arguments(send_node)
81
+ register_offense_to_method_definition_arguments(node)
82
+ end
83
+ end
84
+ alias on_defs on_def
85
+
86
+ private
87
+
88
+ def extract_argument_names_from(args)
89
+ kwargs_name = args.first.source.delete('**') if args.first&.kwrestarg_type?
90
+ block_arg_name = args.last.source.delete('&') if args.last&.blockarg_type?
91
+
92
+ [kwargs_name, block_arg_name].map { |name| name&.to_sym }
93
+ end
94
+
95
+ def forwarding_method?(node, rest_arg, kwargs, block_arg)
96
+ return only_rest_arguments?(node, rest_arg) unless allow_only_rest_arguments?
97
+
98
+ forwarding_method_arguments?(node, rest_arg, block_arg, kwargs)
99
+ end
100
+
101
+ def all_lvars_as_forwarding_method_arguments?(def_node, forwarding_method)
102
+ lvars = def_node.body.each_descendant(:lvar, :lvasgn)
103
+
104
+ begin_pos = forwarding_method.source_range.begin_pos
105
+ end_pos = forwarding_method.source_range.end_pos
106
+
107
+ lvars.all? do |lvar|
108
+ lvar.source_range.begin_pos.between?(begin_pos, end_pos)
109
+ end
110
+ end
111
+
112
+ def register_offense_to_forwarding_method_arguments(forwarding_method)
113
+ add_offense(arguments_range(forwarding_method)) do |corrector|
114
+ range = range_between(
115
+ forwarding_method.loc.selector.end_pos, forwarding_method.source_range.end_pos
116
+ )
117
+ corrector.replace(range, '(...)')
118
+ end
119
+ end
120
+
121
+ def register_offense_to_method_definition_arguments(method_definition)
122
+ add_offense(arguments_range(method_definition)) do |corrector|
123
+ arguments_range = range_with_surrounding_space(
124
+ range: method_definition.arguments.source_range, side: :left
125
+ )
126
+ corrector.replace(arguments_range, '(...)')
127
+ end
128
+ end
129
+
130
+ def arguments_range(node)
131
+ arguments = node.arguments
132
+
133
+ range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
134
+ end
135
+
136
+ def allow_only_rest_arguments?
137
+ cop_config.fetch('AllowOnlyRestArgument', true)
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -131,10 +131,6 @@ module RuboCop
131
131
  "#{indent(macro)}#{macro.method_name} #{rest_args.map(&:source).join(', ')}"
132
132
  end
133
133
  end
134
-
135
- def indent(node)
136
- ' ' * node.loc.column
137
- end
138
134
  end
139
135
  end
140
136
  end
@@ -42,6 +42,8 @@ module RuboCop
42
42
  convertible = true
43
43
 
44
44
  branch_conditions(node).each do |branch_condition|
45
+ return false if regexp_with_working_captures?(branch_condition)
46
+
45
47
  conditions << []
46
48
  convertible = collect_conditions(branch_condition, target, conditions.last)
47
49
  break unless convertible
@@ -49,9 +51,7 @@ module RuboCop
49
51
 
50
52
  return unless convertible
51
53
 
52
- add_offense(node) do |corrector|
53
- autocorrect(corrector, node)
54
- end
54
+ add_offense(node) { |corrector| autocorrect(corrector, node) }
55
55
  end
56
56
 
57
57
  private
@@ -107,7 +107,7 @@ module RuboCop
107
107
  when :include?, :cover?
108
108
  receiver = deparenthesize(node.receiver)
109
109
  node.arguments.first if receiver.range_type?
110
- when :match, :match?
110
+ when :match, :match?, :=~
111
111
  find_target_in_match_node(node)
112
112
  end
113
113
  end
@@ -227,8 +227,20 @@ module RuboCop
227
227
  range_between(node.parent.loc.keyword.begin_pos, node.loc.expression.end_pos)
228
228
  end
229
229
 
230
- def indent(node)
231
- ' ' * node.loc.column
230
+ # Named captures work with `=~` (if regexp is on lhs) and with `match` (both sides)
231
+ def regexp_with_working_captures?(node)
232
+ case node.type
233
+ when :match_with_lvasgn
234
+ lhs, _rhs = *node
235
+ node.loc.selector.source == '=~' && regexp_with_named_captures?(lhs)
236
+ when :send
237
+ lhs, method, rhs = *node
238
+ method == :match && [lhs, rhs].any? { |n| regexp_with_named_captures?(n) }
239
+ end
240
+ end
241
+
242
+ def regexp_with_named_captures?(node)
243
+ node.regexp_type? && node.each_capture(named: true).count.positive?
232
244
  end
233
245
  end
234
246
  end