Skip to content

Commit d7c1550

Browse files
committed
Handle properly stringifying single line blocks
1 parent 0596532 commit d7c1550

File tree

5 files changed

+41
-26
lines changed

5 files changed

+41
-26
lines changed

spec/compiler/crystal/tools/playground_spec.cr

+3-7
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ private def instrument(source)
88
instrumented.to_s
99
end
1010

11-
private def assert_agent(source, expected)
11+
private def assert_agent(source, expected, *, file : String = __FILE__, line : Int32 = __LINE__)
1212
# parse/to_s expected so block syntax and spaces do not bother
1313
expected = Parser.new(expected).parse.to_s
1414

15-
instrument(source).should contain(expected)
15+
instrument(source).should contain(expected), file: file, line: line
1616

1717
# whatever case should work before it should work with appended lines
1818
instrument("#{source}\n1\n").should contain(expected)
@@ -520,11 +520,7 @@ describe Playground::AgentInstrumentorTransformer do
520520
_p.i(5) { 'b' }
521521
end
522522
end
523-
_p.i(7) do
524-
baz do
525-
'c'
526-
end
527-
end
523+
_p.i(7) { baz { 'c' } }
528524
end
529525
end
530526
CRYSTAL

spec/compiler/normalize/array_literal_spec.cr

+2-6
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,7 @@ describe "Normalize: array literal" do
8282
__temp_2 = [2]
8383
__temp_3 = Foo.new
8484
__temp_3 << __temp_1
85-
__temp_2.each do |__temp_4|
86-
__temp_3 << __temp_4
87-
end
85+
__temp_2.each { |__temp_4| __temp_3 << __temp_4 }
8886
__temp_3
8987
CRYSTAL
9088
end
@@ -95,9 +93,7 @@ describe "Normalize: array literal" do
9593
__temp_2 = [2]
9694
__temp_3 = Foo(typeof(__temp_1, ::Enumerable.element_type(__temp_2))).new
9795
__temp_3 << __temp_1
98-
__temp_2.each do |__temp_4|
99-
__temp_3 << __temp_4
100-
end
96+
__temp_2.each { |__temp_4| __temp_3 << __temp_4 }
10197
__temp_3
10298
CRYSTAL
10399
end

spec/compiler/parser/to_s_spec.cr

+15-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ describe "ASTNode#to_s" do
5252
expect_to_s %(foo &.bar), %(foo(&.bar))
5353
expect_to_s %(foo &.bar(1, 2, 3)), %(foo(&.bar(1, 2, 3)))
5454
expect_to_s %(foo x: 1, y: 2, &.bar), %(foo(x: 1, y: 2, &.bar))
55-
expect_to_s %(foo { |i| i.bar { i } }), "foo do |i|\n i.bar do\n i\n end\nend"
55+
expect_to_s %(foo { |i| i.bar { i } })
5656
expect_to_s %(foo do |k, v|\n k.bar(1, 2, 3)\nend)
5757
expect_to_s %(foo(3, &.*(2)))
5858
expect_to_s %(return begin\n 1\n 2\nend)
@@ -108,6 +108,16 @@ describe "ASTNode#to_s" do
108108
expect_to_s "def foo(x, @[Foo] **args)\nend"
109109
expect_to_s "def foo(x, **args, &block)\nend"
110110
expect_to_s "def foo(@[Foo] x, @[Bar] **args, @[Baz] &block)\nend"
111+
expect_to_s "{% [1, 2, 3].each { |v| pp(v) } %}"
112+
expect_to_s "{%\n [1, 2, 3].each { |v| pp(v) }\n%}"
113+
expect_to_s "{% [1, 2, 3].find(&.!.even?) %}", "{% [1, 2, 3].find() { |__arg0| !__arg0.even? } %}"
114+
expect_to_s <<-'CR'
115+
{%
116+
[1, 2, 3].find do |e|
117+
e.even?
118+
end
119+
%}
120+
CR
111121

