diff --git a/snapshots/unary_method_calls.txt b/snapshots/unary_method_calls.txt new file mode 100644 index 0000000000..7a3032ba0d --- /dev/null +++ b/snapshots/unary_method_calls.txt @@ -0,0 +1,33 @@ +@ ProgramNode (location: (1,0)-(2,5)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(2,5)) + ├── flags: ∅ + └── body: (length: 2) + ├── @ CallNode (location: (1,0)-(1,5)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ IntegerNode (location: (1,0)-(1,2)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 42 + │ ├── call_operator_loc: (1,2)-(1,3) = "." + │ ├── name: :~ + │ ├── message_loc: (1,3)-(1,5) = "~@" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: ∅ + └── @ CallNode (location: (2,0)-(2,5)) + ├── flags: newline + ├── receiver: + │ @ IntegerNode (location: (2,0)-(2,2)) + │ ├── flags: static_literal, decimal + │ └── value: 42 + ├── call_operator_loc: (2,2)-(2,3) = "." + ├── name: :! + ├── message_loc: (2,3)-(2,5) = "!@" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + └── block: ∅ diff --git a/src/prism.c b/src/prism.c index 95e7d09050..a92de163f5 100644 --- a/src/prism.c +++ b/src/prism.c @@ -2721,6 +2721,8 @@ pm_call_node_binary_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t return node; } +static const uint8_t * parse_operator_symbol_name(const pm_token_t *); + /** * Allocate and initialize a new CallNode node from a call expression. */ @@ -2749,7 +2751,11 @@ pm_call_node_call_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *o pm_node_flag_set((pm_node_t *)node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION); } - node->name = pm_parser_constant_id_token(parser, message); + /** + * If the final character is `@` as is the case for `foo.~@`, + * we should ignore the @ in the same way we do for symbols. + */ + node->name = pm_parser_constant_id_location(parser, message->start, parse_operator_symbol_name(message)); return node; } @@ -19702,7 +19708,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_parser_scope_pop(parser); /** - * If the final character is @. As is the case when defining + * If the final character is `@` as is the case when defining * methods to override the unary operators, we should ignore * the @ in the same way we do for symbols. */ diff --git a/test/prism/fixtures/unary_method_calls.txt b/test/prism/fixtures/unary_method_calls.txt new file mode 100644 index 0000000000..dda85e4bdb --- /dev/null +++ b/test/prism/fixtures/unary_method_calls.txt @@ -0,0 +1,2 @@ +42.~@ +42.!@ diff --git a/test/prism/ruby/parser_test.rb b/test/prism/ruby/parser_test.rb index 016fda91f0..3104369d3e 100644 --- a/test/prism/ruby/parser_test.rb +++ b/test/prism/ruby/parser_test.rb @@ -109,6 +109,9 @@ class ParserTest < TestCase # Regex with \c escape "unescaping.txt", "seattlerb/regexp_esc_C_slash.txt", + + # https://github.com/whitequark/parser/issues/1084 + "unary_method_calls.txt", ] # These files are failing to translate their lexer output into the lexer diff --git a/test/prism/ruby/ruby_parser_test.rb b/test/prism/ruby/ruby_parser_test.rb index 7640ddaf1c..42a888be82 100644 --- a/test/prism/ruby/ruby_parser_test.rb +++ b/test/prism/ruby/ruby_parser_test.rb @@ -57,6 +57,7 @@ class RubyParserTest < TestCase "spanning_heredoc.txt", "symbols.txt", "tilde_heredocs.txt", + "unary_method_calls.txt", "unparser/corpus/literal/literal.txt", "while.txt", "whitequark/cond_eflipflop.txt",