All functionalities implemented. Also implemented ability to skip searching for references through std

This commit is contained in:
Luuk de Gram 2021-03-06 20:55:59 +01:00
parent 3d8a9732fc
commit ac8a00342e
No known key found for this signature in database
GPG Key ID: A002B174963DBB7D
5 changed files with 489 additions and 127 deletions

View File

@ -35,15 +35,7 @@ pub fn getDocCommentTokenIndex(tree: ast.Tree, node: ast.Node.Index) ?ast.TokenI
if (tokens[idx] == .keyword_pub and idx > 0) if (tokens[idx] == .keyword_pub and idx > 0)
idx -= 1; idx -= 1;
}, },
.error_value => idx -= 1, else => idx -= 1,
.container_field,
.container_field_init,
.container_field_align,
=> idx -= 1,
.test_decl => idx -= 1,
else => {
log.debug("Doc comment check for tag: {s}", .{tags[node]});
},
} }
// Find first doc comment token // Find first doc comment token
@ -103,9 +95,12 @@ pub fn collectDocComments(
/// Gets a function signature (keywords, name, return value) /// Gets a function signature (keywords, name, return value)
pub fn getFunctionSignature(tree: ast.Tree, func: ast.full.FnProto) []const u8 { pub fn getFunctionSignature(tree: ast.Tree, func: ast.full.FnProto) []const u8 {
const start = offsets.tokenLocation(tree, func.ast.fn_token).start; const start = offsets.tokenLocation(tree, func.ast.fn_token);
const end = offsets.tokenLocation(tree, tree.nodes.items(.main_token)[func.ast.return_type]).end; // return type can be 0 when user wrote incorrect fn signature
return tree.source[start..end]; // to ensure we don't break, just end the signature at end of fn token
if (func.ast.return_type == 0) return tree.source[start.start..start.end];
const end = offsets.tokenLocation(tree, tree.lastToken(func.ast.return_type)).end;
return tree.source[start.start..end];
} }
/// Gets a function snippet insert text /// Gets a function snippet insert text
@ -240,12 +235,7 @@ pub fn getDeclNameToken(tree: ast.Tree, node: ast.Node.Index) ?ast.TokenIndex {
.container_field_align => tree.containerFieldAlign(node).ast.name_token, .container_field_align => tree.containerFieldAlign(node).ast.name_token,
.identifier => main_token, .identifier => main_token,
.error_value => main_token + 2, // 'error'.<main_token +2>
// @TODO: Errors
// .error_=> {
// const tag = node.castTag(.ErrorTag).?;
// return tag.name_token;
// },
// lhs of main token is name token, so use `node` - 1 // lhs of main token is name token, so use `node` - 1
.test_decl => if (tree.tokens.items(.tag)[main_token + 1] == .string_literal) .test_decl => if (tree.tokens.items(.tag)[main_token + 1] == .string_literal)
@ -328,9 +318,7 @@ fn resolveVarDeclAliasInternal(
break :block NodeWithHandle{ .node = resolved_node, .handle = resolved.handle }; break :block NodeWithHandle{ .node = resolved_node, .handle = resolved.handle };
} else return null; } else return null;
if (try lookupSymbolContainer(store, arena, container_node, tree.tokenSlice(datas[node_handle.node].rhs), false)) |inner_decl| { return try lookupSymbolContainer(store, arena, container_node, tree.tokenSlice(datas[node_handle.node].rhs), false);
return inner_decl;
}
} }
return null; return null;
} }
@ -366,22 +354,70 @@ pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocato
return null; return null;
} }
/// Returns `true` when the given `node` is one of the block tags
fn isBlock(tree: ast.Tree, node: ast.Node.Index) bool {
return switch (tree.nodes.items(.tag)[node]) {
.block,
.block_semicolon,
.block_two,
.block_two_semicolon,
=> true,
else => false,
};
}
/// Returns `true` when the given `node` is one of the call tags
fn isCall(tree: ast.Tree, node: ast.Node.Index) bool {
return switch (tree.nodes.items(.tag)[node]) {
.call,
.call_comma,
.call_one,
.call_one_comma,
.async_call,
.async_call_comma,
.async_call_one,
.async_call_one_comma,
=> true,
else => false,
};
}
fn findReturnStatementInternal( fn findReturnStatementInternal(
tree: ast.Tree, tree: ast.Tree,
fn_decl: *ast.Node.FnProto, fn_decl: ast.full.FnProto,
base_node: *ast.Node, body: ast.Node.Index,
already_found: *bool, already_found: *bool,
) ?*ast.Node.ControlFlowExpression { ) ?ast.Node.Index {
var result: ?*ast.Node.ControlFlowExpression = null; var result: ?ast.Node.Index = null;
var child_idx: usize = 0;
while (base_node.iterate(child_idx)) |child_node| : (child_idx += 1) { const node_tags = tree.nodes.items(.tag);
if (child_node.castTag(.Return)) |cfe| { const datas = tree.nodes.items(.data);
// If we are calling ourselves recursively, ignore this return.
if (cfe.getRHS()) |rhs| { if (!isBlock(tree, body)) return null;
if (rhs.castTag(.Call)) |call_node| {
if (call_node.lhs.tag == .Identifier) { const statements: []const ast.Node.Index = switch (node_tags[body]) {
if (std.mem.eql(u8, getDeclName(tree, call_node.lhs).?, getDeclName(tree, &fn_decl.base).?)) { .block, .block_semicolon => tree.extra_data[datas[body].lhs..datas[body].rhs],
.block_two, .block_two_semicolon => blk: {
const statements = &[_]ast.Node.Index{ datas[body].lhs, datas[body].rhs };
const len: usize = if (datas[body].lhs == 0)
@as(usize, 0)
else if (datas[body].rhs == 0)
@as(usize, 1)
else
@as(usize, 2);
break :blk statements[0..len];
},
else => unreachable,
};
for (statements) |child_idx| {
if (node_tags[child_idx] == .@"return") {
if (datas[child_idx].lhs != 0) {
const lhs = datas[child_idx].lhs;
if (isCall(tree, lhs)) {
const call_name = getDeclName(tree, datas[lhs].lhs);
if (call_name) |name| {
if (std.mem.eql(u8, name, tree.tokenSlice(fn_decl.name_token.?))) {
continue; continue;
} }
} }
@ -390,18 +426,19 @@ fn findReturnStatementInternal(
if (already_found.*) return null; if (already_found.*) return null;
already_found.* = true; already_found.* = true;
result = cfe; result = child_idx;
continue; continue;
} }
result = findReturnStatementInternal(tree, fn_decl, child_node, already_found); result = findReturnStatementInternal(tree, fn_decl, child_idx, already_found);
} }
return result; return result;
} }
fn findReturnStatement(tree: ast.Tree, fn_decl: *ast.Node.FnProto) ?*ast.Node.ControlFlowExpression { fn findReturnStatement(tree: ast.Tree, fn_decl: ast.full.FnProto, body: ast.Node.Index) ?ast.Node.Index {
var already_found = false; var already_found = false;
return findReturnStatementInternal(tree, fn_decl, fn_decl.getBodyNode().?, &already_found); return findReturnStatementInternal(tree, fn_decl, body, &already_found);
} }
/// Resolves the return type of a function /// Resolves the return type of a function
@ -415,14 +452,25 @@ pub fn resolveReturnType(
) !?TypeWithHandle { ) !?TypeWithHandle {
const tree = handle.tree; const tree = handle.tree;
if (isTypeFunction(tree, fn_decl) and fn_body != null) { if (isTypeFunction(tree, fn_decl) and fn_body != null) {
// @TODO: find return statement inside fn body of `type` (generic) functions // If this is a type function and it only contains a single return statement that returns
// a container declaration, we will return that declaration.
const ret = findReturnStatement(tree, fn_decl, fn_body.?) orelse return null;
const data = tree.nodes.items(.data)[ret];
if (data.lhs != 0) {
return try resolveTypeOfNodeInternal(store, arena, .{
.node = data.lhs,
.handle = handle,
}, bound_type_params);
}
return null;
} }
if (fn_decl.ast.return_type == 0) return null; if (fn_decl.ast.return_type == 0) return null;
return resolveTypeOfNodeInternal(store, arena, .{ return ((try resolveTypeOfNodeInternal(store, arena, .{
.node = fn_decl.ast.return_type, .node = fn_decl.ast.return_type,
.handle = handle, .handle = handle,
}, bound_type_params); }, bound_type_params)) orelse return null).instanceTypeVal();
} }
/// Resolves the child type of an optional type /// Resolves the child type of an optional type
@ -647,7 +695,7 @@ pub fn resolveTypeOfNodeInternal(
switch (child.decl.*) { switch (child.decl.*) {
.ast_node => |n| { .ast_node => |n| {
if (n == node) return null; if (n == node) return null;
if (varDecl(tree, n)) |var_decl| { if (varDecl(child.handle.tree, n)) |var_decl| {
if (var_decl.ast.init_node != 0 and var_decl.ast.init_node == node) return null; if (var_decl.ast.init_node != 0 and var_decl.ast.init_node == node) return null;
} }
}, },
@ -721,7 +769,7 @@ pub fn resolveTypeOfNodeInternal(
const call_param_type = (try resolveTypeOfNodeInternal(store, arena, .{ const call_param_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = call.ast.params[it.param_i - 1 - @boolToInt(has_self_param)], .node = call.ast.params[it.param_i - 1 - @boolToInt(has_self_param)],
.handle = decl.handle, .handle = handle,
}, bound_type_params)) orelse continue; }, bound_type_params)) orelse continue;
if (!call_param_type.type.is_type_val) continue; if (!call_param_type.type.is_type_val) continue;
@ -810,7 +858,7 @@ pub fn resolveTypeOfNodeInternal(
arena, arena,
.{ .node = left_type_node, .handle = left_type.handle }, .{ .node = left_type_node, .handle = left_type.handle },
rhs_str, rhs_str,
left_type.type.is_type_val, !left_type.type.is_type_val,
)) |child| { )) |child| {
return try child.resolveType(store, arena, bound_type_params); return try child.resolveType(store, arena, bound_type_params);
} else return null; } else return null;
@ -829,13 +877,13 @@ pub fn resolveTypeOfNodeInternal(
}, bound_type_params)) orelse return null; }, bound_type_params)) orelse return null;
return try resolveUnwrapErrorType(store, arena, left_type, bound_type_params); return try resolveUnwrapErrorType(store, arena, left_type, bound_type_params);
}, },
.error_union => return TypeWithHandle.typeVal(node_handle),
.array_type, .array_type,
.array_type_sentinel, .array_type_sentinel,
.optional_type, .optional_type,
.ptr_type_aligned, .ptr_type_aligned,
.ptr_type, .ptr_type,
.ptr_type_bit_range, .ptr_type_bit_range,
.error_union,
=> return TypeWithHandle.typeVal(node_handle), => return TypeWithHandle.typeVal(node_handle),
.@"try" => { .@"try" => {
const rhs_type = (try resolveTypeOfNodeInternal(store, arena, .{ const rhs_type = (try resolveTypeOfNodeInternal(store, arena, .{
@ -860,7 +908,11 @@ pub fn resolveTypeOfNodeInternal(
.handle = rhs_type.handle, .handle = rhs_type.handle,
}; };
}, },
.builtin_call, .builtin_call_comma, .builtin_call_two, .builtin_call_two_comma => { .builtin_call,
.builtin_call_comma,
.builtin_call_two,
.builtin_call_two_comma,
=> {
const data = datas[node]; const data = datas[node];
const params = switch (node_tags[node]) { const params = switch (node_tags[node]) {
.builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs], .builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
@ -935,15 +987,24 @@ pub fn resolveTypeOfNodeInternal(
.container_decl_trailing, .container_decl_trailing,
.container_decl_two, .container_decl_two,
.container_decl_two_trailing, .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,
=> { => {
return TypeWithHandle.typeVal(node_handle); return TypeWithHandle.typeVal(node_handle);
}, },
.fn_proto, .fn_proto_multi, .fn_proto_one, .fn_proto_simple, .fn_decl => { .fn_proto,
.fn_proto_multi,
.fn_proto_one,
.fn_proto_simple,
.fn_decl,
=> {
var buf: [1]ast.Node.Index = undefined; var buf: [1]ast.Node.Index = undefined;
const fn_proto = fnProto(tree, node, &buf).?;
// This is a function type // This is a function type
if (fn_proto.name_token == null) { if (fnProto(tree, node, &buf).?.name_token == null) {
return TypeWithHandle.typeVal(node_handle); return TypeWithHandle.typeVal(node_handle);
} }
@ -952,7 +1013,9 @@ pub fn resolveTypeOfNodeInternal(
.handle = handle, .handle = handle,
}; };
}, },
.multiline_string_literal, .string_literal => return TypeWithHandle{ .multiline_string_literal,
.string_literal,
=> return TypeWithHandle{
.type = .{ .data = .{ .other = node }, .is_type_val = false }, .type = .{ .data = .{ .other = node }, .is_type_val = false },
.handle = handle, .handle = handle,
}, },
@ -1317,11 +1380,7 @@ pub fn nodeToString(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
.container_field => return tree.tokenSlice(tree.containerField(node).ast.name_token), .container_field => return tree.tokenSlice(tree.containerField(node).ast.name_token),
.container_field_init => return tree.tokenSlice(tree.containerFieldInit(node).ast.name_token), .container_field_init => return tree.tokenSlice(tree.containerFieldInit(node).ast.name_token),
.container_field_align => return tree.tokenSlice(tree.containerFieldAlign(node).ast.name_token), .container_field_align => return tree.tokenSlice(tree.containerFieldAlign(node).ast.name_token),
// @TODO: Error tag name .error_value => return tree.tokenSlice(data[node].rhs),
// .ErrorTag => {
// const tag = node.castTag(.ErrorTag).?;
// return tree.tokenSlice(tag.name_token);
// },
.identifier => return tree.tokenSlice(main_token), .identifier => return tree.tokenSlice(main_token),
.fn_proto, .fn_proto,
.fn_proto_multi, .fn_proto_multi,
@ -2005,6 +2064,7 @@ fn iterateSymbolsContainerInternal(
.label_decl => continue, .label_decl => continue,
else => {}, else => {},
} }
const decl = DeclWithHandle{ .decl = &entry.value, .handle = handle }; const decl = DeclWithHandle{ .decl = &entry.value, .handle = handle };
if (handle != orig_handle and !decl.isPublic()) continue; if (handle != orig_handle and !decl.isPublic()) continue;
try callback(context, decl); try callback(context, decl);
@ -2136,12 +2196,24 @@ fn resolveUse(
if (std.mem.indexOfScalar(ast.Node.Index, use_trail.items, use) != null) continue; if (std.mem.indexOfScalar(ast.Node.Index, use_trail.items, use) != null) continue;
try use_trail.append(use); try use_trail.append(use);
const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = handle.tree.nodes.items(.data)[use].lhs, .handle = handle })) orelse continue; const use_expr = (try resolveTypeOfNode(
store,
arena,
.{ .node = handle.tree.nodes.items(.data)[use].lhs, .handle = handle },
)) orelse continue;
const use_expr_node = switch (use_expr.type.data) { const use_expr_node = switch (use_expr.type.data) {
.other => |n| n, .other => |n| n,
else => continue, else => continue,
}; };
if (try lookupSymbolContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, symbol, false, use_trail)) |candidate| { if (try lookupSymbolContainerInternal(
store,
arena,
.{ .node = use_expr_node, .handle = use_expr.handle },
symbol,
false,
use_trail,
)) |candidate| {
if (candidate.handle != handle and !candidate.isPublic()) { if (candidate.handle != handle and !candidate.isPublic()) {
continue; continue;
} }
@ -2183,24 +2255,24 @@ fn lookupSymbolGlobalInternal(
use_trail: *std.ArrayList(ast.Node.Index), use_trail: *std.ArrayList(ast.Node.Index),
) error{OutOfMemory}!?DeclWithHandle { ) error{OutOfMemory}!?DeclWithHandle {
for (handle.document_scope.scopes) |scope| { for (handle.document_scope.scopes) |scope| {
if (source_index >= scope.range.start and source_index < scope.range.end) { // if (source_index >= scope.range.start and source_index < scope.range.end) {
if (scope.decls.getEntry(symbol)) |candidate| { if (scope.decls.getEntry(symbol)) |candidate| {
switch (candidate.value) { switch (candidate.value) {
.ast_node => |node| { .ast_node => |node| {
if (handle.tree.nodes.items(.tag)[node].isContainerField()) continue; if (handle.tree.nodes.items(.tag)[node].isContainerField()) continue;
}, },
.label_decl => continue, .label_decl => continue,
else => {}, else => {},
}
return DeclWithHandle{
.decl = &candidate.value,
.handle = handle,
};
} }
return DeclWithHandle{
if (try resolveUse(store, arena, scope.uses, symbol, handle, use_trail)) |result| return result; .decl = &candidate.value,
.handle = handle,
};
} }
if (try resolveUse(store, arena, scope.uses, symbol, handle, use_trail)) |result| return result;
// }
if (scope.range.start > source_index) return null; if (scope.range.start > source_index) return null;
} }
@ -2235,7 +2307,7 @@ fn lookupSymbolContainerInternal(
const token_tags = tree.tokens.items(.tag); const token_tags = tree.tokens.items(.tag);
const main_token = tree.nodes.items(.main_token)[container]; const main_token = tree.nodes.items(.main_token)[container];
const is_enum = if (isContainer(node_tags[container]) and node_tags[container] != .root) const is_enum = if (container != 0 and isContainer(node_tags[container]))
token_tags[main_token] == .keyword_enum token_tags[main_token] == .keyword_enum
else else
false; false;
@ -2397,7 +2469,6 @@ pub fn declMembers(tree: ast.Tree, tag: ast.Node.Tag, node_idx: ast.Node.Index,
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(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 => tree.taggedUnionTwo(buffer, node_idx).ast.members, .tagged_union_two, .tagged_union_two_trailing => tree.taggedUnionTwo(buffer, node_idx).ast.members,
.root => tree.rootDecls(), .root => tree.rootDecls(),
// @TODO: Fix error set declarations
.error_set_decl => &[_]ast.Node.Index{}, .error_set_decl => &[_]ast.Node.Index{},
else => unreachable, else => unreachable,
}; };
@ -2425,6 +2496,7 @@ fn makeScopeInternal(
tree: ast.Tree, tree: ast.Tree,
node_idx: ast.Node.Index, node_idx: ast.Node.Index,
) error{OutOfMemory}!void { ) error{OutOfMemory}!void {
// if (node_idx > tree.nodes.len) return;
const tags = tree.nodes.items(.tag); const tags = tree.nodes.items(.tag);
const token_tags = tree.tokens.items(.tag); const token_tags = tree.tokens.items(.tag);
const data = tree.nodes.items(.data); const data = tree.nodes.items(.data);
@ -2460,13 +2532,12 @@ fn makeScopeInternal(
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, decl); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, decl);
const name = getDeclName(tree, decl) orelse continue; const name = getDeclName(tree, decl) orelse continue;
// @TODO: implement tests if (tags[decl] == .test_decl) {
// if (decl.tag == .TestDecl) { try tests.append(decl);
// try tests.append(decl); continue;
// continue; }
// }
if (tags[decl] == .error_set_decl) { if (node == .error_set_decl) {
(try error_completions.addOne(allocator)).* = .{ (try error_completions.addOne(allocator)).* = .{
.label = name, .label = name,
.kind = .Constant, .kind = .Constant,
@ -2490,7 +2561,6 @@ fn makeScopeInternal(
continue; continue;
} }
// @TODO: We can probably just use node_idx directly instead of first transforming to container
const container_decl: ?ast.full.ContainerDecl = switch (node) { const container_decl: ?ast.full.ContainerDecl = switch (node) {
.container_decl, .container_decl_trailing => tree.containerDecl(node_idx), .container_decl, .container_decl_trailing => tree.containerDecl(node_idx),
.container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx), .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx),
@ -2537,7 +2607,12 @@ fn makeScopeInternal(
} }
switch (node) { switch (node) {
.fn_proto, .fn_proto_one, .fn_proto_simple, .fn_proto_multi, .fn_decl => |fn_tag| { .fn_proto,
.fn_proto_one,
.fn_proto_simple,
.fn_proto_multi,
.fn_decl,
=> |fn_tag| {
var buf: [1]ast.Node.Index = undefined; var buf: [1]ast.Node.Index = undefined;
const func = fnProto(tree, node_idx, &buf).?; const func = fnProto(tree, node_idx, &buf).?;
@ -2569,7 +2644,11 @@ fn makeScopeInternal(
.test_decl => { .test_decl => {
return try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].rhs); return try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].rhs);
}, },
.block, .block_semicolon, .block_two, .block_two_semicolon => { .block,
.block_semicolon,
.block_two,
.block_two_semicolon,
=> {
const first_token = tree.firstToken(node_idx); const first_token = tree.firstToken(node_idx);
const last_token = tree.lastToken(node_idx); const last_token = tree.lastToken(node_idx);
@ -2638,10 +2717,9 @@ fn makeScopeInternal(
scopes.items[scope_idx].uses = uses.toOwnedSlice(); scopes.items[scope_idx].uses = uses.toOwnedSlice();
return; return;
}, },
.@"comptime", .@"nosuspend" => { .@"if",
return try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].lhs); .if_simple,
}, => {
.@"if", .if_simple => {
const if_node: ast.full.If = if (node == .@"if") const if_node: ast.full.If = if (node == .@"if")
tree.ifFull(node_idx) tree.ifFull(node_idx)
else else
@ -2697,7 +2775,12 @@ fn makeScopeInternal(
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, if_node.ast.else_expr); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, if_node.ast.else_expr);
} }
}, },
.@"while", .while_simple, .while_cont, .@"for", .for_simple => { .@"while",
.while_simple,
.while_cont,
.@"for",
.for_simple,
=> {
const while_node: ast.full.While = switch (node) { const while_node: ast.full.While = switch (node) {
.@"while" => tree.whileFull(node_idx), .@"while" => tree.whileFull(node_idx),
.while_simple => tree.whileSimple(node_idx), .while_simple => tree.whileSimple(node_idx),
@ -2773,7 +2856,9 @@ fn makeScopeInternal(
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, while_node.ast.else_expr); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, while_node.ast.else_expr);
} }
}, },
.switch_case, .switch_case_one => { .switch_case,
.switch_case_one,
=> {
const switch_case: ast.full.SwitchCase = switch (node) { const switch_case: ast.full.SwitchCase = switch (node) {
.switch_case => tree.switchCase(node_idx), .switch_case => tree.switchCase(node_idx),
.switch_case_one => tree.switchCaseOne(node_idx), .switch_case_one => tree.switchCaseOne(node_idx),
@ -2809,7 +2894,11 @@ fn makeScopeInternal(
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, switch_case.ast.target_expr); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, switch_case.ast.target_expr);
}, },
.global_var_decl, .local_var_decl, .aligned_var_decl, .simple_var_decl => { .global_var_decl,
.local_var_decl,
.aligned_var_decl,
.simple_var_decl,
=> {
const var_decl = varDecl(tree, node_idx).?; const var_decl = varDecl(tree, node_idx).?;
if (var_decl.ast.type_node != 0) { if (var_decl.ast.type_node != 0) {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, var_decl.ast.type_node); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, var_decl.ast.type_node);
@ -2819,13 +2908,206 @@ fn makeScopeInternal(
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, var_decl.ast.init_node); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, var_decl.ast.init_node);
} }
}, },
.call,
.call_comma,
.call_one,
.call_one_comma,
.async_call,
.async_call_comma,
.async_call_one,
.async_call_one_comma,
=> {
var buf: [1]ast.Node.Index = undefined;
const call: ast.full.Call = switch (node) {
.async_call,
.async_call_comma,
.call,
.call_comma,
=> tree.callFull(node_idx),
.async_call_one,
.async_call_one_comma,
.call_one,
.call_one_comma,
=> tree.callOne(&buf, node_idx),
else => unreachable,
};
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, call.ast.fn_expr);
for (call.ast.params) |param|
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, param);
},
.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,
=> {
var buf: [2]ast.Node.Index = undefined;
const struct_init: ast.full.StructInit = switch (node) {
.struct_init, .struct_init_comma => tree.structInit(node_idx),
.struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node_idx),
.struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(&buf, node_idx),
.struct_init_one, .struct_init_one_comma => tree.structInitOne(buf[0..1], node_idx),
else => unreachable,
};
if (struct_init.ast.type_expr != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, struct_init.ast.type_expr);
for (struct_init.ast.fields) |field| {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, field);
}
},
.array_init,
.array_init_comma,
.array_init_dot,
.array_init_dot_comma,
.array_init_dot_two,
.array_init_dot_two_comma,
.array_init_one,
.array_init_one_comma,
=> {
var buf: [2]ast.Node.Index = undefined;
const array_init: ast.full.ArrayInit = switch (node) {
.array_init, .array_init_comma => tree.arrayInit(node_idx),
.array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node_idx),
.array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(&buf, node_idx),
.array_init_one, .array_init_one_comma => tree.arrayInitOne(buf[0..1], node_idx),
else => unreachable,
};
if (array_init.ast.type_expr != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, array_init.ast.type_expr);
for (array_init.ast.elements) |elem| {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, elem);
}
},
.container_field,
.container_field_align,
.container_field_init,
=> {
const field = containerField(tree, node_idx).?;
if (field.ast.type_expr != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, field.ast.type_expr);
if (field.ast.align_expr != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, field.ast.align_expr);
if (field.ast.value_expr != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, field.ast.value_expr);
},
.builtin_call,
.builtin_call_comma,
.builtin_call_two,
.builtin_call_two_comma,
=> {
const b_data = data[node_idx];
const params = switch (node) {
.builtin_call, .builtin_call_comma => tree.extra_data[b_data.lhs..b_data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (b_data.lhs == 0)
&[_]ast.Node.Index{}
else if (b_data.rhs == 0)
&[_]ast.Node.Index{b_data.lhs}
else
&[_]ast.Node.Index{ b_data.lhs, b_data.rhs },
else => unreachable,
};
for (params) |param| {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, param);
}
},
.ptr_type,
.ptr_type_aligned,
.ptr_type_bit_range,
.ptr_type_sentinel,
=> {
const ptr_type: ast.full.PtrType = ptrType(tree, node_idx).?;
if (ptr_type.ast.sentinel != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, ptr_type.ast.sentinel);
if (ptr_type.ast.align_node != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, ptr_type.ast.align_node);
if (ptr_type.ast.child_type != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, ptr_type.ast.child_type);
},
.slice,
.slice_open,
.slice_sentinel,
=> {
const slice: ast.full.Slice = switch (node) {
.slice => tree.slice(node_idx),
.slice_open => tree.sliceOpen(node_idx),
.slice_sentinel => tree.sliceSentinel(node_idx),
else => unreachable,
};
if (slice.ast.sliced != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, slice.ast.sliced);
if (slice.ast.start != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, slice.ast.start);
if (slice.ast.end != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, slice.ast.end);
if (slice.ast.sentinel != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, slice.ast.sentinel);
},
// no scope
.@"asm",
.asm_simple,
.asm_output,
.asm_input,
.error_value,
.@"anytype",
.multiline_string_literal,
.string_literal,
.enum_literal,
.identifier,
.anyframe_type,
.anyframe_literal,
.char_literal,
.integer_literal,
.float_literal,
.false_literal,
.true_literal,
.null_literal,
.undefined_literal,
.unreachable_literal,
.@"continue",
=> {},
.@"break", .@"defer" => {
if (data[node_idx].rhs != 0)
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].rhs);
},
// all lhs kind of nodes
.@"return",
.@"resume",
.field_access,
.@"suspend",
.deref,
.@"try",
.@"await",
.optional_type,
.@"comptime",
.@"nosuspend",
.bool_not,
.negation,
.bit_not,
.negation_wrap,
.address_of,
.grouped_expression,
.unwrap_optional,
=> {
if (data[node_idx].lhs != 0) {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].lhs);
}
},
else => { else => {
// log.debug("Implement makeScopeInternal for node type: '{s}'", .{node}); if (data[node_idx].lhs != 0)
// @TODO: Could we just do node_idx + 1 here? try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].lhs);
// var child_idx: usize = 0; if (data[node_idx].rhs != 0)
// while (node.iterate(child_idx)) |child_node| : (child_idx += 1) { try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].rhs);
// try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, child_node);
// }
}, },
} }
} }

