diff --git a/src/main.zig b/src/main.zig index c4fb530..af6fc2c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -298,27 +298,53 @@ fn completeGlobal(id: i64, document: *types.TextDocument, config: Config) !void }); } -fn completeFieldAccess(id: i64, document: *types.TextDocument, index: usize, config: Config) !void { - var tree = try std.zig.parse(allocator, sane_text); - defer tree.deinit(); +fn completeFieldAccess(id: i64, document: *types.TextDocument, position: types.Position, config: Config) !void { + if (document.sane_text) |sane_text| { + var tree = try std.zig.parse(allocator, sane_text); + defer tree.deinit(); - // We use a local arena allocator to deallocate all temporary data without iterating - var arena = std.heap.ArenaAllocator.init(allocator); - var completions = std.ArrayList(types.CompletionItem).init(&arena.allocator); - // Deallocate all temporary data. - defer arena.deinit(); + // We use a local arena allocator to deallocate all temporary data without iterating + var arena = std.heap.ArenaAllocator.init(allocator); + var completions = std.ArrayList(types.CompletionItem).init(&arena.allocator); + // Deallocate all temporary data. + defer arena.deinit(); - try log("{}", .{}); + var line = try document.getLine(@intCast(usize, position.line)); + try log("{}", .{line}); + var tokenizer = std.zig.Tokenizer.init(line); - try send(types.Response{ - .id = .{.Integer = id}, - .result = .{ - .CompletionList = .{ - .isIncomplete = false, - .items = completions.items, + if (analysis.getNodeFromTokens(tree, &tree.root_node.base, &tokenizer)) |node| { + var index: usize = 0; + while (node.iterate(index)) |child_node| { + try completions.append(.{ + .label = analysis.nodeToString(tree, child_node), + .kind = .Variable, + }); + + index += 1; + } + } + + try send(types.Response{ + .id = .{.Integer = id}, + .result = .{ + .CompletionList = .{ + .isIncomplete = false, + .items = completions.items, + }, }, - }, - }); + }); + } else { + return try send(types.Response{ + .id = .{.Integer = id}, + .result = .{ + .CompletionList = .{ + .isIncomplete = false, + .items = &[_]types.CompletionItem{}, + }, + }, + }); + } } // Compute builtin completions at comptime. @@ -588,7 +614,7 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config) !v } else if (pos_context == .var_access or pos_context == .empty) { try completeGlobal(id, document, config); } else if (pos_context == .field_access) { - try completeFieldAccess(id, document, pos_index, config); + try completeFieldAccess(id, document, pos, config); } else { try respondGeneric(id, no_completions_response); } diff --git a/src/types.zig b/src/types.zig index 856fc8c..8375cec 100644 --- a/src/types.zig +++ b/src/types.zig @@ -158,6 +158,18 @@ pub const TextDocument = struct { return @intCast(usize, index); } + + pub fn getLine(self: TextDocument, target_line: usize) ![]const u8 { + var split_iterator = std.mem.split(self.text, "\n"); + + var line: i64 = 0; + while (line < target_line) : (line += 1) { + _ = split_iterator.next() orelse return error.InvalidParams; + } + if (split_iterator.next()) |next| { + return next; + } else return error.InvalidParams; + } }; pub const TextEdit = struct {