rubocop 1.50.1 → 1.51.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/config/default.yml +20 -3
  4. data/lib/rubocop/config.rb +4 -0
  5. data/lib/rubocop/config_obsoletion.rb +2 -2
  6. data/lib/rubocop/cop/base.rb +4 -0
  7. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
  8. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -1
  9. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  10. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
  11. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +25 -34
  12. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +7 -19
  13. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +42 -52
  14. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +38 -55
  15. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  16. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +8 -27
  17. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +7 -26
  18. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +4 -21
  19. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +6 -30
  20. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
  21. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +12 -1
  22. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  23. data/lib/rubocop/cop/lint/erb_new_arguments.rb +2 -2
  24. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -2
  25. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  26. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  27. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
  28. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
  29. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  30. data/lib/rubocop/cop/lint/useless_assignment.rb +56 -1
  31. data/lib/rubocop/cop/lint/void.rb +62 -6
  32. data/lib/rubocop/cop/mixin/comments_help.rb +6 -2
  33. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  34. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  35. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +22 -7
  36. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
  37. data/lib/rubocop/cop/style/attr.rb +11 -1
  38. data/lib/rubocop/cop/style/collection_compact.rb +13 -6
  39. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  40. data/lib/rubocop/cop/style/combinable_loops.rb +26 -6
  41. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  42. data/lib/rubocop/cop/style/copyright.rb +5 -2
  43. data/lib/rubocop/cop/style/documentation.rb +1 -1
  44. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  45. data/lib/rubocop/cop/style/exact_regexp_match.rb +62 -0
  46. data/lib/rubocop/cop/style/guard_clause.rb +2 -0
  47. data/lib/rubocop/cop/style/hash_except.rb +19 -8
  48. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  49. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
  50. data/lib/rubocop/cop/style/invertible_unless_condition.rb +9 -5
  51. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  52. data/lib/rubocop/cop/style/redundant_fetch_block.rb +6 -4
  53. data/lib/rubocop/cop/style/redundant_line_continuation.rb +5 -1
  54. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  55. data/lib/rubocop/cop/style/require_order.rb +9 -4
  56. data/lib/rubocop/cop/style/semicolon.rb +12 -1
  57. data/lib/rubocop/cop/style/special_global_vars.rb +2 -2
  58. data/lib/rubocop/cop/team.rb +1 -1
  59. data/lib/rubocop/cop/variable_force/assignment.rb +4 -0
  60. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  61. data/lib/rubocop/result_cache.rb +1 -1
  62. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  63. data/lib/rubocop/target_ruby.rb +3 -2
  64. data/lib/rubocop/version.rb +3 -3
  65. data/lib/rubocop.rb +1 -0
  66. metadata +5 -4
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Ensures that each key in a multi-line hash
7
7
  # starts on a separate line.
8
8
  #
9
- # @example AllowMultilineFinalElement: false (default)
9
+ # @example
10
10
  #
11
11
  # # bad
12
12
  # {
@@ -14,11 +14,6 @@ module RuboCop
14
14
  # c: 3
15
15
  # }
16
16
  #
17
- # # bad
18
- # { a: 1, b: {
19
- # c: 3,
20
- # }}
21
- #
22
17
  # # good
23
18
  # {
24
19
  # a: 1,
@@ -34,34 +29,20 @@ module RuboCop
34
29
  # }
35
30
  # }
36
31
  #
37
- # @example AllowMultilineFinalElement: true
32
+ # @example AllowMultilineFinalElement: false (default)
38
33
  #
39
34
  # # bad
40
- # {
41
- # a: 1, b: 2,
42
- # c: 3
43
- # }
44
- #
45
- # # good
46
35
  # { a: 1, b: {
47
36
  # c: 3,
48
37
  # }}
49
38
  #
50
- # # good
51
- # {
52
- # a: 1,
53
- # b: 2,
54
- # c: 3
55
- # }
56
- #
39
+ # @example AllowMultilineFinalElement: true
57
40
  #
58
41
  # # good
59
- # {
60
- # a: 1,
61
- # b: {
62
- # c: 3,
63
- # }
64
- # }
42
+ # { a: 1, b: {
43
+ # c: 3,
44
+ # }}
45
+ #
65
46
  class MultilineHashKeyLineBreaks < Base
