astgen: fix firstToken for container_decl, switch_case, asm, while/for, assign_destructure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 23:24:12 +00:00
parent 2d4d3e0695
commit 3c55dcc3b8

106
astgen.c
View File

@@ -601,6 +601,7 @@ static void advanceSourceCursor(AstGenCtx* ag, uint32_t end) {
// Mirrors tree.firstToken (Ast.zig:596). // Mirrors tree.firstToken (Ast.zig:596).
// Recurse through nodes to find the first token. // Recurse through nodes to find the first token.
static uint32_t firstToken(const Ast* tree, uint32_t node) { static uint32_t firstToken(const Ast* tree, uint32_t node) {
uint32_t end_offset = 0;
uint32_t n = node; uint32_t n = node;
while (1) { while (1) {
AstNodeTag tag = tree->nodes.tags[n]; 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_SENTINEL:
case AST_NODE_PTR_TYPE: case AST_NODE_PTR_TYPE:
case AST_NODE_PTR_TYPE_BIT_RANGE: 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 // Return main_token - 1: dot-prefixed inits and enum_literal
// (Ast.zig:645-654). // (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:
case AST_NODE_STRUCT_INIT_DOT_TWO_COMMA: case AST_NODE_STRUCT_INIT_DOT_TWO_COMMA:
case AST_NODE_ENUM_LITERAL: 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 // Recurse into LHS: all binary ops and compound expressions
// (Ast.zig:656-733). // (Ast.zig:656-733).
@@ -767,7 +768,7 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) {
break; break;
} }
} }
return i; return i - end_offset;
} }
// Fn decls: scan backwards for modifiers (Ast.zig:737-759). // Fn decls: scan backwards for modifiers (Ast.zig:737-759).
case AST_NODE_FN_DECL: case AST_NODE_FN_DECL:
@@ -788,7 +789,7 @@ static uint32_t firstToken(const Ast* tree, uint32_t node) {
break; break;
} }
} }
return i; return i - end_offset;
} }
// Container fields: check for preceding comptime (Ast.zig:761-769). // Container fields: check for preceding comptime (Ast.zig:761-769).
case AST_NODE_CONTAINER_FIELD_INIT: 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: { case AST_NODE_CONTAINER_FIELD: {
uint32_t mt = tree->nodes.main_tokens[n]; uint32_t mt = tree->nodes.main_tokens[n];
if (mt > 0 && tree->tokens.tags[mt - 1] == TOKEN_KEYWORD_COMPTIME) if (mt > 0 && tree->tokens.tags[mt - 1] == TOKEN_KEYWORD_COMPTIME)
return mt - 1; end_offset++;
return mt; return mt - end_offset;
} }
// Blocks: check for label (Ast.zig:794-805). // Blocks: check for label (Ast.zig:794-805).
case AST_NODE_BLOCK: 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]; uint32_t lbrace = tree->nodes.main_tokens[n];
if (lbrace >= 2 && tree->tokens.tags[lbrace - 1] == TOKEN_COLON if (lbrace >= 2 && tree->tokens.tags[lbrace - 1] == TOKEN_COLON
&& tree->tokens.tags[lbrace - 2] == TOKEN_IDENTIFIER) && tree->tokens.tags[lbrace - 2] == TOKEN_IDENTIFIER)
return lbrace - 2; end_offset += 2;
return lbrace; 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. // Fallback for any remaining node types.
default: default:
return tree->nodes.main_tokens[n]; return tree->nodes.main_tokens[n] - end_offset;
} }
} }
} }