From 7440eb4b11cd2da5283a8060bab0139c269a4195 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 4 Dec 2025 11:58:51 +0100 Subject: [PATCH] Fix `%Q` with newline delimiter and heredoc interpolation The lexer did not jump to the `heredoc_end`, causing the heredoc end delimiter to be parsed twice. Normally the heredocs get flushed when a newline is encountered. But because the newline is part of the string delimiter, that codepath is not taken. Fixes [Bug #21758] --- .../heredoc_percent_q_newline_delimiter.txt | 114 ++++++++++++++++++ src/prism.c | 7 ++ .../heredoc_percent_q_newline_delimiter.txt | 11 ++ .../heredoc_percent_q_newline_delimiter.txt | 22 ++++ test/prism/ruby/parser_test.rb | 3 + test/prism/ruby/ruby_parser_test.rb | 1 + 6 files changed, 158 insertions(+) create mode 100644 snapshots/heredoc_percent_q_newline_delimiter.txt create mode 100644 test/prism/errors/heredoc_percent_q_newline_delimiter.txt create mode 100644 test/prism/fixtures/heredoc_percent_q_newline_delimiter.txt diff --git a/snapshots/heredoc_percent_q_newline_delimiter.txt b/snapshots/heredoc_percent_q_newline_delimiter.txt new file mode 100644 index 0000000000..75c436b670 --- /dev/null +++ b/snapshots/heredoc_percent_q_newline_delimiter.txt @@ -0,0 +1,114 @@ +@ ProgramNode (location: (1,0)-(22,0)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(22,0)) + ├── flags: ∅ + └── body: (length: 7) + ├── @ InterpolatedStringNode (location: (1,0)-(3,0)) + │ ├── flags: newline, static_literal, mutable + │ ├── opening_loc: (1,0)-(2,0) = "%Q\n" + │ ├── parts: (length: 1) + │ │ └── @ EmbeddedStatementsNode (location: (2,0)-(2,6)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (2,0)-(2,2) = "\#{" + │ │ ├── statements: + │ │ │ @ StatementsNode (location: (2,2)-(2,5)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ StringNode (location: (2,2)-(2,5)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: (2,2)-(2,5) = "<heredoc_end) { + parser_flush_heredoc_end(parser); + } + lex_state_set(parser, PM_LEX_STATE_END); lex_mode_pop(parser); LEX(PM_TOKEN_STRING_END); diff --git a/test/prism/errors/heredoc_percent_q_newline_delimiter.txt b/test/prism/errors/heredoc_percent_q_newline_delimiter.txt new file mode 100644 index 0000000000..73664c071f --- /dev/null +++ b/test/prism/errors/heredoc_percent_q_newline_delimiter.txt @@ -0,0 +1,11 @@ +%q +#{<