From 3c55dcc3b89151a0d5b0a21c081fc1e4ee654f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Fri, 13 Feb 2026 23:24:12 +0000 Subject: [PATCH] astgen: fix firstToken for container_decl, switch_case, asm, while/for, assign_destructure Co-Authored-By: Claude Opus 4.6 --- astgen.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 9 deletions(-) diff --git a/astgen.c b/astgen.c index f3ca341747..52e6836f57 100644 --- a/astgen.c +++ b/astgen.c @@ -601,6 +601,7 @@ static void advanceSourceCursor(AstGenCtx* ag, uint32_t end) { // Mirrors tree.firstToken (Ast.zig:596). // Recurse through nodes to find the first token. static uint32_t firstToken(const Ast* tree, uint32_t node) { + uint32_t end_offset = 0; uint32_t n = node; while (1) { AstNodeTag tag = tree->nodes.tags[n]; @@ -654,7 +655,7 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) { case AST_NODE_PTR_TYPE_SENTINEL: case AST_NODE_PTR_TYPE: case AST_NODE_PTR_TYPE_BIT_RANGE: - return tree->nodes.main_tokens[n]; + return tree->nodes.main_tokens[n] - end_offset; // Return main_token - 1: dot-prefixed inits and enum_literal // (Ast.zig:645-654). @@ -667,7 +668,7 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) { case AST_NODE_STRUCT_INIT_DOT_TWO: case AST_NODE_STRUCT_INIT_DOT_TWO_COMMA: case AST_NODE_ENUM_LITERAL: - return tree->nodes.main_tokens[n] - 1; + return tree->nodes.main_tokens[n] - 1 - end_offset; // Recurse into LHS: all binary ops and compound expressions // (Ast.zig:656-733). @@ -767,7 +768,7 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) { break; } } - return i; + return i - end_offset; } // Fn decls: scan backwards for modifiers (Ast.zig:737-759). case AST_NODE_FN_DECL: @@ -788,7 +789,7 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) { break; } } - return i; + return i - end_offset; } // Container fields: check for preceding comptime (Ast.zig:761-769). case AST_NODE_CONTAINER_FIELD_INIT: @@ -796,8 +797,8 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) { case AST_NODE_CONTAINER_FIELD: { uint32_t mt = tree->nodes.main_tokens[n]; if (mt > 0 && tree->tokens.tags[mt - 1] == TOKEN_KEYWORD_COMPTIME) - return mt - 1; - return mt; + end_offset++; + return mt - end_offset; } // Blocks: check for label (Ast.zig:794-805). case AST_NODE_BLOCK: @@ -807,12 +808,99 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) { uint32_t lbrace = tree->nodes.main_tokens[n]; if (lbrace >= 2 && tree->tokens.tags[lbrace - 1] == TOKEN_COLON && tree->tokens.tags[lbrace - 2] == TOKEN_IDENTIFIER) - return lbrace - 2; - return lbrace; + end_offset += 2; + return lbrace - end_offset; } + // Container decls: check for packed/extern (Ast.zig:807-826). + case AST_NODE_CONTAINER_DECL: + case AST_NODE_CONTAINER_DECL_TRAILING: + case AST_NODE_CONTAINER_DECL_TWO: + case AST_NODE_CONTAINER_DECL_TWO_TRAILING: + case AST_NODE_CONTAINER_DECL_ARG: + case AST_NODE_CONTAINER_DECL_ARG_TRAILING: + case AST_NODE_TAGGED_UNION: + case AST_NODE_TAGGED_UNION_TRAILING: + case AST_NODE_TAGGED_UNION_TWO: + case AST_NODE_TAGGED_UNION_TWO_TRAILING: + case AST_NODE_TAGGED_UNION_ENUM_TAG: + case AST_NODE_TAGGED_UNION_ENUM_TAG_TRAILING: { + uint32_t mt = tree->nodes.main_tokens[n]; + if (mt > 0) { + TokenizerTag prev = tree->tokens.tags[mt - 1]; + if (prev == TOKEN_KEYWORD_PACKED + || prev == TOKEN_KEYWORD_EXTERN) + end_offset++; + } + return mt - end_offset; + } + + // Switch cases: check for inline/else/values (Ast.zig:834-847). + case AST_NODE_SWITCH_CASE_ONE: + if (tree->nodes.datas[n].lhs == 0) + return tree->nodes.main_tokens[n] - 1 - end_offset; + n = tree->nodes.datas[n].lhs; + continue; + case AST_NODE_SWITCH_CASE_INLINE_ONE: + if (tree->nodes.datas[n].lhs == 0) + return tree->nodes.main_tokens[n] - 2; + end_offset += 1; + n = tree->nodes.datas[n].lhs; + continue; + case AST_NODE_SWITCH_CASE: { + uint32_t extra_idx = tree->nodes.datas[n].lhs; + uint32_t items_start = tree->extra_data.arr[extra_idx]; + uint32_t items_end = tree->extra_data.arr[extra_idx + 1]; + if (items_start == items_end) + return tree->nodes.main_tokens[n] - 1 - end_offset; + n = tree->extra_data.arr[items_start]; + continue; + } + case AST_NODE_SWITCH_CASE_INLINE: { + uint32_t extra_idx = tree->nodes.datas[n].lhs; + uint32_t items_start = tree->extra_data.arr[extra_idx]; + uint32_t items_end = tree->extra_data.arr[extra_idx + 1]; + if (items_start == items_end) + return tree->nodes.main_tokens[n] - 2; + end_offset += 1; + n = tree->extra_data.arr[items_start]; + continue; + } + + // Asm output/input: first token is '[' before main_token + // (Ast.zig:849-852). + case AST_NODE_ASM_OUTPUT: + case AST_NODE_ASM_INPUT: + return tree->nodes.main_tokens[n] - 1 - end_offset; + + // While/for: check for inline and label (Ast.zig:854-870). + case AST_NODE_WHILE_SIMPLE: + case AST_NODE_WHILE_CONT: + case AST_NODE_WHILE: + case AST_NODE_FOR_SIMPLE: + case AST_NODE_FOR: { + uint32_t result = tree->nodes.main_tokens[n]; + if (result > 0 + && tree->tokens.tags[result - 1] == TOKEN_KEYWORD_INLINE) + result--; + if (result >= 2 && tree->tokens.tags[result - 1] == TOKEN_COLON + && tree->tokens.tags[result - 2] == TOKEN_IDENTIFIER) + result -= 2; + return result - end_offset; + } + + // Assign destructure: recurse into first variable + // (Ast.zig:735). + case AST_NODE_ASSIGN_DESTRUCTURE: { + uint32_t extra_start = tree->nodes.datas[n].lhs; + // extra_data[extra_start] = variable_count + // extra_data[extra_start + 1 .. +1+count] = variables + n = tree->extra_data.arr[extra_start + 1]; + continue; + } + // Fallback for any remaining node types. default: - return tree->nodes.main_tokens[n]; + return tree->nodes.main_tokens[n] - end_offset; } } }