diff options
20 files changed, 735 insertions, 316 deletions
diff --git a/prism/prism.c b/prism/prism.c index f9ce0aef70..a432d1a454 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -8582,12 +8582,17 @@ parser_lex(pm_parser_t *parser) { } } - if ( - lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE && - (lex_mode->as.heredoc.common_whitespace > whitespace) && - peek_at(parser, start) != '\n' - ) { - lex_mode->as.heredoc.common_whitespace = whitespace; + if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) { + if ((lex_mode->as.heredoc.common_whitespace > whitespace) && peek_at(parser, start) != '\n') { + lex_mode->as.heredoc.common_whitespace = whitespace; + } + + parser->current.end = breakpoint + 1; + + if (!was_escaped_newline) { + pm_token_buffer_flush(parser, &token_buffer); + LEX(PM_TOKEN_STRING_CONTENT); + } } // Otherwise we hit a newline and it wasn't followed by @@ -8613,45 +8618,46 @@ parser_lex(pm_parser_t *parser) { } uint8_t peeked = peek(parser); - switch (peeked) { - case '\r': - parser->current.end++; - if (peek(parser) != '\n') { - if (quote == PM_HEREDOC_QUOTE_SINGLE) { + if (quote == PM_HEREDOC_QUOTE_SINGLE) { + switch (peeked) { + case '\r': + parser->current.end++; + if (peek(parser) != '\n') { pm_token_buffer_push(&token_buffer, '\\'); + pm_token_buffer_push(&token_buffer, '\r'); + break; } - pm_token_buffer_push(&token_buffer, '\r'); - break; - } - /* fallthrough */ - case '\n': - // If this is a dedenting heredoc then we need - // to leave the escaped newline in place so that - // it can be removed later when we dedent the - // heredoc. - if (quote == PM_HEREDOC_QUOTE_SINGLE || lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) { + /* fallthrough */ + case '\n': pm_token_buffer_push(&token_buffer, '\\'); pm_token_buffer_push(&token_buffer, '\n'); - } - - token_buffer.cursor = parser->current.end + 1; - breakpoint = parser->current.end; - - if (quote != PM_HEREDOC_QUOTE_SINGLE) { - was_escaped_newline = true; - } - - continue; - default: - if (quote == PM_HEREDOC_QUOTE_SINGLE) { + token_buffer.cursor = parser->current.end + 1; + breakpoint = parser->current.end; + continue; + default: + parser->current.end++; pm_token_buffer_push(&token_buffer, '\\'); pm_token_buffer_push(&token_buffer, peeked); + break; + } + } else { + switch (peeked) { + case '\r': parser->current.end++; - } else { + if (peek(parser) != '\n') { + pm_token_buffer_push(&token_buffer, '\r'); + break; + } + /* fallthrough */ + case '\n': + was_escaped_newline = true; + token_buffer.cursor = parser->current.end + 1; + breakpoint = parser->current.end; + continue; + default: escape_read(parser, &token_buffer.buffer, PM_ESCAPE_FLAG_NONE); - } - - break; + break; + } } token_buffer.cursor = parser->current.end; @@ -11147,9 +11153,8 @@ parse_method_definition_name(pm_parser_t *parser) { } } -static pm_string_t * -parse_heredoc_dedent_single_node(pm_parser_t *parser, pm_string_t *string, bool dedent_node, size_t common_whitespace, pm_heredoc_quote_t quote) -{ +static void +parse_heredoc_dedent_string(pm_string_t *string, size_t common_whitespace) { // Get a reference to the string struct that is being held by the string // node. This is the value we're going to actually manipulate. pm_string_ensure_owned(string); @@ -11158,80 +11163,37 @@ parse_heredoc_dedent_single_node(pm_parser_t *parser, pm_string_t *string, bool // destination to move bytes into. We'll also use it for bounds checking // since we don't require that these strings be null terminated. size_t dest_length = pm_string_length(string); - uint8_t *source_start = (uint8_t *) string->source; - - const uint8_t *source_cursor = source_start; + const uint8_t *source_cursor = (uint8_t *) string->source; const uint8_t *source_end = source_cursor + dest_length; // We're going to move bytes backward in the string when we get leading // whitespace, so we'll maintain a pointer to the current position in the // string that we're writing to. - uint8_t *dest_cursor = source_start; - - while (source_cursor < source_end) { - // If we need to dedent the next element within the heredoc or the next - // line within the string node, then we'll do it here. - if (dedent_node) { - size_t trimmed_whitespace = 0; - - // While we haven't reached the amount of common whitespace that we need - // to trim and we haven't reached the end of the string, we'll keep - // trimming whitespace. Trimming in this context means skipping over - // these bytes such that they aren't copied into the new string. - while ((source_cursor < source_end) && pm_char_is_inline_whitespace(*source_cursor) && trimmed_whitespace < common_whitespace) { - if (*source_cursor == '\t') { - trimmed_whitespace = (trimmed_whitespace / PM_TAB_WHITESPACE_SIZE + 1) * PM_TAB_WHITESPACE_SIZE; - if (trimmed_whitespace > common_whitespace) break; - } else { - trimmed_whitespace++; - } - - source_cursor++; - dest_length--; - } - } - - // At this point we have dedented all that we need to, so we need to find - // the next newline. - const uint8_t *breakpoint = next_newline(source_cursor, source_end - source_cursor); - - if (breakpoint == NULL) { - // If there isn't another newline, then we can just move the rest of the - // string and break from the loop. - memmove(dest_cursor, source_cursor, (size_t) (source_end - source_cursor)); - break; + size_t trimmed_whitespace = 0; + + // While we haven't reached the amount of common whitespace that we need to + // trim and we haven't reached the end of the string, we'll keep trimming + // whitespace. Trimming in this context means skipping over these bytes such + // that they aren't copied into the new string. + while ((source_cursor < source_end) && pm_char_is_inline_whitespace(*source_cursor) && trimmed_whitespace < common_whitespace) { + if (*source_cursor == '\t') { + trimmed_whitespace = (trimmed_whitespace / PM_TAB_WHITESPACE_SIZE + 1) * PM_TAB_WHITESPACE_SIZE; + if (trimmed_whitespace > common_whitespace) break; + } else { + trimmed_whitespace++; } - // Otherwise, we need to move everything including the newline, and - // then set the dedent_node flag to true. - if (breakpoint < source_end) breakpoint++; - memmove(dest_cursor, source_cursor, (size_t) (breakpoint - source_cursor)); - dest_cursor += (breakpoint - source_cursor); - source_cursor = breakpoint; - dedent_node = true; + source_cursor++; + dest_length--; } - // We only want to write this node into the list if it has any content. + memmove((uint8_t *) string->source, source_cursor, (size_t) (source_end - source_cursor)); string->length = dest_length; - - if (dest_length != 0) { - pm_unescape_manipulate_string(parser, string, (quote == PM_HEREDOC_QUOTE_SINGLE) ? PM_UNESCAPE_MINIMAL : PM_UNESCAPE_ALL); - } - return string; } // Take a heredoc node that is indented by a ~ and trim the leading whitespace. static void -parse_heredoc_dedent(pm_parser_t *parser, pm_node_t *heredoc_node, pm_heredoc_quote_t quote, size_t common_whitespace) -{ - pm_node_list_t *nodes; - - if (quote == PM_HEREDOC_QUOTE_BACKTICK) { - nodes = &((pm_interpolated_x_string_node_t *) heredoc_node)->parts; - } else { - nodes = &((pm_interpolated_string_node_t *) heredoc_node)->parts; - } - +parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_whitespace) { // The next node should be dedented if it's the first node in the list or if // if follows a string node. bool dedent_next = true; @@ -11254,7 +11216,10 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_t *heredoc_node, pm_heredoc_qu } pm_string_node_t *string_node = ((pm_string_node_t *) node); - parse_heredoc_dedent_single_node(parser, &string_node->unescaped, dedent_next, common_whitespace, quote); + if (dedent_next) { + parse_heredoc_dedent_string(&string_node->unescaped, common_whitespace); + } + if (string_node->unescaped.length == 0) { pm_node_destroy(parser, node); } else { @@ -12574,12 +12539,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { cast->base.type = PM_X_STRING_NODE; } - node = (pm_node_t *) cast; - - if (indent == PM_HEREDOC_INDENT_TILDE && (lex_mode->as.heredoc.common_whitespace != (size_t) -1) && (lex_mode->as.heredoc.common_whitespace != 0)) { - parse_heredoc_dedent_single_node(parser, &cast->unescaped, true, lex_mode->as.heredoc.common_whitespace, quote); + size_t common_whitespace = lex_mode->as.heredoc.common_whitespace; + if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { + parse_heredoc_dedent_string(&cast->unescaped, common_whitespace); } + node = (pm_node_t *) cast; lex_state_set(parser, PM_LEX_STATE_END); expect1(parser, PM_TOKEN_HEREDOC_END, PM_ERR_HEREDOC_TERM); } else { @@ -12629,8 +12594,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { // If this is a heredoc that is indented with a ~, then we need // to dedent each line by the common leading whitespace. - if (indent == PM_HEREDOC_INDENT_TILDE && (lex_mode->as.heredoc.common_whitespace != (size_t) -1) && (lex_mode->as.heredoc.common_whitespace != 0)) { - parse_heredoc_dedent(parser, node, quote, lex_mode->as.heredoc.common_whitespace); + size_t common_whitespace = lex_mode->as.heredoc.common_whitespace; + if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { + pm_node_list_t *nodes; + if (quote == PM_HEREDOC_QUOTE_BACKTICK) { + nodes = &((pm_interpolated_x_string_node_t *) node)->parts; + } else { + nodes = &((pm_interpolated_string_node_t *) node)->parts; + } + + parse_heredoc_dedent(parser, nodes, common_whitespace); } } } diff --git a/test/prism/snapshots/dos_endings.txt b/test/prism/snapshots/dos_endings.txt index d01c5a7ac9..7e553ed932 100644 --- a/test/prism/snapshots/dos_endings.txt +++ b/test/prism/snapshots/dos_endings.txt @@ -72,12 +72,22 @@ │ │ └── arguments: (length: 1) │ │ └── @ CallNode (location: (17,8)-(17,19)) │ │ ├── receiver: - │ │ │ @ StringNode (location: (17,8)-(17,14)) - │ │ │ ├── flags: ∅ + │ │ │ @ InterpolatedStringNode (location: (17,8)-(17,14)) │ │ │ ├── opening_loc: (17,8)-(17,14) = "<<~EOF" - │ │ │ ├── content_loc: (18,0)-(19,0) = "\r\n baz\r\n" - │ │ │ ├── closing_loc: (20,0)-(20,0) = " EOF\r\n" - │ │ │ └── unescaped: "\nbaz\r\n" + │ │ │ ├── parts: (length: 2) + │ │ │ │ ├── @ StringNode (location: (18,0)-(18,0)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── content_loc: (18,0)-(18,0) = "\r\n" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "\n" + │ │ │ │ └── @ StringNode (location: (19,0)-(19,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (19,0)-(19,0) = " baz\r\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "baz\r\n" + │ │ │ └── closing_loc: (20,0)-(20,0) = " EOF\r\n" │ │ ├── call_operator_loc: (17,14)-(17,15) = "." │ │ ├── message_loc: (17,15)-(17,19) = "chop" │ │ ├── opening_loc: ∅ diff --git a/test/prism/snapshots/heredocs_nested.txt b/test/prism/snapshots/heredocs_nested.txt index 8680dd2346..0e76652072 100644 --- a/test/prism/snapshots/heredocs_nested.txt +++ b/test/prism/snapshots/heredocs_nested.txt @@ -5,7 +5,7 @@ └── body: (length: 1) └── @ InterpolatedStringNode (location: (1,0)-(1,7)) ├── opening_loc: (1,0)-(1,7) = "<<~RUBY" - ├── parts: (length: 3) + ├── parts: (length: 4) │ ├── @ StringNode (location: (2,0)-(2,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ @@ -24,10 +24,16 @@ │ │ │ ├── closing_loc: (6,0)-(6,0) = "RUBY\n" │ │ │ └── unescaped: " hello\n" │ │ └── closing_loc: (7,0)-(7,1) = "}" - │ └── @ StringNode (location: (7,1)-(8,0)) + │ ├── @ StringNode (location: (7,1)-(7,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (7,1)-(7,0) = "\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "\n" + │ └── @ StringNode (location: (8,0)-(8,0)) │ ├── flags: ∅ │ ├── opening_loc: ∅ - │ ├── content_loc: (7,1)-(8,0) = "\npost\n" + │ ├── content_loc: (8,0)-(8,0) = "post\n" │ ├── closing_loc: ∅ - │ └── unescaped: "\npost\n" + │ └── unescaped: "post\n" └── closing_loc: (9,0)-(9,0) = "RUBY\n" diff --git a/test/prism/snapshots/heredocs_with_ignored_newlines.txt b/test/prism/snapshots/heredocs_with_ignored_newlines.txt index 280a01f879..361c8687aa 100644 --- a/test/prism/snapshots/heredocs_with_ignored_newlines.txt +++ b/test/prism/snapshots/heredocs_with_ignored_newlines.txt @@ -9,9 +9,55 @@ │ ├── content_loc: (2,0)-(1,0) = "" │ ├── closing_loc: (2,0)-(2,0) = "HERE\n" │ └── unescaped: "" - └── @ StringNode (location: (4,0)-(4,8)) - ├── flags: ∅ + └── @ InterpolatedStringNode (location: (4,0)-(4,8)) ├── opening_loc: (4,0)-(4,8) = "<<~THERE" - ├── content_loc: (5,0)-(13,0) = " way over\n <<HERE\n not here\n HERE\n\n <<~BUT\\\n but\n BUT\n there\n" - ├── closing_loc: (14,0)-(14,0) = "THERE\n" - └── unescaped: "way over\n<<HERE\n not here\nHERE\n\n<<~BUT but\nBUT\n there\n" + ├── parts: (length: 8) + │ ├── @ StringNode (location: (5,0)-(5,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (5,0)-(5,0) = " way over\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "way over\n" + │ ├── @ StringNode (location: (6,0)-(6,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (6,0)-(6,0) = " <<HERE\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "<<HERE\n" + │ ├── @ StringNode (location: (7,0)-(7,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (7,0)-(7,0) = " not here\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: " not here\n" + │ ├── @ StringNode (location: (8,0)-(8,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (8,0)-(8,0) = " HERE\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "HERE\n" + │ ├── @ StringNode (location: (9,0)-(9,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (9,0)-(9,0) = "\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "\n" + │ ├── @ StringNode (location: (10,0)-(11,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (10,0)-(11,0) = " <<~BUT\\\n but\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "<<~BUT but\n" + │ ├── @ StringNode (location: (12,0)-(12,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (12,0)-(12,0) = " BUT\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "BUT\n" + │ └── @ StringNode (location: (13,0)-(13,0)) + │ ├── flags: ∅ + │ ├── opening_loc: ∅ + │ ├── content_loc: (13,0)-(13,0) = " there\n" + │ ├── closing_loc: ∅ + │ └── unescaped: " there\n" + └── closing_loc: (14,0)-(14,0) = "THERE\n" diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly.txt index bc5273e9ac..207da6b038 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly.txt @@ -8,10 +8,26 @@ ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "a" ├── value: - │ @ StringNode (location: (1,4)-(1,12)) - │ ├── flags: ∅ + │ @ InterpolatedStringNode (location: (1,4)-(1,12)) │ ├── opening_loc: (1,4)-(1,12) = "<<~\"EOF\"" - │ ├── content_loc: (2,0)-(4,0) = " x\n y\n z\n" - │ ├── closing_loc: (5,0)-(5,0) = " EOF\n" - │ └── unescaped: "x\ny\nz\n" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (2,0)-(2,0) = " x\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "x\n" + │ │ ├── @ StringNode (location: (3,0)-(3,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (3,0)-(3,0) = " y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "y\n" + │ │ └── @ StringNode (location: (4,0)-(4,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (4,0)-(4,0) = " z\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "z\n" + │ └── closing_loc: (5,0)-(5,0) = " EOF\n" └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt index eeaa6e73d6..43703cbe04 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt @@ -21,10 +21,10 @@ │ │ │ @ InterpolatedStringNode (location: (1,8)-(1,14)) │ │ │ ├── opening_loc: (1,8)-(1,14) = "<<~EOF" │ │ │ ├── parts: (length: 3) - │ │ │ │ ├── @ StringNode (location: (2,0)-(3,4)) + │ │ │ │ ├── @ StringNode (location: (2,0)-(2,0)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── content_loc: (2,0)-(3,4) = "\n " + │ │ │ │ │ ├── content_loc: (2,0)-(2,0) = "\n" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "\n" │ │ │ │ ├── @ EmbeddedStatementsNode (location: (3,4)-(3,10)) diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt index 8adeee53bf..a9abc3f40a 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt @@ -8,10 +8,26 @@ ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "a" ├── value: - │ @ StringNode (location: (1,4)-(1,10)) - │ ├── flags: ∅ + │ @ InterpolatedStringNode (location: (1,4)-(1,10)) │ ├── opening_loc: (1,4)-(1,10) = "<<~EOF" - │ ├── content_loc: (2,0)-(4,0) = " x\n\n z\n" - │ ├── closing_loc: (5,0)-(5,0) = "EOF\n" - │ └── unescaped: "x\n\nz\n" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (2,0)-(2,0) = " x\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "x\n" + │ │ ├── @ StringNode (location: (3,0)-(3,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (3,0)-(3,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ └── @ StringNode (location: (4,0)-(4,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (4,0)-(4,0) = " z\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "z\n" + │ └── closing_loc: (5,0)-(5,0) = "EOF\n" └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt index 620b29591c..122a6ad05f 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt @@ -10,13 +10,19 @@ ├── value: │ @ InterpolatedStringNode (location: (1,4)-(1,10)) │ ├── opening_loc: (1,4)-(1,10) = "<<~EOF" - │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (2,0)-(3,3)) + │ ├── parts: (length: 5) + │ │ ├── @ StringNode (location: (2,0)-(2,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (2,0)-(3,3) = " w\n x" + │ │ │ ├── content_loc: (2,0)-(2,0) = " w\n" │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: " w\nx" + │ │ │ └── unescaped: " w\n" + │ │ ├── @ StringNode (location: (3,0)-(3,3)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (3,0)-(3,3) = " x" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "x" │ │ ├── @ EmbeddedStatementsNode (location: (3,3)-(3,8)) │ │ │ ├── opening_loc: (3,3)-(3,5) = "\#{" │ │ │ ├── statements: @@ -25,11 +31,17 @@ │ │ │ │ └── @ IntegerNode (location: (3,5)-(3,7)) │ │ │ │ └── flags: decimal │ │ │ └── closing_loc: (3,7)-(3,8) = "}" - │ │ └── @ StringNode (location: (3,8)-(4,0)) + │ │ ├── @ StringNode (location: (3,8)-(3,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (3,8)-(3,0) = " y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: " y\n" + │ │ └── @ StringNode (location: (4,0)-(4,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (3,8)-(4,0) = " y\n z\n" + │ │ ├── content_loc: (4,0)-(4,0) = " z\n" │ │ ├── closing_loc: ∅ - │ │ └── unescaped: " y\n z\n" + │ │ └── unescaped: " z\n" │ └── closing_loc: (5,0)-(5,0) = " EOF\n" └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs.txt index f876ffa456..dc7ec36a9e 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs.txt @@ -8,10 +8,20 @@ ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "a" ├── value: - │ @ StringNode (location: (1,4)-(1,12)) - │ ├── flags: ∅ + │ @ InterpolatedStringNode (location: (1,4)-(1,12)) │ ├── opening_loc: (1,4)-(1,12) = "<<~\"EOF\"" - │ ├── content_loc: (2,0)-(3,0) = " blah blah\n\t blah blah\n" - │ ├── closing_loc: (4,0)-(4,0) = " EOF\n" - │ └── unescaped: "blah blah\n blah blah\n" + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (2,0)-(2,0) = " blah blah\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "blah blah\n" + │ │ └── @ StringNode (location: (3,0)-(3,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (3,0)-(3,0) = "\t blah blah\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: " blah blah\n" + │ └── closing_loc: (4,0)-(4,0) = " EOF\n" └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt index 32a8b64ce4..9d0962371d 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt @@ -8,10 +8,20 @@ ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "a" ├── value: - │ @ StringNode (location: (1,4)-(1,12)) - │ ├── flags: ∅ + │ @ InterpolatedStringNode (location: (1,4)-(1,12)) │ ├── opening_loc: (1,4)-(1,12) = "<<~\"EOF\"" - │ ├── content_loc: (2,0)-(3,0) = " blah blah\n \tblah blah\n" - │ ├── closing_loc: (4,0)-(4,0) = " EOF\n" - │ └── unescaped: "blah blah\n\tblah blah\n" + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (2,0)-(2,0) = " blah blah\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "blah blah\n" + │ │ └── @ StringNode (location: (3,0)-(3,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (3,0)-(3,0) = " \tblah blah\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "\tblah blah\n" + │ └── closing_loc: (4,0)-(4,0) = " EOF\n" └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt index edf33da732..1d93f974eb 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt @@ -8,10 +8,26 @@ ├── depth: 0 ├── name_loc: (1,0)-(1,1) = "a" ├── value: - │ @ StringNode (location: (1,4)-(1,10)) - │ ├── flags: ∅ + │ @ InterpolatedStringNode (location: (1,4)-(1,10)) │ ├── opening_loc: (1,4)-(1,10) = "<<~EOF" - │ ├── content_loc: (2,0)-(4,0) = " x\n \n z\n" - │ ├── closing_loc: (5,0)-(5,0) = "EOF\n" - │ └── unescaped: "x\n\nz\n" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (2,0)-(2,0) = " x\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "x\n" + │ │ ├── @ StringNode (location: (3,0)-(3,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (3,0)-(3,0) = " \n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ └── @ StringNode (location: (4,0)-(4,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (4,0)-(4,0) = " z\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "z\n" + │ └── closing_loc: (5,0)-(5,0) = "EOF\n" └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/tilde_heredocs.txt b/test/prism/snapshots/tilde_heredocs.txt index b0b060255c..3d3335776d 100644 --- a/test/prism/snapshots/tilde_heredocs.txt +++ b/test/prism/snapshots/tilde_heredocs.txt @@ -9,12 +9,28 @@ │ ├── content_loc: (2,0)-(2,0) = " a\n" │ ├── closing_loc: (3,0)-(3,0) = "EOF\n" │ └── unescaped: "a\n" - ├── @ StringNode (location: (5,0)-(5,6)) - │ ├── flags: ∅ + ├── @ InterpolatedStringNode (location: (5,0)-(5,6)) │ ├── opening_loc: (5,0)-(5,6) = "<<~EOF" - │ ├── content_loc: (6,0)-(8,0) = "\ta\n b\n\t\tc\n" - │ ├── closing_loc: (9,0)-(9,0) = "EOF\n" - │ └── unescaped: "\ta\nb\n\t\tc\n" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (6,0)-(6,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (6,0)-(6,0) = "\ta\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\ta\n" + │ │ ├── @ StringNode (location: (7,0)-(7,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (7,0)-(7,0) = " b\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "b\n" + │ │ └── @ StringNode (location: (8,0)-(8,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (8,0)-(8,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" │ ├── parts: (length: 2) @@ -60,10 +76,10 @@ ├── @ InterpolatedStringNode (location: (19,0)-(19,6)) │ ├── opening_loc: (19,0)-(19,6) = "<<~EOF" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (20,0)-(21,1)) + │ │ ├── @ StringNode (location: (20,0)-(20,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (20,0)-(21,1) = " a\n " + │ │ │ ├── content_loc: (20,0)-(20,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " a\n" │ │ ├── @ EmbeddedStatementsNode (location: (21,1)-(21,5)) @@ -84,10 +100,10 @@ ├── @ InterpolatedStringNode (location: (24,0)-(24,6)) │ ├── opening_loc: (24,0)-(24,6) = "<<~EOF" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (25,0)-(26,2)) + │ │ ├── @ StringNode (location: (25,0)-(25,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (25,0)-(26,2) = " a\n " + │ │ │ ├── content_loc: (25,0)-(25,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ ├── @ EmbeddedStatementsNode (location: (26,2)-(26,6)) @@ -105,73 +121,193 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "\n" │ └── closing_loc: (27,0)-(27,0) = "EOF\n" - ├── @ StringNode (location: (29,0)-(29,6)) - │ ├── flags: ∅ + ├── @ InterpolatedStringNode (location: (29,0)-(29,6)) │ ├── opening_loc: (29,0)-(29,6) = "<<~EOF" - │ ├── content_loc: (30,0)-(31,0) = " a\n b\n" - │ ├── closing_loc: (32,0)-(32,0) = "EOF\n" - │ └── unescaped: "a\nb\n" - ├── @ StringNode (location: (34,0)-(34,6)) - │ ├── flags: ∅ + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (30,0)-(30,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (30,0)-(30,0) = " a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a\n" + │ │ └── @ StringNode (location: (31,0)-(31,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (31,0)-(31,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" - │ ├── content_loc: (35,0)-(36,0) = " a\n b\n" - │ ├── closing_loc: (37,0)-(37,0) = "EOF\n" - │ └── unescaped: "a\n b\n" - ├── @ StringNode (location: (39,0)-(39,6)) - │ ├── flags: ∅ + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (35,0)-(35,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (35,0)-(35,0) = " a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a\n" + │ │ └── @ StringNode (location: (36,0)-(36,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (36,0)-(36,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" - │ ├── content_loc: (40,0)-(41,0) = "\t\t\ta\n\t\tb\n" - │ ├── closing_loc: (42,0)-(42,0) = "EOF\n" - │ └── unescaped: "\ta\nb\n" + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (40,0)-(40,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (40,0)-(40,0) = "\t\t\ta\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\ta\n" + │ │ └── @ StringNode (location: (41,0)-(41,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (41,0)-(41,0) = "\t\tb\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "b\n" + │ └── closing_loc: (42,0)-(42,0) = "EOF\n" ├── @ StringNode (location: (44,0)-(44,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" │ └── unescaped: "a \#{1}\n" - ├── @ StringNode (location: (48,0)-(48,6)) - │ ├── flags: ∅ + ├── @ InterpolatedStringNode (location: (48,0)-(48,6)) │ ├── opening_loc: (48,0)-(48,6) = "<<~EOF" - │ ├── content_loc: (49,0)-(50,0) = "\ta\n\t b\n" - │ ├── closing_loc: (51,0)-(51,0) = "EOF\n" - │ └── unescaped: "a\n b\n" - ├── @ StringNode (location: (53,0)-(53,6)) - │ ├── flags: ∅ + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (49,0)-(49,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (49,0)-(49,0) = "\ta\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a\n" + │ │ └── @ StringNode (location: (50,0)-(50,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (50,0)-(50,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" - │ ├── content_loc: (54,0)-(55,0) = "\t a\n\tb\n" - │ ├── closing_loc: (56,0)-(56,0) = "EOF\n" - │ └── unescaped: " a\nb\n" - ├── @ StringNode (location: (58,0)-(58,6)) - │ ├── flags: ∅ + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (54,0)-(54,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (54,0)-(54,0) = "\t a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: " a\n" + │ │ └── @ StringNode (location: (55,0)-(55,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (55,0)-(55,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" - │ ├── content_loc: (59,0)-(60,0) = " \ta\n b\n" - │ ├── closing_loc: (61,0)-(61,0) = "EOF\n" - │ └── unescaped: "a\nb\n" - ├── @ StringNode (location: (63,0)-(63,6)) - │ ├── flags: ∅ + │ ├── 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" - │ ├── content_loc: (64,0)-(66,0) = " a\n\n b\n" - │ ├── closing_loc: (67,0)-(67,0) = "EOF\n" - │ └── unescaped: "a\n\nb\n" - ├── @ StringNode (location: (69,0)-(69,6)) - │ ├── flags: ∅ + │ ├── 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" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ └── @ StringNode (location: (66,0)-(66,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (66,0)-(66,0) = " b\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "b\n" + │ └── closing_loc: (67,0)-(67,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (69,0)-(69,6)) │ ├── opening_loc: (69,0)-(69,6) = "<<~EOF" - │ ├── content_loc: (70,0)-(72,0) = " a\n\n b\n" - │ ├── closing_loc: (73,0)-(73,0) = "EOF\n" - │ └── unescaped: "a\n\nb\n" - ├── @ StringNode (location: (75,0)-(75,6)) - │ ├── flags: ∅ + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (70,0)-(70,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (70,0)-(70,0) = " a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a\n" + │ │ ├── @ StringNode (location: (71,0)-(71,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (71,0)-(71,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ └── @ StringNode (location: (72,0)-(72,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (72,0)-(72,0) = " b\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "b\n" + │ └── closing_loc: (73,0)-(73,0) = "EOF\n" + ├── @ InterpolatedStringNode (location: (75,0)-(75,6)) │ ├── opening_loc: (75,0)-(75,6) = "<<~EOF" - │ ├── content_loc: (76,0)-(80,0) = " a\n\n\n\n b\n" - │ ├── closing_loc: (81,0)-(81,0) = "EOF\n" - │ └── unescaped: "a\n\n\n\nb\n" + │ ├── parts: (length: 5) + │ │ ├── @ StringNode (location: (76,0)-(76,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (76,0)-(76,0) = " a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a\n" + │ │ ├── @ StringNode (location: (77,0)-(77,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (77,0)-(77,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ ├── @ StringNode (location: (78,0)-(78,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (78,0)-(78,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ ├── @ StringNode (location: (79,0)-(79,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (79,0)-(79,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ └── @ StringNode (location: (80,0)-(80,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (80,0)-(80,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" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (84,0)-(85,2)) + │ │ ├── @ StringNode (location: (84,0)-(84,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (84,0)-(85,2) = "\n " + │ │ │ ├── content_loc: (84,0)-(84,0) = "\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\n" │ │ ├── @ EmbeddedStatementsNode (location: (85,2)-(85,6)) @@ -191,7 +327,7 @@ │ └── closing_loc: (86,0)-(86,0) = " EOF\n" └── @ InterpolatedStringNode (location: (88,0)-(88,6)) ├── opening_loc: (88,0)-(88,6) = "<<~EOT" - ├── parts: (length: 2) + ├── parts: (length: 3) │ ├── @ EmbeddedStatementsNode (location: (89,2)-(89,6)) │ │ ├── opening_loc: (89,2)-(89,4) = "\#{" │ │ ├── statements: @@ -200,10 +336,16 @@ │ │ │ └── @ IntegerNode (location: (89,4)-(89,5)) │ │ │ └── flags: decimal │ │ └── closing_loc: (89,5)-(89,6) = "}" - │ └── @ StringNode (location: (89,6)-(90,0)) + │ ├── @ StringNode (location: (89,6)-(89,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (89,6)-(89,0) = "\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "\n" + │ └── @ StringNode (location: (90,0)-(90,0)) │ ├── flags: ∅ │ ├── opening_loc: ∅ - │ ├── content_loc: (89,6)-(90,0) = "\n\tb\n" + │ ├── content_loc: (90,0)-(90,0) = "\tb\n" │ ├── closing_loc: ∅ - │ └── unescaped: "\n\tb\n" + │ └── unescaped: "\tb\n" └── closing_loc: (91,0)-(91,0) = "EOT\n" diff --git a/test/prism/snapshots/unparser/corpus/semantic/dstr.txt b/test/prism/snapshots/unparser/corpus/semantic/dstr.txt index 126886f3e0..f52663c5a1 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/dstr.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/dstr.txt @@ -62,10 +62,10 @@ ├── @ InterpolatedStringNode (location: (26,0)-(26,6)) │ ├── opening_loc: (26,0)-(26,6) = "<<~DOC" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (27,0)-(28,2)) + │ │ ├── @ StringNode (location: (27,0)-(27,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (27,0)-(28,2) = " a\n " + │ │ │ ├── content_loc: (27,0)-(27,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ ├── @ EmbeddedStatementsNode (location: (28,2)-(28,5)) @@ -81,30 +81,46 @@ │ └── closing_loc: (29,0)-(29,0) = "DOC\n" ├── @ InterpolatedStringNode (location: (31,0)-(31,6)) │ ├── opening_loc: (31,0)-(31,6) = "<<~DOC" - │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (32,0)-(33,2)) + │ ├── parts: (length: 4) + │ │ ├── @ StringNode (location: (32,0)-(32,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (32,0)-(33,2) = " a\n " + │ │ │ ├── content_loc: (32,0)-(32,0) = " a\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a\n" │ │ ├── @ EmbeddedStatementsNode (location: (33,2)-(33,5)) │ │ │ ├── opening_loc: (33,2)-(33,4) = "\#{" │ │ │ ├── statements: ∅ │ │ │ └── closing_loc: (33,4)-(33,5) = "}" - │ │ └── @ StringNode (location: (33,5)-(34,0)) + │ │ ├── @ StringNode (location: (33,5)-(33,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (33,5)-(33,0) = "\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\n" + │ │ └── @ StringNode (location: (34,0)-(34,0)) │ │ ├── flags: ∅ │ │ ├── opening_loc: ∅ - │ │ ├── content_loc: (33,5)-(34,0) = "\n b\n" + │ │ ├── content_loc: (34,0)-(34,0) = " b\n" │ │ ├── closing_loc: ∅ - │ │ └── unescaped: "\nb\n" + │ │ └── unescaped: "b\n" │ └── closing_loc: (35,0)-(35,0) = "DOC\n" - ├── @ StringNode (location: (37,0)-(37,6)) - │ ├── flags: ∅ + ├── @ InterpolatedStringNode (location: (37,0)-(37,6)) │ ├── opening_loc: (37,0)-(37,6) = "<<~DOC" - │ ├── content_loc: (38,0)-(39,0) = " a\n b\n" - │ ├── closing_loc: (40,0)-(40,0) = "DOC\n" - │ └── unescaped: "a\n b\n" + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (38,0)-(38,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (38,0)-(38,0) = " a\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a\n" + │ │ └── @ StringNode (location: (39,0)-(39,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (39,0)-(39,0) = " b\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: " b\n" + │ └── closing_loc: (40,0)-(40,0) = "DOC\n" ├── @ StringNode (location: (42,0)-(42,7)) │ ├── flags: ∅ │ ├── opening_loc: (42,0)-(42,7) = "<<'DOC'" diff --git a/test/prism/snapshots/whitequark/dedenting_heredoc.txt b/test/prism/snapshots/whitequark/dedenting_heredoc.txt index 891eba567f..6155f22fd2 100644 --- a/test/prism/snapshots/whitequark/dedenting_heredoc.txt +++ b/test/prism/snapshots/whitequark/dedenting_heredoc.txt @@ -14,10 +14,10 @@ │ │ └── @ InterpolatedStringNode (location: (1,2)-(1,8)) │ │ ├── opening_loc: (1,2)-(1,8) = "<<~\"E\"" │ │ ├── parts: (length: 3) - │ │ │ ├── @ StringNode (location: (2,0)-(3,2)) + │ │ │ ├── @ StringNode (location: (2,0)-(2,0)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── content_loc: (2,0)-(3,2) = " x\n " + │ │ │ │ ├── content_loc: (2,0)-(2,0) = " x\n" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " x\n" │ │ │ ├── @ EmbeddedStatementsNode (location: (3,2)-(3,10)) @@ -54,10 +54,10 @@ │ │ └── @ InterpolatedStringNode (location: (6,2)-(6,8)) │ │ ├── opening_loc: (6,2)-(6,8) = "<<~\"E\"" │ │ ├── parts: (length: 3) - │ │ │ ├── @ StringNode (location: (7,0)-(8,2)) + │ │ │ ├── @ StringNode (location: (7,0)-(7,0)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── content_loc: (7,0)-(8,2) = " x\n " + │ │ │ │ ├── content_loc: (7,0)-(7,0) = " x\n" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: " x\n" │ │ │ ├── @ EmbeddedStatementsNode (location: (8,2)-(8,8)) @@ -95,12 +95,22 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (11,2)-(11,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (11,2)-(11,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (11,2)-(11,6)) │ │ ├── opening_loc: (11,2)-(11,6) = "<<~E" - │ │ ├── content_loc: (12,0)-(13,0) = "\tx\n y\n" - │ │ ├── closing_loc: (14,0)-(14,0) = "E\n" - │ │ └── unescaped: "x\ny\n" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (12,0)-(12,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (12,0)-(12,0) = "\tx\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "x\n" + │ │ │ └── @ StringNode (location: (13,0)-(13,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (13,0)-(13,0) = " y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "y\n" + │ │ └── closing_loc: (14,0)-(14,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -113,12 +123,22 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (16,2)-(16,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (16,2)-(16,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (16,2)-(16,6)) │ │ ├── opening_loc: (16,2)-(16,6) = "<<~E" - │ │ ├── content_loc: (17,0)-(18,0) = "\tx\n y\n" - │ │ ├── closing_loc: (19,0)-(19,0) = "E\n" - │ │ └── unescaped: "\tx\ny\n" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (17,0)-(17,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (17,0)-(17,0) = "\tx\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "\tx\n" + │ │ │ └── @ StringNode (location: (18,0)-(18,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (18,0)-(18,0) = " y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "y\n" + │ │ └── closing_loc: (19,0)-(19,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -131,12 +151,22 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (21,2)-(21,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (21,2)-(21,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (21,2)-(21,6)) │ │ ├── opening_loc: (21,2)-(21,6) = "<<~E" - │ │ ├── content_loc: (22,0)-(23,0) = " \tx\n y\n" - │ │ ├── closing_loc: (24,0)-(24,0) = "E\n" - │ │ └── unescaped: "x\ny\n" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (22,0)-(22,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (22,0)-(22,0) = " \tx\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "x\n" + │ │ │ └── @ StringNode (location: (23,0)-(23,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (23,0)-(23,0) = " y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "y\n" + │ │ └── closing_loc: (24,0)-(24,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -149,12 +179,22 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (26,2)-(26,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (26,2)-(26,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (26,2)-(26,6)) │ │ ├── opening_loc: (26,2)-(26,6) = "<<~E" - │ │ ├── content_loc: (27,0)-(28,0) = " \tx\n\ty\n" - │ │ ├── closing_loc: (29,0)-(29,0) = "E\n" - │ │ └── unescaped: "\tx\ny\n" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (27,0)-(27,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (27,0)-(27,0) = " \tx\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "\tx\n" + │ │ │ └── @ StringNode (location: (28,0)-(28,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (28,0)-(28,0) = "\ty\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "y\n" + │ │ └── closing_loc: (29,0)-(29,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -167,12 +207,22 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (31,2)-(31,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (31,2)-(31,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (31,2)-(31,6)) │ │ ├── opening_loc: (31,2)-(31,6) = "<<~E" - │ │ ├── content_loc: (32,0)-(33,0) = " x\n \\\ty\n" - │ │ ├── closing_loc: (34,0)-(34,0) = "E\n" - │ │ └── unescaped: " x\n\ty\n" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (32,0)-(32,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (32,0)-(32,0) = " x\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: " x\n" + │ │ │ └── @ StringNode (location: (33,0)-(33,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (33,0)-(33,0) = " \\\ty\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\ty\n" + │ │ └── closing_loc: (34,0)-(34,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -185,12 +235,22 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (36,2)-(36,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (36,2)-(36,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (36,2)-(36,6)) │ │ ├── opening_loc: (36,2)-(36,6) = "<<~E" - │ │ ├── content_loc: (37,0)-(38,0) = " x\n \\ y\n" - │ │ ├── closing_loc: (39,0)-(39,0) = "E\n" - │ │ └── unescaped: " x\n y\n" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (37,0)-(37,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (37,0)-(37,0) = " x\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: " x\n" + │ │ │ └── @ StringNode (location: (38,0)-(38,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (38,0)-(38,0) = " \\ y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: " y\n" + │ │ └── closing_loc: (39,0)-(39,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -221,12 +281,28 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (44,2)-(44,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (44,2)-(44,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (44,2)-(44,6)) │ │ ├── opening_loc: (44,2)-(44,6) = "<<~E" - │ │ ├── content_loc: (45,0)-(47,0) = " x\n\ny\n" - │ │ ├── closing_loc: (48,0)-(48,0) = "E\n" - │ │ └── unescaped: " x\n\ny\n" + │ │ ├── parts: (length: 3) + │ │ │ ├── @ StringNode (location: (45,0)-(45,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (45,0)-(45,0) = " x\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: " x\n" + │ │ │ ├── @ StringNode (location: (46,0)-(46,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (46,0)-(46,0) = "\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "\n" + │ │ │ └── @ StringNode (location: (47,0)-(47,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (47,0)-(47,0) = "y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "y\n" + │ │ └── closing_loc: (48,0)-(48,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -239,12 +315,28 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (50,2)-(50,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (50,2)-(50,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (50,2)-(50,6)) │ │ ├── opening_loc: (50,2)-(50,6) = "<<~E" - │ │ ├── content_loc: (51,0)-(53,0) = " x\n \n y\n" - │ │ ├── closing_loc: (54,0)-(54,0) = "E\n" - │ │ └── unescaped: "x\n \ny\n" + │ │ ├── parts: (length: 3) + │ │ │ ├── @ StringNode (location: (51,0)-(51,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (51,0)-(51,0) = " x\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "x\n" + │ │ │ ├── @ StringNode (location: (52,0)-(52,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (52,0)-(52,0) = " \n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: " \n" + │ │ │ └── @ StringNode (location: (53,0)-(53,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (53,0)-(53,0) = " y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "y\n" + │ │ └── closing_loc: (54,0)-(54,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -257,12 +349,22 @@ │ ├── arguments: │ │ @ ArgumentsNode (location: (56,2)-(56,6)) │ │ └── arguments: (length: 1) - │ │ └── @ StringNode (location: (56,2)-(56,6)) - │ │ ├── flags: ∅ + │ │ └── @ InterpolatedStringNode (location: (56,2)-(56,6)) │ │ ├── opening_loc: (56,2)-(56,6) = "<<~E" - │ │ ├── content_loc: (57,0)-(58,0) = " x\n y\n" - │ │ ├── closing_loc: (59,0)-(59,0) = "E\n" - │ │ └── unescaped: "x\n y\n" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (57,0)-(57,0)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (57,0)-(57,0) = " x\n" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "x\n" + │ │ │ └── @ StringNode (location: (58,0)-(58,0)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (58,0)-(58,0) = " y\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: " y\n" + │ │ └── closing_loc: (59,0)-(59,0) = "E\n" │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ @@ -332,10 +434,10 @@ │ └── @ InterpolatedXStringNode (location: (72,2)-(72,8)) │ ├── opening_loc: (72,2)-(72,8) = "<<~`E`" │ ├── parts: (length: 3) - │ │ ├── @ StringNode (location: (73,0)-(74,2)) + │ │ ├── @ StringNode (location: (73,0)-(73,0)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── content_loc: (73,0)-(74,2) = " x\n " + │ │ │ ├── content_loc: (73,0)-(73,0) = " x\n" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: " x\n" │ │ ├── @ EmbeddedStatementsNode (location: (74,2)-(74,8)) diff --git a/test/prism/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt b/test/prism/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt index ac083f3edc..aa9b58063c 100644 --- a/test/prism/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt +++ b/test/prism/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt @@ -3,9 +3,19 @@ └── statements: @ StatementsNode (location: (1,0)-(1,8)) └── body: (length: 1) - └── @ StringNode (location: (1,0)-(1,8)) - ├── flags: ∅ + └── @ InterpolatedStringNode (location: (1,0)-(1,8)) ├── opening_loc: (1,0)-(1,8) = "<<~'FOO'" - ├── content_loc: (2,0)-(3,0) = " baz\\\\\n qux\n" - ├── closing_loc: (4,0)-(4,0) = "FOO\n" - └── unescaped: "baz\\\nqux\n" + ├── parts: (length: 2) + │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (2,0)-(2,0) = " baz\\\\\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "baz\\\\\n" + │ └── @ StringNode (location: (3,0)-(3,0)) + │ ├── flags: ∅ + │ ├── opening_loc: ∅ + │ ├── content_loc: (3,0)-(3,0) = " qux\n" + │ ├── closing_loc: ∅ + │ └── unescaped: "qux\n" + └── closing_loc: (4,0)-(4,0) = "FOO\n" diff --git a/test/prism/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt b/test/prism/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt index 6d123a3387..5f2502dac8 100644 --- a/test/prism/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt +++ b/test/prism/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt @@ -3,9 +3,19 @@ └── statements: @ StatementsNode (location: (1,0)-(1,8)) └── body: (length: 1) - └── @ StringNode (location: (1,0)-(1,8)) - ├── flags: ∅ + └── @ InterpolatedStringNode (location: (1,0)-(1,8)) ├── opening_loc: (1,0)-(1,8) = "<<~'FOO'" - ├── content_loc: (2,0)-(3,0) = " baz\\\n qux\n" - ├── closing_loc: (4,0)-(4,0) = "FOO\n" - └── unescaped: "baz\\\nqux\n" + ├── parts: (length: 2) + │ ├── @ StringNode (location: (2,0)-(2,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (2,0)-(2,0) = " baz\\\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "baz\\\n" + │ └── @ StringNode (location: (3,0)-(3,0)) + │ ├── flags: ∅ + │ ├── opening_loc: ∅ + │ ├── content_loc: (3,0)-(3,0) = " qux\n" + │ ├── closing_loc: ∅ + │ └── unescaped: "qux\n" + └── closing_loc: (4,0)-(4,0) = "FOO\n" diff --git a/test/prism/snapshots/whitequark/parser_bug_640.txt b/test/prism/snapshots/whitequark/parser_bug_640.txt index 3ddfb52d98..1363dabe3b 100644 --- a/test/prism/snapshots/whitequark/parser_bug_640.txt +++ b/test/prism/snapshots/whitequark/parser_bug_640.txt @@ -8,4 +8,4 @@ ├── opening_loc: (1,0)-(1,6) = "<<~FOO" ├── content_loc: (2,0)-(3,0) = " baz\\\n qux\n" ├── closing_loc: (4,0)-(4,0) = "FOO\n" - └── unescaped: "bazqux\n" + └── unescaped: "baz qux\n" diff --git a/test/prism/snapshots/whitequark/ruby_bug_11989.txt b/test/prism/snapshots/whitequark/ruby_bug_11989.txt index 27ec4058af..2d56025693 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_11989.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_11989.txt @@ -16,7 +16,7 @@ │ ├── opening_loc: (1,2)-(1,8) = "<<~\"E\"" │ ├── content_loc: (2,0)-(2,0) = " x\\n y\n" │ ├── closing_loc: (3,0)-(3,0) = "E\n" - │ └── unescaped: "x\n y\n" + │ └── unescaped: "x\n y\n" ├── closing_loc: ∅ ├── block: ∅ ├── flags: ∅ diff --git a/test/prism/snapshots/whitequark/slash_newline_in_heredocs.txt b/test/prism/snapshots/whitequark/slash_newline_in_heredocs.txt index 2a63c8cb0b..f7a249946a 100644 --- a/test/prism/snapshots/whitequark/slash_newline_in_heredocs.txt +++ b/test/prism/snapshots/whitequark/slash_newline_in_heredocs.txt @@ -9,9 +9,19 @@ │ ├── content_loc: (2,0)-(4,0) = " 1 \\\n 2\n 3\n" │ ├── closing_loc: (5,0)-(5,0) = "E\n" │ └── unescaped: " 1 2\n 3\n" - └── @ StringNode (location: (8,0)-(8,4)) - ├── flags: ∅ + └── @ InterpolatedStringNode (location: (8,0)-(8,4)) ├── opening_loc: (8,0)-(8,4) = "<<~E" - ├── content_loc: (9,0)-(11,0) = " 1 \\\n 2\n 3\n" - ├── closing_loc: (12,0)-(12,0) = "E\n" - └── unescaped: "1 2\n3\n" + ├── parts: (length: 2) + │ ├── @ StringNode (location: (9,0)-(10,0)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (9,0)-(10,0) = " 1 \\\n 2\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "1 2\n" + │ └── @ StringNode (location: (11,0)-(11,0)) + │ ├── flags: ∅ + │ ├── opening_loc: ∅ + │ ├── content_loc: (11,0)-(11,0) = " 3\n" + │ ├── closing_loc: ∅ + │ └── unescaped: "3\n" + └── closing_loc: (12,0)-(12,0) = "E\n" diff --git a/test/prism/unescape_test.rb b/test/prism/unescape_test.rb index de4d1bf1b9..2e7e9fcd3e 100644 --- a/test/prism/unescape_test.rb +++ b/test/prism/unescape_test.rb @@ -67,6 +67,20 @@ module Prism def prism_result(escape) = prism(escape, &:unescaped) end + class Heredoc < Base + def ruby_result(escape) = ruby(escape, &:itself) + def prism_result(escape) + prism(escape) do |node| + case node.type + when :interpolated_string_node, :interpolated_x_string_node + node.parts.flat_map(&:unescaped).join + else + node.unescaped + end + end + end + end + class RegExp < Base def ruby_result(escape) = ruby(escape, &:source) def prism_result(escape) = prism(escape, &:unescaped) @@ -94,30 +108,30 @@ module Prism escapes = [*ascii, *ascii8, *newlines, *octal, *hex2, *hex4, *hex6, *ctrls] contexts = [ - [Context::String.new("?", ""), escapes], - [Context::String.new("'", "'"), escapes], - [Context::String.new("\"", "\""), escapes], - [Context::String.new("%q[", "]"), escapes], - [Context::String.new("%Q[", "]"), escapes], - [Context::String.new("%[", "]"), escapes], - [Context::String.new("`", "`"), escapes], - [Context::String.new("%x[", "]"), escapes], - [Context::String.new("<<H\n", "\nH"), escapes], - [Context::String.new("<<'H'\n", "\nH"), escapes], - [Context::String.new("<<\"H\"\n", "\nH"), escapes], - [Context::String.new("<<`H`\n", "\nH"), escapes], + [Context::String.new("?", ""), escapes], + [Context::String.new("'", "'"), escapes], + [Context::String.new("\"", "\""), escapes], + [Context::String.new("%q[", "]"), escapes], + [Context::String.new("%Q[", "]"), escapes], + [Context::String.new("%[", "]"), escapes], + [Context::String.new("`", "`"), escapes], + [Context::String.new("%x[", "]"), escapes], + [Context::String.new("<<H\n", "\nH"), escapes], + [Context::String.new("<<'H'\n", "\nH"), escapes], + [Context::String.new("<<\"H\"\n", "\nH"), escapes], + [Context::String.new("<<`H`\n", "\nH"), escapes], [Context::String.new("<<-H\n", "\nH"), escapes], [Context::String.new("<<-'H'\n", "\nH"), escapes], [Context::String.new("<<-\"H\"\n", "\nH"), escapes], [Context::String.new("<<-`H`\n", "\nH"), escapes], - # [Context::String.new("<<~H\n", "\nH"), escapes], - # [Context::String.new("<<~'H'\n", "\nH"), escapes], - # [Context::String.new("<<~\"H\"\n", "\nH"), escapes], - # [Context::String.new("<<~`H`\n", "\nH"), escapes], - [Context::List.new("%w[", "]"), escapes], - [Context::List.new("%W[", "]"), escapes], - [Context::List.new("%i[", "]"), escapes], - [Context::List.new("%I[", "]"), escapes], + [Context::Heredoc.new("<<~H\n", "\nH"), escapes], + [Context::Heredoc.new("<<~'H'\n", "\nH"), escapes], + [Context::Heredoc.new("<<~\"H\"\n", "\nH"), escapes], + [Context::Heredoc.new("<<~`H`\n", "\nH"), escapes], + [Context::List.new("%w[", "]"), escapes], + [Context::List.new("%W[", "]"), escapes], + [Context::List.new("%i[", "]"), escapes], + [Context::List.new("%I[", "]"), escapes], # [Context::Symbol.new("%s[", "]"), escapes], # [Context::Symbol.new(":'", "'"), escapes], # [Context::Symbol.new(":\"", "\""), escapes], |
