fix symbol references (#712)

* fix symbol references

* skip references for inline assembly
This commit is contained in:
Techatrix 2022-10-29 10:37:52 +02:00 committed by GitHub
parent 51a7ae2274
commit 7a7576c06d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 63 deletions

View File

@ -82,10 +82,11 @@ fn symbolReferencesInternal(
builder: *Builder, builder: *Builder,
node: Ast.Node.Index, node: Ast.Node.Index,
handle: *const DocumentStore.Handle, handle: *const DocumentStore.Handle,
is_root: bool,
) error{OutOfMemory}!void { ) error{OutOfMemory}!void {
const tree = handle.tree; const tree = handle.tree;
if (node == 0 or node > tree.nodes.len) return; if (!is_root and node == 0 or node > tree.nodes.len) return;
const node_tags = tree.nodes.items(.tag); const node_tags = tree.nodes.items(.tag);
const datas = tree.nodes.items(.data); const datas = tree.nodes.items(.data);
@ -102,7 +103,7 @@ fn symbolReferencesInternal(
const statements = ast.blockStatements(tree, node, &buffer).?; const statements = ast.blockStatements(tree, node, &buffer).?;
for (statements) |stmt| for (statements) |stmt|
try symbolReferencesInternal(builder, stmt, handle); try symbolReferencesInternal(builder, stmt, handle, false);
}, },
.container_decl, .container_decl,
.container_decl_trailing, .container_decl_trailing,
@ -121,7 +122,7 @@ fn symbolReferencesInternal(
=> { => {
var buf: [2]Ast.Node.Index = undefined; var buf: [2]Ast.Node.Index = undefined;
for (ast.declMembers(tree, node, &buf)) |member| for (ast.declMembers(tree, node, &buf)) |member|
try symbolReferencesInternal(builder, member, handle); try symbolReferencesInternal(builder, member, handle, false);
}, },
.global_var_decl, .global_var_decl,
.local_var_decl, .local_var_decl,
@ -129,16 +130,16 @@ fn symbolReferencesInternal(
.aligned_var_decl, .aligned_var_decl,
=> { => {
const var_decl = ast.varDecl(tree, node).?; const var_decl = ast.varDecl(tree, node).?;
try symbolReferencesInternal(builder, var_decl.ast.type_node, handle); try symbolReferencesInternal(builder, var_decl.ast.type_node, handle, false);
try symbolReferencesInternal(builder, var_decl.ast.init_node, handle); try symbolReferencesInternal(builder, var_decl.ast.init_node, handle, false);
}, },
.container_field, .container_field,
.container_field_align, .container_field_align,
.container_field_init, .container_field_init,
=> { => {
const field = ast.containerField(tree, node).?; const field = ast.containerField(tree, node).?;
try symbolReferencesInternal(builder, field.ast.type_expr, handle); try symbolReferencesInternal(builder, field.ast.type_expr, handle, false);
try symbolReferencesInternal(builder, field.ast.value_expr, handle); try symbolReferencesInternal(builder, field.ast.value_expr, handle, false);
}, },
.identifier => { .identifier => {
const child = (try analysis.lookupSymbolGlobal(builder.store, builder.arena, handle, tree.getNodeSource(node), starts[main_tokens[node]])) orelse return; const child = (try analysis.lookupSymbolGlobal(builder.store, builder.arena, handle, tree.getNodeSource(node), starts[main_tokens[node]])) orelse return;
@ -154,43 +155,43 @@ fn symbolReferencesInternal(
const fn_proto = ast.fnProto(tree, node, &buf).?; const fn_proto = ast.fnProto(tree, node, &buf).?;
var it = fn_proto.iterate(&tree); var it = fn_proto.iterate(&tree);
while (ast.nextFnParam(&it)) |param| { while (ast.nextFnParam(&it)) |param| {
try symbolReferencesInternal(builder, param.type_expr, handle); try symbolReferencesInternal(builder, param.type_expr, handle, false);
} }
try symbolReferencesInternal(builder, fn_proto.ast.return_type, handle); try symbolReferencesInternal(builder, fn_proto.ast.return_type, handle, false);
try symbolReferencesInternal(builder, fn_proto.ast.align_expr, handle); try symbolReferencesInternal(builder, fn_proto.ast.align_expr, handle, false);
try symbolReferencesInternal(builder, fn_proto.ast.section_expr, handle); try symbolReferencesInternal(builder, fn_proto.ast.section_expr, handle, false);
try symbolReferencesInternal(builder, fn_proto.ast.callconv_expr, handle); try symbolReferencesInternal(builder, fn_proto.ast.callconv_expr, handle, false);
if (node_tags[node] == .fn_decl) { if (node_tags[node] == .fn_decl) {
try symbolReferencesInternal(builder, datas[node].rhs, handle); try symbolReferencesInternal(builder, datas[node].rhs, handle, false);
} }
}, },
.@"switch", .@"switch",
.switch_comma, .switch_comma,
=> { => {
// TODO When renaming a union(enum) field, also rename switch items that refer to it. // TODO When renaming a union(enum) field, also rename switch items that refer to it.
try symbolReferencesInternal(builder, datas[node].lhs, handle); try symbolReferencesInternal(builder, datas[node].lhs, handle, false);
const extra = tree.extraData(datas[node].rhs, Ast.Node.SubRange); const extra = tree.extraData(datas[node].rhs, Ast.Node.SubRange);
const cases = tree.extra_data[extra.start..extra.end]; const cases = tree.extra_data[extra.start..extra.end];
for (cases) |case| { for (cases) |case| {
try symbolReferencesInternal(builder, case, handle); try symbolReferencesInternal(builder, case, handle, false);
} }
}, },
.switch_case_one, .switch_case_one,
.switch_case_inline_one, .switch_case_inline_one,
=> { => {
const case_one = tree.switchCaseOne(node); const case_one = tree.switchCaseOne(node);
try symbolReferencesInternal(builder, case_one.ast.target_expr, handle); try symbolReferencesInternal(builder, case_one.ast.target_expr, handle, false);
for (case_one.ast.values) |val| for (case_one.ast.values) |val|
try symbolReferencesInternal(builder, val, handle); try symbolReferencesInternal(builder, val, handle, false);
}, },
.switch_case, .switch_case,
.switch_case_inline, .switch_case_inline,
=> { => {
const case = tree.switchCase(node); const case = tree.switchCase(node);
try symbolReferencesInternal(builder, case.ast.target_expr, handle); try symbolReferencesInternal(builder, case.ast.target_expr, handle, false);
for (case.ast.values) |val| for (case.ast.values) |val|
try symbolReferencesInternal(builder, val, handle); try symbolReferencesInternal(builder, val, handle, false);
}, },
.@"while", .@"while",
.while_simple, .while_simple,
@ -199,17 +200,17 @@ fn symbolReferencesInternal(
.@"for", .@"for",
=> { => {
const loop = ast.whileAst(tree, node).?; const loop = ast.whileAst(tree, node).?;
try symbolReferencesInternal(builder, loop.ast.cond_expr, handle); try symbolReferencesInternal(builder, loop.ast.cond_expr, handle, false);
try symbolReferencesInternal(builder, loop.ast.then_expr, handle); try symbolReferencesInternal(builder, loop.ast.then_expr, handle, false);
try symbolReferencesInternal(builder, loop.ast.else_expr, handle); try symbolReferencesInternal(builder, loop.ast.else_expr, handle, false);
}, },
.@"if", .@"if",
.if_simple, .if_simple,
=> { => {
const if_node = ast.ifFull(tree, node); const if_node = ast.ifFull(tree, node);
try symbolReferencesInternal(builder, if_node.ast.cond_expr, handle); try symbolReferencesInternal(builder, if_node.ast.cond_expr, handle, false);
try symbolReferencesInternal(builder, if_node.ast.then_expr, handle); try symbolReferencesInternal(builder, if_node.ast.then_expr, handle, false);
try symbolReferencesInternal(builder, if_node.ast.else_expr, handle); try symbolReferencesInternal(builder, if_node.ast.else_expr, handle, false);
}, },
.ptr_type, .ptr_type,
.ptr_type_aligned, .ptr_type_aligned,
@ -219,15 +220,15 @@ fn symbolReferencesInternal(
const ptr_type = ast.ptrType(tree, node).?; const ptr_type = ast.ptrType(tree, node).?;
if (ptr_type.ast.align_node != 0) { if (ptr_type.ast.align_node != 0) {
try symbolReferencesInternal(builder, ptr_type.ast.align_node, handle); try symbolReferencesInternal(builder, ptr_type.ast.align_node, handle, false);
if (node_tags[node] == .ptr_type_bit_range) { if (node_tags[node] == .ptr_type_bit_range) {
try symbolReferencesInternal(builder, ptr_type.ast.bit_range_start, handle); try symbolReferencesInternal(builder, ptr_type.ast.bit_range_start, handle, false);
try symbolReferencesInternal(builder, ptr_type.ast.bit_range_end, handle); try symbolReferencesInternal(builder, ptr_type.ast.bit_range_end, handle, false);
} }
} }
try symbolReferencesInternal(builder, ptr_type.ast.sentinel, handle); try symbolReferencesInternal(builder, ptr_type.ast.sentinel, handle, false);
try symbolReferencesInternal(builder, ptr_type.ast.child_type, handle); try symbolReferencesInternal(builder, ptr_type.ast.child_type, handle, false);
}, },
.array_init, .array_init,
.array_init_comma, .array_init_comma,
@ -246,9 +247,9 @@ fn symbolReferencesInternal(
.array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(&buf, node), .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(&buf, node),
else => unreachable, else => unreachable,
}; };
try symbolReferencesInternal(builder, array_init.ast.type_expr, handle); try symbolReferencesInternal(builder, array_init.ast.type_expr, handle, false);
for (array_init.ast.elements) |e| for (array_init.ast.elements) |e|
try symbolReferencesInternal(builder, e, handle); try symbolReferencesInternal(builder, e, handle, false);
}, },
.struct_init, .struct_init,
.struct_init_comma, .struct_init_comma,
@ -267,9 +268,9 @@ fn symbolReferencesInternal(
.struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(&buf, node), .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(&buf, node),
else => unreachable, else => unreachable,
}; };
try symbolReferencesInternal(builder, struct_init.ast.type_expr, handle); try symbolReferencesInternal(builder, struct_init.ast.type_expr, handle, false);
for (struct_init.ast.fields) |field| for (struct_init.ast.fields) |field|
try symbolReferencesInternal(builder, field, handle); try symbolReferencesInternal(builder, field, handle, false);
}, },
.call, .call,
.call_comma, .call_comma,
@ -283,10 +284,10 @@ fn symbolReferencesInternal(
var buf: [1]Ast.Node.Index = undefined; var buf: [1]Ast.Node.Index = undefined;
const call = ast.callFull(tree, node, &buf).?; const call = ast.callFull(tree, node, &buf).?;
try symbolReferencesInternal(builder, call.ast.fn_expr, handle); try symbolReferencesInternal(builder, call.ast.fn_expr, handle, false);
for (call.ast.params) |param| { for (call.ast.params) |param| {
try symbolReferencesInternal(builder, param, handle); try symbolReferencesInternal(builder, param, handle, false);
} }
}, },
.slice, .slice,
@ -300,10 +301,10 @@ fn symbolReferencesInternal(
else => unreachable, else => unreachable,
}; };
try symbolReferencesInternal(builder, slice.ast.sliced, handle); try symbolReferencesInternal(builder, slice.ast.sliced, handle, false);
try symbolReferencesInternal(builder, slice.ast.start, handle); try symbolReferencesInternal(builder, slice.ast.start, handle, false);
try symbolReferencesInternal(builder, slice.ast.end, handle); try symbolReferencesInternal(builder, slice.ast.end, handle, false);
try symbolReferencesInternal(builder, slice.ast.sentinel, handle); try symbolReferencesInternal(builder, slice.ast.sentinel, handle, false);
}, },
.builtin_call, .builtin_call,
.builtin_call_comma, .builtin_call_comma,
@ -314,25 +315,26 @@ fn symbolReferencesInternal(
const params = ast.builtinCallParams(tree, node, &buffer).?; const params = ast.builtinCallParams(tree, node, &buffer).?;
for (params) |param| for (params) |param|
try symbolReferencesInternal(builder, param, handle); try symbolReferencesInternal(builder, param, handle, false);
}, },
.@"asm", .@"asm",
.asm_simple, .asm_simple,
=> |tag| { => |tag| {
const full_asm: Ast.full.Asm = if (tag == .@"asm") tree.asmFull(node) else tree.asmSimple(node); const full_asm: Ast.full.Asm = if (tag == .@"asm") tree.asmFull(node) else tree.asmSimple(node);
if (full_asm.ast.items.len == 0) if (full_asm.ast.items.len == 0)
try symbolReferencesInternal(builder, full_asm.ast.template, handle); try symbolReferencesInternal(builder, full_asm.ast.template, handle, false);
for (full_asm.inputs) |input| for (full_asm.inputs) |input|
try symbolReferencesInternal(builder, input, handle); try symbolReferencesInternal(builder, input, handle, false);
for (full_asm.outputs) |output| for (full_asm.outputs) |output|
try symbolReferencesInternal(builder, output, handle); try symbolReferencesInternal(builder, output, handle, false);
}, },
.asm_output => unreachable, // TODO implement references for asm
.asm_input => unreachable, .asm_output => {},
.asm_input => {},
.field_access => { .field_access => {
try symbolReferencesInternal(builder, datas[node].lhs, handle); try symbolReferencesInternal(builder, datas[node].lhs, handle, false);
const rhs_str = ast.tokenSlice(tree, datas[node].rhs) catch return; const rhs_str = ast.tokenSlice(tree, datas[node].rhs) catch return;
var bound_type_params = analysis.BoundTypeParams{}; var bound_type_params = analysis.BoundTypeParams{};
@ -380,12 +382,12 @@ fn symbolReferencesInternal(
.grouped_expression, .grouped_expression,
.@"comptime", .@"comptime",
.@"nosuspend", .@"nosuspend",
=> try symbolReferencesInternal(builder, datas[node].lhs, handle), => try symbolReferencesInternal(builder, datas[node].lhs, handle, false),
.test_decl, .test_decl,
.@"errdefer", .@"errdefer",
.@"defer", .@"defer",
.anyframe_type, .anyframe_type,
=> try symbolReferencesInternal(builder, datas[node].rhs, handle), => try symbolReferencesInternal(builder, datas[node].rhs, handle, false),
.equal_equal, .equal_equal,
.bang_equal, .bang_equal,
.less_than, .less_than,
@ -440,8 +442,8 @@ fn symbolReferencesInternal(
.switch_range, .switch_range,
.error_union, .error_union,
=> { => {
try symbolReferencesInternal(builder, datas[node].lhs, handle); try symbolReferencesInternal(builder, datas[node].lhs, handle, false);
try symbolReferencesInternal(builder, datas[node].rhs, handle); try symbolReferencesInternal(builder, datas[node].rhs, handle, false);
}, },
.anyframe_literal, .anyframe_literal,
.char_literal, .char_literal,
@ -472,15 +474,9 @@ pub fn symbolReferences(
if (include_decl) try builder.add(curr_handle, decl_handle.nameToken()); if (include_decl) try builder.add(curr_handle, decl_handle.nameToken());
switch (decl_handle.decl.*) { switch (decl_handle.decl.*) {
.pointer_payload, .ast_node => {
.switch_payload, try symbolReferencesInternal(&builder, 0, curr_handle, true);
.array_payload,
.array_index,
.ast_node,
=> {
try symbolReferencesInternal(&builder, 0, curr_handle);
if (decl_handle.decl.* != .ast_node) return builder.locations;
if (!workspace) return builder.locations; if (!workspace) return builder.locations;
for (store.handles.values()) |handle| { for (store.handles.values()) |handle| {
@ -494,10 +490,19 @@ pub fn symbolReferences(
for (dependencies.items) |uri| { for (dependencies.items) |uri| {
const hdl = store.getHandle(uri) orelse continue; const hdl = store.getHandle(uri) orelse continue;
try symbolReferencesInternal(&builder, 0, hdl); try symbolReferencesInternal(&builder, 0, hdl, true);
} }
} }
}, },
.pointer_payload,
.switch_payload,
.array_payload,
.array_index,
=> {
try symbolReferencesInternal(&builder, 0, curr_handle, true);
return builder.locations;
},
.param_payload => |pay| blk: { .param_payload => |pay| blk: {
// Rename the param tok. // Rename the param tok.
const param = pay.param; const param = pay.param;
@ -514,7 +519,7 @@ pub fn symbolReferences(
if (!std.meta.eql(candidate, param)) continue; if (!std.meta.eql(candidate, param)) continue;
if (curr_handle.tree.nodes.items(.tag)[proto] != .fn_decl) break :blk; if (curr_handle.tree.nodes.items(.tag)[proto] != .fn_decl) break :blk;
try symbolReferencesInternal(&builder, curr_handle.tree.nodes.items(.data)[proto].rhs, curr_handle); try symbolReferencesInternal(&builder, curr_handle.tree.nodes.items(.data)[proto].rhs, curr_handle, false);
break :blk; break :blk;
} }
} }

View File

@ -16,7 +16,6 @@ const allocator: std.mem.Allocator = std.testing.allocator;
const skip_references_tests = true; const skip_references_tests = true;
test "references" { test "references" {
if (skip_references_tests) return error.SkipZigTest;
try testReferences( try testReferences(
\\const <0> = 0; \\const <0> = 0;
\\const foo = <0>; \\const foo = <0>;
@ -48,7 +47,6 @@ test "references" {
} }
test "references - global scope" { test "references - global scope" {
if (skip_references_tests) return error.SkipZigTest;
try testReferences( try testReferences(
\\const foo = <0>; \\const foo = <0>;
\\const <0> = 0; \\const <0> = 0;