Fixes multiple small bugs:

- Correct completion based on scope
 - Semantic tokens for while/if/else/for keywords
 - Fix crash on import path
This commit is contained in:
Luuk de Gram 2021-03-07 21:54:54 +01:00
parent a078a62a37
commit fd6b94bcc9
No known key found for this signature in database
GPG Key ID: A002B174963DBB7D
3 changed files with 77 additions and 48 deletions

View File

@ -1456,20 +1456,31 @@ pub fn fnProto(tree: ast.Tree, node: ast.Node.Index, buf: *[1]ast.Node.Index) ?a
pub fn getImportStr(tree: ast.Tree, node: ast.Node.Index, source_index: usize) ?[]const u8 {
const node_tags = tree.nodes.items(.tag);
var buf: [2]ast.Node.Index = undefined;
if (isContainer(node_tags[node])) {
const decls = declMembers(tree, node_tags[node], node, &buf);
for (decls) |decl_idx| {
if (!nodeContainsSourceIndex(tree, decl_idx, source_index)) {
continue;
if (getImportStr(tree, decl_idx, source_index)) |name| {
return name;
}
}
return null;
} else if (varDecl(tree, node)) |var_decl| {
return getImportStr(tree, var_decl.ast.init_node, source_index);
} else if (node_tags[node] == .@"usingnamespace") {
return getImportStr(tree, tree.nodes.items(.data)[node].lhs, source_index);
}
if (isBuiltinCall(tree, decl_idx)) {
const builtin_token = tree.nodes.items(.main_token)[decl_idx];
if (!nodeContainsSourceIndex(tree, node, source_index)) {
return null;
}
if (isBuiltinCall(tree, node)) {
const builtin_token = tree.nodes.items(.main_token)[node];
const call_name = tree.tokenSlice(builtin_token);
if (!std.mem.eql(u8, call_name, "@import")) continue;
const data = tree.nodes.items(.data)[decl_idx];
const params = switch (node_tags[decl_idx]) {
if (!std.mem.eql(u8, call_name, "@import")) return null;
const data = tree.nodes.items(.data)[node];
const params = switch (node_tags[node]) {
.builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (data.lhs == 0)
&[_]ast.Node.Index{}
@ -1480,17 +1491,12 @@ pub fn getImportStr(tree: ast.Tree, node: ast.Node.Index, source_index: usize) ?
else => unreachable,
};
if (params.len != 1) continue;
if (params.len != 1) return null;
const import_str = tree.tokenSlice(tree.nodes.items(.main_token)[params[0]]);
return import_str[1 .. import_str.len - 1];
}
if (getImportStr(tree, decl_idx, source_index)) |name| {
return name;
}
}
return null;
}
@ -2105,12 +2111,30 @@ fn iterateSymbolsContainerInternal(
if (std.mem.indexOfScalar(ast.Node.Index, use_trail.items, use) != null) continue;
try use_trail.append(use);
const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = tree.nodes.items(.data)[use].rhs, .handle = handle })) orelse continue;
const rhs = tree.nodes.items(.data)[use].rhs;
// rhs can be invalid so apply the following check to ensure
// we do not go out of bounds when resolving the type
if (rhs == 0 or rhs > tree.nodes.len) continue;
const use_expr = (try resolveTypeOfNode(store, arena, .{
.node = tree.nodes.items(.data)[use].rhs,
.handle = orig_handle,
})) orelse continue;
const use_expr_node = switch (use_expr.type.data) {
.other => |n| n,
else => continue,
};
try iterateSymbolsContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, orig_handle, callback, context, false, use_trail);
try iterateSymbolsContainerInternal(
store,
arena,
.{ .node = use_expr_node, .handle = use_expr.handle },
orig_handle,
callback,
context,
false,
use_trail,
);
}
}
}
@ -2283,7 +2307,7 @@ fn lookupSymbolGlobalInternal(
use_trail: *std.ArrayList(ast.Node.Index),
) error{OutOfMemory}!?DeclWithHandle {
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| {
switch (candidate.value) {
.ast_node => |node| {
@ -2299,7 +2323,7 @@ fn lookupSymbolGlobalInternal(
}
if (try resolveUse(store, arena, scope.uses, symbol, handle, use_trail)) |result| return result;
// }
}
if (scope.range.start > source_index) return null;
}

View File

@ -622,8 +622,8 @@ fn hoverSymbol(
const first_token = param.first_doc_comment orelse
param.comptime_noalias orelse
param.name_token orelse
tree.firstToken(param.type_expr);
const last_token = tree.lastToken(param.anytype_ellipsis3 orelse param.type_expr);
tree.firstToken(param.type_expr); // extern fn
const last_token = param.anytype_ellipsis3 orelse tree.lastToken(param.type_expr);
const start = offsets.tokenLocation(tree, first_token).start;
const end = offsets.tokenLocation(tree, last_token).end;

View File

@ -598,6 +598,7 @@ fn writeNodeTokens(
try writeToken(builder, while_node.label_token, .label);
try writeToken(builder, while_node.inline_token, .keyword);
try writeToken(builder, while_node.ast.while_token, .keyword);
try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, while_node.ast.cond_expr });
try writeToken(builder, while_node.payload_token, .variable);
if (while_node.ast.cont_expr != 0)
@ -607,8 +608,10 @@ fn writeNodeTokens(
try writeToken(builder, while_node.error_token, .variable);
if (while_node.ast.else_expr != 0)
if (while_node.ast.else_expr != 0) {
try writeToken(builder, while_node.else_token, .keyword);
try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, while_node.ast.else_expr });
}
},
.@"if",
.if_simple,
@ -622,8 +625,10 @@ fn writeNodeTokens(
try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, if_node.ast.then_expr });
try writeToken(builder, if_node.error_token, .variable);
if (if_node.ast.else_expr != 0)
if (if_node.ast.else_expr != 0) {
try writeToken(builder, if_node.else_token, .keyword);
try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, if_node.ast.else_expr });
}
},
.array_init,
.array_init_comma,