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