Skip to content

Commit

Permalink
[Fix #7177] Do not insert spaces into string literals
Browse files Browse the repository at this point in the history
  • Loading branch information
buehmann authored and bbatsov committed Sep 29, 2019
1 parent b23e983 commit dbd7ac5
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
* [#7358](https://github.com/rubocop-hq/rubocop/issues/7358): Fix an incorrect autocorrect for `Style/NestedModifier` when parentheses are required in method arguments. ([@koic][])
* [#7361](https://github.com/rubocop-hq/rubocop/issues/7361): Fix a false positive for `Style/TernaryParentheses` when only the closing parenthesis is used in the last line of condition. ([@koic][])
* [#7369](https://github.com/rubocop-hq/rubocop/issues/7369): Fix an infinite loop error for `Layout/IndentAssignment` with `Layout/IndentFirstArgument` when using multiple assignment. ([@koic][])
* [#7177](https://github.com/rubocop-hq/rubocop/issues/7177), [#7370](https://github.com/rubocop-hq/rubocop/issues/7370): When correcting alignment, do not insert spaces into string literals. ([@buehmann][])

### Changes

Expand Down
40 changes: 31 additions & 9 deletions lib/rubocop/cop/correctors/alignment_corrector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ def correct(processed_source, node, column_delta)
expr = node.respond_to?(:loc) ? node.loc.expression : node
return if block_comment_within?(expr)

heredoc_ranges = heredoc_ranges(node)
taboo_ranges = inside_string_ranges(node)

lambda do |corrector|
each_line(expr) do |line_begin_pos|
autocorrect_line(corrector, line_begin_pos, expr, column_delta,
heredoc_ranges)
taboo_ranges)
end
end
end
Expand All @@ -41,10 +41,11 @@ def align_end(processed_source, node, align_to)
private

def autocorrect_line(corrector, line_begin_pos, expr, column_delta,
heredoc_ranges)
taboo_ranges)
range = calculate_range(expr, line_begin_pos, column_delta)
# We must not change indentation of heredoc strings.
return if heredoc_ranges.any? { |h| within?(range, h) }
# We must not change indentation of heredoc strings or inside other
# string literals
return if taboo_ranges.any? { |t| within?(range, t) }

if column_delta.positive?
unless range.resize(1).source == "\n"
Expand All @@ -55,12 +56,33 @@ def autocorrect_line(corrector, line_begin_pos, expr, column_delta,
end
end

def heredoc_ranges(node)
def inside_string_ranges(node)
return [] unless node.is_a?(Parser::AST::Node)

node.each_node(:str, :dstr, :xstr)
.select(&:heredoc?)
.map { |n| n.loc.heredoc_body.join(n.loc.heredoc_end) }
node.each_node(:str, :dstr, :xstr).map { |n| inside_string_range(n) }
.compact
end

def inside_string_range(node)
loc = node.location

if node.heredoc?
loc.heredoc_body.join(loc.heredoc_end)
elsif delimited_string_literal?(node)
loc.begin.end.join(loc.end.begin)
end
end

# Some special kinds of string literals are not composed of literal
# characters between two delimiters:
# - The source map of `?a` responds to :begin and :end but its end is
# nil.
# - The source map of `__FILE__` responds to neither :begin nor :end.
def delimited_string_literal?(node)
loc = node.location

loc.respond_to?(:begin) && loc.begin &&
loc.respond_to?(:end) && loc.end
end

def block_comment_within?(expr)
Expand Down
30 changes: 30 additions & 0 deletions spec/rubocop/cop/alignment_corrector_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,35 @@
OUTPUT
end
end

context 'within string literals' do
it 'does not insert whitespace' do
expect(autocorrect_source(<<~INPUT)).to eq(<<~OUTPUT)
# >> 2
begin
dstr =
'a
b
c'
xstr =
`a
b
c`
end
INPUT
# >> 2
begin
dstr =
'a
b
c'
xstr =
`a
b
c`
end
OUTPUT
end
end
end
end

0 comments on commit dbd7ac5

Please sign in to comment.