From 8cf6029f1acac5b49297188be5c0f390f6ae193d Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Wed, 31 Mar 2021 02:25:49 +0300 Subject: [PATCH] Before documentPositionContext returns .empty, check if an identifier immediately follows the cursor and return .var_access if it does instead. This allows hover and go to definition to work when the cursor is immediately before an identifier. --- src/analysis.zig | 31 +++++++++++++++++++++++++++++-- src/main.zig | 14 ++++++-------- src/offsets.zig | 12 ++++++++++-- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/analysis.zig b/src/analysis.zig index 16b3f5b..04dafda 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -1549,7 +1549,11 @@ fn tokenRangeAppend(prev: SourceRange, token: std.zig.Token) SourceRange { const DocumentPosition = @import("offsets.zig").DocumentPosition; -pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.TextDocument, doc_position: DocumentPosition) !PositionContext { +pub fn documentPositionContext( + arena: *std.heap.ArenaAllocator, + document: types.TextDocument, + doc_position: DocumentPosition, +) !PositionContext { const line = doc_position.line; var tokenizer = std.zig.Tokenizer.init(line[0..doc_position.line_index]); var stack = try std.ArrayList(StackState).initCapacity(&arena.allocator, 8); @@ -1639,7 +1643,30 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types. } return block: { - if (stack.popOrNull()) |state| break :block state.ctx; + if (stack.popOrNull()) |state| { + switch (state.ctx) { + .empty => {}, + .label => |filled| { + // We need to check this because the state could be a filled + // label if only a space follows it + const last_char = line[doc_position.line_index - 1]; + if (!filled or last_char != ' ') { + break :block state.ctx; + } + }, + else => break :block state.ctx, + } + } + if (doc_position.line_index < line.len) { + switch (line[doc_position.line_index]) { + 'a'...'z', 'A'...'Z', '_', '@' => {}, + else => break :block .empty, + } + tokenizer = std.zig.Tokenizer.init(line[doc_position.line_index..]); + const tok = tokenizer.next(); + if (tok.tag == .identifier) + break :block PositionContext{ .var_access = tok.loc }; + } break :block .empty; }; } diff --git a/src/main.zig b/src/main.zig index 14d6315..19b306e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -357,8 +357,6 @@ fn nodeToCompletion( const node_tags = tree.nodes.items(.tag); const datas = tree.nodes.items(.data); const token_tags = tree.tokens.items(.tag); - if (tree.errors.len > 0) - return; const doc_kind: types.MarkupContent.Kind = if (client_capabilities.completion_doc_supports_md) .Markdown @@ -1681,17 +1679,17 @@ fn processJsonRpc(arena: *std.heap.ArenaAllocator, parser: *std.json.Parser, jso logger.debug("Method without return value not implemented: {s}", .{method}); } - fn launchWizard() !void { const dest = - (try known_folders.getPath(allocator, .local_configuration)) - orelse (try known_folders.getPath(allocator, .executable_dir)) - orelse return error.NoConfigPathFound; + (try known_folders.getPath(allocator, .local_configuration)) orelse (try known_folders.getPath(allocator, .executable_dir)) orelse return error.NoConfigPathFound; defer allocator.free(dest); try setup.wizard(allocator, dest); } -const stack_frames = switch (std.builtin.mode) { .Debug => 10, else => 0 }; +const stack_frames = switch (std.builtin.mode) { + .Debug => 10, + else => 0, +}; var gpa_state = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = stack_frames }){}; pub fn main() anyerror!void { @@ -1711,7 +1709,7 @@ pub fn main() anyerror!void { std.debug.print("Enabled debug logging\n", .{}); } else if (std.mem.eql(u8, arg, "config")) { try launchWizard(); - args_it.deinit(); + args_it.deinit(); return; } else { std.debug.print("Unrecognized argument {s}\n", .{arg}); diff --git a/src/offsets.zig b/src/offsets.zig index 12c6471..534e6f7 100644 --- a/src/offsets.zig +++ b/src/offsets.zig @@ -30,7 +30,11 @@ pub fn documentPosition(doc: types.TextDocument, position: types.Position, encod if (index < 0 or index > @intCast(i64, doc.text.len)) { return error.InvalidParams; } - return DocumentPosition{ .line = line, .absolute_index = @intCast(usize, index), .line_index = @intCast(usize, position.character) }; + return DocumentPosition{ + .line = line, + .absolute_index = @intCast(usize, index), + .line_index = @intCast(usize, position.character), + }; } else { const utf8 = doc.text[line_start_idx..]; var utf8_idx: usize = 0; @@ -50,7 +54,11 @@ pub fn documentPosition(doc: types.TextDocument, position: types.Position, encod } utf8_idx = next_utf8_idx; } - return DocumentPosition{ .line = line, .absolute_index = line_start_idx + utf8_idx, .line_index = utf8_idx }; + return DocumentPosition{ + .line = line, + .absolute_index = line_start_idx + utf8_idx, + .line_index = utf8_idx, + }; } }