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 },
|
.data = .{ .container = node_idx },
|
||||||
};
|
};
|
||||||
const scope_idx = scopes.items.len - 1;
|
const scope_idx = scopes.items.len - 1;
|
||||||
var uses = std.ArrayList(*const ast.Node.Index).init(allocator);
|
var uses = std.ArrayListUnmanaged(*const ast.Node.Index){};
|
||||||
var tests = std.ArrayList(ast.Node.Index).init(allocator);
|
var tests = std.ArrayListUnmanaged(ast.Node.Index){};
|
||||||
|
|
||||||
errdefer {
|
errdefer {
|
||||||
scopes.items[scope_idx].decls.deinit();
|
scopes.items[scope_idx].decls.deinit();
|
||||||
uses.deinit();
|
uses.deinit(allocator);
|
||||||
tests.deinit();
|
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| {
|
for (ast_decls) |*ptr_decl| {
|
||||||
const decl = ptr_decl.*;
|
const decl = ptr_decl.*;
|
||||||
if (tags[decl] == .@"usingnamespace") {
|
if (tags[decl] == .@"usingnamespace") {
|
||||||
try uses.append(ptr_decl);
|
try uses.append(allocator, ptr_decl);
|
||||||
continue;
|
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;
|
const name = getDeclName(tree, decl) orelse continue;
|
||||||
if (tags[decl] == .test_decl) {
|
if (tags[decl] == .test_decl) {
|
||||||
try tests.append(decl);
|
try tests.append(allocator, decl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node_tag == .error_set_decl) {
|
const container_field = switch (tags[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]) {
|
|
||||||
.container_field => tree.containerField(decl),
|
.container_field => tree.containerField(decl),
|
||||||
.container_field_align => tree.containerFieldAlign(decl),
|
.container_field_align => tree.containerFieldAlign(decl),
|
||||||
.container_field_init => tree.containerFieldInit(decl),
|
.container_field_init => tree.containerFieldInit(decl),
|
||||||
@ -2658,7 +2669,7 @@ fn makeScopeInternal(
|
|||||||
continue;
|
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, .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),
|
||||||
.container_decl_two, .container_decl_two_trailing => blk: {
|
.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].tests = tests.toOwnedSlice(allocator);
|
||||||
scopes.items[scope_idx].uses = uses.toOwnedSlice();
|
scopes.items[scope_idx].uses = uses.toOwnedSlice(allocator);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2727,21 +2738,63 @@ fn makeScopeInternal(
|
|||||||
|
|
||||||
var it = func.iterate(tree);
|
var it = func.iterate(tree);
|
||||||
while (it.next()) |param| {
|
while (it.next()) |param| {
|
||||||
|
// Add parameter decls
|
||||||
if (param.name_token) |name_token| {
|
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
|
// 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) {
|
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;
|
return;
|
||||||
},
|
},
|
||||||
.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,
|
||||||
.block_semicolon,
|
.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 std = @import("std");
|
||||||
const types = @import("types.zig");
|
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 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_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_default = comptime if (is_struct) std.meta.trait.hasDecls(actual_type, .{
|
||||||
const is_transform = comptime if (is_struct) std.meta.trait.hasDecls(actual_type, .{ "original_type", "transform" }) else false;
|
"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 (value.Object.get(field.name)) |json_field| {
|
||||||
if (is_exists) {
|
if (is_exists) {
|
||||||
@ -46,7 +56,10 @@ fn fromDynamicTreeInternal(arena: *std.heap.ArenaAllocator, value: std.json.Valu
|
|||||||
} else if (is_transform) {
|
} else if (is_transform) {
|
||||||
var original_value: actual_type.original_type = undefined;
|
var original_value: actual_type.original_type = undefined;
|
||||||
try fromDynamicTreeInternal(arena, json_field, &original_value);
|
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) {
|
} else if (is_default) {
|
||||||
try fromDynamicTreeInternal(arena, json_field, &@field(out, field.name).value);
|
try fromDynamicTreeInternal(arena, json_field, &@field(out, field.name).value);
|
||||||
} else if (is_optional) {
|
} else if (is_optional) {
|
||||||
@ -117,11 +130,7 @@ pub fn fromDynamicTree(arena: *std.heap.ArenaAllocator, comptime T: type, value:
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! This file contains request types zls handles.
|
const MaybeStringArray = Default([]const []const u8, &.{});
|
||||||
//! Note that the parameter types may be incomplete.
|
|
||||||
//! We only define what we actually use.
|
|
||||||
|
|
||||||
const MaybeStringArray = Default([]const []const u8, &[0][]const u8{});
|
|
||||||
|
|
||||||
pub const Initialize = struct {
|
pub const Initialize = struct {
|
||||||
pub const ClientCapabilities = struct {
|
pub const ClientCapabilities = struct {
|
||||||
|
@ -331,8 +331,8 @@ const InitializeResult = struct {
|
|||||||
workspaceSymbolProvider: bool,
|
workspaceSymbolProvider: bool,
|
||||||
rangeProvider: bool,
|
rangeProvider: bool,
|
||||||
documentProvider: bool,
|
documentProvider: bool,
|
||||||
workspace: struct {
|
workspace: ?struct {
|
||||||
workspaceFolders: struct {
|
workspaceFolders: ?struct {
|
||||||
supported: bool,
|
supported: bool,
|
||||||
changeNotifications: bool,
|
changeNotifications: bool,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user