View File

@ -25,3 +25,7 @@ enable_semantic_tokens: bool = true,
/// Whether to enable `*` and `?` operators in completion lists /// Whether to enable `*` and `?` operators in completion lists
operator_completions: bool = true, operator_completions: bool = true,
/// Skips references to std. This will improve lookup speeds.
/// Going to definition however will continue to work
skip_std_references: bool = true,

View File

@ -366,6 +366,7 @@ fn nodeToCompletion(
.arena = arena, .arena = arena,
.orig_handle = orig_handle, .orig_handle = orig_handle,
}; };
logger.debug("eklafgaef", .{});
try analysis.iterateSymbolsContainer(&document_store, arena, node_handle, orig_handle, declToCompletion, context, !is_type_val); try analysis.iterateSymbolsContainer(&document_store, arena, node_handle, orig_handle, declToCompletion, context, !is_type_val);
} }
@ -427,7 +428,11 @@ fn nodeToCompletion(
}); });
} }
}, },
.global_var_decl, .local_var_decl, .aligned_var_decl, .simple_var_decl => { .global_var_decl,
.local_var_decl,
.aligned_var_decl,
.simple_var_decl,
=> {
const var_decl = analysis.varDecl(tree, node).?; const var_decl = analysis.varDecl(tree, node).?;
const is_const = token_tags[var_decl.ast.mut_token] == .keyword_const; const is_const = token_tags[var_decl.ast.mut_token] == .keyword_const;
@ -448,7 +453,10 @@ fn nodeToCompletion(
.detail = analysis.getVariableSignature(tree, var_decl), .detail = analysis.getVariableSignature(tree, var_decl),
}); });
}, },
.container_field, .container_field_align, .container_field_init => { .container_field,
.container_field_align,
.container_field_init,
=> {
const field = analysis.containerField(tree, node).?; const field = analysis.containerField(tree, node).?;
try list.append(.{ try list.append(.{
.label = handle.tree.tokenSlice(field.ast.name_token), .label = handle.tree.tokenSlice(field.ast.name_token),
@ -457,13 +465,19 @@ fn nodeToCompletion(
.detail = analysis.getContainerFieldSignature(handle.tree, field), .detail = analysis.getContainerFieldSignature(handle.tree, field),
}); });
}, },
.array_type, .array_type_sentinel => { .array_type,
.array_type_sentinel,
=> {
try list.append(.{ try list.append(.{
.label = "len", .label = "len",
.kind = .Field, .kind = .Field,
}); });
}, },
.ptr_type, .ptr_type_aligned, .ptr_type_bit_range, .ptr_type_sentinel => { .ptr_type,
.ptr_type_aligned,
.ptr_type_bit_range,
.ptr_type_sentinel,
=> {
const ptr_type = analysis.ptrType(tree, node).?; const ptr_type = analysis.ptrType(tree, node).?;
switch (ptr_type.size) { switch (ptr_type.size) {
@ -496,7 +510,7 @@ fn nodeToCompletion(
.kind = .Field, .kind = .Field,
}); });
}, },
else => if (analysis.nodeToString(handle.tree, node)) |string| { else => if (analysis.nodeToString(tree, node)) |string| {
try list.append(.{ try list.append(.{
.label = string, .label = string,
.kind = .Field, .kind = .Field,
@ -828,10 +842,26 @@ fn renameDefinitionLabel(arena: *std.heap.ArenaAllocator, id: types.RequestId, h
}); });
} }
fn referencesDefinitionGlobal(arena: *std.heap.ArenaAllocator, id: types.RequestId, handle: *DocumentStore.Handle, pos_index: usize, include_decl: bool) !void { fn referencesDefinitionGlobal(
arena: *std.heap.ArenaAllocator,
id: types.RequestId,
handle: *DocumentStore.Handle,
pos_index: usize,
include_decl: bool,
skip_std_references: bool,
) !void {
const decl = (try getSymbolGlobal(arena, pos_index, handle)) orelse return try respondGeneric(id, null_result_response); const decl = (try getSymbolGlobal(arena, pos_index, handle)) orelse return try respondGeneric(id, null_result_response);
var locs = std.ArrayList(types.Location).init(&arena.allocator); var locs = std.ArrayList(types.Location).init(&arena.allocator);
try references.symbolReferences(arena, &document_store, decl, offset_encoding, include_decl, &locs, std.ArrayList(types.Location).append); try references.symbolReferences(
arena,
&document_store,
decl,
offset_encoding,
include_decl,
&locs,
std.ArrayList(types.Location).append,
skip_std_references,
);
try send(arena, types.Response{ try send(arena, types.Response{
.id = id, .id = id,
.result = .{ .Locations = locs.items }, .result = .{ .Locations = locs.items },
@ -849,7 +879,7 @@ fn referencesDefinitionFieldAccess(
) !void { ) !void {
const decl = (try getSymbolFieldAccess(handle, arena, position, range, config)) orelse return try respondGeneric(id, null_result_response); const decl = (try getSymbolFieldAccess(handle, arena, position, range, config)) orelse return try respondGeneric(id, null_result_response);
var locs = std.ArrayList(types.Location).init(&arena.allocator); var locs = std.ArrayList(types.Location).init(&arena.allocator);
try references.symbolReferences(arena, &document_store, decl, offset_encoding, include_decl, &locs, std.ArrayList(types.Location).append); try references.symbolReferences(arena, &document_store, decl, offset_encoding, include_decl, &locs, std.ArrayList(types.Location).append, config.skip_std_references);
try send(arena, types.Response{ try send(arena, types.Response{
.id = id, .id = id,
.result = .{ .Locations = locs.items }, .result = .{ .Locations = locs.items },
@ -885,7 +915,15 @@ fn hasComment(tree: ast.Tree, start_token: ast.TokenIndex, end_token: ast.TokenI
fn declToCompletion(context: DeclToCompletionContext, decl_handle: analysis.DeclWithHandle) !void { fn declToCompletion(context: DeclToCompletionContext, decl_handle: analysis.DeclWithHandle) !void {
const tree = decl_handle.handle.tree; const tree = decl_handle.handle.tree;
switch (decl_handle.decl.*) { switch (decl_handle.decl.*) {
.ast_node => |node| try nodeToCompletion(context.arena, context.completions, .{ .node = node, .handle = decl_handle.handle }, null, context.orig_handle, false, context.config.*), .ast_node => |node| try nodeToCompletion(
context.arena,
context.completions,
.{ .node = node, .handle = decl_handle.handle },
null,
context.orig_handle,
false,
context.config.*,
),
.param_decl => |param| { .param_decl => |param| {
const doc_kind: types.MarkupContent.Kind = if (client_capabilities.completion_doc_supports_md) .Markdown else .PlainText; const doc_kind: types.MarkupContent.Kind = if (client_capabilities.completion_doc_supports_md) .Markdown else .PlainText;
const doc = if (param.first_doc_comment) |doc_comments| const doc = if (param.first_doc_comment) |doc_comments|
@ -1419,7 +1457,7 @@ fn referencesHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req:
const include_decl = req.params.context.includeDeclaration; const include_decl = req.params.context.includeDeclaration;
switch (pos_context) { switch (pos_context) {
.var_access => try referencesDefinitionGlobal(arena, id, handle, doc_position.absolute_index, include_decl), .var_access => try referencesDefinitionGlobal(arena, id, handle, doc_position.absolute_index, include_decl, config.skip_std_references),
.field_access => |range| try referencesDefinitionFieldAccess(arena, id, handle, doc_position, range, include_decl, config), .field_access => |range| try referencesDefinitionFieldAccess(arena, id, handle, doc_position, range, include_decl, config),
.label => try referencesDefinitionLabel(arena, id, handle, doc_position.absolute_index, include_decl), .label => try referencesDefinitionLabel(arena, id, handle, doc_position.absolute_index, include_decl),
else => try respondGeneric(id, null_result_response), else => try respondGeneric(id, null_result_response),

View File

@ -122,7 +122,11 @@ fn symbolReferencesInternal(
for (analysis.declMembers(tree, node_tags[node], node, &buf)) |member| for (analysis.declMembers(tree, node_tags[node], node, &buf)) |member|
try symbolReferencesInternal(arena, store, .{ .node = member, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = member, .handle = handle }, decl, encoding, context, handler);
}, },
.global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => { .global_var_decl,
.local_var_decl,
.simple_var_decl,
.aligned_var_decl,
=> {
const var_decl = analysis.varDecl(tree, node).?; const var_decl = analysis.varDecl(tree, node).?;
if (var_decl.ast.type_node != 0) { if (var_decl.ast.type_node != 0) {
try symbolReferencesInternal(arena, store, .{ .node = var_decl.ast.type_node, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = var_decl.ast.type_node, .handle = handle }, decl, encoding, context, handler);
@ -131,12 +135,13 @@ fn symbolReferencesInternal(
try symbolReferencesInternal(arena, store, .{ .node = var_decl.ast.init_node, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = var_decl.ast.init_node, .handle = handle }, decl, encoding, context, handler);
} }
}, },
// @TODO: Usingnamespace .@"usingnamespace" => {
// .Use => { try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
// 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, .container_field_align, .container_field_init => { .container_field_init,
=> {
const field = analysis.containerField(tree, node).?; const field = analysis.containerField(tree, node).?;
if (field.ast.type_expr != 0) { if (field.ast.type_expr != 0) {
try symbolReferencesInternal(arena, store, .{ .node = field.ast.type_expr, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = field.ast.type_expr, .handle = handle }, decl, encoding, context, handler);
@ -152,7 +157,12 @@ fn symbolReferencesInternal(
} }
} }
}, },
.fn_proto, .fn_proto_multi, .fn_proto_one, .fn_proto_simple, .fn_decl => { .fn_proto,
.fn_proto_multi,
.fn_proto_one,
.fn_proto_simple,
.fn_decl,
=> {
var buf: [1]ast.Node.Index = undefined; var buf: [1]ast.Node.Index = undefined;
const fn_proto = analysis.fnProto(tree, node, &buf).?; const fn_proto = analysis.fnProto(tree, node, &buf).?;
var it = fn_proto.iterate(tree); var it = fn_proto.iterate(tree);
@ -189,7 +199,9 @@ fn symbolReferencesInternal(
.@"nosuspend" => { .@"nosuspend" => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
}, },
.@"switch", .switch_comma => { .@"switch",
.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(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler); 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 extra = tree.extraData(datas[node].rhs, ast.Node.SubRange);
@ -212,7 +224,12 @@ fn symbolReferencesInternal(
for (case.ast.values) |val| for (case.ast.values) |val|
try symbolReferencesInternal(arena, store, .{ .node = val, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = val, .handle = handle }, decl, encoding, context, handler);
}, },
.@"while", .while_simple, .while_cont, .for_simple, .@"for" => { .@"while",
.while_simple,
.while_cont,
.for_simple,
.@"for",
=> {
const loop: ast.full.While = switch (node_tags[node]) { const loop: ast.full.While = switch (node_tags[node]) {
.@"while" => tree.whileFull(node), .@"while" => tree.whileFull(node),
.while_simple => tree.whileSimple(node), .while_simple => tree.whileSimple(node),
@ -230,7 +247,9 @@ fn symbolReferencesInternal(
try symbolReferencesInternal(arena, store, .{ .node = loop.ast.else_expr, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = loop.ast.else_expr, .handle = handle }, decl, encoding, context, handler);
} }
}, },
.@"if", .if_simple => { .@"if",
.if_simple,
=> {
const if_node: ast.full.If = if (node_tags[node] == .@"if") tree.ifFull(node) else tree.ifSimple(node); 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.cond_expr, .handle = handle }, decl, encoding, context, handler);
@ -239,11 +258,17 @@ fn symbolReferencesInternal(
try symbolReferencesInternal(arena, store, .{ .node = if_node.ast.else_expr, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = if_node.ast.else_expr, .handle = handle }, decl, encoding, context, handler);
} }
}, },
.array_type, .array_type_sentinel => { .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].lhs, .handle = handle }, decl, encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
}, },
.ptr_type, .ptr_type_aligned, .ptr_type_bit_range, .ptr_type_sentinel => { .ptr_type,
.ptr_type_aligned,
.ptr_type_bit_range,
.ptr_type_sentinel,
=> {
const ptr_type = analysis.ptrType(tree, node).?; const ptr_type = analysis.ptrType(tree, node).?;
if (ptr_type.ast.align_node != 0) { if (ptr_type.ast.align_node != 0) {
@ -334,7 +359,10 @@ fn symbolReferencesInternal(
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);
} }
}, },
.slice, .slice_sentinel, .slice_open => |s| { .slice,
.slice_sentinel,
.slice_open,
=> |s| {
const slice: ast.full.Slice = switch (s) { const slice: ast.full.Slice = switch (s) {
.slice => tree.slice(node), .slice => tree.slice(node),
.slice_open => tree.sliceOpen(node), .slice_open => tree.sliceOpen(node),
@ -353,13 +381,18 @@ fn symbolReferencesInternal(
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler); 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); try symbolReferencesInternal(arena, store, .{ .node = datas[node].rhs, .handle = handle }, decl, encoding, context, handler);
}, },
.deref, .unwrap_optional => { .deref,
.unwrap_optional,
=> {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
}, },
.grouped_expression => { .grouped_expression => {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
}, },
.@"return", .@"break", .@"continue" => { .@"return",
.@"break",
.@"continue",
=> {
if (datas[node].lhs != 0) { if (datas[node].lhs != 0) {
try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = datas[node].lhs, .handle = handle }, decl, encoding, context, handler);
} }
@ -389,7 +422,9 @@ fn symbolReferencesInternal(
for (params) |param| for (params) |param|
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler); try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);
}, },
.@"asm", .asm_simple => |a| { .@"asm",
.asm_simple,
=> |a| {
const _asm: ast.full.Asm = if (a == .@"asm") tree.asmFull(node) else tree.asmSimple(node); const _asm: ast.full.Asm = if (a == .@"asm") tree.asmFull(node) else tree.asmSimple(node);
if (_asm.ast.items.len == 0) 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 = _asm.ast.template, .handle = handle }, decl, encoding, context, handler);
@ -491,6 +526,7 @@ pub fn symbolReferences(
include_decl: bool, include_decl: bool,
context: anytype, context: anytype,
comptime handler: anytype, comptime handler: anytype,
skip_std_references: bool,
) !void { ) !void {
std.debug.assert(decl_handle.decl.* != .label_decl); std.debug.assert(decl_handle.decl.* != .label_decl);
const curr_handle = decl_handle.handle; const curr_handle = decl_handle.handle;
@ -500,16 +536,18 @@ pub fn symbolReferences(
var handles = std.ArrayList(*DocumentStore.Handle).init(&arena.allocator); var handles = std.ArrayList(*DocumentStore.Handle).init(&arena.allocator);
var handle_it = store.handles.iterator(); var handle_it = store.handles.iterator();
while (handle_it.next()) |entry| { while (handle_it.next()) |entry| {
if (skip_std_references and std.mem.indexOf(u8, entry.key, "std") != null) {
if (!include_decl or entry.value != curr_handle)
continue;
}
try handles.append(entry.value); try handles.append(entry.value);
} }
for (handles.items) |handle| { for (handles.items) |handle| {
if (include_decl and handle == curr_handle) { if (include_decl and handle == curr_handle) {
try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler); try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler);
try symbolReferencesInternal(arena, store, .{ .node = 0, .handle = handle }, decl_handle, encoding, context, handler);
} }
// @TODO: make references across files working try symbolReferencesInternal(arena, store, .{ .node = 0, .handle = handle }, decl_handle, encoding, context, handler);
// try symbolReferencesInternal(arena, store, .{ .node = 0, .handle = handle }, decl_handle, encoding, context, handler);
} }
}, },
.param_decl => |param| { .param_decl => |param| {

View File

@ -40,7 +40,7 @@ pub fn renameSymbol(
.edits = edits, .edits = edits,
.allocator = &arena.allocator, .allocator = &arena.allocator,
.new_name = new_name, .new_name = new_name,
}, refHandler); }, refHandler, true);
} }
pub fn renameLabel( pub fn renameLabel(