From c1ba26e0a206d9685020355c87700acaf1965a31 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 28 May 2020 18:18:48 +0300 Subject: [PATCH] implement completion for enum literals --- src/analysis.zig | 28 ++++++++++++++++++++-------- src/document_store.zig | 32 +++++++++++++++++++------------- src/main.zig | 9 +++++++++ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/analysis.zig b/src/analysis.zig index 4eefae9..c282b6c 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -408,10 +408,9 @@ pub fn resolveTypeOfNode(analysis_ctx: *AnalysisContext, node: *ast.Node) ?*ast. .ErrorSetDecl => { const set = node.cast(ast.Node.ErrorSetDecl).?; var i: usize = 0; - while (set.iterate(i)) |decl| : (i+=1) { - const tag = decl.cast(ast.Node.ErrorTag).?; + while (set.iterate(i)) |decl| : (i += 1) { // TODO handle errors better? - analysis_ctx.error_completions.add(analysis_ctx.tree(), tag) catch {}; + analysis_ctx.error_completions.add(analysis_ctx.tree(), decl) catch {}; } return node; }, @@ -507,6 +506,20 @@ pub fn resolveTypeOfNode(analysis_ctx: *AnalysisContext, node: *ast.Node) ?*ast. }, .ContainerDecl => { analysis_ctx.onContainer(node.cast(ast.Node.ContainerDecl).?) catch return null; + + const container = node.cast(ast.Node.ContainerDecl).?; + const kind = analysis_ctx.tree().token_ids[container.kind_token]; + + if (kind == .Keyword_struct or (kind == .Keyword_union and container.init_arg_expr == .None)) { + return node; + } + + var i: usize = 0; + while (container.iterate(i)) |decl| : (i += 1) { + if (decl.id != .ContainerField) continue; + // TODO handle errors better? + analysis_ctx.enum_completions.add(analysis_ctx.tree(), decl) catch {}; + } return node; }, .MultilineStringLiteral, .StringLiteral, .FnProto => return node, @@ -1080,7 +1093,7 @@ fn addOutlineNodes(allocator: *std.mem.Allocator, children: *std.ArrayList(types // _ = try children.append(try getDocumentSymbolsInternal(allocator, tree, cchild)); return; }, - else => {} + else => {}, } std.debug.warn("{}\n", .{child.id}); _ = try children.append(try getDocumentSymbolsInternal(allocator, tree, child)); @@ -1088,7 +1101,6 @@ fn addOutlineNodes(allocator: *std.mem.Allocator, children: *std.ArrayList(types fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, node: *ast.Node) anyerror!types.DocumentSymbol { // const symbols = std.ArrayList(types.DocumentSymbol).init(allocator); - const start_loc = tree.tokenLocation(0, node.firstToken()); const end_loc = tree.tokenLocation(0, node.lastToken()); const range = types.Range{ @@ -1099,14 +1111,14 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, no .end = .{ .line = @intCast(i64, end_loc.line), .character = @intCast(i64, end_loc.column), - } + }, }; if (getDeclName(tree, node) == null) { std.debug.warn("NULL NAME: {}\n", .{node.id}); } - // TODO: Get my lazy bum to fix detail newlines + // TODO: Get my lazy bum to fix detail newlines return types.DocumentSymbol{ .name = getDeclName(tree, node) orelse "no_name", // .detail = (try getDocComments(allocator, tree, node)) orelse "", @@ -1115,7 +1127,7 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, no .FnProto => .Function, .VarDecl => .Variable, .ContainerField => .Field, - else => .Variable + else => .Variable, }, .range = range, .selectionRange = range, diff --git a/src/document_store.zig b/src/document_store.zig index 54f3183..e9f867e 100644 --- a/src/document_store.zig +++ b/src/document_store.zig @@ -30,35 +30,35 @@ pub const Handle = struct { } }; -pub const ErrorCompletion = struct { +pub const TagStore = struct { values: std.StringHashMap(void), - completions: std.ArrayList(types.CompletionItem), + completions: std.ArrayListUnmanaged(types.CompletionItem), - pub fn init(allocator: *std.mem.Allocator) ErrorCompletion { + pub fn init(allocator: *std.mem.Allocator) TagStore { return .{ .values = std.StringHashMap(void).init(allocator), - .completions = std.ArrayList(types.CompletionItem).init(allocator), + .completions = .{}, }; } - pub fn deinit(self: *ErrorCompletion) void { + pub fn deinit(self: *TagStore) void { const alloc = self.values.allocator; for (self.completions.items) |item| { alloc.free(item.label); if (item.documentation) |some| alloc.free(some.value); } self.values.deinit(); - self.completions.deinit(); + self.completions.deinit(self.values.allocator); } - pub fn add(self: *ErrorCompletion, tree: *std.zig.ast.Tree, tag: *std.zig.ast.Node.ErrorTag) !void { - const name = tree.tokenSlice(tag.name_token); + pub fn add(self: *TagStore, tree: *std.zig.ast.Tree, tag: *std.zig.ast.Node) !void { + const name = analysis.nodeToString(tree, tag).?; if (self.values.contains(name)) return; const alloc = self.values.allocator; const item = types.CompletionItem{ .label = try std.mem.dupe(alloc, u8, name), .kind = .Constant, - .documentation = if (try analysis.getDocComments(alloc, tree, &tag.base)) |docs| + .documentation = if (try analysis.getDocComments(alloc, tree, tag)) |docs| .{ .kind = .Markdown, .value = docs, @@ -68,7 +68,7 @@ pub const ErrorCompletion = struct { }; try self.values.putNoClobber(item.label, {}); - try self.completions.append(item); + try self.completions.append(self.values.allocator, item); } }; @@ -78,7 +78,8 @@ has_zig: bool, build_files: std.ArrayListUnmanaged(*BuildFile), build_runner_path: []const u8, -error_completions: ErrorCompletion, +error_completions: TagStore, +enum_completions: TagStore, pub fn init( self: *DocumentStore, @@ -91,7 +92,8 @@ pub fn init( self.has_zig = has_zig; self.build_files = .{}; self.build_runner_path = build_runner_path; - self.error_completions = ErrorCompletion.init(allocator); + self.error_completions = TagStore.init(allocator); + self.enum_completions = TagStore.init(allocator); } const LoadPackagesContext = struct { @@ -523,7 +525,8 @@ pub const AnalysisContext = struct { scope_nodes: []*std.zig.ast.Node, in_container: *std.zig.ast.Node, std_uri: ?[]const u8, - error_completions: *ErrorCompletion, + error_completions: *TagStore, + enum_completions: *TagStore, pub fn tree(self: AnalysisContext) *std.zig.ast.Tree { return self.handle.tree; @@ -631,6 +634,7 @@ pub const AnalysisContext = struct { .in_container = self.in_container, .std_uri = self.std_uri, .error_completions = self.error_completions, + .enum_completions = self.enum_completions, }; } }; @@ -671,6 +675,7 @@ pub fn analysisContext( .in_container = in_container, .std_uri = std_uri, .error_completions = &self.error_completions, + .enum_completions = &self.enum_completions, }; } @@ -701,4 +706,5 @@ pub fn deinit(self: *DocumentStore) void { self.build_files.deinit(self.allocator); self.error_completions.deinit(); + self.enum_completions.deinit(); } diff --git a/src/main.zig b/src/main.zig index edfbf4c..6502f3c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -769,6 +769,15 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config) !v }, }, }), + .enum_literal => try send(types.Response{ + .id = .{ .Integer = id }, + .result = .{ + .CompletionList = .{ + .isIncomplete = false, + .items = document_store.enum_completions.completions.items, + }, + }, + }), else => try respondGeneric(id, no_completions_response), } } else {