112122
# 14216
113123
expect_to_s "def foo(x, **args, &block : _ -> _)\nend"
@@ -458,12 +468,14 @@ describe "ASTNode#to_s" do
458468
expect_to_s "->::foo(Int32, String)"
459469
expect_to_s "->::Foo::Bar.foo"
460470
expect_to_s "yield(1)"
461-
expect_to_s "foo { |(x, y)| x }", <<-CODE
471+
expect_to_s "foo { |(x, y)| x }"
472+
expect_to_s "foo do |(x, y)|\n x\nend", <<-CODE
462473
foo do |(x, y)|
463474
x
464475
end
465476
CODE
466-
expect_to_s "foo { |(x, (y, z))| x }", <<-CODE
477+
expect_to_s "foo { |(x, (y, z))| x }"
478+
expect_to_s "foo do |(x, (y, z))|\n x\nend", <<-CODE
467479
foo do |(x, (y, z))|
468480
x
469481
end

src/compiler/crystal/syntax/to_s.cr

+18-7
Original file line numberDiff line numberDiff line change
@@ -1111,18 +1111,19 @@ module Crystal
11111111
end
11121112

11131113
def visit(node : Block)
1114-
@str << "do"
1114+
# If the node's body end location is on the same line as the start of the block itself, it's on a single line.
1115+
single_line_block = (node_loc = node.location) && (end_loc = node.body.end_location) && end_loc.line_number == node_loc.line_number
1116+
1117+
@str << (single_line_block ? '{' : "do")
11151118

11161119
unless node.args.empty?
11171120
@str << " |"
11181121
node.args.each_with_index do |arg, i|
11191122
@str << ", " if i > 0
11201123
@str << '*' if i == node.splat_index
1121-
11221124
if arg.name == ""
11231125
# This is an unpack
11241126
unpack = node.unpacks.not_nil![i]
1125-
11261127
visit_unpack(unpack)
11271128
else
11281129
arg.accept self
@@ -1131,11 +1132,21 @@ module Crystal
11311132
@str << '|'
11321133
end
11331134

1134-
newline
1135-
accept_with_indent(node.body)
1135+
@str << ' ' if single_line_block
11361136

1137-
append_indent
1138-
@str << "end"
1137+
if single_line_block
1138+
node.body.accept self
1139+
else
1140+
newline
1141+
accept_with_indent node.body
1142+
end
1143+
1144+
if single_line_block
1145+
@str << ' ' << '}'
1146+
else
1147+
append_indent
1148+
@str << "end"
1149+
end
11391150

11401151
false
11411152
end

src/compiler/crystal/tools/playground/agent_instrumentor_transformer.cr

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ module Crystal
7777
if node.is_a?(TupleLiteral)
7878
args << ArrayLiteral.new(node.elements.map { |e| StringLiteral.new(e.to_s).as(ASTNode) })
7979
end
80-
call = Call.new(Call.new("_p"), "i", args, Block.new([] of Var, node.as(ASTNode)))
80+
call = Call.new(Call.new("_p"), "i", args, Block.new([] of Var, node.as(ASTNode)).at(node))
8181
call = Cast.new(call, TypeOf.new([node.clone] of ASTNode)) if add_as_typeof
8282
call = Splat.new(call) if splat
8383
call
@@ -98,7 +98,7 @@ module Crystal
9898
node.values = if node.values.size == 1
9999
[instrument(node.values[0])] of ASTNode
100100
else
101-
rhs = TupleLiteral.new(node.values)
101+
rhs = TupleLiteral.new(node.values).at(node)
102102
rhs.location = node.location
103103
[instrument(rhs)] of ASTNode
104104
end
@@ -145,7 +145,7 @@ module Crystal
145145
end
146146

147147
private def instrument_args_and_splat(node : Call)
148-
args = TupleLiteral.new(node.args)
148+
args = TupleLiteral.new(node.args).at(node)
149149
args.location = node.location
150150
node.args = [Splat.new(instrument(args))] of ASTNode
151151
node

0 commit comments

Comments
 (0)