Skip to content

Commit 7df6c76

Browse files
russell-stripembj
authored andcommitted
Flatten dstr nesting that results from implicit string concatenation
This extra nesting happens when a dstr is generated from implicit string concatenation and one of the strings being concatenated is itself a dstr. Example: "foo" "bar #{baz}" Without this preprocessor, this turns into: "foo#{"bar#{baz}"}" With this preprocessor, this turns into: "foobar #{baz}"
1 parent 5d982ec commit 7df6c76

2 files changed

Lines changed: 39 additions & 1 deletion

File tree

lib/unparser/preprocessor.rb

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,44 @@ def chunked_children
149149

150150
end # CollapseStrChildren
151151

152-
# Preprocessor eliminating unneded dstr nodes
152+
# Preprocessor flattening unneeded dstr nesting. This happens when a dstr is generated from
153+
# implicit string concatenation, and one of the strings being concatenated is itself a dstr.
154+
#
155+
# Example: "foo" "bar #{baz}"
156+
#
157+
# Without this preprocessor, this turns into: "foo#{"bar#{baz}"}"
158+
# With this preprocessor, this turns into: "foobar #{baz}"
159+
class FlattenImplicitDSTR < self
160+
161+
# No need to register :dsym, because Ruby doesn't do implicit concatenation of symbols
162+
register :dstr
163+
164+
# Return preprocessor result
165+
#
166+
# @return [Parser::AST::Node]
167+
#
168+
# @api private
169+
#
170+
def result
171+
# This should only ever be true for DSTR nodes that are a result of implicit concatenation
172+
# (see the comments on this class). Any other DSTR node would have a :begin node as a child.
173+
if children.any? && children.all? { |child| [:dstr, :str].include?(child.type) }
174+
flat_children = children.flat_map do |child|
175+
if child.type.equal?(:str)
176+
child
177+
else # child.type is dstr
178+
child.children
179+
end
180+
end
181+
node.updated(nil, flat_children)
182+
else
183+
node
184+
end
185+
end
186+
187+
end # FlattenImplicitDSTR
188+
189+
# Preprocessor eliminating unneeded dstr nodes
153190
class CompactDSTR < self
154191

155192
register :dstr

spec/unit/unparser_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ def foo(bar:, baz: "value")
139139
context 'string' do
140140
assert_generates '?c', '"c"'
141141
assert_generates '"foo" "bar"', '"foobar"'
142+
assert_generates '"foo" "bar #{baz}"', '"foobar #{baz}"'
142143
assert_generates '%Q(foo"#{@bar})', '"foo\\"#{@bar}"'
143144
assert_terminated '"\""'
144145
assert_terminated '"foo#{1}bar"'

0 commit comments

Comments
 (0)