66
47
  include MultilineElementLineBreaks
67
48
  extend AutoCorrector
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # NOTE: This cop does not move the first argument, if you want that to
10
10
  # be on a separate line, see `Layout/FirstMethodArgumentLineBreak`.
11
11
  #
12
- # @example AllowMultilineFinalElement: false (default)
12
+ # @example
13
13
  #
14
14
  # # bad
15
15
  # foo(a, b,
@@ -31,6 +31,8 @@ module RuboCop
31
31
  # # good
32
32
  # foo(a, b, c)
33
33
  #
34
+ # @example AllowMultilineFinalElement: false (default)
35
+ #
34
36
  # # good
35
37
  # foo(
36
38
  # a,
@@ -42,26 +44,6 @@ module RuboCop
42
44
  #
43
45
  # @example AllowMultilineFinalElement: true
44
46
  #
45
- # # bad
46
- # foo(a, b,
47
- # c
48
- # )
49
- #
50
- # # good
51
- # foo(a, b, {
52
- # foo: "bar",
53
- # })
54
- #
55
- # # good
56
- # foo(
57
- # a,
58
- # b,
59
- # c
60
- # )
61
- #
62
- # # good
63
- # foo(a, b, c)
64
- #
65
47
  # # good
66
48
  # foo(
67
49
  # a,
@@ -70,6 +52,7 @@ module RuboCop
70
52
  # foo: "bar",
71
53
  # }
72
54
  # )
55
+ #
73
56
  class MultilineMethodArgumentLineBreaks < Base
74
57
  include MultilineElementLineBreaks
75
58
  extend AutoCorrector
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # NOTE: This cop does not move the first argument, if you want that to
10
10
  # be on a separate line, see `Layout/FirstMethodParameterLineBreak`.
11
11
  #
12
- # @example AllowMultilineFinalElement: false (default)
12
+ # @example
13
13
  #
14
14
  # # bad
15
15
  # def foo(a, b,
@@ -17,12 +17,6 @@ module RuboCop
17
17
  # )
18
18
  # end
19
19
  #
20
- # # bad
21
- # def foo(a, b = {
22
- # foo: "bar",
23
- # })
24
- # end
25
- #
26
20
  # # good
27
21
  # def foo(
28
22
  # a,
@@ -44,40 +38,22 @@ module RuboCop
44
38
  # def foo(a, b, c)
45
39
  # end
46
40
  #
47
- # @example AllowMultilineFinalElement: true
41
+ # @example AllowMultilineFinalElement: false (default)
48
42
  #
49
43
  # # bad
50
- # def foo(a, b,
51
- # c
52
- # )
53
- # end
54
- #
55
- # # good
56
44
  # def foo(a, b = {
57
45
  # foo: "bar",
58
46
  # })
59
47
  # end
60
48
  #
61
- # # good
62
- # def foo(
63
- # a,
64
- # b,
65
- # c
66
- # )
67
- # end
49
+ # @example AllowMultilineFinalElement: true
68
50
  #
69
51
  # # good
70
- # def foo(
71
- # a,
72
- # b = {
73
- # foo: "bar",
74
- # }
75
- # )
52
+ # def foo(a, b = {
53
+ # foo: "bar",
54
+ # })
76
55
  # end
77
56
  #
78
- # # good
79
- # def foo(a, b, c)
80
- # end
81
57
  class MultilineMethodParameterLineBreaks < Base
82
58
  include MultilineElementLineBreaks
83
59
  extend AutoCorrector
@@ -236,6 +236,8 @@ module RuboCop
236
236
  end
237
237
 
238
238
  def offense(begin_pos, end_pos, msg, style_param = 'EnforcedStyle')
239
+ return if begin_pos > end_pos
240
+
239
241
  range = range_between(begin_pos, end_pos)
240
242
  add_offense(range, message: msg) do |corrector|
241
243
  case range.source
@@ -52,6 +52,8 @@ module RuboCop
52
52
  # expect { do_something }.to not_change { object.attribute }
53
53
  #
54
54
  class AmbiguousBlockAssociation < Base
