Skip to content

Commit

Permalink
Merge pull request #9950 from jonas054/9945_fix_TrailingWhitespace
Browse files Browse the repository at this point in the history
[Fix #9945] Fix heredoc indentation in trailing space corrections
  • Loading branch information
koic committed Jul 24, 2021
2 parents 047f001 + fa5ad0f commit b5f3438
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 8 deletions.
1 change: 1 addition & 0 deletions changelog/fix_heredoc_trailing_spaces.md
@@ -0,0 +1 @@
* [#9945](https://github.com/rubocop/rubocop/issues/9945): Fix auto-correction of lines in heredocs with only spaces in `Layout/TrailingWhitespace`. ([@jonas054][])
7 changes: 0 additions & 7 deletions lib/rubocop/cop/layout/heredoc_indentation.rb
Expand Up @@ -143,13 +143,6 @@ def base_indent_level(node)
indent_level(base_line)
end

def indent_level(str)
indentations = str.lines
.map { |line| line[/^\s*/] }
.reject { |line| line.end_with?("\n") }
indentations.empty? ? 0 : indentations.min_by(&:size).size
end

# Returns '~', '-' or nil
def heredoc_indent_type(node)
node.source[/^<<([~-])/, 1]
Expand Down
25 changes: 24 additions & 1 deletion lib/rubocop/cop/layout/trailing_whitespace.rb
Expand Up @@ -41,6 +41,7 @@ module Layout
#
class TrailingWhitespace < Base
include RangeHelp
include Heredoc
extend AutoCorrector

MSG = 'Trailing whitespace detected.'
Expand All @@ -54,6 +55,8 @@ def on_new_investigation
end
end

def on_heredoc(_node); end

private

def process_line(line, lineno)
Expand All @@ -63,13 +66,33 @@ def process_line(line, lineno)
range = offense_range(lineno, line)
add_offense(range) do |corrector|
if heredoc
corrector.wrap(range, "\#{'", "'}") unless static?(heredoc)
process_line_in_heredoc(corrector, range, heredoc)
else
corrector.remove(range)
end
end
end

def process_line_in_heredoc(corrector, range, heredoc)
indent_level = indent_level(find_heredoc(range.line).loc.heredoc_body.source)
whitespace_only = whitespace_only?(range)
if whitespace_only && whitespace_is_indentation?(range, indent_level)
corrector.remove(range)
elsif !static?(heredoc)
range = range_between(range.begin_pos + indent_level, range.end_pos) if whitespace_only
corrector.wrap(range, "\#{'", "'}")
end
end

def whitespace_is_indentation?(range, level)
range.source[/ +/].length <= level
end

def whitespace_only?(range)
source = range_with_surrounding_space(range: range).source
source.start_with?("\n") && source.end_with?("\n")
end

def static?(heredoc)
heredoc.loc.expression.source.end_with? "'"
end
Expand Down
7 changes: 7 additions & 0 deletions lib/rubocop/cop/mixin/heredoc.rb
Expand Up @@ -20,6 +20,13 @@ def on_heredoc(_node)

private

def indent_level(str)
indentations = str.lines
.map { |line| line[/^\s*/] }
.reject { |line| line.end_with?("\n") }
indentations.empty? ? 0 : indentations.min_by(&:size).size
end

def delimiter_string(node)
node.source.match(OPENING_DELIMITER).captures[1]
end
Expand Down
43 changes: 43 additions & 0 deletions spec/rubocop/cop/layout/trailing_whitespace_spec.rb
Expand Up @@ -144,6 +144,49 @@
RUBY
end

it 'corrects by removing trailing whitespace used for indentation in a heredoc string' do
expect_offense(<<~RUBY)
x = <<~EXAMPLE
no trailing
#{trailing_whitespace}
^^ Trailing whitespace detected.
no trailing
#{trailing_whitespace}
^ Trailing whitespace detected.
no trailing
EXAMPLE
RUBY

expect_correction(<<~RUBY)
x = <<~EXAMPLE
no trailing
no trailing
no trailing
EXAMPLE
RUBY
end

it 'corrects a whitespace line in a heredoc string that is longer than the indentation' do
expect_offense(<<~RUBY)
x = <<~EXAMPLE
no trailing
#{trailing_whitespace}
^^^ Trailing whitespace detected.
no trailing
EXAMPLE
RUBY

expect_correction(<<~RUBY)
x = <<~EXAMPLE
no trailing
\#{' '}
no trailing
EXAMPLE
RUBY
end

it 'does not correct trailing whitespace in a static heredoc string' do
expect_offense(<<~RUBY)
x = <<~'EXAMPLE'
Expand Down

0 comments on commit b5f3438

Please sign in to comment.