Fix symbolReferencesInternal

This commit is contained in:
Luuk de Gram 2021-03-01 19:34:28 +01:00
parent e82ea30e6f
commit ada0d13ba9
No known key found for this signature in database
GPG Key ID: A002B174963DBB7D
2 changed files with 333 additions and 237 deletions

View File

@ -2261,21 +2261,15 @@ pub fn isContainer(tag: ast.Node.Tag) bool {
/// Returns the member indices of a given declaration container.
/// Asserts given `tag` is a container node
fn declMembers(tree: ast.Tree, tag: ast.Node.Tag, node_idx: ast.Node.Index) []const ast.Node.Index {
pub fn declMembers(tree: ast.Tree, tag: ast.Node.Tag, node_idx: ast.Node.Index, buffer: *[2]ast.Node.Index) []const ast.Node.Index {
std.debug.assert(isContainer(tag));
return switch (tag) {
.container_decl, .container_decl_trailing => tree.containerDecl(node_idx).ast.members,
.container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx).ast.members,
.container_decl_two, .container_decl_two_trailing => blk: {
var buffer: [2]ast.Node.Index = undefined;
break :blk tree.containerDeclTwo(&buffer, node_idx).ast.members;
},
.container_decl_two, .container_decl_two_trailing => tree.containerDeclTwo(&buffer, node_idx).ast.members,
.tagged_union, .tagged_union_trailing => tree.taggedUnion(node_idx).ast.members,
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(node_idx).ast.members,
.tagged_union_two, .tagged_union_two_trailing => blk: {
var buffer: [2]ast.Node.Index = undefined;
break :blk tree.taggedUnionTwo(&buffer, node_idx).ast.members;
},
.tagged_union_two, .tagged_union_two_trailing => tree.taggedUnionTwo(&buffer, node_idx).ast.members,
.root => tree.rootDecls(),
// @TODO: Fix error set declarations
.error_set_decl => &[_]ast.Node.Index{},
@ -2312,6 +2306,7 @@ fn makeScopeInternal(
const node = tags[node_idx];
if (isContainer(node)) {
var buf: [2]ast.Node.Index = undefined;
const ast_decls = declMembers(tree, node, node_idx);
(try scopes.addOne(allocator)).* = .{

View File

@ -77,263 +77,326 @@ fn symbolReferencesInternal(
) error{OutOfMemory}!void {
const node = node_handle.node;
const handle = node_handle.handle;
const tree = handle.tree;
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 (handle.tree.nodes.items(.tag)[node]) {
.ContainerDecl, .Root, .Block => {
var idx: usize = 0;
while (node.iterate(idx)) |child| : (idx += 1) {
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
}
},
.VarDecl => {
const var_decl = node.cast(ast.Node.VarDecl).?;
if (var_decl.getTypeNode()) |type_node| {
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
}
if (var_decl.getInitNode()) |init_node| {
try symbolReferencesInternal(arena, store, .{ .node = init_node, .handle = handle }, decl, encoding, context, handler);
}
},
.Use => {
const use = node.cast(ast.Node.Use).?;
try symbolReferencesInternal(arena, store, .{ .node = use.expr, .handle = handle }, decl, encoding, context, handler);
},
.ContainerField => {
const field = node.cast(ast.Node.ContainerField).?;
if (field.type_expr) |type_node| {
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
}
if (field.value_expr) |init_node| {
try symbolReferencesInternal(arena, store, .{ .node = init_node, .handle = handle }, decl, encoding, context, handler);
}
},
.Identifier => {
if (try analysis.lookupSymbolGlobal(store, arena, handle, handle.tree.getNodeSource(node), handle.tree.token_locs[node.firstToken()].start)) |child| {
if (std.meta.eql(decl, child)) {
try tokenReference(handle, node.firstToken(), encoding, context, handler);
}
}
},
.FnProto => {
const fn_proto = node.cast(ast.Node.FnProto).?;
for (fn_proto.paramsConst()) |param| {
switch (param.param_type) {
.type_expr => |type_node| {
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
},
else => {},
}
}
switch (fn_proto.return_type) {
.Explicit, .InferErrorSet => |type_node| {
try symbolReferencesInternal(arena, store, .{ .node = type_node, .handle = handle }, decl, encoding, context, handler);
switch (node_tags[node]) {
.block, .block_semicolon, .block_two, .block_two_semicolon => {
const statements: []const ast.Node.Index = switch (node_tags[node]) {
.block, .block_semicolon => tree.extra_data[datas[node].lhs..datas[node].rhs],
.block_two, .block_two_semicolon => blk: {
const statements = &[_]ast.Node.Index{ datas[node].lhs, datas[node].rhs };
const len: usize = if (datas[node].lhs == 0)
@as(usize, 0)
else if (datas[node].rhs == 0)
@as(usize, 1)
else
@as(usize, 2);
break :blk statements[0..len];
},
else => {},
else => unreachable,
};
for (statements) |stmt|
try symbolReferencesInternal(arena, store, .{ .node = stmt, .handle = handle }, decl, encoding, context, handler);
},
.container_decl,
.container_decl_trailing,
.container_decl_arg,
.container_decl_arg_trailing,
.container_decl_two,
.container_decl_two_trailing,
.tagged_union,
.tagged_union_trailing,
.tagged_union_two,
.tagged_union_two_trailing,
.tagged_union_enum_tag,
.tagged_union_enum_tag_trailing,
.root,
.error_set_decl,
=> {
var buf: [2]ast.Node.Index = undefined;
for (analysis.declMembers(tree, node_tags[node], node, &buf)) |member|
try symbolReferencesInternal(arena, store, .{ .node = member, .handle = handle }, decl, encoding, context, handler);
},
.global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => {
const var_decl = analysis.varDecl(tree, node).?;
if (var_decl.ast.type_node != 0) {
try symbolReferencesInternal(arena, store, .{ .node = var_decl.ast.type_node, .handle = handle }, decl, encoding, context, handler);
}
if (fn_proto.getAlignExpr()) |align_expr| {
try symbolReferencesInternal(arena, store, .{ .node = align_expr, .handle = handle }, decl, encoding, context, handler);
}
if (fn_proto.getSectionExpr()) |section_expr| {
try symbolReferencesInternal(arena, store, .{ .node = section_expr, .handle = handle }, decl, encoding, context, handler);
}
if (fn_proto.getCallconvExpr()) |callconv_expr| {
try symbolReferencesInternal(arena, store, .{ .node = callconv_expr, .handle = handle }, decl, encoding, context, handler);
}
if (fn_proto.getBodyNode()) |body| {
try symbolReferencesInternal(arena, store, .{ .node = body, .handle = handle }, decl, encoding, context, handler);
if (var_decl.ast.init_node != 0) {
try symbolReferencesInternal(arena, store, .{ .node = var_decl.ast.init_node, .handle = handle }, decl, encoding, context, handler);
}
},
.AnyFrameType => {
const anyframe_type = node.cast(ast.Node.AnyFrameType).?;
if (anyframe_type.result) |result| {
try symbolReferencesInternal(arena, store, .{ .node = result.return_type, .handle = handle }, decl, encoding, context, handler);
// @TODO: Usingnamespace
// .Use => {
// const use = node.cast(ast.Node.Use).?;
// try symbolReferencesInternal(arena, store, .{ .node = use.expr, .handle = handle }, decl, encoding, context, handler);
// },
.container_field, .container_field_align, .container_field_init => {
const field = analysis.containerField(node).?;
if (field.ast.type_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = field.ast.type_expr, .handle = handle }, decl, encoding, context, handler);
}
if (field.ast.value_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = field.ast.value_expr, .handle = handle }, decl, encoding, context, handler);
}
},
.Defer => {
const defer_node = node.cast(ast.Node.Defer).?;
try symbolReferencesInternal(arena, store, .{ .node = defer_node.expr, .handle = handle }, decl, encoding, context, handler);
},
.Comptime => {
const comptime_node = node.cast(ast.Node.Comptime).?;
try symbolReferencesInternal(arena, store, .{ .node = comptime_node.expr, .handle = handle }, decl, encoding, context, handler);
},
.Nosuspend => {
const nosuspend_node = node.cast(ast.Node.Nosuspend).?;
try symbolReferencesInternal(arena, store, .{ .node = nosuspend_node.expr, .handle = handle }, decl, encoding, context, handler);
},
.Switch => {
// TODO When renaming a union(enum) field, also rename switch items that refer to it.
const switch_node = node.cast(ast.Node.Switch).?;
try symbolReferencesInternal(arena, store, .{ .node = switch_node.expr, .handle = handle }, decl, encoding, context, handler);
for (switch_node.casesConst()) |case| {
if (case.*.cast(ast.Node.SwitchCase)) |case_node| {
try symbolReferencesInternal(arena, store, .{ .node = case_node.expr, .handle = handle }, decl, encoding, context, handler);
.identifier => {
if (try analysis.lookupSymbolGlobal(store, arena, handle, tree.getNodeSource(node), starts[main_tokens[nodes]])) |child| {
if (std.meta.eql(decl, child)) {
try tokenReference(handle, main_tokens[node], encoding, context, handler);
}
}
},
.While => {
const while_node = node.cast(ast.Node.While).?;
try symbolReferencesInternal(arena, store, .{ .node = while_node.condition, .handle = handle }, decl, encoding, context, handler);
if (while_node.continue_expr) |cont_expr| {
try symbolReferencesInternal(arena, store, .{ .node = cont_expr, .handle = handle }, decl, encoding, context, handler);
.fn_proto, .fn_proto_multi, .fn_proto_one, .fn_proto_simple, .fn_decl => {
var buf: [1]ast.Node.Index = undefined;
const fn_proto = analysis.fnProto(tree, node, &buf).?;
var it = fn_proto.iterate(tree);
while (it.next()) |param| {
if (param.type_expr != 0)
try symbolReferencesInternal(arena, store, .{ .node = param.type_expr, .handle = handle }, decl, encoding, context, handler);
}
try symbolReferencesInternal(arena, store, .{ .node = while_node.body, .handle = handle }, decl, encoding, context, handler);
if (while_node.@"else") |else_node| {
try symbolReferencesInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, encoding, context, handler);
if (fn_proto.ast.return_type != 0) {
try symbolReferencesInternal(arena, store, .{ .node = fn_proto.ast.return_type, .handle = handle }, decl, encoding, context, handler);
}
if (fn_proto.ast.align_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = fn_proto.ast.align_expr, .handle = handle }, decl, encoding, context, handler);
}
if (fn_proto.ast.section_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = fn_proto.ast.section_expr, .handle = handle }, decl, encoding, context, handler);
}
if (fn_proto.ast.callconv_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = fn_proto.ast.callconv_expr, .handle = handle }, decl, encoding, context, handler);
}
if (node_tags[node] == .fn_decl) {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
}
},
.For => {
const for_node = node.cast(ast.Node.For).?;
try symbolReferencesInternal(arena, store, .{ .node = for_node.array_expr, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = for_node.body, .handle = handle }, decl, encoding, context, handler);
if (for_node.@"else") |else_node| {
try symbolReferencesInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, encoding, context, handler);
.anyframe_type => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
},
.@"defer" => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
},
.@"comptime" => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
},
.@"nosuspend" => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
},
.@"switch", .switch_comma => {
// TODO When renaming a union(enum) field, also rename switch items that refer to it.
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
const extra = tree.extraData(datas[node].rhs, ast.Node.SubRange);
const cases = tree.extra_data[extra.start..extra.end];
for (cases) |case| {
try symbolReferencesInternal(arena, store, .{ .node = case, .handle = handle }, decl, encoding, context, handler);
}
},
.If => {
const if_node = node.cast(ast.Node.If).?;
try symbolReferencesInternal(arena, store, .{ .node = if_node.condition, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = if_node.body, .handle = handle }, decl, encoding, context, handler);
if (if_node.@"else") |else_node| {
try symbolReferencesInternal(arena, store, .{ .node = else_node.body, .handle = handle }, decl, encoding, context, handler);
.switch_case_one => {
const case_one = tree.switchCaseOne(node);
for (case_one.ast.values) |val|
try symbolReferencesInternal(arena, store, .{ .node = val, .handle = handle }, decl, encoding, context, handler);
},
.switch_case => {
const case = tree.switchCase(node);
for (case_one.ast.values) |val|
try symbolReferencesInternal(arena, store, .{ .node = val, .handle = handle }, decl, encoding, context, handler);
},
.@"while", .while_simple, .while_con, .for_simple, .@"for" => {
const loop: ast.full.While = switch (node_tags[node]) {
.@"while" => tree.whileFull(node),
.while_simple => tree.whileSimple(node),
.while_con => tree.whileCont(node),
.for_simple => tree.forSimple(node),
.@"for" => tree.forFull(node),
else => unreachable,
};
try symbolReferencesInternal(arena, store, .{ .node = loop.ast.cond_expr, .handle = handle }, decl, encoding, context, handler);
if (loop.ast.cont_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = loop.ast.cont_expr, .handle = handle }, decl, encoding, context, handler);
}
try symbolReferencesInternal(arena, store, .{ .node = loop.ast.then_expr, .handle = handle }, decl, encoding, context, handler);
if (loop.ast.else_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = loop.ast.else_expr, .handle = handle }, decl, encoding, context, handler);
}
},
.ArrayType => {
const info = node.castTag(.ArrayType).?;
try symbolReferencesInternal(arena, store, .{ .node = info.len_expr, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = info.rhs, .handle = handle }, decl, encoding, context, handler);
.@"if", .if_simple => {
const if_node: ast.full.If = if (node_tags[node] == .@"if") tree.ifFull(node) else tree.ifSimple(node);
try symbolReferencesInternal(arena, store, .{ .node = if_node.ast.cond_expr, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = if_node.ast.then_expr, .handle = handle }, decl, encoding, context, handler);
if (if_node.ast.else_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = if_node.ast.else_expr, .handle = handle }, decl, encoding, context, handler);
}
},
.ArrayTypeSentinel => {
const info = node.castTag(.ArrayTypeSentinel).?;
try symbolReferencesInternal(arena, store, .{ .node = info.len_expr, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = info.sentinel, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = info.rhs, .handle = handle }, decl, encoding, context, handler);
.array_type, .array_type_sentinel => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
},
.PtrType, .SliceType => {
const info = switch (node.tag) {
.PtrType => node.castTag(.PtrType).?.ptr_info,
.SliceType => node.castTag(.SliceType).?.ptr_info,
.ptr_type, .ptr_type_aligned, .ptr_type_bit_range, .ptr_type_sentinel => {
const ptr_type = analysis.ptrType(tree, node).?;
if (ptr_type.ast.align_node != 0) {
try symbolReferencesInternal(arena, store, .{ .node = ptr_type.ast.align_node, .handle = handle }, decl, encoding, context, handler);
if (node_tags[node] == .ptr_type_bit_range) {
try symbolReferencesInternal(arena, store, .{
.node = ptr_type.ast.bit_range_start,
.handle = handle,
}, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{
.node = ptr_type.ast.bit_range_end,
.handle = handle,
}, decl, encoding, context, handler);
}
}
if (ptr_type.ast.sentinel != 0) {
try symbolReferencesInternal(arena, store, .{ .node = ptr_type.ast.sentinel, .handle = handle }, decl, encoding, context, handler);
}
try symbolReferencesInternal(arena, store, .{ .node = ptr_type.ast.child_type, .handle = handle }, decl, encoding, context, handler);
},
.address_of, .@"await", .bit_not, .bool_not, .optional_type, .negation, .negation_wrap, .@"resume", .@"try" => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
},
.array_init,
.array_init_comma,
.array_init_dot,
.array_init_dot_comma,
.array_init_one,
.array_init_one_comma,
.array_init_dot_two,
.array_init_dot_two_comma,
=> |n| {
var buf: [2]ast.Node.Index = undefined;
const array_init = switch (n) {
.array_init, .array_init_comma => tree.arrayInit(node),
.array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node),
.array_init_one, .array_init_one_comma => tree.arrayInitOne(&buf[0..1], node),
.array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(&buf, node),
else => unreachable,
};
if (array_init.ast.type_expr != 0)
try symbolReferencesInternal(arena, store, .{ .node = array_init.ast.type_expr, .handle = handle }, decl, encoding, context, handler);
for (array_init.ast.elements) |e|
try symbolReferencesInternal(arena, store, .{ .node = e, .handle = handle }, decl, encoding, context, handler);
},
.struct_init,
.struct_init_comma,
.struct_init_dot,
.struct_init_dot_comma,
.struct_init_dot_two,
.struct_init_dot_two_comma,
.struct_init_one,
.struct_init_one_comma,
=> |n| {
var buf: [2]ast.Node.Index = undefined;
const struct_init: ast.full.StructInit = switch (n) {
.struct_init, .struct_init_comma => tree.structInit(node),
.struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node),
.struct_init_one, .struct_init_one_comma => tree.structInitOne(&buf[0..1], node),
.struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(&buf, node),
else => unreachable,
};
if (struct_init.ast.type_expr != 0)
try symbolReferencesInternal(arena, store, .{ .node = struct_init.ast.type_expr, .handle = handle }, decl, encoding, context, handler);
for (struct_init.ast.fields) |field|
try symbolReferencesInternal(arena, store, .{ .node = field, .handle = handle }, decl, encoding, context, handler);
},
.call,
.call_comma,
.call_one,
.call_one_comma,
.async_call,
.async_call_comma,
.async_call_one,
.async_call_one_comma,
=> |c| {
var buf: [1]ast.Node.Index = undefined;
const call: ast.full.Call = switch (c) {
.call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
.call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&buf, node),
else => unreachable,
};
if (call.ast.fn_expr != 0)
try symbolReferencesInternal(arena, store, .{ .node = call.ast.fn_expr, .handle = handle }, decl, encoding, context, handler);
for (call.ast.params) |param| {
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);
}
},
.slice, .slice_sentinel, .slice_open => |s| {
const slice: ast.full.Slice = switch (s) {
.slice => tree.slice(node),
.slice_open => tree.sliceOpen(node),
.slice_sentinel => tree.sliceSentinel(node),
else => unreachable,
};
if (info.align_info) |align_info| {
try symbolReferencesInternal(arena, store, .{ .node = align_info.node, .handle = handle }, decl, encoding, context, handler);
if (align_info.bit_range) |range| {
try symbolReferencesInternal(arena, store, .{ .node = range.start, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = range.end, .handle = handle }, decl, encoding, context, handler);
}
}
if (info.sentinel) |sentinel| {
try symbolReferencesInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, encoding, context, handler);
}
switch (node.tag) {
.PtrType => try symbolReferencesInternal(arena, store, .{ .node = node.castTag(.PtrType).?.rhs, .handle = handle }, decl, encoding, context, handler),
.SliceType => try symbolReferencesInternal(arena, store, .{ .node = node.castTag(.SliceType).?.rhs, .handle = handle }, decl, encoding, context, handler),
else => unreachable,
try symbolReferencesInternal(arena, store, .{ .node = slice.ast.sliced, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = slice.ast.start, .handle = handle }, decl, encoding, context, handler);
if (slice.ast.end != 0)
try symbolReferencesInternal(arena, store, .{ .node = slice.ast.end, .handle = handle }, decl, encoding, context, handler);
if (slice.ast.sentinel != 0)
try symbolReferencesInternal(arena, store, .{ .node = slice.ast.sentinel, .handle = handle }, decl, encoding, context, handler);
},
.array_access => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
},
.deref, .unwrap_optional => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
},
.grouped_expression => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
},
.@"return", .@"break", .@"continue" => {
if (datas[node].lhs != 0) {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
}
},
.AddressOf, .Await, .BitNot, .BoolNot, .OptionalType, .Negation, .NegationWrap, .Resume, .Try => {
const prefix_op = node.cast(ast.Node.SimplePrefixOp).?;
try symbolReferencesInternal(arena, store, .{ .node = prefix_op.rhs, .handle = handle }, decl, encoding, context, handler);
},
.FieldInitializer => {
// TODO Rename field initializer names when needed
const field_init = node.cast(ast.Node.FieldInitializer).?;
try symbolReferencesInternal(arena, store, .{ .node = field_init.expr, .handle = handle }, decl, encoding, context, handler);
},
.ArrayInitializer => {
const array_init = node.cast(ast.Node.ArrayInitializer).?;
try symbolReferencesInternal(arena, store, .{ .node = array_init.lhs, .handle = handle }, decl, encoding, context, handler);
for (array_init.listConst()) |child| {
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
.@"suspend" => {
if (datas[node].lhs != 0) {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
}
},
.ArrayInitializerDot => {
const array_init = node.cast(ast.Node.ArrayInitializerDot).?;
for (array_init.listConst()) |child| {
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
}
},
.StructInitializer => {
// TODO Rename field initializer names when needed
const struct_init = node.cast(ast.Node.StructInitializer).?;
try symbolReferencesInternal(arena, store, .{ .node = struct_init.lhs, .handle = handle }, decl, encoding, context, handler);
for (struct_init.listConst()) |child| {
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
}
},
.StructInitializerDot => {
const struct_init = node.cast(ast.Node.StructInitializerDot).?;
for (struct_init.listConst()) |child| {
try symbolReferencesInternal(arena, store, .{ .node = child, .handle = handle }, decl, encoding, context, handler);
}
},
.Call => {
const call = node.cast(ast.Node.Call).?;
try symbolReferencesInternal(arena, store, .{ .node = call.lhs, .handle = handle }, decl, encoding, context, handler);
for (call.paramsConst()) |param| {
.builtin_call,
.builtin_call_comma,
.builtin_call_two,
.builtin_call_two_comma,
=> {
const builtin_call = analysis.builtinCallParams();
for (analysis.builtinCallParams()) |param|
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);
}
},
.Slice => {
const slice = node.castTag(.Slice).?;
try symbolReferencesInternal(arena, store, .{ .node = slice.lhs, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = slice.start, .handle = handle }, decl, encoding, context, handler);
if (slice.end) |end| {
try symbolReferencesInternal(arena, store, .{ .node = end, .handle = handle }, decl, encoding, context, handler);
}
if (slice.sentinel) |sentinel| {
try symbolReferencesInternal(arena, store, .{ .node = sentinel, .handle = handle }, decl, encoding, context, handler);
}
},
.ArrayAccess => {
const arr_acc = node.castTag(.ArrayAccess).?;
try symbolReferencesInternal(arena, store, .{ .node = arr_acc.lhs, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = arr_acc.index_expr, .handle = handle }, decl, encoding, context, handler);
},
.Deref, .UnwrapOptional => {
const suffix = node.cast(ast.Node.SimpleSuffixOp).?;
try symbolReferencesInternal(arena, store, .{ .node = suffix.lhs, .handle = handle }, decl, encoding, context, handler);
},
.GroupedExpression => {
const grouped = node.cast(ast.Node.GroupedExpression).?;
try symbolReferencesInternal(arena, store, .{ .node = grouped.expr, .handle = handle }, decl, encoding, context, handler);
},
.Return, .Break, .Continue => {
const cfe = node.cast(ast.Node.ControlFlowExpression).?;
if (cfe.getRHS()) |rhs| {
try symbolReferencesInternal(arena, store, .{ .node = rhs, .handle = handle }, decl, encoding, context, handler);
}
},
.Suspend => {
const suspend_node = node.cast(ast.Node.Suspend).?;
if (suspend_node.body) |body| {
try symbolReferencesInternal(arena, store, .{ .node = body, .handle = handle }, decl, encoding, context, handler);
}
},
.BuiltinCall => {
const builtin_call = node.cast(ast.Node.BuiltinCall).?;
for (builtin_call.paramsConst()) |param| {
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);
}
},
// TODO Inline asm expr
.TestDecl => {
const test_decl = node.cast(ast.Node.TestDecl).?;
try symbolReferencesInternal(arena, store, .{ .node = test_decl.body_node, .handle = handle }, decl, encoding, context, handler);
},
.Period => {
const infix_op = node.cast(ast.Node.SimpleInfixOp).?;
.@"asm", .asm_simple => |a| {
const _asm: ast.full.Asm = if (a == .@"asm") tree.asmFull(node) else tree.asmSimple(node);
if (_asm.ast.items.len == 0)
try symbolReferencesInternal(arena, store, .{ .node = _asm.ast.template, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = infix_op.lhs, .handle = handle }, decl, encoding, context, handler);
for (_asm.inputs) |input|
try symbolReferencesInternal(arena, store, .{ .node = input, .handle = handle }, decl, encoding, context, handler);
const rhs_str = analysis.nodeToString(handle.tree, infix_op.rhs) orelse return;
for (_asm.outputs) |output|
try symbolReferencesInternal(arena, store, .{ .node = output, .handle = handle }, decl, encoding, context, handler);
},
.test_decl => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
},
.field_access => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
const rhs_str = analysis.nodeToString(handle.tree, datas[node].rhs) orelse return;
var bound_type_params = analysis.BoundTypeParams.init(&arena.allocator);
const left_type = try analysis.resolveFieldAccessLhsType(
store,
arena,
(try analysis.resolveTypeOfNodeInternal(store, arena, .{
.node = infix_op.lhs,
.node = datas[node].lhs,
.handle = handle,
}, &bound_type_params)) orelse return,
&bound_type_params,
@ -352,15 +415,53 @@ fn symbolReferencesInternal(
!left_type.type.is_type_val,
)) |child| {
if (std.meta.eql(child, decl)) {
try tokenReference(handle, infix_op.rhs.firstToken(), encoding, context, handler);
try tokenReference(handle, tree.firstToken(datas[node].rhs), encoding, context, handler);
}
}
},
.Add, .AddWrap, .ArrayCat, .ArrayMult, .Assign, .AssignBitAnd, .AssignBitOr, .AssignBitShiftLeft, .AssignBitShiftRight, .AssignBitXor, .AssignDiv, .AssignSub, .AssignSubWrap, .AssignMod, .AssignAdd, .AssignAddWrap, .AssignMul, .AssignMulWrap, .BangEqual, .BitAnd, .BitOr, .BitShiftLeft, .BitShiftRight, .BitXor, .BoolOr, .Div, .EqualEqual, .ErrorUnion, .GreaterOrEqual, .GreaterThan, .LessOrEqual, .LessThan, .MergeErrorSets, .Mod, .Mul, .MulWrap, .Range, .Sub, .SubWrap, .OrElse => {
const infix_op = node.cast(ast.Node.SimpleInfixOp).?;
try symbolReferencesInternal(arena, store, .{ .node = infix_op.lhs, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = infix_op.rhs, .handle = handle }, decl, encoding, context, handler);
.add,
.add_wrap,
.array_cat,
.array_mult,
.assign,
.assign_bit_and,
.assign_bit_or,
.assign_bit_shift_left,
.assign_bit_shift_right,
.assign_bit_xor,
.assign_div,
.assign_sub,
.assign_sub_wrap,
.assign_mod,
.assign_add,
.assign_add_wrap,
.assign_mul,
.assign_mul_wrap,
.bang_equal,
.bit_and,
.bit_or,
.bit_shift_left,
.bit_shift_right,
.bit_xor,
.bool_or,
.div,
.equal_equal,
.error_union,
.greater_or_equal,
.greater_than,
.less_or_equal,
.less_than,
.merge_error_sets,
.mod,
.mul,
.mul_wrap,
.range,
.sub,
.sub_wrap,
.@"orelse",
=> {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
},
else => {},
}