55
+ extend AutoCorrector
56
+
55
57
  include AllowedMethods
56
58
  include AllowedPattern
57
59
 
@@ -68,7 +70,9 @@ module RuboCop
68
70
 
69
71
  message = message(node)
70
72
 
71
- add_offense(node, message: message)
73
+ add_offense(node, message: message) do |corrector|
74
+ wrap_in_parentheses(corrector, node)
75
+ end
72
76
  end
73
77
  alias on_csend on_send
74
78
 
@@ -89,6 +93,13 @@ module RuboCop
89
93
 
90
94
  format(MSG, param: block_param.source, method: block_param.send_node.source)
91
95
  end
96
+
97
+ def wrap_in_parentheses(corrector, node)
98
+ range = node.loc.selector.end.join(node.first_argument.source_range.begin)
99
+
100
+ corrector.replace(range, '(')
101
+ corrector.insert_after(node.last_argument, ')')
102
+ end
92
103
  end
93
104
  end
94
105
  end
@@ -107,7 +107,7 @@ module RuboCop
107
107
 
108
108
  def pattern_identity(pattern)
109
109
  pattern_source = if pattern.hash_pattern_type? || pattern.match_alt_type?
110
- pattern.children.map(&:source).sort
110
+ pattern.children.map(&:source).sort.to_s
111
111
  else
112
112
  pattern.source
113
113
  end
@@ -8,9 +8,9 @@ module RuboCop
8
8
  #
9
9
  # [source,console]
10
10
  # ----
11
- # % cat example.rb
11
+ # $ cat example.rb
12
12
  # ERB.new('hi', nil, '-', '@output_buffer')
13
- # % ruby -rerb example.rb
13
+ # $ ruby -rerb example.rb
14
14
  # example.rb:1: warning: Passing safe_level with the 2nd argument of ERB.new is
15
15
  # deprecated. Do not use it, and specify other arguments as keyword arguments.
16
16
  # example.rb:1: warning: Passing trim_mode with the 3rd argument of ERB.new is
@@ -6,6 +6,9 @@ module RuboCop
6
6
  #
7
7
  # This cop checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.
8
8
  #
9
+ # When an array of IO objects waiting for an exception (the third argument of `IO.select`)
10
+ # is used as an argument, there is no alternative API, so offenses are not registered.
11
+ #
9
12
  # NOTE: When the method is successful the return value of `IO.select` is `[[IO]]`,
10
13
  # and the return value of `io.wait_readable` and `io.wait_writable` are `self`.
11
14
  # They are not autocorrected when assigning a return value because these types are different.
@@ -42,8 +45,8 @@ module RuboCop
42
45
  PATTERN
43
46
 
44
47
  def on_send(node)
45
- read, write, _excepts, timeout = *io_select(node)
46
- return unless read
48
+ read, write, excepts, timeout = *io_select(node)
49
+ return if excepts && !excepts.children.empty?
47
50
  return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read)
48
51
 
49
52
  preferred = preferred_method(read, write, timeout)
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Checks uses of lambda without a literal block.
7
7
  # It emulates the following warning in Ruby 3.0:
8
8
  #
9
- # % ruby -vwe 'lambda(&proc {})'
9
+ # $ ruby -vwe 'lambda(&proc {})'
10
10
  # ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
11
11
  # -e:1: warning: lambda without a literal block is deprecated; use the proc without
12
12
  # lambda instead
@@ -6,13 +6,13 @@ module RuboCop
6
6
  # Checks for uses of numbered parameter assignment.
7
7
  # It emulates the following warning in Ruby 2.7:
8
8
  #
9
- # % ruby -ve '_1 = :value'
9
+ # $ ruby -ve '_1 = :value'
10
10
  # ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
11
11
  # -e:1: warning: `_1' is reserved for numbered parameter; consider another name
12
12
  #
13
13
  # Assigning to a numbered parameter (from `_1` to `_9`) causes an error in Ruby 3.0.
14
14
  #
15
- # % ruby -ve '_1 = :value'
15
+ # $ ruby -ve '_1 = :value'
16
16
  # ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
17
17
  # -e:1: _1 is reserved for numbered parameter
18
18
  #
