From 3659a5c1a95a481854fd67737f5c68c74b884fcd Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Mon, 6 Jul 2020 01:32:14 +0300 Subject: [PATCH] Added find references handler --- src/main.zig | 65 +++++++++++++++++++++++++++++++++++++++++++++++- src/requests.zig | 6 +++-- src/types.zig | 7 ++++-- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/main.zig b/src/main.zig index 47dac5c..7d5440d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -10,6 +10,7 @@ const requests = @import("requests.zig"); const types = @import("types.zig"); const analysis = @import("analysis.zig"); const URI = @import("uri.zig"); +const references = @import("references.zig"); const rename = @import("rename.zig"); const offsets = @import("offsets.zig"); @@ -740,6 +741,44 @@ fn renameDefinitionLabel(arena: *std.heap.ArenaAllocator, id: types.RequestId, h }); } +fn referencesDefinitionGlobal(arena: *std.heap.ArenaAllocator, id: types.RequestId, handle: *DocumentStore.Handle, pos_index: usize, include_decl: bool) !void { + const decl = (try getSymbolGlobal(arena, pos_index, handle)) orelse return try respondGeneric(id, null_result_response); + var locs = std.ArrayList(types.Location).init(&arena.allocator); + try references.symbolReferences(arena, &document_store, decl, offset_encoding, include_decl, &locs, std.ArrayList(types.Location).append); + try send(arena, types.Response{ + .id = id, + .result = .{ .Locations = locs.items }, + }); +} + +fn referencesDefinitionFieldAccess( + arena: *std.heap.ArenaAllocator, + id: types.RequestId, + handle: *DocumentStore.Handle, + position: offsets.DocumentPosition, + range: analysis.SourceRange, + include_decl: bool, + config: Config, +) !void { + const decl = (try getSymbolFieldAccess(handle, arena, position, range, config)) orelse return try respondGeneric(id, null_result_response); + var locs = std.ArrayList(types.Location).init(&arena.allocator); + try references.symbolReferences(arena, &document_store, decl, offset_encoding, include_decl, &locs, std.ArrayList(types.Location).append); + try send(arena, types.Response{ + .id = id, + .result = .{ .Locations = locs.items }, + }); +} + +fn referencesDefinitionLabel(arena: *std.heap.ArenaAllocator, id: types.RequestId, handle: *DocumentStore.Handle, pos_index: usize, include_decl: bool) !void { + const decl = (try getLabelGlobal(pos_index, handle)) orelse return try respondGeneric(id, null_result_response); + var locs = std.ArrayList(types.Location).init(&arena.allocator); + try references.labelReferences(arena, decl, offset_encoding, include_decl, &locs, std.ArrayList(types.Location).append); + try send(arena, types.Response{ + .id = id, + .result = .{ .Locations = locs.items }, + }); +} + const DeclToCompletionContext = struct { completions: *std.ArrayList(types.CompletionItem), config: *const Config, @@ -1260,7 +1299,7 @@ fn formattingHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: fn renameHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.Rename, config: Config) !void { const handle = document_store.getHandle(req.params.textDocument.uri) orelse { - std.log.debug(.main, "Trying to got to definition in non existent document {}", .{req.params.textDocument.uri}); + std.log.debug(.main, "Trying to rename in non existent document {}", .{req.params.textDocument.uri}); return try respondGeneric(id, null_result_response); }; @@ -1280,6 +1319,29 @@ fn renameHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requ } } +fn referencesHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.References, config: Config) !void { + const handle = document_store.getHandle(req.params.textDocument.uri) orelse { + std.log.debug(.main, "Trying to get references in non existent document {}", .{req.params.textDocument.uri}); + return try respondGeneric(id, null_result_response); + }; + + if (req.params.position.character >= 0) { + const doc_position = try offsets.documentPosition(handle.document, req.params.position, offset_encoding); + const pos_context = try analysis.documentPositionContext(arena, handle.document, doc_position); + + const this_config = configFromUriOr(req.params.textDocument.uri, config); + const include_decl = req.params.context.includeDeclaration; + switch (pos_context) { + .var_access => try referencesDefinitionGlobal(arena, id, handle, doc_position.absolute_index, include_decl), + .field_access => |range| try referencesDefinitionFieldAccess(arena, id, handle, doc_position, range, include_decl, this_config), + .label => try referencesDefinitionLabel(arena, id, handle, doc_position.absolute_index, include_decl), + else => try respondGeneric(id, null_result_response), + } + } else { + try respondGeneric(id, null_result_response); + } +} + // Needed for the hack seen below. fn extractErr(val: var) anyerror { val catch |e| return e; @@ -1327,6 +1389,7 @@ fn processJsonRpc(arena: *std.heap.ArenaAllocator, parser: *std.json.Parser, jso .{ "textDocument/documentSymbol", requests.DocumentSymbols, documentSymbolsHandler }, .{ "textDocument/formatting", requests.Formatting, formattingHandler }, .{ "textDocument/rename", requests.Rename, renameHandler }, + .{ "textDocument/references", requests.References, referencesHandler }, }; // Hack to avoid `return`ing in the inline for, which causes bugs. diff --git a/src/requests.zig b/src/requests.zig index fbbabd4..0bfd646 100644 --- a/src/requests.zig +++ b/src/requests.zig @@ -209,10 +209,12 @@ pub const Rename = struct { }, }; -pub const Reference = struct { +pub const References = struct { params: struct { textDocument: TextDocumentIdentifier, position: types.Position, - includeDeclaration: bool, + context: struct { + includeDeclaration: bool, + }, }, }; diff --git a/src/types.zig b/src/types.zig index f39ff1e..bfe0d1c 100644 --- a/src/types.zig +++ b/src/types.zig @@ -18,11 +18,13 @@ pub const Object = json.ObjectMap; pub const DocumentUri = String; pub const Position = struct { - line: Integer, character: Integer, + line: Integer, + character: Integer, }; pub const Range = struct { - start: Position, end: Position, + start: Position, + end: Position, }; pub const Location = struct { @@ -56,6 +58,7 @@ pub const ResponseParams = union(enum) { DocumentSymbols: []DocumentSymbol, SemanticTokens: struct { data: []const u32 }, TextEdits: []TextEdit, + Locations: []Location, WorkspaceEdit: WorkspaceEdit, };