From 0b88dde268905aefccebd2b4cf9dd95318cb8ba4 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Tue, 28 Jul 2026 17:15:50 +0900 Subject: [PATCH] Include the trailing `?` in a keyword key's symbol location `parse_keyword_key` handles keys like `foo?:`, where the `?` is part of the method-name-ish key: it interns `foo?` as the constant, but built the symbol node's location from `current_token` alone, so the location covered `foo` and stopped short of the `?`. Extend the range to the end of the `?` token so the location matches the name it is the location of. This is not observable from Ruby -- `rbs_ast_symbol_t` is translated with `ID2SYM` and the wasm serializer writes only the `constant_id`, both of which drop the location. It matters for consumers that read the C AST directly, such as the Rust crate's owned AST. Co-Authored-By: Claude Opus 5 (1M context) --- src/parser.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/parser.c b/src/parser.c index b56970c93e..358e99bbab 100644 --- a/src/parser.c +++ b/src/parser.c @@ -405,18 +405,21 @@ NODISCARD static bool parse_keyword_key(rbs_parser_t *parser, rbs_ast_symbol_t **key) { rbs_parser_advance(parser); - rbs_location_range symbol_range = rbs_location_range_current_token(parser); + rbs_range_t symbol_range = parser->current_token.range; if (parser->next_token.type == pQUESTION) { + // The `?` is part of the key, so it is part of the location too. + symbol_range.end = parser->next_token.range.end; + *key = rbs_ast_symbol_new( ALLOCATOR(), - symbol_range, + RBS_RANGE_LEX2AST(symbol_range), &parser->constant_pool, intern_token_start_end(parser, parser->current_token, parser->next_token) ); rbs_parser_advance(parser); } else { - *key = rbs_ast_symbol_new(ALLOCATOR(), symbol_range, &parser->constant_pool, INTERN_TOKEN(parser, parser->current_token)); + *key = rbs_ast_symbol_new(ALLOCATOR(), RBS_RANGE_LEX2AST(symbol_range), &parser->constant_pool, INTERN_TOKEN(parser, parser->current_token)); } return true;