@@ -65,13 +65,13 @@ module RuboCop
65
65
  def on_when(node)
66
66
  regexp_conditions = node.conditions.select(&:regexp_type?)
67
67
 
68
- @valid_ref = regexp_conditions.map { |condition| check_regexp(condition) }.compact.max
68
+ @valid_ref = regexp_conditions.filter_map { |condition| check_regexp(condition) }.max
69
69
  end
70
70
 
71
71
  def on_in_pattern(node)
72
72
  regexp_patterns = regexp_patterns(node)
73
73
 
74
- @valid_ref = regexp_patterns.map { |pattern| check_regexp(pattern) }.compact.max
74
+ @valid_ref = regexp_patterns.filter_map { |pattern| check_regexp(pattern) }.max
75
75
  end
76
76
 
77
77
  def on_nth_ref(node)
@@ -47,7 +47,7 @@ module RuboCop
47
47
  return if node.receiver
48
48
 
49
49
  node.each_child_node(:send) do |child|
50
- next unless child.method?(:to_s)
50
+ next if !child.method?(:to_s) || child.arguments.any?
51
51
 
52
52
  register_offense(child, "`#{node.method_name}`")
53
53
  end
@@ -8,25 +8,39 @@ module RuboCop
8
8
  # always ignored. This is detected automatically since Ruby 2.7.
9
9
  #
10
10
  # @example
11
+ # # bad
12
+ # return 1
11
13
  #
12
- # # Detected since Ruby 2.7
13
- # return 1 # 1 is always ignored.
14
+ # # good
15
+ # return
14
16
  class TopLevelReturnWithArgument < Base
15
- # This cop works by validating the ancestors of the return node. A
16
- # top-level return node's ancestors should not be of block, def, or
17
- # defs type.
17
+ extend AutoCorrector
18
18
 
19
19
  MSG = 'Top level return with argument detected.'
20
20
 
21
21
  def on_return(return_node)
22
- add_offense(return_node) if return_node.arguments? && ancestors_valid?(return_node)
22
+ return unless top_level_return_with_any_argument?(return_node)
23
+
24
+ add_offense(return_node) do |corrector|
25
+ remove_arguments(corrector, return_node)
26
+ end
23
27
  end
24
28
 
25
29
  private
26
30
 
27
- def ancestors_valid?(return_node)
28
- prohibited_ancestors = return_node.each_ancestor(:block, :def, :defs)
29
- prohibited_ancestors.none?
31
+ def top_level_return_with_any_argument?(return_node)
32
+ top_level_return?(return_node) && return_node.arguments?
33
+ end
34
+
35
+ def remove_arguments(corrector, return_node)
36
+ corrector.replace(return_node, 'return')
37
+ end
38
+
39
+ # This cop works by validating the ancestors of the return node. A
40
+ # top-level return node's ancestors should not be of block, def, or
41
+ # defs type.
42
+ def top_level_return?(return_node)
43
+ return_node.each_ancestor(:block, :def, :defs).none?
30
44
  end
31
45
  end
32
46
  end
@@ -13,6 +13,12 @@ module RuboCop
13
13
  # reassignments and properly handles varied cases such as branch, loop,
14
14
  # rescue, ensure, etc.
15
15
  #
16
+ # @safety
17
+ # This cop's autocorrection is unsafe because removing assignment from
18
+ # operator assignment can cause NameError if this assignment has been used to declare
19
+ # local variable. For example, replacing `a ||= 1` to `a || 1` may cause
20
+ # "undefined local variable or method `a' for main:Object (NameError)".
21
+ #
16
22
  # @example
17
23
  #
18
24
  # # bad
@@ -31,6 +37,10 @@ module RuboCop
31
37
  # do_something(some_var)
32
38
  # end
33
39
  class UselessAssignment < Base
40
+ extend AutoCorrector
41
+
42
+ include RangeHelp
43
+
34
44
  MSG = 'Useless assignment to variable - `%<variable>s`.'
35
45
 
36
46
  def self.joining_forces
@@ -55,7 +65,9 @@ module RuboCop
55
65
  assignment.node.loc.name
56
66
  end
57
67
 
