feat: lots more work on LSP support (WIP)
First valid response from clangd.
This commit is contained in:
parent
de13780a3c
commit
98104658b4
3 changed files with 358 additions and 49 deletions
63
src/LSP.zig
63
src/LSP.zig
|
@ -9,7 +9,7 @@ pid: ?tp.pid,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const module_name = @typeName(Self);
|
const module_name = @typeName(Self);
|
||||||
const sp_tag = "LSP";
|
const sp_tag = "child";
|
||||||
const debug_lsp = true;
|
const debug_lsp = true;
|
||||||
pub const Error = error{ OutOfMemory, Exit };
|
pub const Error = error{ OutOfMemory, Exit };
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ const Process = struct {
|
||||||
recv_buf: std.ArrayList(u8),
|
recv_buf: std.ArrayList(u8),
|
||||||
parent: tp.pid,
|
parent: tp.pid,
|
||||||
tag: [:0]const u8,
|
tag: [:0]const u8,
|
||||||
|
sp_tag: [:0]const u8,
|
||||||
log_file: ?std.fs.File = null,
|
log_file: ?std.fs.File = null,
|
||||||
next_id: i32 = 0,
|
next_id: i32 = 0,
|
||||||
requests: std.AutoHashMap(i32, tp.pid),
|
requests: std.AutoHashMap(i32, tp.pid),
|
||||||
|
@ -63,6 +64,10 @@ const Process = struct {
|
||||||
|
|
||||||
pub fn create(a: std.mem.Allocator, cmd: tp.message, tag: [:0]const u8) Error!tp.pid {
|
pub fn create(a: std.mem.Allocator, cmd: tp.message, tag: [:0]const u8) Error!tp.pid {
|
||||||
const self = try a.create(Process);
|
const self = try a.create(Process);
|
||||||
|
var sp_tag_ = std.ArrayList(u8).init(a);
|
||||||
|
defer sp_tag_.deinit();
|
||||||
|
try sp_tag_.appendSlice(tag);
|
||||||
|
try sp_tag_.appendSlice("-" ++ sp_tag);
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.a = a,
|
.a = a,
|
||||||
.cmd = try cmd.clone(a),
|
.cmd = try cmd.clone(a),
|
||||||
|
@ -71,6 +76,7 @@ const Process = struct {
|
||||||
.parent = tp.self_pid().clone(),
|
.parent = tp.self_pid().clone(),
|
||||||
.tag = try a.dupeZ(u8, tag),
|
.tag = try a.dupeZ(u8, tag),
|
||||||
.requests = std.AutoHashMap(i32, tp.pid).init(a),
|
.requests = std.AutoHashMap(i32, tp.pid).init(a),
|
||||||
|
.sp_tag = try sp_tag_.toOwnedSliceSentinel(0),
|
||||||
};
|
};
|
||||||
return tp.spawn_link(self.a, self, Process.start, tag) catch |e| tp.exit_error(e);
|
return tp.spawn_link(self.a, self, Process.start, tag) catch |e| tp.exit_error(e);
|
||||||
}
|
}
|
||||||
|
@ -78,16 +84,19 @@ const Process = struct {
|
||||||
fn deinit(self: *Process) void {
|
fn deinit(self: *Process) void {
|
||||||
var i = self.requests.iterator();
|
var i = self.requests.iterator();
|
||||||
while (i.next()) |req| req.value_ptr.deinit();
|
while (i.next()) |req| req.value_ptr.deinit();
|
||||||
|
self.a.free(self.sp_tag);
|
||||||
self.recv_buf.deinit();
|
self.recv_buf.deinit();
|
||||||
self.a.free(self.cmd.buf);
|
self.a.free(self.cmd.buf);
|
||||||
if (self.log_file) |file| file.close();
|
|
||||||
self.close() catch {};
|
self.close() catch {};
|
||||||
|
self.write_log("### terminated LSP process ###\n", .{});
|
||||||
|
if (self.log_file) |file| file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(self: *Process) tp.result {
|
fn close(self: *Process) tp.result {
|
||||||
if (self.sp) |*sp| {
|
if (self.sp) |*sp| {
|
||||||
defer self.sp = null;
|
defer self.sp = null;
|
||||||
try sp.close();
|
try sp.close();
|
||||||
|
self.write_log("### closed ###\n", .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +104,7 @@ const Process = struct {
|
||||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ " start" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ " start" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
_ = tp.set_trap(true);
|
_ = tp.set_trap(true);
|
||||||
self.sp = tp.subprocess.init(self.a, self.cmd, sp_tag, .Pipe) catch |e| return tp.exit_error(e);
|
self.sp = tp.subprocess.init(self.a, self.cmd, self.sp_tag, .Pipe) catch |e| return tp.exit_error(e);
|
||||||
tp.receive(&self.receiver);
|
tp.receive(&self.receiver);
|
||||||
|
|
||||||
var log_file_path = std.ArrayList(u8).init(self.a);
|
var log_file_path = std.ArrayList(u8).init(self.a);
|
||||||
|
@ -111,21 +120,24 @@ const Process = struct {
|
||||||
errdefer self.deinit();
|
errdefer self.deinit();
|
||||||
var method: []u8 = "";
|
var method: []u8 = "";
|
||||||
var bytes: []u8 = "";
|
var bytes: []u8 = "";
|
||||||
|
var err: []u8 = "";
|
||||||
|
var code: u32 = 0;
|
||||||
|
|
||||||
if (try m.match(.{ "REQ", tp.extract(&method), tp.extract(&bytes) })) {
|
if (try m.match(.{ "REQ", tp.extract(&method), tp.extract(&bytes) })) {
|
||||||
self.send_request(from, method, bytes) catch |e| return tp.exit_error(e);
|
self.send_request(from, method, bytes) catch |e| return tp.exit_error(e);
|
||||||
} else if (try m.match(.{ "NTFY", tp.extract(&method), tp.extract(&bytes) })) {
|
} else if (try m.match(.{ "NTFY", tp.extract(&method), tp.extract(&bytes) })) {
|
||||||
self.send_notification(method, bytes) catch |e| return tp.exit_error(e);
|
self.send_notification(method, bytes) catch |e| return tp.exit_error(e);
|
||||||
} else if (try m.match(.{"close"})) {
|
} else if (try m.match(.{"close"})) {
|
||||||
|
self.write_log("### LSP close ###\n", .{});
|
||||||
try self.close();
|
try self.close();
|
||||||
} else if (try m.match(.{ sp_tag, "stdout", tp.extract(&bytes) })) {
|
} else if (try m.match(.{ self.sp_tag, "stdout", tp.extract(&bytes) })) {
|
||||||
self.handle_output(bytes) catch |e| return tp.exit_error(e);
|
self.handle_output(bytes) catch |e| return tp.exit_error(e);
|
||||||
} else if (try m.match(.{ sp_tag, "term", tp.more })) {
|
} else if (try m.match(.{ self.sp_tag, "term", tp.extract(&err), tp.extract(&code) })) {
|
||||||
self.handle_terminated() catch |e| return tp.exit_error(e);
|
self.handle_terminated(err, code) catch |e| return tp.exit_error(e);
|
||||||
} else if (try m.match(.{ sp_tag, "stderr", tp.extract(&bytes) })) {
|
} else if (try m.match(.{ self.sp_tag, "stderr", tp.extract(&bytes) })) {
|
||||||
self.write_log("{s}\n", .{bytes});
|
self.write_log("{s}\n", .{bytes});
|
||||||
} else if (try m.match(.{ "exit", "normal" })) {
|
} else if (try m.match(.{ "exit", "normal" })) {
|
||||||
return tp.exit_normal();
|
// self.write_log("### exit normal ###\n", .{});
|
||||||
} else {
|
} else {
|
||||||
const e = tp.unexpected(m);
|
const e = tp.unexpected(m);
|
||||||
self.write_log("{s}\n", .{tp.error_text()});
|
self.write_log("{s}\n", .{tp.error_text()});
|
||||||
|
@ -189,9 +201,9 @@ const Process = struct {
|
||||||
try self.frame_message_recv();
|
try self.frame_message_recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_terminated(self: *Process) !void {
|
fn handle_terminated(self: *Process, err: []const u8, code: u32) !void {
|
||||||
self.write_log("terminated\n", .{});
|
self.write_log("### subprocess terminated {s} {d} ###\n", .{ err, code });
|
||||||
try self.parent.send(.{ self.tag, "done" });
|
try self.parent.send(.{ sp_tag, self.tag, "done" });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_request(self: *Process, from: tp.pid_ref, method: []const u8, params_cb: []const u8) !void {
|
fn send_request(self: *Process, from: tp.pid_ref, method: []const u8, params_cb: []const u8) !void {
|
||||||
|
@ -218,7 +230,7 @@ const Process = struct {
|
||||||
var output = std.ArrayList(u8).init(self.a);
|
var output = std.ArrayList(u8).init(self.a);
|
||||||
defer output.deinit();
|
defer output.deinit();
|
||||||
const writer = output.writer();
|
const writer = output.writer();
|
||||||
try writer.print("Content-Length: {d}\r\n\r\n", .{json.len});
|
try writer.print("Content-Length: {d}\r\nContent-Type: application/vscode-jsonrpc; charset=utf-8\r\n\r\n", .{json.len});
|
||||||
_ = try writer.write(json);
|
_ = try writer.write(json);
|
||||||
|
|
||||||
try sp.send(output.items);
|
try sp.send(output.items);
|
||||||
|
@ -273,6 +285,16 @@ const Process = struct {
|
||||||
const json = if (params) |p| try cbor.toJsonPrettyAlloc(self.a, p) else null;
|
const json = if (params) |p| try cbor.toJsonPrettyAlloc(self.a, p) else null;
|
||||||
defer if (json) |p| self.a.free(p);
|
defer if (json) |p| self.a.free(p);
|
||||||
self.write_log("### RECV req: {d}\nmethod: {s}\n{s}\n###\n", .{ id, method, json orelse "no params" });
|
self.write_log("### RECV req: {d}\nmethod: {s}\n{s}\n###\n", .{ id, method, json orelse "no params" });
|
||||||
|
var msg = std.ArrayList(u8).init(self.a);
|
||||||
|
defer msg.deinit();
|
||||||
|
const writer = msg.writer();
|
||||||
|
try cbor.writeArrayHeader(writer, 6);
|
||||||
|
try cbor.writeValue(writer, sp_tag);
|
||||||
|
try cbor.writeValue(writer, self.tag);
|
||||||
|
try cbor.writeValue(writer, "request");
|
||||||
|
try cbor.writeValue(writer, method);
|
||||||
|
try cbor.writeValue(writer, id);
|
||||||
|
if (params) |p| _ = try writer.write(p) else try cbor.writeValue(writer, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive_lsp_response(self: *Process, id: i32, result: ?[]const u8, err: ?[]const u8) !void {
|
fn receive_lsp_response(self: *Process, id: i32, result: ?[]const u8, err: ?[]const u8) !void {
|
||||||
|
@ -285,13 +307,15 @@ const Process = struct {
|
||||||
var msg = std.ArrayList(u8).init(self.a);
|
var msg = std.ArrayList(u8).init(self.a);
|
||||||
defer msg.deinit();
|
defer msg.deinit();
|
||||||
const writer = msg.writer();
|
const writer = msg.writer();
|
||||||
try cbor.writeArrayHeader(writer, 2);
|
try cbor.writeArrayHeader(writer, 4);
|
||||||
|
try cbor.writeValue(writer, sp_tag);
|
||||||
|
try cbor.writeValue(writer, self.tag);
|
||||||
if (err) |err_| {
|
if (err) |err_| {
|
||||||
try cbor.writeValue(writer, "error");
|
try cbor.writeValue(writer, "error");
|
||||||
try cbor.writeValue(writer, err_);
|
_ = try writer.write(err_);
|
||||||
} else if (result) |result_| {
|
} else if (result) |result_| {
|
||||||
try cbor.writeValue(writer, "result");
|
try cbor.writeValue(writer, "result");
|
||||||
try cbor.writeValue(writer, result_);
|
_ = try writer.write(result_);
|
||||||
}
|
}
|
||||||
try from.send_raw(.{ .buf = msg.items });
|
try from.send_raw(.{ .buf = msg.items });
|
||||||
}
|
}
|
||||||
|
@ -300,6 +324,15 @@ const Process = struct {
|
||||||
const json = if (params) |p| try cbor.toJsonPrettyAlloc(self.a, p) else null;
|
const json = if (params) |p| try cbor.toJsonPrettyAlloc(self.a, p) else null;
|
||||||
defer if (json) |p| self.a.free(p);
|
defer if (json) |p| self.a.free(p);
|
||||||
self.write_log("### RECV notify:\nmethod: {s}\n{s}\n###\n", .{ method, json orelse "no params" });
|
self.write_log("### RECV notify:\nmethod: {s}\n{s}\n###\n", .{ method, json orelse "no params" });
|
||||||
|
var msg = std.ArrayList(u8).init(self.a);
|
||||||
|
defer msg.deinit();
|
||||||
|
const writer = msg.writer();
|
||||||
|
try cbor.writeArrayHeader(writer, 5);
|
||||||
|
try cbor.writeValue(writer, sp_tag);
|
||||||
|
try cbor.writeValue(writer, self.tag);
|
||||||
|
try cbor.writeValue(writer, "notify");
|
||||||
|
try cbor.writeValue(writer, method);
|
||||||
|
if (params) |p| _ = try writer.write(p) else try cbor.writeValue(writer, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_log(self: *Process, comptime format: []const u8, args: anytype) void {
|
fn write_log(self: *Process, comptime format: []const u8, args: anytype) void {
|
||||||
|
|
342
src/Project.zig
342
src/Project.zig
|
@ -41,27 +41,9 @@ fn get_lsp(self: *Self) !LSP {
|
||||||
self.lsp = try LSP.open(self.a, tp.message.fmt(.{self.lsp_name}), self.lsp_name);
|
self.lsp = try LSP.open(self.a, tp.message.fmt(.{self.lsp_name}), self.lsp_name);
|
||||||
const uri = try self.make_URI(null);
|
const uri = try self.make_URI(null);
|
||||||
defer self.a.free(uri);
|
defer self.a.free(uri);
|
||||||
const response = try self.lsp.?.send_request(self.a, "initialize", .{
|
const basename_begin = std.mem.lastIndexOfScalar(u8, self.name, std.fs.path.sep);
|
||||||
.processId = std.os.linux.getpid(),
|
const basename = if (basename_begin) |begin| self.name[begin + 1 ..] else self.name;
|
||||||
.rootUri = uri,
|
const response = try self.send_lsp_init_request(self.name, basename, uri);
|
||||||
.clientInfo = .{ .name = root.application_name },
|
|
||||||
.capabilities = .{
|
|
||||||
.workspace = .{
|
|
||||||
.applyEdit = true,
|
|
||||||
.codeLens = .{ .refreshSupport = true },
|
|
||||||
.configuration = true,
|
|
||||||
.diagnostics = .{ .refreshSupport = true },
|
|
||||||
.fileOperations = .{
|
|
||||||
.didCreate = true,
|
|
||||||
.didDelete = true,
|
|
||||||
.didRename = true,
|
|
||||||
.willCreate = true,
|
|
||||||
.willDelete = true,
|
|
||||||
.willRename = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
defer self.a.free(response.buf);
|
defer self.a.free(response.buf);
|
||||||
return self.lsp.?;
|
return self.lsp.?;
|
||||||
}
|
}
|
||||||
|
@ -69,9 +51,9 @@ fn get_lsp(self: *Self) !LSP {
|
||||||
fn make_URI(self: *Self, file_path: ?[]const u8) ![]const u8 {
|
fn make_URI(self: *Self, file_path: ?[]const u8) ![]const u8 {
|
||||||
var buf = std.ArrayList(u8).init(self.a);
|
var buf = std.ArrayList(u8).init(self.a);
|
||||||
if (file_path) |path|
|
if (file_path) |path|
|
||||||
try buf.writer().print("file:/{s}/{s}", .{ self.name, path })
|
try buf.writer().print("file://{s}/{s}", .{ self.name, path })
|
||||||
else
|
else
|
||||||
try buf.writer().print("file:/{s}", .{self.name});
|
try buf.writer().print("file://{s}", .{self.name});
|
||||||
return buf.toOwnedSlice();
|
return buf.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,19 +93,13 @@ pub fn query_recent_files(self: *Self, from: tp.pid_ref, max: usize, query: []co
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn did_open(self: *Self, from: tp.pid_ref, file_path: []const u8, file_type: []const u8, version: usize, text: []const u8) tp.result {
|
pub fn did_open(self: *Self, from: tp.pid_ref, file_path: []const u8, file_type: []const u8, version: usize, text: []const u8) tp.result {
|
||||||
|
_ = from; // autofix
|
||||||
const lsp = self.get_lsp() catch |e| return tp.exit_error(e);
|
const lsp = self.get_lsp() catch |e| return tp.exit_error(e);
|
||||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||||
defer self.a.free(uri);
|
defer self.a.free(uri);
|
||||||
const response = try lsp.send_request(self.a, "textDocument/didOpen", .{
|
try lsp.send_notification("textDocument/didOpen", .{
|
||||||
.textDocument = .{
|
.textDocument = .{ .uri = uri, .languageId = file_type, .version = version, .text = text },
|
||||||
.uri = uri,
|
|
||||||
.languageId = file_type,
|
|
||||||
.version = version,
|
|
||||||
.text = text,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
defer self.a.free(response.buf);
|
|
||||||
_ = from;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn goto_definition(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) tp.result {
|
pub fn goto_definition(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) tp.result {
|
||||||
|
@ -135,5 +111,305 @@ pub fn goto_definition(self: *Self, from: tp.pid_ref, file_path: []const u8, row
|
||||||
.position = .{ .line = row, .character = col },
|
.position = .{ .line = row, .character = col },
|
||||||
});
|
});
|
||||||
defer self.a.free(response.buf);
|
defer self.a.free(response.buf);
|
||||||
_ = from;
|
try from.send_raw(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_lsp_init_request(self: *Self, project_path: []const u8, project_basename: []const u8, project_uri: []const u8) error{Exit}!tp.message {
|
||||||
|
return self.lsp.?.send_request(self.a, "initialize", .{
|
||||||
|
.processId = std.os.linux.getpid(),
|
||||||
|
.rootPath = project_path,
|
||||||
|
.rootUri = project_uri,
|
||||||
|
.workspaceFolders = .{
|
||||||
|
.{
|
||||||
|
.uri = project_uri,
|
||||||
|
.name = project_basename,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.trace = "verbose",
|
||||||
|
.locale = "en-us",
|
||||||
|
.clientInfo = .{
|
||||||
|
.name = root.application_name,
|
||||||
|
.version = "0.0.1",
|
||||||
|
},
|
||||||
|
.capabilities = .{
|
||||||
|
.workspace = .{
|
||||||
|
.applyEdit = true,
|
||||||
|
.workspaceEdit = .{
|
||||||
|
.documentChanges = true,
|
||||||
|
.resourceOperations = .{
|
||||||
|
"create",
|
||||||
|
"rename",
|
||||||
|
"delete",
|
||||||
|
},
|
||||||
|
.failureHandling = "textOnlyTransactional",
|
||||||
|
.normalizesLineEndings = true,
|
||||||
|
.changeAnnotationSupport = .{ .groupsOnLabel = true },
|
||||||
|
},
|
||||||
|
.configuration = true,
|
||||||
|
.didChangeWatchedFiles = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.relativePatternSupport = true,
|
||||||
|
},
|
||||||
|
.symbol = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.symbolKind = .{
|
||||||
|
.valueSet = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
|
||||||
|
},
|
||||||
|
.tagSupport = .{ .valueSet = .{1} },
|
||||||
|
.resolveSupport = .{ .properties = .{"location.range"} },
|
||||||
|
},
|
||||||
|
.codeLens = .{ .refreshSupport = true },
|
||||||
|
.executeCommand = .{ .dynamicRegistration = true },
|
||||||
|
.didChangeConfiguration = .{ .dynamicRegistration = true },
|
||||||
|
.workspaceFolders = true,
|
||||||
|
.semanticTokens = .{ .refreshSupport = true },
|
||||||
|
.fileOperations = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.didCreate = true,
|
||||||
|
.didRename = true,
|
||||||
|
.didDelete = true,
|
||||||
|
.willCreate = true,
|
||||||
|
.willRename = true,
|
||||||
|
.willDelete = true,
|
||||||
|
},
|
||||||
|
.inlineValue = .{ .refreshSupport = true },
|
||||||
|
.inlayHint = .{ .refreshSupport = true },
|
||||||
|
.diagnostics = .{ .refreshSupport = true },
|
||||||
|
},
|
||||||
|
.textDocument = .{
|
||||||
|
.publishDiagnostics = .{
|
||||||
|
.relatedInformation = true,
|
||||||
|
.versionSupport = false,
|
||||||
|
.tagSupport = .{ .valueSet = .{ 1, 2 } },
|
||||||
|
.codeDescriptionSupport = true,
|
||||||
|
.dataSupport = true,
|
||||||
|
},
|
||||||
|
.synchronization = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.willSave = true,
|
||||||
|
.willSaveWaitUntil = true,
|
||||||
|
.didSave = true,
|
||||||
|
},
|
||||||
|
.completion = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.contextSupport = true,
|
||||||
|
.completionItem = .{
|
||||||
|
.snippetSupport = true,
|
||||||
|
.commitCharactersSupport = true,
|
||||||
|
.documentationFormat = .{
|
||||||
|
"markdown",
|
||||||
|
"plaintext",
|
||||||
|
},
|
||||||
|
.deprecatedSupport = true,
|
||||||
|
.preselectSupport = true,
|
||||||
|
.tagSupport = .{ .valueSet = .{1} },
|
||||||
|
.insertReplaceSupport = true,
|
||||||
|
.resolveSupport = .{ .properties = .{
|
||||||
|
"documentation",
|
||||||
|
"detail",
|
||||||
|
"additionalTextEdits",
|
||||||
|
} },
|
||||||
|
.insertTextModeSupport = .{ .valueSet = .{ 1, 2 } },
|
||||||
|
.labelDetailsSupport = true,
|
||||||
|
},
|
||||||
|
.insertTextMode = 2,
|
||||||
|
.completionItemKind = .{
|
||||||
|
.valueSet = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
|
||||||
|
},
|
||||||
|
.completionList = .{ .itemDefaults = .{
|
||||||
|
"commitCharacters",
|
||||||
|
"editRange",
|
||||||
|
"insertTextFormat",
|
||||||
|
"insertTextMode",
|
||||||
|
} },
|
||||||
|
},
|
||||||
|
.hover = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.contentFormat = .{ "markdown", "plaintext" },
|
||||||
|
},
|
||||||
|
.signatureHelp = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.signatureInformation = .{
|
||||||
|
.documentationFormat = .{ "markdown", "plaintext" },
|
||||||
|
.parameterInformation = .{ .labelOffsetSupport = true },
|
||||||
|
.activeParameterSupport = true,
|
||||||
|
},
|
||||||
|
.contextSupport = true,
|
||||||
|
},
|
||||||
|
.definition = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.linkSupport = true,
|
||||||
|
},
|
||||||
|
.references = .{ .dynamicRegistration = true },
|
||||||
|
.documentHighlight = .{ .dynamicRegistration = true },
|
||||||
|
.documentSymbol = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.symbolKind = .{
|
||||||
|
.valueSet = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
|
||||||
|
},
|
||||||
|
.hierarchicalDocumentSymbolSupport = true,
|
||||||
|
.tagSupport = .{ .valueSet = .{1} },
|
||||||
|
.labelSupport = true,
|
||||||
|
},
|
||||||
|
.codeAction = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.isPreferredSupport = true,
|
||||||
|
.disabledSupport = true,
|
||||||
|
.dataSupport = true,
|
||||||
|
.resolveSupport = .{ .properties = .{"edit"} },
|
||||||
|
.codeActionLiteralSupport = .{
|
||||||
|
.codeActionKind = .{
|
||||||
|
.valueSet = .{
|
||||||
|
"",
|
||||||
|
"quickfix",
|
||||||
|
"refactor",
|
||||||
|
"refactor.extract",
|
||||||
|
"refactor.inline",
|
||||||
|
"refactor.rewrite",
|
||||||
|
"source",
|
||||||
|
"source.organizeImports",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.honorsChangeAnnotations = false,
|
||||||
|
},
|
||||||
|
.codeLens = .{ .dynamicRegistration = true },
|
||||||
|
.formatting = .{ .dynamicRegistration = true },
|
||||||
|
.rangeFormatting = .{ .dynamicRegistration = true },
|
||||||
|
.onTypeFormatting = .{ .dynamicRegistration = true },
|
||||||
|
.rename = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.prepareSupport = true,
|
||||||
|
.prepareSupportDefaultBehavior = 1,
|
||||||
|
.honorsChangeAnnotations = true,
|
||||||
|
},
|
||||||
|
.documentLink = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.tooltipSupport = true,
|
||||||
|
},
|
||||||
|
.typeDefinition = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.linkSupport = true,
|
||||||
|
},
|
||||||
|
.implementation = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.linkSupport = true,
|
||||||
|
},
|
||||||
|
.colorProvider = .{ .dynamicRegistration = true },
|
||||||
|
.foldingRange = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.rangeLimit = 5000,
|
||||||
|
.lineFoldingOnly = true,
|
||||||
|
.foldingRangeKind = .{ .valueSet = .{ "comment", "imports", "region" } },
|
||||||
|
.foldingRange = .{ .collapsedText = false },
|
||||||
|
},
|
||||||
|
.declaration = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.linkSupport = true,
|
||||||
|
},
|
||||||
|
.selectionRange = .{ .dynamicRegistration = true },
|
||||||
|
.callHierarchy = .{ .dynamicRegistration = true },
|
||||||
|
.semanticTokens = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.tokenTypes = .{
|
||||||
|
"namespace",
|
||||||
|
"type",
|
||||||
|
"class",
|
||||||
|
"enum",
|
||||||
|
"interface",
|
||||||
|
"struct",
|
||||||
|
"typeParameter",
|
||||||
|
"parameter",
|
||||||
|
"variable",
|
||||||
|
"property",
|
||||||
|
"enumMember",
|
||||||
|
"event",
|
||||||
|
"function",
|
||||||
|
"method",
|
||||||
|
"macro",
|
||||||
|
"keyword",
|
||||||
|
"modifier",
|
||||||
|
"comment",
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"regexp",
|
||||||
|
"operator",
|
||||||
|
"decorator",
|
||||||
|
},
|
||||||
|
.tokenModifiers = .{
|
||||||
|
"declaration",
|
||||||
|
"definition",
|
||||||
|
"readonly",
|
||||||
|
"static",
|
||||||
|
"deprecated",
|
||||||
|
"abstract",
|
||||||
|
"async",
|
||||||
|
"modification",
|
||||||
|
"documentation",
|
||||||
|
"defaultLibrary",
|
||||||
|
},
|
||||||
|
.formats = .{"relative"},
|
||||||
|
.requests = .{
|
||||||
|
.range = true,
|
||||||
|
.full = .{ .delta = true },
|
||||||
|
},
|
||||||
|
.multilineTokenSupport = false,
|
||||||
|
.overlappingTokenSupport = false,
|
||||||
|
.serverCancelSupport = true,
|
||||||
|
.augmentsSyntaxTokens = true,
|
||||||
|
},
|
||||||
|
.linkedEditingRange = .{ .dynamicRegistration = true },
|
||||||
|
.typeHierarchy = .{ .dynamicRegistration = true },
|
||||||
|
.inlineValue = .{ .dynamicRegistration = true },
|
||||||
|
.inlayHint = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.resolveSupport = .{
|
||||||
|
.properties = .{
|
||||||
|
"tooltip",
|
||||||
|
"textEdits",
|
||||||
|
"label.tooltip",
|
||||||
|
"label.location",
|
||||||
|
"label.command",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.diagnostic = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.relatedDocumentSupport = false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.window = .{
|
||||||
|
.showMessage = .{
|
||||||
|
.messageActionItem = .{ .additionalPropertiesSupport = true },
|
||||||
|
},
|
||||||
|
.showDocument = .{ .support = true },
|
||||||
|
.workDoneProgress = true,
|
||||||
|
},
|
||||||
|
.general = .{
|
||||||
|
.staleRequestSupport = .{
|
||||||
|
.cancel = true,
|
||||||
|
.retryOnContentModified = .{
|
||||||
|
"textDocument/semanticTokens/full",
|
||||||
|
"textDocument/semanticTokens/range",
|
||||||
|
"textDocument/semanticTokens/full/delta",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.regularExpressions = .{
|
||||||
|
.engine = "ECMAScript",
|
||||||
|
.version = "ES2020",
|
||||||
|
},
|
||||||
|
.markdown = .{
|
||||||
|
.parser = "marked",
|
||||||
|
.version = "1.1.0",
|
||||||
|
},
|
||||||
|
.positionEncodings = .{"utf-16"},
|
||||||
|
},
|
||||||
|
.notebookDocument = .{
|
||||||
|
.synchronization = .{
|
||||||
|
.dynamicRegistration = true,
|
||||||
|
.executionSummarySupport = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ pub const Editor = struct {
|
||||||
|
|
||||||
file_path: ?[]const u8,
|
file_path: ?[]const u8,
|
||||||
buffer: ?*Buffer,
|
buffer: ?*Buffer,
|
||||||
lsp_version: usize = 0,
|
lsp_version: usize = 1,
|
||||||
|
|
||||||
cursels: CurSel.List,
|
cursels: CurSel.List,
|
||||||
cursels_saved: CurSel.List,
|
cursels_saved: CurSel.List,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue