Fixed error completion generation when making document scopes
This commit is contained in:
parent
4529b056cd
commit
2d168ed63e
103
src/analysis.zig
103
src/analysis.zig
@ -2611,41 +2611,52 @@ fn makeScopeInternal(
|
||||
.data = .{ .container = node_idx },
|
||||
};
|
||||
const scope_idx = scopes.items.len - 1;
|
||||
var uses = std.ArrayList(*const ast.Node.Index).init(allocator);
|
||||
var tests = std.ArrayList(ast.Node.Index).init(allocator);
|
||||
var uses = std.ArrayListUnmanaged(*const ast.Node.Index){};
|
||||
var tests = std.ArrayListUnmanaged(ast.Node.Index){};
|
||||
|
||||
errdefer {
|
||||
scopes.items[scope_idx].decls.deinit();
|
||||
uses.deinit();
|
||||
tests.deinit();
|
||||
uses.deinit(allocator);
|
||||
tests.deinit(allocator);
|
||||
}
|
||||
|
||||
if (node_tag == .error_set_decl) {
|
||||
// All identifiers in main_token..data.lhs are error fields.
|
||||
var i = main_tokens[node_idx];
|
||||
while (i < data[node_idx].rhs) : (i += 1) {
|
||||
if (token_tags[i] == .identifier) {
|
||||
(try error_completions.addOne(allocator)).* = .{
|
||||
.label = tree.tokenSlice(i),
|
||||
.kind = .Constant,
|
||||
.insertTextFormat = .PlainText,
|
||||
.insertText = tree.tokenSlice(i),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ast_decls) |*ptr_decl| {
|
||||
const decl = ptr_decl.*;
|
||||
if (tags[decl] == .@"usingnamespace") {
|
||||
try uses.append(ptr_decl);
|
||||
try uses.append(allocator, ptr_decl);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
if (tags[decl] == .test_decl) {
|
||||
try tests.append(decl);
|
||||
try tests.append(allocator, decl);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node_tag == .error_set_decl) {
|
||||
(try error_completions.addOne(allocator)).* = .{
|
||||
.label = name,
|
||||
.kind = .Constant,
|
||||
.documentation = if (try getDocComments(allocator, tree, decl, .Markdown)) |docs| .{
|
||||
.kind = .Markdown,
|
||||
.value = docs,
|
||||
} else null,
|
||||
};
|
||||
}
|
||||
|
||||
const container_field: ?ast.full.ContainerField = switch (tags[decl]) {
|
||||
const container_field = switch (tags[decl]) {
|
||||
.container_field => tree.containerField(decl),
|
||||
.container_field_align => tree.containerFieldAlign(decl),
|
||||
.container_field_init => tree.containerFieldInit(decl),
|
||||
@ -2658,7 +2669,7 @@ fn makeScopeInternal(
|
||||
continue;
|
||||
}
|
||||
|
||||
const container_decl: ?ast.full.ContainerDecl = switch (node_tag) {
|
||||
const container_decl = switch (node_tag) {
|
||||
.container_decl, .container_decl_trailing => tree.containerDecl(node_idx),
|
||||
.container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx),
|
||||
.container_decl_two, .container_decl_two_trailing => blk: {
|
||||
@ -2700,8 +2711,8 @@ fn makeScopeInternal(
|
||||
}
|
||||
}
|
||||
|
||||
scopes.items[scope_idx].tests = tests.toOwnedSlice();
|
||||
scopes.items[scope_idx].uses = uses.toOwnedSlice();
|
||||
scopes.items[scope_idx].tests = tests.toOwnedSlice(allocator);
|
||||
scopes.items[scope_idx].uses = uses.toOwnedSlice(allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2727,21 +2738,63 @@ fn makeScopeInternal(
|
||||
|
||||
var it = func.iterate(tree);
|
||||
while (it.next()) |param| {
|
||||
// Add parameter decls
|
||||
if (param.name_token) |name_token| {
|
||||
if (try scopes.items[scope_idx].decls.fetchPut(tree.tokenSlice(name_token), .{ .param_decl = param })) |existing| {
|
||||
if (try scopes.items[scope_idx].decls.fetchPut(
|
||||
tree.tokenSlice(name_token),
|
||||
.{ .param_decl = param },
|
||||
)) |existing| {
|
||||
// TODO record a redefinition error
|
||||
}
|
||||
}
|
||||
// Visit parameter types to pick up any error sets and enum
|
||||
// completions
|
||||
try makeScopeInternal(
|
||||
allocator,
|
||||
scopes,
|
||||
error_completions,
|
||||
enum_completions,
|
||||
tree,
|
||||
param.type_expr,
|
||||
);
|
||||
}
|
||||
|
||||
// Visit the return type
|
||||
try makeScopeInternal(
|
||||
allocator,
|
||||
scopes,
|
||||
error_completions,
|
||||
enum_completions,
|
||||
tree,
|
||||
// TODO: This should be the proto
|
||||
if (fn_tag == .fn_decl)
|
||||
data[data[node_idx].lhs].rhs
|
||||
else
|
||||
data[node_idx].rhs,
|
||||
);
|
||||
// Visit the function body
|
||||
if (fn_tag == .fn_decl) {
|
||||
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, data[node_idx].rhs);
|
||||
try makeScopeInternal(
|
||||
allocator,
|
||||
scopes,
|
||||
error_completions,
|
||||
enum_completions,
|
||||
tree,
|
||||
data[node_idx].rhs,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
.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,
|
||||
|
@ -1,3 +1,7 @@
|
||||
//! This file contains request types zls handles.
|
||||
//! Note that the parameter types may be incomplete.
|
||||
//! We only define what we actually use.
|
||||
|
||||
const std = @import("std");
|
||||
const types = @import("types.zig");
|
||||
|
||||
@ -37,8 +41,14 @@ fn fromDynamicTreeInternal(arena: *std.heap.ArenaAllocator, value: std.json.Valu
|
||||
const actual_type = if (is_optional) std.meta.Child(field.field_type) else field.field_type;
|
||||
|
||||
const is_struct = comptime std.meta.trait.is(.Struct)(actual_type);
|
||||
const is_default = comptime if (is_struct) std.meta.trait.hasDecls(actual_type, .{ "default", "value_type" }) else false;
|
||||
const is_transform = comptime if (is_struct) std.meta.trait.hasDecls(actual_type, .{ "original_type", "transform" }) else false;
|
||||
const is_default = comptime if (is_struct) std.meta.trait.hasDecls(actual_type, .{
|
||||
"default",
|
||||
"value_type",
|
||||
}) else false;
|
||||
const is_transform = comptime if (is_struct) std.meta.trait.hasDecls(actual_type, .{
|
||||
"original_type",
|
||||
"transform",
|
||||
}) else false;
|
||||
|
||||
if (value.Object.get(field.name)) |json_field| {
|
||||
if (is_exists) {
|
||||
@ -46,7 +56,10 @@ fn fromDynamicTreeInternal(arena: *std.heap.ArenaAllocator, value: std.json.Valu
|
||||
} else if (is_transform) {
|
||||
var original_value: actual_type.original_type = undefined;
|
||||
try fromDynamicTreeInternal(arena, json_field, &original_value);
|
||||
@field(out, field.name) = actual_type{ .value = actual_type.transform(original_value) catch return error.MalformedJson };
|
||||
@field(out, field.name) = actual_type{
|
||||
.value = actual_type.transform(original_value) catch
|
||||
return error.MalformedJson,
|
||||
};
|
||||
} else if (is_default) {
|
||||
try fromDynamicTreeInternal(arena, json_field, &@field(out, field.name).value);
|
||||
} else if (is_optional) {
|
||||
@ -117,11 +130,7 @@ pub fn fromDynamicTree(arena: *std.heap.ArenaAllocator, comptime T: type, value:
|
||||
return out;
|
||||
}
|
||||
|
||||
//! This file contains request types zls handles.
|
||||
//! Note that the parameter types may be incomplete.
|
||||
//! We only define what we actually use.
|
||||
|
||||
const MaybeStringArray = Default([]const []const u8, &[0][]const u8{});
|
||||
const MaybeStringArray = Default([]const []const u8, &.{});
|
||||
|
||||
pub const Initialize = struct {
|
||||
pub const ClientCapabilities = struct {
|
||||
|
@ -331,8 +331,8 @@ const InitializeResult = struct {
|
||||
workspaceSymbolProvider: bool,
|
||||
rangeProvider: bool,
|
||||
documentProvider: bool,
|
||||
workspace: struct {
|
||||
workspaceFolders: struct {
|
||||
workspace: ?struct {
|
||||
workspaceFolders: ?struct {
|
||||
supported: bool,
|
||||
changeNotifications: bool,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user