58
- add_offense(location, message: message)
68
+ add_offense(location, message: message) do |corrector|
69
+ autocorrect(corrector, assignment)
70
+ end
59
71
  end
60
72
  end
61
73
 
@@ -119,6 +131,49 @@ module RuboCop
119
131
 
120
132
  node.receiver.nil? && !node.arguments?
121
133
  end
134
+
135
+ def autocorrect(corrector, assignment)
136
+ if assignment.exception_assignment?
137
+ remove_exception_assignment_part(corrector, assignment.node)
138
+ elsif assignment.multiple_assignment?
139
+ rename_variable_with_underscore(corrector, assignment.node)
140
+ elsif assignment.operator_assignment?
141
+ remove_trailing_character_from_operator(corrector, assignment.node)
142
+ elsif assignment.regexp_named_capture?
143
+ replace_named_capture_group_with_non_capturing_group(corrector, assignment.node,
144
+ assignment.variable.name)
145
+ else
146
+ remove_local_variable_assignment_part(corrector, assignment.node)
147
+ end
148
+ end
149
+
150
+ def remove_exception_assignment_part(corrector, node)
151
+ corrector.remove(
152
+ range_between(
153
+ (node.parent.children.first&.source_range || node.parent.location.keyword).end_pos,
154
+ node.source_range.end_pos
155
+ )
156
+ )
157
+ end
158
+
159
+ def rename_variable_with_underscore(corrector, node)
160
+ corrector.replace(node, '_')
161
+ end
162
+
163
+ def remove_trailing_character_from_operator(corrector, node)
164
+ corrector.remove(node.parent.location.operator.end.adjust(begin_pos: -1))
165
+ end
166
+
167
+ def replace_named_capture_group_with_non_capturing_group(corrector, node, variable_name)
168
+ corrector.replace(
169
+ node.children.first,
170
+ node.children.first.source.sub(/\(\?<#{variable_name}>/, '(?:')
171
+ )
172
+ end
173
+
174
+ def remove_local_variable_assignment_part(corrector, node)
175
+ corrector.replace(node, node.expression.source)
176
+ end
122
177
  end
123
178
  end
124
179
  end
@@ -41,6 +41,10 @@ module RuboCop
41
41
  # do_something(some_array)
42
42
  # end
43
43
  class Void < Base
44
+ extend AutoCorrector
45
+
46
+ include RangeHelp
47
+
44
48
  OP_MSG = 'Operator `%<op>s` used in void context.'
45
49
  VAR_MSG = 'Variable `%<var>s` used in void context.'
46
50
  LIT_MSG = 'Literal `%<lit>s` used in void context.'
@@ -100,31 +104,43 @@ module RuboCop
100
104
  def check_void_op(node)
101
105
  return unless node.send_type? && OPERATORS.include?(node.method_name)
102
106
 
103
- add_offense(node.loc.selector, message: format(OP_MSG, op: node.method_name))
107
+ add_offense(node.loc.selector,
108
+ message: format(OP_MSG, op: node.method_name)) do |corrector|
109
+ autocorrect_void_op(corrector, node)
110
+ end
104
111
  end
105
112
 
106
113
  def check_var(node)
107
114
  return unless node.variable? || node.const_type?
108
115
 
109
- add_offense(node.loc.name, message: format(VAR_MSG, var: node.loc.name.source))
116
+ add_offense(node.loc.name,
117
+ message: format(VAR_MSG, var: node.loc.name.source)) do |corrector|
118
+ autocorrect_void_var(corrector, node)
119
+ end
110
120
  end
111
121
 
112
122
  def check_literal(node)
113
123
  return if !node.literal? || node.xstr_type? || node.range_type?
114
124
 
115
- add_offense(node, message: format(LIT_MSG, lit: node.source))
125
+ add_offense(node, message: format(LIT_MSG, lit: node.source)) do |corrector|
126
+ autocorrect_void_literal(corrector, node)
127
+ end
116
128
  end
117
129
 
118
130
  def check_self(node)
119
131
  return unless node.self_type?
120
132
 
121
- add_offense(node, message: SELF_MSG)
133
+ add_offense(node, message: SELF_MSG) do |corrector|
134
+ autocorrect_void_self(corrector, node)
135
+ end
122
136
  end
123
137
 
124
138
  def check_void_expression(node)
125
139
  return unless node.defined_type? || node.lambda_or_proc?
126
140
 
127
- add_offense(node, message: format(EXPRESSION_MSG, expression: node.source))
141
+ add_offense(node, message: format(EXPRESSION_MSG, expression: node.source)) do |corrector|
142
+ autocorrect_void_expression(corrector, node)
143
+ end
128
144
  end
129
145
 
130
146
  def check_nonmutating(node)
@@ -139,7 +155,10 @@ module RuboCop
139
155
  "#{method_name}!"
140
156
  end
141
157
  add_offense(node,
142
- message: format(NONMUTATING_MSG, method: method_name, suggest: suggestion))
158
+ message: format(NONMUTATING_MSG, method: method_name,
159
+ suggest: suggestion)) do |corrector|
160
+ autocorrect_nonmutating_send(corrector, node, suggestion)
161
+ end
143
162
  end
144
163
 
145
164
  def in_void_context?(node)
@@ -149,6 +168,43 @@ module RuboCop
149
168
 
150
169
  VOID_CONTEXT_TYPES.include?(parent.type) && parent.void_context?
151
170
  end
171
+
172
+ def autocorrect_void_op(corrector, node)
173
+ if node.arguments.empty?
174
+ corrector.replace(node, node.receiver.source)
175
+ else
176
+ corrector.replace(
177
+ range_with_surrounding_space(range: node.loc.selector, side: :both,
178
+ newlines: false),
179
+ "\n"
180
+ )
181
+ end
182
+ end
183
+
184
+ def autocorrect_void_var(corrector, node)
185
+ corrector.remove(range_with_surrounding_space(range: node.loc.name, side: :left))
186
+ end
187
+
188
+ def autocorrect_void_literal(corrector, node)
189
+ corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
190
+ end
191
+
192
+ def autocorrect_void_self(corrector, node)
193
+ corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
194
+ end
195
+
196
+ def autocorrect_void_expression(corrector, node)
197
+ corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
198
+ end
199
+
200
+ def autocorrect_nonmutating_send(corrector, node, suggestion)
201
+ send_node = if node.send_type?
202
+ node
203
+ else
204
+ node.send_node
205
+ end
206
+ corrector.replace(send_node.loc.selector, suggestion)
207
+ end
152
208
  end
153
209
  end
154
210
  end
@@ -62,12 +62,16 @@ module RuboCop
62
62
  # Returns the end line of a node, which might be a comment and not part of the AST
63
63
  # End line is considered either the line at which another node starts, or
64
64
  # the line at which the parent node ends.
65
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
65
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
66
66
  def find_end_line(node)
67
67
  if node.if_type? && node.else?
68
68
  node.loc.else.line
69
69
  elsif node.if_type? && node.ternary?
70
70
  node.else_branch.loc.line
71
+ elsif node.if_type? && node.elsif?
72
+ node.each_ancestor(:if).find(&:if?).loc.end.line
73
+ elsif node.block_type? || node.numblock_type?
74
+ node.loc.end.line
71
75
  elsif (next_sibling = node.right_sibling) && next_sibling.is_a?(AST::Node)
72
76
  next_sibling.loc.line
73
77
  elsif (parent = node.parent)
@@ -76,7 +80,7 @@ module RuboCop
76
80
  node.loc.end.line
77
81
  end
78
82
  end
79
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
83
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
80
84
  end
81
85
  end
82
86
  end
@@ -36,7 +36,7 @@ module RuboCop
36
36
  end
37
37
 
38
38
  def allowed_type?(token)
39
- %i[tRPAREN tRBRACK tPIPE].include?(token.type)
39
+ %i[tRPAREN tRBRACK tPIPE tSTRING_DEND].include?(token.type)
40
40
  end
41
41
 
42
42
  def space_forbidden_before_rcurly?
@@ -76,7 +76,7 @@ module RuboCop
76
76
  end
77
77
 
78
78
  def contains_constant?(node)
79
- node.branches.any?(&:const_type?)
79
+ node.branches.compact.any?(&:const_type?)
80
80
  end
81
81
  end
82
82
  end