diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 05c14e33f5c99e..3570af136a4fb7 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -155,21 +155,8 @@ def deep_freeze # Binary search through the offsets to find the line number for the given # byte offset. def find_line(byte_offset) - left = 0 - right = offsets.length - 1 - - while left <= right - mid = left + (right - left) / 2 - return mid if (offset = offsets[mid]) == byte_offset - - if offset < byte_offset - left = mid + 1 - else - right = mid - 1 - end - end - - left - 1 + index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length + index - 1 end end diff --git a/lib/tempfile.rb b/lib/tempfile.rb index 27ebb96439c7f3..cd512bb1c5224b 100644 --- a/lib/tempfile.rb +++ b/lib/tempfile.rb @@ -550,8 +550,8 @@ def open(*args, **kw) # # Implementation note: # -# The keyword argument +anonymous=true+ is implemented using FILE_SHARE_DELETE on Windows. -# O_TMPFILE is used on Linux. +# The keyword argument anonymous=true is implemented using +FILE_SHARE_DELETE+ on Windows. +# +O_TMPFILE+ is used on Linux. # # Related: Tempfile.new. # diff --git a/prism/config.yml b/prism/config.yml index 3acab9f58d5d44..5e29d6fa181c34 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1860,7 +1860,7 @@ nodes: comment: | Represents the location of the `class` keyword. - class Foo; end + class Foo end ^^^^^ - name: constant_path type: node @@ -1899,19 +1899,19 @@ nodes: comment: | Represents the location of the `end` keyword. - class Foo; end - ^^^ + class Foo end + ^^^ - name: name type: constant comment: | The name of the class. - class Foo; end # name `:Foo` + class Foo end # name `:Foo` comment: | Represents a class declaration involving the `class` keyword. - class Foo; end - ^^^^^^^^^^^^^^ + class Foo end + ^^^^^^^^^^^^^ - name: ClassVariableAndWriteNode fields: - name: name @@ -3306,6 +3306,9 @@ nodes: - EmbeddedVariableNode - InterpolatedStringNode # `"a" "#{b}"` - on error: XStringNode # `<<`FOO` "bar" + - on error: InterpolatedXStringNode + - on error: SymbolNode + - on error: InterpolatedSymbolNode - name: closing_loc type: location? newline: parts diff --git a/prism/prism.c b/prism/prism.c index 186cdd354c9843..3d60e008c48a0a 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -5344,8 +5344,10 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_ break; case PM_X_STRING_NODE: case PM_INTERPOLATED_X_STRING_NODE: - // If this is an x string, then this is a syntax error. But we want - // to handle it here so that we don't fail the assertion. + case PM_SYMBOL_NODE: + case PM_INTERPOLATED_SYMBOL_NODE: + // These will only happen in error cases. But we want to handle it + // here so that we don't fail the assertion. CLEAR_FLAGS(node); break; default: @@ -8443,7 +8445,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { if (*cursor == '\\' && (cursor + 1 < end)) cursor++; } value_end = cursor; - if (*cursor == '"') cursor++; + if (cursor < end && *cursor == '"') cursor++; } else { value_start = cursor; while (cursor < end && *cursor != '"' && *cursor != ';' && !pm_char_is_whitespace(*cursor)) cursor++; @@ -17336,7 +17338,11 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node pm_node_t *value = NULL; if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { - value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key); + if (PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)) { + value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key); + } else { + value = (pm_node_t *) pm_missing_node_create(parser, key->location.end, key->location.end); + } } else { value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY, (uint16_t) (depth + 1)); } @@ -22861,8 +22867,8 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // If the shebang does not include "ruby" and this is the main script being // parsed, then we will start searching the file for a shebang that does // contain "ruby" as if -x were passed on the command line. - const uint8_t *newline = next_newline(parser->start, parser->end - parser->start); - size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->start); + const uint8_t *newline = next_newline(parser->current.end, parser->end - parser->current.end); + size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->current.end); if (length > 2 && parser->current.end[0] == '#' && parser->current.end[1] == '!') { const char *engine; diff --git a/test/prism/errors/label_in_interpolated_string.txt b/test/prism/errors/label_in_interpolated_string.txt new file mode 100644 index 00000000000000..e8f40dd2a8aa69 --- /dev/null +++ b/test/prism/errors/label_in_interpolated_string.txt @@ -0,0 +1,14 @@ +case in el""Q +^~~~ expected a predicate for a case matching statement + ^ expected a delimiter after the patterns of an `in` clause + ^ unexpected constant, expecting end-of-input + !"""#{in el"":Q + ^~ unexpected 'in', assuming it is closing the parent 'in' clause + ^ expected a `}` to close the embedded expression + ^~ cannot parse the string part + ^~ cannot parse the string part + ^ cannot parse the string part + ^~~~~~~~~~~ unexpected label + ^~~~~~~~~~~ expected a string for concatenation + ^ expected an `end` to close the `case` statement + diff --git a/test/prism/errors/pattern_string_key.txt b/test/prism/errors/pattern_string_key.txt new file mode 100644 index 00000000000000..9f28feddb96dea --- /dev/null +++ b/test/prism/errors/pattern_string_key.txt @@ -0,0 +1,8 @@ +case:a +in b:"","#{}" + ^~~~~ expected a label after the `,` in the hash pattern + ^ expected a pattern expression after the key + ^ expected a delimiter after the patterns of an `in` clause + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected an `end` to close the `case` statement +