feat: WIP start work on goto_definition LSP command

This commit is contained in:
CJ van den Berg 2024-03-31 22:38:25 +02:00
parent eb94bf5258
commit 2e8fd58ba5
5 changed files with 121 additions and 82 deletions

View file

@ -4,6 +4,8 @@ const cbor = @import("cbor");
const log = @import("log");
const tracy = @import("tracy");
const Project = @import("Project.zig");
pid: tp.pid_ref,
const Self = @This();
@ -55,6 +57,13 @@ pub fn query_recent_files(max: usize, query: []const u8) tp.result {
return (try get()).pid.send(.{ "query_recent_files", project, max, query });
}
pub fn goto_definition(file_path: []const u8, file_type: []const u8, row: usize, col: usize) tp.result {
const project = tp.env.get().str("project");
if (project.len == 0)
return tp.exit("No project");
return (try get()).pid.send(.{ "goto_definition", project, file_path, file_type, row, col });
}
const Process = struct {
a: std.mem.Allocator,
parent: tp.pid,
@ -101,9 +110,12 @@ const Process = struct {
var project_directory: []const u8 = undefined;
var path: []const u8 = undefined;
var query: []const u8 = undefined;
var file_type: []const u8 = undefined;
var high: i64 = 0;
var low: i64 = 0;
var max: usize = 0;
var row: usize = 0;
var col: usize = 0;
if (try m.match(.{ "walk_tree_entry", tp.extract(&project_directory), tp.extract(&path), tp.extract(&high), tp.extract(&low) })) {
const mtime = (@as(i128, @intCast(high)) << 64) | @as(i128, @intCast(low));
@ -126,6 +138,8 @@ const Process = struct {
self.request_recent_files(from, project_directory, max) catch |e| return from.send_raw(tp.exit_message(e));
} else if (try m.match(.{ "query_recent_files", tp.extract(&project_directory), tp.extract(&max), tp.extract(&query) })) {
self.query_recent_files(from, project_directory, max, query) catch |e| return from.send_raw(tp.exit_message(e));
} else if (try m.match(.{ "goto_definition", tp.extract(&project_directory), tp.extract(&path), tp.extract(&file_type), tp.extract(&row), tp.extract(&col) })) {
self.goto_definition(from, project_directory, path, file_type, row, col) catch |e| return from.send_raw(tp.exit_message(e));
} else if (try m.match(.{"shutdown"})) {
if (self.walker) |pid| pid.send(.{"stop"}) catch {};
try from.send(.{ "project_manager", "shutdown" });
@ -161,67 +175,10 @@ const Process = struct {
_ = matched;
// self.logger.print("queried: {s} for {s} match {d} in {d} ms", .{ project_directory, query, matched, std.time.milliTimestamp() - start_time });
}
};
const Project = struct {
a: std.mem.Allocator,
name: []const u8,
files: std.ArrayList(File),
open_time: i64,
const File = struct {
path: []const u8,
mtime: i128,
};
fn init(a: std.mem.Allocator, name: []const u8) error{OutOfMemory}!Project {
return .{
.a = a,
.name = try a.dupe(u8, name),
.files = std.ArrayList(File).init(a),
.open_time = std.time.milliTimestamp(),
};
}
fn deinit(self: *Project) void {
for (self.files.items) |file| self.a.free(file.path);
self.files.deinit();
self.a.free(self.name);
}
fn add_file(self: *Project, path: []const u8, mtime: i128) error{OutOfMemory}!void {
(try self.files.addOne()).* = .{ .path = try self.a.dupe(u8, path), .mtime = mtime };
}
fn sort_files_by_mtime(self: *Project) void {
const less_fn = struct {
fn less_fn(_: void, lhs: File, rhs: File) bool {
return lhs.mtime > rhs.mtime;
}
}.less_fn;
std.mem.sort(File, self.files.items, {}, less_fn);
}
fn request_recent_files(self: *Project, from: tp.pid_ref, max: usize) error{ OutOfMemory, Exit }!void {
defer from.send(.{ "PRJ", "recent_done", "" }) catch {};
for (self.files.items, 0..) |file, i| {
try from.send(.{ "PRJ", "recent", file.path });
if (i >= max) return;
}
}
fn query_recent_files(self: *Project, from: tp.pid_ref, max: usize, query: []const u8) error{ OutOfMemory, Exit }!usize {
var i: usize = 0;
defer from.send(.{ "PRJ", "recent_done", query }) catch {};
for (self.files.items) |file| {
if (file.path.len < query.len) continue;
if (std.mem.indexOf(u8, file.path, query)) |_| {
try from.send(.{ "PRJ", "recent", file.path });
i += 1;
if (i >= max) return i;
}
}
return i;
fn goto_definition(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, file_type: []const u8, row: usize, col: usize) tp.result {
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
return project.goto_definition(from, file_path, file_type, row, col);
}
};