Add basic LSP configuration capabilities
This commit is contained in:
parent
528d57fdf7
commit
9e0077985e
3 changed files with 36 additions and 12 deletions
|
|
@ -314,7 +314,7 @@ fn get_existing_language_server(self: *Self, language_server: []const u8) ?*cons
|
|||
return null;
|
||||
}
|
||||
|
||||
fn get_language_server_instance(self: *Self, language_server: []const u8) StartLspError!*const LSP {
|
||||
fn get_language_server_instance(self: *Self, language_server: []const u8, language_server_options: []const u8) StartLspError!*const LSP {
|
||||
if (self.get_existing_language_server(language_server)) |lsp| return lsp;
|
||||
const lsp = try LSP.open(self.allocator, self.name, .{ .buf = language_server });
|
||||
errdefer lsp.deinit();
|
||||
|
|
@ -324,15 +324,15 @@ fn get_language_server_instance(self: *Self, language_server: []const u8) StartL
|
|||
const basename = if (basename_begin) |begin| self.name[begin + 1 ..] else self.name;
|
||||
|
||||
errdefer lsp.deinit();
|
||||
try self.send_lsp_init_request(lsp, self.name, basename, uri, language_server);
|
||||
try self.send_lsp_init_request(lsp, self.name, basename, uri, language_server, language_server_options);
|
||||
try self.language_servers.put(try self.allocator.dupe(u8, language_server), lsp);
|
||||
return lsp;
|
||||
}
|
||||
|
||||
fn get_or_start_language_server(self: *Self, file_path: []const u8, language_server: []const u8) StartLspError!*const LSP {
|
||||
fn get_or_start_language_server(self: *Self, file_path: []const u8, language_server: []const u8, language_server_options: []const u8) StartLspError!*const LSP {
|
||||
if (self.file_language_server_name.get(file_path)) |lsp_name|
|
||||
return self.get_existing_language_server(lsp_name) orelse error.LspFailed;
|
||||
const lsp = try self.get_language_server_instance(language_server);
|
||||
const lsp = try self.get_language_server_instance(language_server, language_server_options);
|
||||
const key = try self.allocator.dupe(u8, file_path);
|
||||
const value = try self.allocator.dupe(u8, language_server);
|
||||
try self.file_language_server_name.put(key, value);
|
||||
|
|
@ -762,10 +762,10 @@ pub fn delete_task(self: *Self, command: []const u8) error{}!void {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn did_open(self: *Self, file_path: []const u8, file_type: []const u8, language_server: []const u8, version: usize, text: []const u8) StartLspError!void {
|
||||
pub fn did_open(self: *Self, file_path: []const u8, file_type: []const u8, language_server: []const u8, language_server_options: []const u8, version: usize, text: []const u8) StartLspError!void {
|
||||
defer std.heap.c_allocator.free(text);
|
||||
self.update_mru(file_path, 0, 0) catch {};
|
||||
const lsp = try self.get_or_start_language_server(file_path, language_server);
|
||||
const lsp = try self.get_or_start_language_server(file_path, language_server, language_server_options);
|
||||
const uri = try self.make_URI(file_path);
|
||||
defer self.allocator.free(uri);
|
||||
lsp.send_notification("textDocument/didOpen", .{
|
||||
|
|
@ -1999,7 +1999,7 @@ pub fn unsupported_lsp_request(self: *Self, from: tp.pid_ref, cbor_id: []const u
|
|||
return LSP.send_error_response(self.allocator, from, cbor_id, LSP.ErrorCode.MethodNotFound, method) catch error.ClientFailed;
|
||||
}
|
||||
|
||||
fn send_lsp_init_request(self: *Self, lsp: *const LSP, project_path: []const u8, project_basename: []const u8, project_uri: []const u8, language_server: []const u8) !void {
|
||||
fn send_lsp_init_request(self: *Self, lsp: *const LSP, project_path: []const u8, project_basename: []const u8, project_uri: []const u8, language_server: []const u8, language_server_options: []const u8) !void {
|
||||
const handler: struct {
|
||||
language_server: []const u8,
|
||||
lsp: LSP,
|
||||
|
|
@ -2025,8 +2025,28 @@ fn send_lsp_init_request(self: *Self, lsp: *const LSP, project_path: []const u8,
|
|||
};
|
||||
|
||||
const version = if (root.version.len > 0 and root.version[0] == 'v') root.version[1..] else root.version;
|
||||
const Options = struct {
|
||||
pub fn cborEncode(options: @This(), writer: *std.Io.Writer) std.io.Writer.Error!void {
|
||||
const msg = std.mem.replaceOwned(u8, options.alloc, options.option, "\\\"", "\"") catch {
|
||||
try cbor.writeValue(writer, "");
|
||||
return;
|
||||
};
|
||||
defer options.alloc.free(msg);
|
||||
|
||||
const toCbor = cbor.fromJsonAlloc(options.alloc, msg[1..]) catch {
|
||||
try cbor.writeValue(writer, "");
|
||||
return;
|
||||
};
|
||||
defer options.alloc.free(toCbor);
|
||||
|
||||
writer.writeAll(toCbor) catch return error.WriteFailed;
|
||||
}
|
||||
option: []const u8,
|
||||
alloc: std.mem.Allocator,
|
||||
};
|
||||
const initOptions: Options = .{ .option = language_server_options, .alloc = self.allocator };
|
||||
try lsp.send_request(self.allocator, "initialize", .{
|
||||
.initializationOptions = initOptions,
|
||||
.processId = if (builtin.os.tag == .linux) std.os.linux.getpid() else null,
|
||||
.rootPath = project_path,
|
||||
.rootUri = project_uri,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ comment: ?[]const u8 = null,
|
|||
parser: ?[]const u8 = null,
|
||||
formatter: ?[]const []const u8 = null,
|
||||
language_server: ?[]const []const u8 = null,
|
||||
language_server_options: ?[]const u8 = null,
|
||||
first_line_matches_prefix: ?[]const u8 = null,
|
||||
first_line_matches_content: ?[]const u8 = null,
|
||||
first_line_matches: ?[]const u8 = null,
|
||||
|
|
@ -36,6 +37,7 @@ fn from_file_type(file_type: syntax.FileType) @This() {
|
|||
.comment = file_type.comment,
|
||||
.formatter = lsp_defaults.formatter,
|
||||
.language_server = lsp_defaults.language_server,
|
||||
.language_server_options = "",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,8 @@ pub fn did_open(file_path: []const u8, file_type: file_type_config, version: usi
|
|||
return error.NoProject;
|
||||
const text_ptr: usize = if (text.len > 0) @intFromPtr(text.ptr) else 0;
|
||||
const language_server = file_type.language_server orelse return;
|
||||
return send(.{ "did_open", project, file_path, file_type.name, language_server, version, text_ptr, text.len });
|
||||
const language_server_options = file_type.language_server_options orelse return;
|
||||
return send(.{ "did_open", project, file_path, file_type.name, language_server, language_server_options, version, text_ptr, text.len });
|
||||
}
|
||||
|
||||
pub fn did_change(file_path: []const u8, version: usize, text_dst: []const u8, text_src: []const u8, eol_mode: Buffer.EolMode) (ProjectManagerError || ProjectError)!void {
|
||||
|
|
@ -376,6 +377,7 @@ const Process = struct {
|
|||
var query: []const u8 = undefined;
|
||||
var file_type: []const u8 = undefined;
|
||||
var language_server: []const u8 = undefined;
|
||||
var language_server_options: []const u8 = undefined;
|
||||
var method: []const u8 = undefined;
|
||||
var cbor_id: []const u8 = undefined;
|
||||
var params_cb: []const u8 = undefined;
|
||||
|
|
@ -444,9 +446,9 @@ const Process = struct {
|
|||
self.add_task(project_directory, task) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||
} else if (try cbor.match(m.buf, .{ "delete_task", tp.extract(&project_directory), tp.extract(&task) })) {
|
||||
self.delete_task(project_directory, task) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||
} else if (try cbor.match(m.buf, .{ "did_open", tp.extract(&project_directory), tp.extract(&path), tp.extract(&file_type), tp.extract_cbor(&language_server), tp.extract(&version), tp.extract(&text_ptr), tp.extract(&text_len) })) {
|
||||
} else if (try cbor.match(m.buf, .{ "did_open", tp.extract(&project_directory), tp.extract(&path), tp.extract(&file_type), tp.extract_cbor(&language_server), tp.extract_cbor(&language_server_options), tp.extract(&version), tp.extract(&text_ptr), tp.extract(&text_len) })) {
|
||||
const text = if (text_len > 0) @as([*]const u8, @ptrFromInt(text_ptr))[0..text_len] else "";
|
||||
self.did_open(project_directory, path, file_type, language_server, version, text) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||
self.did_open(project_directory, path, file_type, language_server, language_server_options, version, text) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed;
|
||||
} else if (try cbor.match(m.buf, .{ "did_change", tp.extract(&project_directory), tp.extract(&path), tp.extract(&version), tp.extract(&text_dst_ptr), tp.extract(&text_dst_len), tp.extract(&text_src_ptr), tp.extract(&text_src_len), tp.extract(&eol_mode) })) {
|
||||
const text_dst = if (text_dst_len > 0) @as([*]const u8, @ptrFromInt(text_dst_ptr))[0..text_dst_len] else "";
|
||||
const text_src = if (text_src_len > 0) @as([*]const u8, @ptrFromInt(text_src_ptr))[0..text_src_len] else "";
|
||||
|
|
@ -635,11 +637,11 @@ const Process = struct {
|
|||
try project.request_vcs_status(from);
|
||||
}
|
||||
|
||||
fn did_open(self: *Process, project_directory: []const u8, file_path: []const u8, file_type: []const u8, language_server: []const u8, version: usize, text: []const u8) (ProjectError || Project.StartLspError || CallError || cbor.Error)!void {
|
||||
fn did_open(self: *Process, project_directory: []const u8, file_path: []const u8, file_type: []const u8, language_server: []const u8, language_server_options: []const u8, version: usize, text: []const u8) (ProjectError || Project.StartLspError || CallError || cbor.Error)!void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_open" });
|
||||
defer frame.deinit();
|
||||
const project = self.projects.get(project_directory) orelse return error.NoProject;
|
||||
return project.did_open(file_path, file_type, language_server, version, text);
|
||||
return project.did_open(file_path, file_type, language_server, language_server_options, version, text);
|
||||
}
|
||||
|
||||
fn did_change(self: *Process, project_directory: []const u8, file_path: []const u8, version: usize, text_dst: []const u8, text_src: []const u8, eol_mode: Buffer.EolMode) (ProjectError || Project.LspError)!void {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue