diff options
author | Kevin Newton <kddnewton@gmail.com> | 2023-10-17 11:45:49 -0400 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2023-10-18 16:09:16 +0000 |
commit | 8210cc4218b639b699c73ac273b62422d5718e10 (patch) | |
tree | 921cdeb6a614fb703e7cc3187ce8546b698ba9b1 | |
parent | c82b10bbc3a3293ba9464c27ac5e778c70d2fe9b (diff) |
[ruby/prism] Fix lex compat when dedent should be 0
https://github.com/ruby/prism/commit/41c0e0e06e
-rw-r--r-- | lib/prism/lex_compat.rb | 9 | ||||
-rw-r--r-- | test/prism/fixtures/tilde_heredocs.txt | 6 | ||||
-rw-r--r-- | test/prism/heredoc_dedent_test.rb | 5 | ||||
-rw-r--r-- | test/prism/snapshots/tilde_heredocs.txt | 350 |
4 files changed, 209 insertions, 161 deletions
diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index a17d4eaadd..4801fe364b 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -357,6 +357,7 @@ module Prism @dedent_next = true @dedent = nil @embexpr_balance = 0 + @ended_on_newline = false end # As tokens are coming in, we track the minimum amount of common leading @@ -366,13 +367,14 @@ module Prism case token.event when :on_embexpr_beg, :on_heredoc_beg @embexpr_balance += 1 + @dedent = 0 if @dedent_next && @ended_on_newline when :on_embexpr_end, :on_heredoc_end @embexpr_balance -= 1 when :on_tstring_content if embexpr_balance == 0 line = token.value - if !(line.strip.empty? && line.end_with?("\n")) && dedent_next + if dedent_next && !(line.strip.empty? && line.end_with?("\n")) leading = line[/\A(\s*)\n?/, 1] next_dedent = 0 @@ -385,11 +387,16 @@ module Prism end @dedent = [dedent, next_dedent].compact.min + @dedent_next = true + @ended_on_newline = line.end_with?("\n") + tokens << token + return end end end @dedent_next = token.event == :on_tstring_content && embexpr_balance == 0 + @ended_on_newline = false tokens << token end diff --git a/test/prism/fixtures/tilde_heredocs.txt b/test/prism/fixtures/tilde_heredocs.txt index 415d4d42c8..cca47ef00b 100644 --- a/test/prism/fixtures/tilde_heredocs.txt +++ b/test/prism/fixtures/tilde_heredocs.txt @@ -1,5 +1,11 @@ <<~EOF a +#{1} + a +EOF + +<<~EOF + a EOF <<~EOF diff --git a/test/prism/heredoc_dedent_test.rb b/test/prism/heredoc_dedent_test.rb index 1943235731..9fbc4d936a 100644 --- a/test/prism/heredoc_dedent_test.rb +++ b/test/prism/heredoc_dedent_test.rb @@ -7,8 +7,13 @@ module Prism filepath = File.expand_path("fixtures/tilde_heredocs.txt", __dir__) File.read(filepath).split(/(?=\n)\n(?=<)/).each_with_index do |heredoc, index| + # The first example in this file has incorrect dedent calculated by + # TruffleRuby so we skip it. + next if index == 0 && RUBY_ENGINE == "truffleruby" + define_method "test_heredoc_#{index}" do node = Prism.parse(heredoc).value.statements.body.first + if node.is_a?(StringNode) actual = node.unescaped else diff --git a/test/prism/snapshots/tilde_heredocs.txt b/test/prism/snapshots/tilde_heredocs.txt index 3d3335776d..3f9ca04707 100644 --- a/test/prism/snapshots/tilde_heredocs.txt +++ b/test/prism/snapshots/tilde_heredocs.txt @@ -1,247 +1,255 @@ -@ ProgramNode (location: (1,0)-(88,6)) +@ ProgramNode (location: (1,0)-(94,6)) ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(88,6)) - └── body: (length: 18) - ├── @ StringNode (location: (1,0)-(1,6)) - │ ├── flags: ∅ + @ StatementsNode (location: (1,0)-(94,6)) + └── body: (length: 19) + ├── @ InterpolatedStringNode (location: (1,0)-(1,6)) │ ├── opening_loc: (1,0)-(1,6) = "<<~EOF" - │ ├── content_loc: (2,0)-(2,0) = " a\n" - │ ├── closing_loc: (3,0)-(3,0) = "EOF\n" + │ ├── parts: (length: 4) + │ │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (2,0)-(2,0) = " a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: " a\n" + │ │ ├── @ EmbeddedStatementsNode (location: (3,0)-(3,4)) + │ │ │ ├── opening_loc: (3,0)-(3,2) = "\#{" + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (3,2)-(3,3)) + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ IntegerNode (location: (3,2)-(3,3)) + │ │ │ │ └── flags: decimal + │ │ │ └── closing_loc: (3,3)-(3,4) = "}" + │ │ ├── @ StringNode (location: (3,4)-(3,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (3,4)-(3,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ └── @ StringNode (location: (4,0)-(4,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (4,0)-(4,0) = " a\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: " a\n" + │ └── closing_loc: (5,0)-(5,0) = "EOF\n" + ├── @ StringNode (location: (7,0)-(7,6)) + │ ├── flags: ∅ + │ ├── opening_loc: (7,0)-(7,6) = "<<~EOF" + │ ├── content_loc: (8,0)-(8,0) = " a\n" + │ ├── closing_loc: (9,0)-(9,0) = "EOF\n" │ └── unescaped: "a\n" - ├── @ InterpolatedStringNode (location: (5,0)-(5,6)) - │ ├── opening_loc: (5,0)-(5,6) = "<<~EOF" + ├── @ InterpolatedStringNode (location: (11,0)-(11,6)) + │ ├── opening_loc: (11,0)-(11,6) = "<<~EOF" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (6,0)-(6,0)) + │ │ ├── @ StringNode (location: (12,0)-(12,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (6,0)-(6,0) = "\ta\n" + │ │ │ ├── content_loc: (12,0)-(12,0) = "\ta\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\ta\n" - │ │ ├── @ StringNode (location: (7,0)-(7,0)) + │ │ ├── @ StringNode (location: (13,0)-(13,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (7,0)-(7,0) = " b\n" + │ │ │ ├── content_loc: (13,0)-(13,0) = " b\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b\n" - │ │ └── @ StringNode (location: (8,0)-(8,0)) + │ │ └── @ StringNode (location: (14,0)-(14,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (8,0)-(8,0) = "\t\tc\n" + │ │ ├── content_loc: (14,0)-(14,0) = "\t\tc\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\t\tc\n" - │ └── closing_loc: (9,0)-(9,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (11,0)-(11,6)) - │ ├── opening_loc: (11,0)-(11,6) = "<<~EOF" + │ └── closing_loc: (15,0)-(15,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (17,0)-(17,6)) + │ ├── opening_loc: (17,0)-(17,6) = "<<~EOF" │ ├── parts: (length: 2) - │ │ ├── @ EmbeddedStatementsNode (location: (12,2)-(12,6)) - │ │ │ ├── opening_loc: (12,2)-(12,4) = "\#{" + │ │ ├── @ EmbeddedStatementsNode (location: (18,2)-(18,6)) + │ │ │ ├── opening_loc: (18,2)-(18,4) = "\#{" │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (12,4)-(12,5)) + │ │ │ │ @ StatementsNode (location: (18,4)-(18,5)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (12,4)-(12,5)) + │ │ │ │ └── @ IntegerNode (location: (18,4)-(18,5)) │ │ │ │ └── flags: decimal - │ │ │ └── closing_loc: (12,5)-(12,6) = "}" - │ │ └── @ StringNode (location: (12,6)-(12,0)) + │ │ │ └── closing_loc: (18,5)-(18,6) = "}" + │ │ └── @ StringNode (location: (18,6)-(18,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (12,6)-(12,0) = " a\n" + │ │ ├── content_loc: (18,6)-(18,0) = " a\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " a\n" - │ └── closing_loc: (13,0)-(13,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (15,0)-(15,6)) - │ ├── opening_loc: (15,0)-(15,6) = "<<~EOF" + │ └── closing_loc: (19,0)-(19,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (21,0)-(21,6)) + │ ├── opening_loc: (21,0)-(21,6) = "<<~EOF" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (16,0)-(16,4)) + │ │ ├── @ StringNode (location: (22,0)-(22,4)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (16,0)-(16,4) = " a " + │ │ │ ├── content_loc: (22,0)-(22,4) = " a " │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a " - │ │ ├── @ EmbeddedStatementsNode (location: (16,4)-(16,8)) - │ │ │ ├── opening_loc: (16,4)-(16,6) = "\#{" + │ │ ├── @ EmbeddedStatementsNode (location: (22,4)-(22,8)) + │ │ │ ├── opening_loc: (22,4)-(22,6) = "\#{" │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (16,6)-(16,7)) + │ │ │ │ @ StatementsNode (location: (22,6)-(22,7)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (16,6)-(16,7)) + │ │ │ │ └── @ IntegerNode (location: (22,6)-(22,7)) │ │ │ │ └── flags: decimal - │ │ │ └── closing_loc: (16,7)-(16,8) = "}" - │ │ └── @ StringNode (location: (16,8)-(16,0)) + │ │ │ └── closing_loc: (22,7)-(22,8) = "}" + │ │ └── @ StringNode (location: (22,8)-(22,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (16,8)-(16,0) = "\n" + │ │ ├── content_loc: (22,8)-(22,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" - │ └── closing_loc: (17,0)-(17,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (19,0)-(19,6)) - │ ├── opening_loc: (19,0)-(19,6) = "<<~EOF" + │ └── closing_loc: (23,0)-(23,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (25,0)-(25,6)) + │ ├── opening_loc: (25,0)-(25,6) = "<<~EOF" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (20,0)-(20,0)) + │ │ ├── @ StringNode (location: (26,0)-(26,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (20,0)-(20,0) = " a\n" + │ │ │ ├── content_loc: (26,0)-(26,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" - │ │ ├── @ EmbeddedStatementsNode (location: (21,1)-(21,5)) - │ │ │ ├── opening_loc: (21,1)-(21,3) = "\#{" + │ │ ├── @ EmbeddedStatementsNode (location: (27,1)-(27,5)) + │ │ │ ├── opening_loc: (27,1)-(27,3) = "\#{" │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (21,3)-(21,4)) + │ │ │ │ @ StatementsNode (location: (27,3)-(27,4)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (21,3)-(21,4)) + │ │ │ │ └── @ IntegerNode (location: (27,3)-(27,4)) │ │ │ │ └── flags: decimal - │ │ │ └── closing_loc: (21,4)-(21,5) = "}" - │ │ └── @ StringNode (location: (21,5)-(21,0)) + │ │ │ └── closing_loc: (27,4)-(27,5) = "}" + │ │ └── @ StringNode (location: (27,5)-(27,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (21,5)-(21,0) = "\n" + │ │ ├── content_loc: (27,5)-(27,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" - │ └── closing_loc: (22,0)-(22,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (24,0)-(24,6)) - │ ├── opening_loc: (24,0)-(24,6) = "<<~EOF" + │ └── closing_loc: (28,0)-(28,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (30,0)-(30,6)) + │ ├── opening_loc: (30,0)-(30,6) = "<<~EOF" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (25,0)-(25,0)) + │ │ ├── @ StringNode (location: (31,0)-(31,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (25,0)-(25,0) = " a\n" + │ │ │ ├── content_loc: (31,0)-(31,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" - │ │ ├── @ EmbeddedStatementsNode (location: (26,2)-(26,6)) - │ │ │ ├── opening_loc: (26,2)-(26,4) = "\#{" + │ │ ├── @ EmbeddedStatementsNode (location: (32,2)-(32,6)) + │ │ │ ├── opening_loc: (32,2)-(32,4) = "\#{" │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (26,4)-(26,5)) + │ │ │ │ @ StatementsNode (location: (32,4)-(32,5)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (26,4)-(26,5)) + │ │ │ │ └── @ IntegerNode (location: (32,4)-(32,5)) │ │ │ │ └── flags: decimal - │ │ │ └── closing_loc: (26,5)-(26,6) = "}" - │ │ └── @ StringNode (location: (26,6)-(26,0)) + │ │ │ └── closing_loc: (32,5)-(32,6) = "}" + │ │ └── @ StringNode (location: (32,6)-(32,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (26,6)-(26,0) = "\n" + │ │ ├── content_loc: (32,6)-(32,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" - │ └── closing_loc: (27,0)-(27,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (29,0)-(29,6)) - │ ├── opening_loc: (29,0)-(29,6) = "<<~EOF" + │ └── closing_loc: (33,0)-(33,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (35,0)-(35,6)) + │ ├── opening_loc: (35,0)-(35,6) = "<<~EOF" │ ├── parts: (length: 2) - │ │ ├── @ StringNode (location: (30,0)-(30,0)) + │ │ ├── @ StringNode (location: (36,0)-(36,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (30,0)-(30,0) = " a\n" + │ │ │ ├── content_loc: (36,0)-(36,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" - │ │ └── @ StringNode (location: (31,0)-(31,0)) + │ │ └── @ StringNode (location: (37,0)-(37,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (31,0)-(31,0) = " b\n" + │ │ ├── content_loc: (37,0)-(37,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" - │ └── closing_loc: (32,0)-(32,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (34,0)-(34,6)) - │ ├── opening_loc: (34,0)-(34,6) = "<<~EOF" + │ └── closing_loc: (38,0)-(38,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (40,0)-(40,6)) + │ ├── opening_loc: (40,0)-(40,6) = "<<~EOF" │ ├── parts: (length: 2) - │ │ ├── @ StringNode (location: (35,0)-(35,0)) + │ │ ├── @ StringNode (location: (41,0)-(41,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (35,0)-(35,0) = " a\n" + │ │ │ ├── content_loc: (41,0)-(41,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" - │ │ └── @ StringNode (location: (36,0)-(36,0)) + │ │ └── @ StringNode (location: (42,0)-(42,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (36,0)-(36,0) = " b\n" + │ │ ├── content_loc: (42,0)-(42,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " b\n" - │ └── closing_loc: (37,0)-(37,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (39,0)-(39,6)) - │ ├── opening_loc: (39,0)-(39,6) = "<<~EOF" + │ └── closing_loc: (43,0)-(43,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (45,0)-(45,6)) + │ ├── opening_loc: (45,0)-(45,6) = "<<~EOF" │ ├── parts: (length: 2) - │ │ ├── @ StringNode (location: (40,0)-(40,0)) + │ │ ├── @ StringNode (location: (46,0)-(46,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (40,0)-(40,0) = "\t\t\ta\n" + │ │ │ ├── content_loc: (46,0)-(46,0) = "\t\t\ta\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\ta\n" - │ │ └── @ StringNode (location: (41,0)-(41,0)) + │ │ └── @ StringNode (location: (47,0)-(47,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (41,0)-(41,0) = "\t\tb\n" + │ │ ├── content_loc: (47,0)-(47,0) = "\t\tb\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" - │ └── closing_loc: (42,0)-(42,0) = "EOF\n" - ├── @ StringNode (location: (44,0)-(44,8)) + │ └── closing_loc: (48,0)-(48,0) = "EOF\n" + ├── @ StringNode (location: (50,0)-(50,8)) │ ├── flags: ∅ - │ ├── opening_loc: (44,0)-(44,8) = "<<~'EOF'" - │ ├── content_loc: (45,0)-(45,0) = " a \#{1}\n" - │ ├── closing_loc: (46,0)-(46,0) = "EOF\n" + │ ├── opening_loc: (50,0)-(50,8) = "<<~'EOF'" + │ ├── content_loc: (51,0)-(51,0) = " a \#{1}\n" + │ ├── closing_loc: (52,0)-(52,0) = "EOF\n" │ └── unescaped: "a \#{1}\n" - ├── @ InterpolatedStringNode (location: (48,0)-(48,6)) - │ ├── opening_loc: (48,0)-(48,6) = "<<~EOF" + ├── @ InterpolatedStringNode (location: (54,0)-(54,6)) + │ ├── opening_loc: (54,0)-(54,6) = "<<~EOF" │ ├── parts: (length: 2) - │ │ ├── @ StringNode (location: (49,0)-(49,0)) + │ │ ├── @ StringNode (location: (55,0)-(55,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (49,0)-(49,0) = "\ta\n" + │ │ │ ├── content_loc: (55,0)-(55,0) = "\ta\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" - │ │ └── @ StringNode (location: (50,0)-(50,0)) + │ │ └── @ StringNode (location: (56,0)-(56,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (50,0)-(50,0) = "\t b\n" + │ │ ├── content_loc: (56,0)-(56,0) = "\t b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: " b\n" - │ └── closing_loc: (51,0)-(51,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (53,0)-(53,6)) - │ ├── opening_loc: (53,0)-(53,6) = "<<~EOF" + │ └── closing_loc: (57,0)-(57,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (59,0)-(59,6)) + │ ├── opening_loc: (59,0)-(59,6) = "<<~EOF" │ ├── parts: (length: 2) - │ │ ├── @ StringNode (location: (54,0)-(54,0)) + │ │ ├── @ StringNode (location: (60,0)-(60,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (54,0)-(54,0) = "\t a\n" + │ │ │ ├── content_loc: (60,0)-(60,0) = "\t a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" - │ │ └── @ StringNode (location: (55,0)-(55,0)) + │ │ └── @ StringNode (location: (61,0)-(61,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (55,0)-(55,0) = "\tb\n" + │ │ ├── content_loc: (61,0)-(61,0) = "\tb\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" - │ └── closing_loc: (56,0)-(56,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (58,0)-(58,6)) - │ ├── opening_loc: (58,0)-(58,6) = "<<~EOF" + │ └── closing_loc: (62,0)-(62,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (64,0)-(64,6)) + │ ├── opening_loc: (64,0)-(64,6) = "<<~EOF" │ ├── parts: (length: 2) - │ │ ├── @ StringNode (location: (59,0)-(59,0)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (59,0)-(59,0) = " \ta\n" - │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "a\n" - │ │ └── @ StringNode (location: (60,0)-(60,0)) - │ │ ├── flags: ∅ - │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (60,0)-(60,0) = " b\n" - │ │ ├── closing_loc: ∅ - │ │ └── unescaped: "b\n" - │ └── closing_loc: (61,0)-(61,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (63,0)-(63,6)) - │ ├── opening_loc: (63,0)-(63,6) = "<<~EOF" - │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (64,0)-(64,0)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (64,0)-(64,0) = " a\n" - │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "a\n" │ │ ├── @ StringNode (location: (65,0)-(65,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (65,0)-(65,0) = "\n" + │ │ │ ├── content_loc: (65,0)-(65,0) = " \ta\n" │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "\n" + │ │ │ └── unescaped: "a\n" │ │ └── @ StringNode (location: (66,0)-(66,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (66,0)-(66,0) = " b\n" + │ │ ├── content_loc: (66,0)-(66,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" │ └── closing_loc: (67,0)-(67,0) = "EOF\n" @@ -269,7 +277,7 @@ │ └── closing_loc: (73,0)-(73,0) = "EOF\n" ├── @ InterpolatedStringNode (location: (75,0)-(75,6)) │ ├── opening_loc: (75,0)-(75,6) = "<<~EOF" - │ ├── parts: (length: 5) + │ ├── parts: (length: 3) │ │ ├── @ StringNode (location: (76,0)-(76,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ @@ -282,70 +290,92 @@ │ │ │ ├── content_loc: (77,0)-(77,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" - │ │ ├── @ StringNode (location: (78,0)-(78,0)) + │ │ └── @ StringNode (location: (78,0)-(78,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (78,0)-(78,0) = " b\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "b\n" + │ └── closing_loc: (79,0)-(79,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (81,0)-(81,6)) + │ ├── opening_loc: (81,0)-(81,6) = "<<~EOF" + │ ├── parts: (length: 5) + │ │ ├── @ StringNode (location: (82,0)-(82,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (82,0)-(82,0) = " a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a\n" + │ │ ├── @ StringNode (location: (83,0)-(83,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (83,0)-(83,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ ├── @ StringNode (location: (84,0)-(84,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (78,0)-(78,0) = "\n" + │ │ │ ├── content_loc: (84,0)-(84,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" - │ │ ├── @ StringNode (location: (79,0)-(79,0)) + │ │ ├── @ StringNode (location: (85,0)-(85,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (79,0)-(79,0) = "\n" + │ │ │ ├── content_loc: (85,0)-(85,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" - │ │ └── @ StringNode (location: (80,0)-(80,0)) + │ │ └── @ StringNode (location: (86,0)-(86,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (80,0)-(80,0) = " b\n" + │ │ ├── content_loc: (86,0)-(86,0) = " b\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\n" - │ └── closing_loc: (81,0)-(81,0) = "EOF\n" - ├── @ InterpolatedStringNode (location: (83,0)-(83,6)) - │ ├── opening_loc: (83,0)-(83,6) = "<<~EOF" + │ └── closing_loc: (87,0)-(87,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (89,0)-(89,6)) + │ ├── opening_loc: (89,0)-(89,6) = "<<~EOF" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (84,0)-(84,0)) + │ │ ├── @ StringNode (location: (90,0)-(90,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (84,0)-(84,0) = "\n" + │ │ │ ├── content_loc: (90,0)-(90,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" - │ │ ├── @ EmbeddedStatementsNode (location: (85,2)-(85,6)) - │ │ │ ├── opening_loc: (85,2)-(85,4) = "\#{" + │ │ ├── @ EmbeddedStatementsNode (location: (91,2)-(91,6)) + │ │ │ ├── opening_loc: (91,2)-(91,4) = "\#{" │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (85,4)-(85,5)) + │ │ │ │ @ StatementsNode (location: (91,4)-(91,5)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (85,4)-(85,5)) + │ │ │ │ └── @ IntegerNode (location: (91,4)-(91,5)) │ │ │ │ └── flags: decimal - │ │ │ └── closing_loc: (85,5)-(85,6) = "}" - │ │ └── @ StringNode (location: (85,6)-(85,0)) + │ │ │ └── closing_loc: (91,5)-(91,6) = "}" + │ │ └── @ StringNode (location: (91,6)-(91,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (85,6)-(85,0) = "a\n" + │ │ ├── content_loc: (91,6)-(91,0) = "a\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a\n" - │ └── closing_loc: (86,0)-(86,0) = " EOF\n" - └── @ InterpolatedStringNode (location: (88,0)-(88,6)) - ├── opening_loc: (88,0)-(88,6) = "<<~EOT" + │ └── closing_loc: (92,0)-(92,0) = " EOF\n" + └── @ InterpolatedStringNode (location: (94,0)-(94,6)) + ├── opening_loc: (94,0)-(94,6) = "<<~EOT" ├── parts: (length: 3) - │ ├── @ EmbeddedStatementsNode (location: (89,2)-(89,6)) - │ │ ├── opening_loc: (89,2)-(89,4) = "\#{" + │ ├── @ EmbeddedStatementsNode (location: (95,2)-(95,6)) + │ │ ├── opening_loc: (95,2)-(95,4) = "\#{" │ │ ├── statements: - │ │ │ @ StatementsNode (location: (89,4)-(89,5)) + │ │ │ @ StatementsNode (location: (95,4)-(95,5)) │ │ │ └── body: (length: 1) - │ │ │ └── @ IntegerNode (location: (89,4)-(89,5)) + │ │ │ └── @ IntegerNode (location: (95,4)-(95,5)) │ │ │ └── flags: decimal - │ │ └── closing_loc: (89,5)-(89,6) = "}" - │ ├── @ StringNode (location: (89,6)-(89,0)) + │ │ └── closing_loc: (95,5)-(95,6) = "}" + │ ├── @ StringNode (location: (95,6)-(95,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (89,6)-(89,0) = "\n" + │ │ ├── content_loc: (95,6)-(95,0) = "\n" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" - │ └── @ StringNode (location: (90,0)-(90,0)) + │ └── @ StringNode (location: (96,0)-(96,0)) │ ├── flags: ∅ │ ├── opening_loc: ∅ - │ ├── content_loc: (90,0)-(90,0) = "\tb\n" + │ ├── content_loc: (96,0)-(96,0) = "\tb\n" │ ├── closing_loc: ∅ │ └── unescaped: "\tb\n" - └── closing_loc: (91,0)-(91,0) = "EOT\n" + └── closing_loc: (97,0)-(97,0) = "EOT\n" |