Skip to content

Commit

Permalink
[Fix rubocop#13677] Fix false negative on `Style/RedundantLineContinu…
Browse files Browse the repository at this point in the history
…ation` when the continuation is followed by a percent array

Previously, `start_with_arithmetic_operator?` used a regexp to check if the following line starts with an arithmetic operator (`+`, `-`, `*`, `/` or `%`). However, a percent array (eg. `%i[foo bar]`) also starts with a `%`, and as such, was being marked as a required continuation.

This has been corrected now to check against the first token of the line rather than the first character.

Additionally, the previous regex masked instances where arguments to an unparenthesized method call started with an arithmetic operator character; these cases are now properly handled.
  • Loading branch information
dvandersluis committed Jan 13, 2025
1 parent f852457 commit edb6f2b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog/fix_fix_false_negative_on.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#13677](https://github.com/rubocop/rubocop/issues/13677): Fix false negative on `Style/RedundantLineContinuation` when the continuation is followed by a percent array. ([@dvandersluis][])
12 changes: 8 additions & 4 deletions lib/rubocop/cop/style/redundant_line_continuation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,12 @@ class RedundantLineContinuation < Base
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
ARGUMENT_TYPES = %i[
kDEF kFALSE kNIL kSELF kTRUE tCOLON3 tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER
tIVAR tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
tIVAR tLBRACK tLAMBDA tLCURLY tLPAREN_ARG tQSYMBOLS_BEG tQWORDS_BEG tREGEXP_BEG tSTRING
tSTRING_BEG tSYMBEG tSYMBOL tSYMBOLS_BEG tUMINUS tUPLUS tUNARY_NUM tWORDS_BEG
tXSTRING_BEG
].freeze
ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[tIDENTIFIER kRETURN kBREAK kNEXT kYIELD].freeze
ARITHMETIC_OPERATOR_TOKENS = %i[tPLUS tMINUS tSTAR2 tDIVIDE tPERCENT].freeze

def on_new_investigation
return unless processed_source.ast
Expand All @@ -98,7 +101,7 @@ def on_new_investigation
def require_line_continuation?(range)
!ends_with_backslash_without_comment?(range.source_line) ||
string_concatenation?(range.source_line) ||
start_with_arithmetic_operator?(processed_source[range.line]) ||
start_with_arithmetic_operator?(range) ||
inside_string_literal_or_method_with_argument?(range) ||
leading_dot_method_chain_with_blank_line?(range)
end
Expand Down Expand Up @@ -213,8 +216,9 @@ def method_call_with_arguments?(node)
node.call_type? && !node.arguments.empty?
end

def start_with_arithmetic_operator?(source_line)
%r{\A\s*[+\-*/%]}.match?(source_line)
def start_with_arithmetic_operator?(range)
line_range = processed_source.buffer.line_range(range.line + 1)
ARITHMETIC_OPERATOR_TOKENS.include?(processed_source.first_token_of(line_range).type)
end
end
end
Expand Down
56 changes: 55 additions & 1 deletion spec/rubocop/cop/style/redundant_line_continuation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ def foo
RUBY
end

it 'does not register an offense when line continuations with arithmetic operator' do
it 'does not register an offense when a line continuation precedes an arithmetic operator' do
expect_no_offenses(<<~'RUBY')
1 \
+ 2 \
Expand All @@ -562,6 +562,52 @@ def foo
RUBY
end

context 'when a line continuation precedes the arguments to an unparenthesized method call' do
it 'does not register an offense when the first argument is a lambda' do
expect_no_offenses(<<~'RUBY')
foo \
->() {}
RUBY
end

it 'does not register an offense when the first argument is a unary number' do
expect_no_offenses(<<~'RUBY')
foo \
+1
RUBY
end

it 'does not register an offense when the first argument is a `@+` unary method call' do
expect_no_offenses(<<~'RUBY')
foo \
+bar
RUBY
end

it 'does not register an offense when the first argument is a `@-` unary method call' do
expect_no_offenses(<<~'RUBY')
foo \
-bar
RUBY
end

it 'does not register an offense when the first argument is a regular expression' do
expect_no_offenses(<<~'RUBY')
foo \
/bar/
RUBY
end

%w[% %w %W %i %I %r %x %s].each do |percent_array_type|
it "does not register an offense when the first argument is a `#{percent_array_type}` array" do
expect_no_offenses(<<~RUBY)
foo \\
#{percent_array_type}[bar]
RUBY
end
end
end

it 'does not register an offense when line continuations with comparison operator and the LHS is wrapped in parentheses' do
expect_no_offenses(<<~'RUBY')
(
Expand Down Expand Up @@ -864,4 +910,12 @@ def do_something
data \\
RUBY
end

it 'registers an offense when there is a line continuation inside a method call followed by a percent array' do
expect_offense(<<~'RUBY')
foo(bar, \
^ Redundant line continuation.
%i[baz quux])
RUBY
end
end

0 comments on commit edb6f2b

Please sign in to comment.