add Ast to callback field in iterateChildren

This commit is contained in:
Techatrix 2023-03-03 17:14:14 +01:00 committed by Lee Cannon
parent 0f3319315f
commit 0ee947e8a6
3 changed files with 83 additions and 86 deletions

View File

@ -1163,15 +1163,16 @@ pub fn nextFnParam(it: *Ast.full.FnProto.Iterator) ?Ast.full.FnProto.Param {
}
}
/// returns an Iterator that yields every child of the given node.
/// see `nodeChildrenAlloc` for a non-iterator allocating variant.
/// calls the given `callback` on every child of the given node
/// see `nodeChildrenAlloc` for a non-callback, allocating variant.
/// see `iterateChildrenRecursive` for recursive-iteration.
/// the order in which children are given corresponds to the order in which they are found in the source text
pub fn iterateChildren(
tree: Ast,
node: Ast.Node.Index,
context: anytype,
comptime Error: type,
comptime callback: fn (@TypeOf(context), Ast.Node.Index) Error!void,
comptime callback: fn (@TypeOf(context), Ast, Ast.Node.Index) Error!void,
) Error!void {
const node_tags = tree.nodes.items(.tag);
const node_data = tree.nodes.items(.data);
@ -1200,7 +1201,7 @@ pub fn iterateChildren(
.@"nosuspend",
.asm_simple,
=> {
try callback(context, node_data[node].lhs);
try callback(context, tree, node_data[node].lhs);
},
.test_decl,
@ -1209,7 +1210,7 @@ pub fn iterateChildren(
.@"break",
.anyframe_type,
=> {
try callback(context, node_data[node].rhs);
try callback(context, tree, node_data[node].rhs);
},
.@"catch",
@ -1288,8 +1289,8 @@ pub fn iterateChildren(
.error_union,
.for_range,
=> {
try callback(context, node_data[node].lhs);
try callback(context, node_data[node].rhs);
try callback(context, tree, node_data[node].lhs);
try callback(context, tree, node_data[node].rhs);
},
.root,
@ -1307,7 +1308,7 @@ pub fn iterateChildren(
.block_semicolon,
=> {
for (tree.extra_data[node_data[node].lhs..node_data[node].rhs]) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
@ -1317,18 +1318,18 @@ pub fn iterateChildren(
.aligned_var_decl,
=> {
const var_decl = tree.fullVarDecl(node).?.ast;
try callback(context, var_decl.type_node);
try callback(context, var_decl.align_node);
try callback(context, var_decl.addrspace_node);
try callback(context, var_decl.section_node);
try callback(context, var_decl.init_node);
try callback(context, tree, var_decl.type_node);
try callback(context, tree, var_decl.align_node);
try callback(context, tree, var_decl.addrspace_node);
try callback(context, tree, var_decl.section_node);
try callback(context, tree, var_decl.init_node);
},
.array_type_sentinel => {
const array_type = tree.arrayTypeSentinel(node).ast;
try callback(context, array_type.elem_count);
try callback(context, array_type.sentinel);
try callback(context, array_type.elem_type);
try callback(context, tree, array_type.elem_count);
try callback(context, tree, array_type.sentinel);
try callback(context, tree, array_type.elem_type);
},
.ptr_type_aligned,
@ -1337,12 +1338,12 @@ pub fn iterateChildren(
.ptr_type_bit_range,
=> {
const ptr_type = fullPtrType(tree, node).?.ast;
try callback(context, ptr_type.sentinel);
try callback(context, ptr_type.align_node);
try callback(context, ptr_type.bit_range_start);
try callback(context, ptr_type.bit_range_end);
try callback(context, ptr_type.addrspace_node);
try callback(context, ptr_type.child_type);
try callback(context, tree, ptr_type.sentinel);
try callback(context, tree, ptr_type.align_node);
try callback(context, tree, ptr_type.bit_range_start);
try callback(context, tree, ptr_type.bit_range_end);
try callback(context, tree, ptr_type.addrspace_node);
try callback(context, tree, ptr_type.child_type);
},
.slice_open,
@ -1350,19 +1351,19 @@ pub fn iterateChildren(
.slice_sentinel,
=> {
const slice = tree.fullSlice(node).?;
try callback(context, slice.ast.sliced);
try callback(context, slice.ast.start);
try callback(context, slice.ast.end);
try callback(context, slice.ast.sentinel);
try callback(context, tree, slice.ast.sliced);
try callback(context, tree, slice.ast.start);
try callback(context, tree, slice.ast.end);
try callback(context, tree, slice.ast.sentinel);
},
.array_init,
.array_init_comma,
=> {
const array_init = tree.arrayInit(node).ast;
try callback(context, array_init.type_expr);
try callback(context, tree, array_init.type_expr);
for (array_init.elements) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
@ -1370,9 +1371,9 @@ pub fn iterateChildren(
.struct_init_comma,
=> {
const struct_init = tree.structInit(node).ast;
try callback(context, struct_init.type_expr);
try callback(context, tree, struct_init.type_expr);
for (struct_init.fields) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
@ -1382,9 +1383,9 @@ pub fn iterateChildren(
.async_call_comma,
=> {
const call = tree.callFull(node).ast;
try callback(context, call.fn_expr);
try callback(context, tree, call.fn_expr);
for (call.params) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
@ -1394,9 +1395,9 @@ pub fn iterateChildren(
const cond = node_data[node].lhs;
const extra = tree.extraData(node_data[node].rhs, Ast.Node.SubRange);
const cases = tree.extra_data[extra.start..extra.end];
try callback(context, cond);
try callback(context, tree, cond);
for (cases) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
@ -1407,9 +1408,9 @@ pub fn iterateChildren(
=> {
const switch_case = tree.fullSwitchCase(node).?.ast;
for (switch_case.values) |child| {
try callback(context, child);
try callback(context, tree, child);
}
try callback(context, switch_case.target_expr);
try callback(context, tree, switch_case.target_expr);
},
.while_simple,
@ -1417,29 +1418,29 @@ pub fn iterateChildren(
.@"while",
=> {
const while_ast = fullWhile(tree, node).?.ast;
try callback(context, while_ast.cond_expr);
try callback(context, while_ast.cont_expr);
try callback(context, while_ast.then_expr);
try callback(context, while_ast.else_expr);
try callback(context, tree, while_ast.cond_expr);
try callback(context, tree, while_ast.cont_expr);
try callback(context, tree, while_ast.then_expr);
try callback(context, tree, while_ast.else_expr);
},
.for_simple,
.@"for",
=> {
const for_ast = fullFor(tree, node).?.ast;
for (for_ast.inputs) |child| {
try callback(context, child);
try callback(context, tree, child);
}
try callback(context, for_ast.then_expr);
try callback(context, for_ast.else_expr);
try callback(context, tree, for_ast.then_expr);
try callback(context, tree, for_ast.else_expr);
},
.@"if",
.if_simple,
=> {
const if_ast = fullIf(tree, node).?.ast;
try callback(context, if_ast.cond_expr);
try callback(context, if_ast.then_expr);
try callback(context, if_ast.else_expr);
try callback(context, tree, if_ast.cond_expr);
try callback(context, tree, if_ast.then_expr);
try callback(context, tree, if_ast.else_expr);
},
.fn_proto_simple,
@ -1453,15 +1454,15 @@ pub fn iterateChildren(
var it = fn_proto.iterate(&tree);
while (nextFnParam(&it)) |param| {
try callback(context, param.type_expr);
try callback(context, tree, param.type_expr);
}
try callback(context, fn_proto.ast.align_expr);
try callback(context, fn_proto.ast.addrspace_expr);
try callback(context, fn_proto.ast.section_expr);
try callback(context, fn_proto.ast.callconv_expr);
try callback(context, fn_proto.ast.return_type);
try callback(context, tree, fn_proto.ast.align_expr);
try callback(context, tree, fn_proto.ast.addrspace_expr);
try callback(context, tree, fn_proto.ast.section_expr);
try callback(context, tree, fn_proto.ast.callconv_expr);
try callback(context, tree, fn_proto.ast.return_type);
if (node_tags[node] == .fn_decl) {
try callback(context, node_data[node].rhs);
try callback(context, tree, node_data[node].rhs);
}
},
@ -1469,9 +1470,9 @@ pub fn iterateChildren(
.container_decl_arg_trailing,
=> {
const decl = tree.containerDeclArg(node).ast;
try callback(context, decl.arg);
try callback(context, tree, decl.arg);
for (decl.members) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
@ -1479,24 +1480,24 @@ pub fn iterateChildren(
.tagged_union_enum_tag_trailing,
=> {
const decl = tree.taggedUnionEnumTag(node).ast;
try callback(context, decl.arg);
try callback(context, tree, decl.arg);
for (decl.members) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
.container_field => {
const field = tree.containerField(node).ast;
try callback(context, field.type_expr);
try callback(context, field.align_expr);
try callback(context, field.value_expr);
try callback(context, tree, field.type_expr);
try callback(context, tree, field.align_expr);
try callback(context, tree, field.value_expr);
},
.@"asm" => {
const asm_ast = tree.asmFull(node).ast;
try callback(context, asm_ast.template);
try callback(context, tree, asm_ast.template);
for (asm_ast.items) |child| {
try callback(context, child);
try callback(context, tree, child);
}
},
@ -1519,39 +1520,35 @@ pub fn iterateChildren(
}
}
/// returns an Iterator that recursively yields every child of the given node.
/// calls the given `callback` on every child of the given node and their children
/// see `nodeChildrenRecursiveAlloc` for a non-iterator allocating variant.
pub fn iterateChildrenRecursive(
tree: Ast,
node: Ast.Node.Index,
context: anytype,
comptime Error: type,
comptime callback: fn (@TypeOf(context), Ast.Node.Index) Error!void,
comptime callback: fn (@TypeOf(context), Ast, Ast.Node.Index) Error!void,
) Error!void {
const RecursiveContext = struct {
tree: Ast,
context: @TypeOf(context),
fn recursive_callback(self: @This(), child_node: Ast.Node.Index) Error!void {
fn recursive_callback(ctx: @TypeOf(context), ast: Ast, child_node: Ast.Node.Index) Error!void {
if (child_node == 0) return;
try callback(self.context, child_node);
try iterateChildrenRecursive(self.tree, child_node, self.context, Error, callback);
try callback(ctx, ast, child_node);
try iterateChildren(ast, child_node, ctx, Error, recursive_callback);
}
};
try iterateChildren(tree, node, RecursiveContext{
.tree = tree,
.context = context,
}, Error, RecursiveContext.recursive_callback);
try iterateChildren(tree, node, context, Error, RecursiveContext.recursive_callback);
}
/// returns the children of the given node.
/// see `iterateChildren` for a callback variant
/// see `nodeChildrenRecursiveAlloc` for a recursive variant.
/// caller owns the returned memory
pub fn nodeChildrenAlloc(allocator: std.mem.Allocator, tree: Ast, node: Ast.Node.Index) error{OutOfMemory}![]Ast.Node.Index {
const Context = struct {
children: *std.ArrayList(Ast.Node.Index),
fn callback(self: @This(), child_node: Ast.Node.Index) error{OutOfMemory}!void {
fn callback(self: @This(), ast: Ast, child_node: Ast.Node.Index) error{OutOfMemory}!void {
_ = ast;
if (child_node == 0) return;
try self.children.append(child_node);
}
@ -1569,7 +1566,8 @@ pub fn nodeChildrenAlloc(allocator: std.mem.Allocator, tree: Ast, node: Ast.Node
pub fn nodeChildrenRecursiveAlloc(allocator: std.mem.Allocator, tree: Ast, node: Ast.Node.Index) error{OutOfMemory}![]Ast.Node.Index {
const Context = struct {
children: *std.ArrayList(Ast.Node.Index),
fn callback(self: @This(), child_node: Ast.Node.Index) error{OutOfMemory}!void {
fn callback(self: @This(), ast: Ast, child_node: Ast.Node.Index) error{OutOfMemory}!void {
_ = ast;
if (child_node == 0) return;
try self.children.append(child_node);
}

View File

@ -220,10 +220,9 @@ fn writeCallNodeHint(builder: *Builder, call: Ast.full.Call) !void {
fn writeNodeInlayHint(
builder: *Builder,
tree: Ast,
node: Ast.Node.Index,
) error{OutOfMemory}!void {
const handle = builder.handle;
const tree = handle.tree;
const node_tags = tree.nodes.items(.tag);
const main_tokens = tree.nodes.items(.main_token);
@ -293,7 +292,7 @@ pub fn writeRangeInlayHint(
const nodes = try ast.nodesAtLoc(arena, handle.tree, loc);
for (nodes) |child| {
try writeNodeInlayHint(&builder, child);
try writeNodeInlayHint(&builder, handle.tree, child);
try ast.iterateChildrenRecursive(handle.tree, child, &builder, error{OutOfMemory}, writeNodeInlayHint);
}

View File

@ -85,14 +85,14 @@ const Builder = struct {
try ast.iterateChildrenRecursive(handle.tree, node, &context, error{OutOfMemory}, referenceNode);
}
fn referenceNode(self: *const Context, node: Ast.Node.Index) error{OutOfMemory}!void {
fn referenceNode(self: *const Context, tree: Ast, node: Ast.Node.Index) error{OutOfMemory}!void {
const builder = self.builder;
const handle = self.handle;
const node_tags = handle.tree.nodes.items(.tag);
const datas = handle.tree.nodes.items(.data);
const main_tokens = handle.tree.nodes.items(.main_token);
const starts = handle.tree.tokens.items(.start);
const node_tags = tree.nodes.items(.tag);
const datas = tree.nodes.items(.data);
const main_tokens = tree.nodes.items(.main_token);
const starts = tree.tokens.items(.start);
switch (node_tags[node]) {
.identifier => {
@ -102,7 +102,7 @@ const Builder = struct {
builder.allocator,
builder.store,
handle,
offsets.tokenToSlice(handle.tree, identifier_token),
offsets.tokenToSlice(tree, identifier_token),
starts[identifier_token],
)) orelse return;
@ -134,7 +134,7 @@ const Builder = struct {
self.builder.allocator,
builder.store,
.{ .node = left_type_node, .handle = left_type.handle },
offsets.tokenToSlice(handle.tree, datas[node].rhs),
offsets.tokenToSlice(tree, datas[node].rhs),
!left_type.type.is_type_val,
)) orelse return;