From 131c7f0cdc7d45f96764b9c8036fdd2ae74dba49 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Sat, 21 Dec 2024 14:30:41 -0500 Subject: [PATCH] Apply changes from #15305 --- spec/compiler/parser/parser_spec.cr | 83 +---------------------------- src/compiler/crystal/syntax/to_s.cr | 25 +++++++-- 2 files changed, 22 insertions(+), 86 deletions(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 45b54fc2e2c1..897e5bf7060c 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -40,12 +40,6 @@ private def node_source(string, node) source_between(string, node.location, node.end_location) end -private def assert_location(node : ASTNode, line_number : Int32, column_number : Int32) - location = node.location.should_not be_nil - location.line_number.should eq line_number - location.column_number.should eq column_number -end - private def assert_end_location(source, line_number = 1, column_number = source.size, file = __FILE__, line = __LINE__) it "gets corrects end location for #{source.inspect}", file, line do string = "#{source}; 1" @@ -1124,7 +1118,7 @@ module Crystal it_parses "puts {{**1}}", Call.new(nil, "puts", MacroExpression.new(DoubleSplat.new(1.int32))) it_parses "{{a = 1 if 2}}", MacroExpression.new(If.new(2.int32, Assign.new("a".var, 1.int32))) it_parses "{% a = 1 %}", MacroExpression.new(Assign.new("a".var, 1.int32), output: false) - it_parses "{%\na = 1\n%}", MacroExpression.new(Assign.new("a".var, 1.int32), output: false, multiline: true) + it_parses "{%\na = 1\n%}", MacroExpression.new(Assign.new("a".var, 1.int32), output: false) it_parses "{% a = 1 if 2 %}", MacroExpression.new(If.new(2.int32, Assign.new("a".var, 1.int32)), output: false) it_parses "{% if 1; 2; end %}", MacroExpression.new(If.new(1.int32, 2.int32), output: false) it_parses "{%\nif 1; 2; end\n%}", MacroExpression.new(If.new(1.int32, 2.int32), output: false) @@ -1134,7 +1128,7 @@ module Crystal it_parses "{% unless 1; 2; else 3; end %}", MacroExpression.new(Unless.new(1.int32, 2.int32, 3.int32), output: false) it_parses "{% unless 1\n x\nend %}", MacroExpression.new(Unless.new(1.int32, "x".var), output: false) it_parses "{% x unless 1 %}", MacroExpression.new(Unless.new(1.int32, "x".var), output: false) - it_parses "{%\n1\n2\n3\n%}", MacroExpression.new(Expressions.new([1.int32, 2.int32, 3.int32] of ASTNode), output: false, multiline: true) + it_parses "{%\n1\n2\n3\n%}", MacroExpression.new(Expressions.new([1.int32, 2.int32, 3.int32] of ASTNode), output: false) assert_syntax_error "{% unless 1; 2; elsif 3; 4; end %}" assert_syntax_error "{% unless 1 %} 2 {% elsif 3 %} 3 {% end %}" @@ -2778,79 +2772,6 @@ module Crystal else_node_location.line_number.should eq 7 end - it "sets the correct location for MacroExpressions in a MacroVerbatim in a finished hook with significant whitespace" do - parser = Parser.new(<<-CR) - macro finished - {% verbatim do %} - {% - 10 - - # Foo - - 20 - 30 - - # Bar - - 40 - %} - - {% - 50 - 60 - %} - {% end %} - end - CR - - node = parser.parse.should be_a Macro - - assert_location node, 1, 1 - - macro_body = node.body.should be_a Expressions - verbatim_node = macro_body[1].should be_a MacroVerbatim - - expressions = verbatim_node.exp.as(Expressions).expressions - expressions.size.should eq 5 - - expressions[0].should eq MacroLiteral.new("\n ") - expression = expressions[1].should be_a MacroExpression - - macro_expression = expression.exp.as(Expressions).expressions - macro_expression.size.should eq 10 - macro_expression.select(MacroLiteral).size.should eq 6 - - num = macro_expression[0].should be_a NumberLiteral - num.value.should eq "10" - assert_location num, 4, 7 - - num = macro_expression[4].should be_a NumberLiteral - num.value.should eq "20" - assert_location num, 8, 7 - - num = macro_expression[5].should be_a NumberLiteral - num.value.should eq "30" - assert_location num, 9, 7 - - num = macro_expression[9].should be_a NumberLiteral - num.value.should eq "40" - assert_location num, 13, 7 - - expression = expressions[3].should be_a MacroExpression - - macro_expression = expression.exp.as(Expressions).expressions - macro_expression.size.should eq 2 - macro_expression.select(MacroLiteral).size.should eq 0 - - num = macro_expression[0].should be_a NumberLiteral - num.value.should eq "50" - assert_location num, 17, 7 - - num = macro_expression[1].should be_a NumberLiteral - num.value.should eq "60" - assert_location num, 18, 7 - end - it "sets correct location of Begin within another node" do parser = Parser.new(<<-CR) macro finished diff --git a/src/compiler/crystal/syntax/to_s.cr b/src/compiler/crystal/syntax/to_s.cr index 9f7e9a7ed072..bd8e6dcf9e3e 100644 --- a/src/compiler/crystal/syntax/to_s.cr +++ b/src/compiler/crystal/syntax/to_s.cr @@ -728,14 +728,29 @@ module Crystal end def visit(node : MacroExpression) - @str << (node.output? ? "{{" : "{% ") - @str << ' ' if node.output? - newline if node.multiline? + @str << (node.output? ? "{{ " : node.multiline? ? "{%" : "{% ") + + if node.multiline? + newline + @indent += 1 + end + outside_macro do + # If the MacroExpression consists of a single node we need to manually handle appending indent and trailing newline if #multiline? + # Otherwise, the Expressions logic handles that for us + if !node.exp.is_a? Expressions + append_indent + end + node.exp.accept self end - @str << ' ' if node.output? - @str << (node.output? ? "}}" : " %}") + + if node.multiline? + @indent -= 1 + newline if !node.exp.is_a? Expressions + end + + @str << (node.output? ? " }}" : node.multiline? ? "%}" : " %}") false end