diff --git a/src/Project.zig b/src/Project.zig index 58e6dd8..0948544 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -1082,6 +1082,42 @@ pub fn references(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usi }, handler) catch return error.LspFailed; } +pub fn highlight_references(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) SendGotoRequestError!void { + const lsp = try self.get_language_server(file_path); + const uri = try self.make_URI(file_path); + defer self.allocator.free(uri); + + const handler: struct { + from: tp.pid, + name: []const u8, + project: *Self, + + pub fn deinit(self_: *@This()) void { + std.heap.c_allocator.free(self_.name); + self_.from.deinit(); + } + + pub fn receive(self_: @This(), response: tp.message) !void { + var locations: []const u8 = undefined; + if (try cbor.match(response.buf, .{ "child", tp.string, "result", tp.null_ })) { + return; + } else if (try cbor.match(response.buf, .{ "child", tp.string, "result", tp.extract_cbor(&locations) })) { + _ = try send_reference_list("HREF", self_.from.ref(), locations, self_.name); + } + } + } = .{ + .from = from.clone(), + .name = try std.heap.c_allocator.dupe(u8, self.name), + .project = self, + }; + + lsp.send_request(self.allocator, "textDocument/references", .{ + .textDocument = .{ .uri = uri }, + .position = .{ .line = row, .character = col }, + .context = .{ .includeDeclaration = true }, + }, handler) catch return error.LspFailed; +} + fn send_reference_list(tag: []const u8, to: tp.pid_ref, locations: []const u8, name: []const u8) (error{ InvalidTargetURI, InvalidReferenceList, @@ -1125,109 +1161,6 @@ fn send_reference(tag: []const u8, to: tp.pid_ref, location_: []const u8, name: }; } -pub fn highlight_references(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) SendGotoRequestError!void { - const lsp = try self.get_language_server(file_path); - const uri = try self.make_URI(file_path); - defer self.allocator.free(uri); - - const handler: struct { - from: tp.pid, - file_path: []const u8, - - pub fn deinit(self_: *@This()) void { - std.heap.c_allocator.free(self_.file_path); - self_.from.deinit(); - } - - pub fn receive(self_: @This(), response: tp.message) !void { - var highlights: []const u8 = undefined; - if (try cbor.match(response.buf, .{ "child", tp.string, "result", tp.null_ })) { - return; - } else if (try cbor.match(response.buf, .{ "child", tp.string, "result", tp.extract_cbor(&highlights) })) { - _ = try send_highlight_list(self_.from.ref(), highlights, self_.file_path); - } - } - } = .{ - .from = from.clone(), - .file_path = try std.heap.c_allocator.dupe(u8, file_path), - }; - - lsp.send_request(self.allocator, "textDocument/documentHighlight", .{ - .textDocument = .{ .uri = uri }, - .position = .{ .line = row, .character = col }, - .context = .{ .includeDeclaration = true }, - }, handler) catch return error.LspFailed; -} - -fn send_highlight_list(to: tp.pid_ref, highlights: []const u8, file_path: []const u8) (error{InvalidDocumentHighlightList} || DocumentHighlightError)!usize { - defer to.send(.{ "HREF", file_path, "done" }) catch {}; - var iter = highlights; - var len = try cbor.decodeArrayHeader(&iter); - const count = len; - while (len > 0) : (len -= 1) { - var highlight: []const u8 = undefined; - if (try cbor.matchValue(&iter, cbor.extract_cbor(&highlight))) { - try send_highlight(to, highlight, file_path); - } else return error.InvalidDocumentHighlightList; - } - return count; -} - -fn send_highlight(to: tp.pid_ref, highlight_: []const u8, file_path: []const u8) DocumentHighlightError!void { - const highlight = try read_document_highlight(highlight_); - to.send(.{ - "HREF", - file_path, - highlight.range.start.line + 1, - highlight.range.start.character, - highlight.range.end.line + 1, - highlight.range.end.character, - }) catch |e| { - std.log.err("send HREF (in send_highlight) failed: {t}", .{e}); - return; - }; -} - -const DocumentHighlight = struct { - range: Range, - kind: ?Kind, - - const Kind = enum(u8) { - Text = 1, - Read = 2, - Write = 3, - }; -}; - -const DocumentHighlightError = error{ - InvalidDocumentHighlight, - InvalidDocumentHighlightField, - InvalidDocumentHighlightFieldName, -} || RangeError || cbor.Error; -fn read_document_highlight(document_highlight: []const u8) DocumentHighlightError!DocumentHighlight { - var iter = document_highlight; - var range: ?Range = null; - var kind: ?DocumentHighlight.Kind = null; - var len = try cbor.decodeMapHeader(&iter); - while (len > 0) : (len -= 1) { - var field_name: []const u8 = undefined; - if (!(try cbor.matchString(&iter, &field_name))) return error.InvalidDocumentHighlightFieldName; - if (std.mem.eql(u8, field_name, "range")) { - var range_: []const u8 = undefined; - if (!(try cbor.matchValue(&iter, cbor.extract_cbor(&range_)))) return error.InvalidDocumentHighlightField; - range = try read_range(range_); - } else if (std.mem.eql(u8, field_name, "kind")) { - var kind_: u8 = undefined; - if (!(try cbor.matchValue(&iter, cbor.extract(&kind_)))) return error.InvalidDocumentHighlightField; - kind = std.enums.fromInt(DocumentHighlight.Kind, kind_) orelse return error.InvalidDocumentHighlightField; - } else { - try cbor.skipValue(&iter); - } - } - if (range == null) return error.InvalidDocumentHighlight; - return .{ .range = range.?, .kind = kind }; -} - pub const CompletionError = error{ InvalidTargetURI, } || CompletionListError || CompletionItemError || TextEditError || cbor.Error; diff --git a/src/tui/editor.zig b/src/tui/editor.zig index e19df25..305a3e6 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -6200,7 +6200,6 @@ pub const Editor = struct { } pub fn done_highlight_reference(self: *Self) void { - self.sort_matches(); self.highlight_references_state = .done; } diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 7c75fb8..9e16fb8 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -165,14 +165,14 @@ pub fn receive(self: *Self, from_: tp.pid_ref, m: tp.message) error{Exit}!bool { } self.find_in_files_state = .done; return true; - } else if (try m.match(.{ "HREF", tp.extract(&path), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos) })) { - if (self.get_editor_for_file(path)) |editor| editor.add_highlight_reference(.{ + } else if (try m.match(.{ "HREF", tp.extract(&path), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos), tp.extract(&lines) })) { + if (self.get_active_editor()) |editor| editor.add_highlight_reference(.{ .begin = .{ .row = begin_line, .col = begin_pos }, .end = .{ .row = end_line, .col = end_pos }, }); return true; - } else if (try m.match(.{ "HREF", tp.extract(&path), "done" })) { - if (self.get_editor_for_file(path)) |editor| editor.done_highlight_reference(); + } else if (try m.match(.{ "HREF", "done" })) { + if (self.get_active_editor()) |editor| editor.done_highlight_reference(); return true; } else if (try m.match(.{ "hover", tp.extract(&path), tp.string, tp.extract(&lines), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos) })) { try self.set_info_content(lines, .replace); @@ -1593,16 +1593,6 @@ pub fn get_editor_for_buffer(self: *Self, buffer: *Buffer) ?*ed.Editor { return null; } -pub fn get_editor_for_file(self: *Self, file_path: []const u8) ?*ed.Editor { - for (self.views.widgets.items) |*view| { - const editor = view.widget.get("editor") orelse continue; - if (editor.dynamic_cast(ed.EditorWidget)) |p| - if (std.mem.eql(u8, p.editor.file_path orelse continue, file_path)) - return &p.editor; - } - return null; -} - pub fn get_view_for_file(self: *Self, file_path: []const u8) ?usize { for (self.views.widgets.items, 0..) |*view, n| { const editor = view.widget.get("editor") orelse continue;