Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
| 639d7b6fbe |
4 changed files with 131 additions and 5 deletions
116
src/Project.zig
116
src/Project.zig
|
|
@ -320,6 +320,18 @@ fn make_URI(self: *Self, file_path: ?[]const u8) LspError![]const u8 {
|
||||||
return buf.toOwnedSlice();
|
return buf.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_absolute_file_path(self: *Self, file_path: ?[]const u8) LspError![]const u8 {
|
||||||
|
var buf = std.ArrayList(u8).init(self.allocator);
|
||||||
|
if (file_path) |path| {
|
||||||
|
if (std.fs.path.isAbsolute(path)) {
|
||||||
|
try buf.writer().print("{s}", .{path});
|
||||||
|
} else {
|
||||||
|
try buf.writer().print("{s}{c}{s}", .{ self.name, std.fs.path.sep, path });
|
||||||
|
}
|
||||||
|
} else try buf.writer().print("{s}", .{self.name});
|
||||||
|
return buf.toOwnedSlice();
|
||||||
|
}
|
||||||
|
|
||||||
fn sort_files_by_mtime(self: *Self) void {
|
fn sort_files_by_mtime(self: *Self) void {
|
||||||
sort_by_mtime(File, self.files.items);
|
sort_by_mtime(File, self.files.items);
|
||||||
}
|
}
|
||||||
|
|
@ -835,6 +847,102 @@ fn navigate_to_location_link(from: tp.pid_ref, location_link: []const u8) (Clien
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn goto_definition_omnisharp(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) SendGotoRequestError!void {
|
||||||
|
return self.send_goto_request_omnisharp(from, file_path, row, col, "o#/v2/gotodefinition");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_goto_request_omnisharp(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize, method: []const u8) SendGotoRequestError!void {
|
||||||
|
const lsp = try self.get_language_server(file_path);
|
||||||
|
const abs_file_path = try self.make_absolute_file_path(file_path);
|
||||||
|
defer self.allocator.free(abs_file_path);
|
||||||
|
|
||||||
|
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 result: []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(&result) })) {
|
||||||
|
try navigate_to_definitions_omnisharp(self_.from.ref(), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} = .{
|
||||||
|
.from = from.clone(),
|
||||||
|
.name = try std.heap.c_allocator.dupe(u8, self.name),
|
||||||
|
.project = self,
|
||||||
|
};
|
||||||
|
|
||||||
|
lsp.send_request(self.allocator, method, .{
|
||||||
|
.FileName = abs_file_path,
|
||||||
|
.Line = row,
|
||||||
|
.Column = col,
|
||||||
|
.Timeout = 10000,
|
||||||
|
}, handler) catch return error.LspFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn navigate_to_definitions_omnisharp(from: tp.pid_ref, result: []const u8) (ClientError || InvalidMessageError || cbor.Error)!void {
|
||||||
|
var iter = result;
|
||||||
|
|
||||||
|
var result_len = try cbor.decodeMapHeader(&iter);
|
||||||
|
|
||||||
|
while (result_len > 0) : (result_len -= 1) {
|
||||||
|
if (!(try cbor.matchValue(&iter, "Definitions"))) {
|
||||||
|
try cbor.skipValue(&iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var definitions_len = try cbor.decodeArrayHeader(&iter);
|
||||||
|
while (definitions_len > 0) : (definitions_len -= 1) {
|
||||||
|
var file_path: ?[]const u8 = null;
|
||||||
|
var range: ?Range = null;
|
||||||
|
var len_ = try cbor.decodeMapHeader(&iter);
|
||||||
|
while (len_ > 0) : (len_ -= 1) {
|
||||||
|
if (!(try cbor.matchValue(&iter, "Location"))) {
|
||||||
|
try cbor.skipValue(&iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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.InvalidMessage;
|
||||||
|
if (std.mem.eql(u8, field_name, "FileName")) {
|
||||||
|
var value: []const u8 = undefined;
|
||||||
|
if (!(try cbor.matchValue(&iter, cbor.extract(&value)))) return error.InvalidMessageField;
|
||||||
|
file_path = value;
|
||||||
|
} else if (std.mem.eql(u8, field_name, "Range")) {
|
||||||
|
var value: []const u8 = undefined;
|
||||||
|
if (!(try cbor.matchValue(&iter, cbor.extract_cbor(&value)))) return error.InvalidMessageField;
|
||||||
|
range = try read_range(value);
|
||||||
|
} else {
|
||||||
|
try cbor.skipValue(&iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file_path == null or range == null) return error.InvalidMessageField;
|
||||||
|
if (builtin.os.tag == .windows) {
|
||||||
|
if (file_path[0] == '/') file_path = file_path[1..];
|
||||||
|
for (file_path, 0..) |c, i| if (c == '/') {
|
||||||
|
file_path[i] = '\\';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
from.send(.{ "cmd", "navigate", .{
|
||||||
|
.file = file_path,
|
||||||
|
.goto = .{
|
||||||
|
range.?.start.line + 1,
|
||||||
|
range.?.start.character + 1,
|
||||||
|
},
|
||||||
|
} }) catch return error.ClientFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn references(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) SendGotoRequestError!void {
|
pub fn 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 lsp = try self.get_language_server(file_path);
|
||||||
const uri = try self.make_URI(file_path);
|
const uri = try self.make_URI(file_path);
|
||||||
|
|
@ -1500,11 +1608,11 @@ fn read_range(range: []const u8) !Range {
|
||||||
while (len > 0) : (len -= 1) {
|
while (len > 0) : (len -= 1) {
|
||||||
var field_name: []const u8 = undefined;
|
var field_name: []const u8 = undefined;
|
||||||
if (!(try cbor.matchString(&iter, &field_name))) return error.InvalidMessage;
|
if (!(try cbor.matchString(&iter, &field_name))) return error.InvalidMessage;
|
||||||
if (std.mem.eql(u8, field_name, "start")) {
|
if (std.mem.eql(u8, field_name, "start") or std.mem.eql(u8, field_name, "Start")) {
|
||||||
var position: []const u8 = undefined;
|
var position: []const u8 = undefined;
|
||||||
if (!(try cbor.matchValue(&iter, cbor.extract_cbor(&position)))) return error.InvalidMessageField;
|
if (!(try cbor.matchValue(&iter, cbor.extract_cbor(&position)))) return error.InvalidMessageField;
|
||||||
start = try read_position(position);
|
start = try read_position(position);
|
||||||
} else if (std.mem.eql(u8, field_name, "end")) {
|
} else if (std.mem.eql(u8, field_name, "end") or std.mem.eql(u8, field_name, "End")) {
|
||||||
var position: []const u8 = undefined;
|
var position: []const u8 = undefined;
|
||||||
if (!(try cbor.matchValue(&iter, cbor.extract_cbor(&position)))) return error.InvalidMessageField;
|
if (!(try cbor.matchValue(&iter, cbor.extract_cbor(&position)))) return error.InvalidMessageField;
|
||||||
end = try read_position(position);
|
end = try read_position(position);
|
||||||
|
|
@ -1525,9 +1633,9 @@ fn read_position(position: []const u8) !Position {
|
||||||
while (len > 0) : (len -= 1) {
|
while (len > 0) : (len -= 1) {
|
||||||
var field_name: []const u8 = undefined;
|
var field_name: []const u8 = undefined;
|
||||||
if (!(try cbor.matchString(&iter, &field_name))) return error.InvalidMessage;
|
if (!(try cbor.matchString(&iter, &field_name))) return error.InvalidMessage;
|
||||||
if (std.mem.eql(u8, field_name, "line")) {
|
if (std.mem.eql(u8, field_name, "line") or std.mem.eql(u8, field_name, "Line")) {
|
||||||
if (!(try cbor.matchValue(&iter, cbor.extract(&line)))) return error.InvalidMessageField;
|
if (!(try cbor.matchValue(&iter, cbor.extract(&line)))) return error.InvalidMessageField;
|
||||||
} else if (std.mem.eql(u8, field_name, "character")) {
|
} else if (std.mem.eql(u8, field_name, "character") or std.mem.eql(u8, field_name, "Column")) {
|
||||||
if (!(try cbor.matchValue(&iter, cbor.extract(&character)))) return error.InvalidMessageField;
|
if (!(try cbor.matchValue(&iter, cbor.extract(&character)))) return error.InvalidMessageField;
|
||||||
} else {
|
} else {
|
||||||
try cbor.skipValue(&iter);
|
try cbor.skipValue(&iter);
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,13 @@ pub fn goto_type_definition(file_path: []const u8, row: usize, col: usize) (Proj
|
||||||
return send(.{ "goto_type_definition", project, file_path, row, col });
|
return send(.{ "goto_type_definition", project, file_path, row, col });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn goto_definition_omnisharp(file_path: []const u8, row: usize, col: usize) (ProjectManagerError || ProjectError)!void {
|
||||||
|
const project = tp.env.get().str("project");
|
||||||
|
if (project.len == 0)
|
||||||
|
return error.NoProject;
|
||||||
|
return send(.{ "goto_definition_omnisharp", project, file_path, row, col });
|
||||||
|
}
|
||||||
|
|
||||||
pub fn references(file_path: []const u8, row: usize, col: usize) (ProjectManagerError || ProjectError)!void {
|
pub fn references(file_path: []const u8, row: usize, col: usize) (ProjectManagerError || ProjectError)!void {
|
||||||
const project = tp.env.get().str("project");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
|
|
@ -397,6 +404,8 @@ const Process = struct {
|
||||||
self.goto_implementation(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
self.goto_implementation(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||||
} else if (try cbor.match(m.buf, .{ "goto_type_definition", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
} else if (try cbor.match(m.buf, .{ "goto_type_definition", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
||||||
self.goto_type_definition(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
self.goto_type_definition(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||||
|
} else if (try cbor.match(m.buf, .{ "goto_definition_omnisharp", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
||||||
|
self.goto_definition_omnisharp(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||||
} else if (try cbor.match(m.buf, .{ "references", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
} else if (try cbor.match(m.buf, .{ "references", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
||||||
self.references(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
self.references(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||||
} else if (try cbor.match(m.buf, .{ "completion", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
} else if (try cbor.match(m.buf, .{ "completion", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
||||||
|
|
@ -569,6 +578,13 @@ const Process = struct {
|
||||||
return project.goto_type_definition(from, file_path, row, col);
|
return project.goto_type_definition(from, file_path, row, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn goto_definition_omnisharp(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) (ProjectError || Project.SendGotoRequestError)!void {
|
||||||
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".goto_definition_omnisharp" });
|
||||||
|
defer frame.deinit();
|
||||||
|
const project = self.projects.get(project_directory) orelse return error.NoProject;
|
||||||
|
return project.goto_definition_omnisharp(from, file_path, row, col);
|
||||||
|
}
|
||||||
|
|
||||||
fn references(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) (ProjectError || Project.SendGotoRequestError)!void {
|
fn references(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) (ProjectError || Project.SendGotoRequestError)!void {
|
||||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".references" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".references" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
|
|
|
||||||
|
|
@ -5480,7 +5480,7 @@ pub const Editor = struct {
|
||||||
pub fn goto_definition(self: *Self, _: Context) Result {
|
pub fn goto_definition(self: *Self, _: Context) Result {
|
||||||
const file_path = self.file_path orelse return;
|
const file_path = self.file_path orelse return;
|
||||||
const primary = self.get_primary();
|
const primary = self.get_primary();
|
||||||
return project_manager.goto_definition(file_path, primary.cursor.row, primary.cursor.col);
|
return project_manager.goto_definition_omnisharp(file_path, primary.cursor.row, primary.cursor.col);
|
||||||
}
|
}
|
||||||
pub const goto_definition_meta: Meta = .{ .description = "Language: Goto definition" };
|
pub const goto_definition_meta: Meta = .{ .description = "Language: Goto definition" };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CompletionItemKind = enum(u8) {
|
const CompletionItemKind = enum(u8) {
|
||||||
|
None = 0,
|
||||||
Text = 1,
|
Text = 1,
|
||||||
Method = 2,
|
Method = 2,
|
||||||
Function = 3,
|
Function = 3,
|
||||||
|
|
@ -146,6 +147,7 @@ const CompletionItemKind = enum(u8) {
|
||||||
|
|
||||||
fn kind_icon(kind: CompletionItemKind) []const u8 {
|
fn kind_icon(kind: CompletionItemKind) []const u8 {
|
||||||
return switch (kind) {
|
return switch (kind) {
|
||||||
|
.None => " ",
|
||||||
.Text => "",
|
.Text => "",
|
||||||
.Method => "",
|
.Method => "",
|
||||||
.Function => "",
|
.Function => "",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue