refactor: dynamically allocate LSP client handles
This commit is contained in:
parent
efdad96054
commit
5d256413da
2 changed files with 33 additions and 18 deletions
26
src/LSP.zig
26
src/LSP.zig
|
@ -17,22 +17,34 @@ const OutOfMemoryError = error{OutOfMemory};
|
||||||
const SendError = error{SendFailed};
|
const SendError = error{SendFailed};
|
||||||
const SpawnError = error{ThespianSpawnFailed};
|
const SpawnError = error{ThespianSpawnFailed};
|
||||||
|
|
||||||
pub fn open(allocator: std.mem.Allocator, project: []const u8, cmd: tp.message) (error{ ThespianSpawnFailed, InvalidLspCommand } || cbor.Error)!Self {
|
pub fn open(
|
||||||
return .{ .allocator = allocator, .pid = try Process.create(allocator, project, cmd) };
|
allocator: std.mem.Allocator,
|
||||||
|
project: []const u8,
|
||||||
|
cmd: tp.message,
|
||||||
|
) (error{ ThespianSpawnFailed, InvalidLspCommand } || cbor.Error)!*const Self {
|
||||||
|
const self = try allocator.create(Self);
|
||||||
|
errdefer allocator.destroy(self);
|
||||||
|
self.* = .{
|
||||||
|
.allocator = allocator,
|
||||||
|
.pid = try Process.create(allocator, project, cmd),
|
||||||
|
};
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Self) void {
|
pub fn deinit(self: *const Self) void {
|
||||||
self.pid.send(.{"close"}) catch {};
|
self.pid.send(.{"close"}) catch {};
|
||||||
self.pid.deinit();
|
self.pid.deinit();
|
||||||
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn term(self: Self) void {
|
pub fn term(self: *const Self) void {
|
||||||
self.pid.send(.{"term"}) catch {};
|
self.pid.send(.{"term"}) catch {};
|
||||||
self.pid.deinit();
|
self.pid.deinit();
|
||||||
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_request(
|
pub fn send_request(
|
||||||
self: Self,
|
self: *const Self,
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
method: []const u8,
|
method: []const u8,
|
||||||
m: anytype,
|
m: anytype,
|
||||||
|
@ -44,14 +56,14 @@ pub fn send_request(
|
||||||
return RequestContext(@TypeOf(ctx)).send(allocator, self.pid.ref(), ctx, tp.message.fmt(.{ "REQ", method, cb.items }));
|
return RequestContext(@TypeOf(ctx)).send(allocator, self.pid.ref(), ctx, tp.message.fmt(.{ "REQ", method, cb.items }));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_notification(self: Self, method: []const u8, m: anytype) (OutOfMemoryError || SendError)!void {
|
pub fn send_notification(self: *const Self, method: []const u8, m: anytype) (OutOfMemoryError || SendError)!void {
|
||||||
var cb = std.ArrayList(u8).init(self.allocator);
|
var cb = std.ArrayList(u8).init(self.allocator);
|
||||||
defer cb.deinit();
|
defer cb.deinit();
|
||||||
try cbor.writeValue(cb.writer(), m);
|
try cbor.writeValue(cb.writer(), m);
|
||||||
return self.send_notification_raw(method, cb.items);
|
return self.send_notification_raw(method, cb.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_notification_raw(self: Self, method: []const u8, cb: []const u8) SendError!void {
|
pub fn send_notification_raw(self: *const Self, method: []const u8, cb: []const u8) SendError!void {
|
||||||
self.pid.send(.{ "NTFY", method, cb }) catch return error.SendFailed;
|
self.pid.send(.{ "NTFY", method, cb }) catch return error.SendFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ files: std.ArrayListUnmanaged(File) = .empty,
|
||||||
pending: std.ArrayListUnmanaged(File) = .empty,
|
pending: std.ArrayListUnmanaged(File) = .empty,
|
||||||
longest_file_path: usize = 0,
|
longest_file_path: usize = 0,
|
||||||
open_time: i64,
|
open_time: i64,
|
||||||
language_servers: std.StringHashMap(LSP),
|
language_servers: std.StringHashMap(*const LSP),
|
||||||
file_language_server: std.StringHashMap(LSP),
|
file_language_server: std.StringHashMap(*const LSP),
|
||||||
tasks: std.ArrayList(Task),
|
tasks: std.ArrayList(Task),
|
||||||
persistent: bool = false,
|
persistent: bool = false,
|
||||||
logger: log.Logger,
|
logger: log.Logger,
|
||||||
|
@ -74,8 +74,8 @@ pub fn init(allocator: std.mem.Allocator, name: []const u8) OutOfMemoryError!Sel
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.name = try allocator.dupe(u8, name),
|
.name = try allocator.dupe(u8, name),
|
||||||
.open_time = std.time.milliTimestamp(),
|
.open_time = std.time.milliTimestamp(),
|
||||||
.language_servers = std.StringHashMap(LSP).init(allocator),
|
.language_servers = std.StringHashMap(*const LSP).init(allocator),
|
||||||
.file_language_server = std.StringHashMap(LSP).init(allocator),
|
.file_language_server = std.StringHashMap(*const LSP).init(allocator),
|
||||||
.tasks = std.ArrayList(Task).init(allocator),
|
.tasks = std.ArrayList(Task).init(allocator),
|
||||||
.logger = log.logger("project"),
|
.logger = log.logger("project"),
|
||||||
.logger_lsp = log.logger("lsp"),
|
.logger_lsp = log.logger("lsp"),
|
||||||
|
@ -261,11 +261,14 @@ pub fn restore_state_v0(self: *Self, data: []const u8) error{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_language_server_instance(self: *Self, language_server: []const u8) StartLspError!LSP {
|
fn get_language_server_instance(self: *Self, language_server: []const u8) StartLspError!*const LSP {
|
||||||
if (self.language_servers.get(language_server)) |lsp| {
|
if (self.language_servers.get(language_server)) |lsp| {
|
||||||
if (!lsp.pid.expired()) return lsp;
|
if (lsp.pid.expired()) {
|
||||||
lsp.deinit();
|
|
||||||
_ = self.language_servers.remove(language_server);
|
_ = self.language_servers.remove(language_server);
|
||||||
|
lsp.deinit();
|
||||||
|
} else {
|
||||||
|
return lsp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const lsp = try LSP.open(self.allocator, self.name, .{ .buf = language_server });
|
const lsp = try LSP.open(self.allocator, self.name, .{ .buf = language_server });
|
||||||
errdefer lsp.deinit();
|
errdefer lsp.deinit();
|
||||||
|
@ -279,7 +282,7 @@ fn get_language_server_instance(self: *Self, language_server: []const u8) StartL
|
||||||
return lsp;
|
return lsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_or_start_language_server(self: *Self, file_path: []const u8, language_server: []const u8) StartLspError!LSP {
|
fn get_or_start_language_server(self: *Self, file_path: []const u8, language_server: []const u8) StartLspError!*const LSP {
|
||||||
const lsp = self.file_language_server.get(file_path) orelse blk: {
|
const lsp = self.file_language_server.get(file_path) orelse blk: {
|
||||||
const new_lsp = try self.get_language_server_instance(language_server);
|
const new_lsp = try self.get_language_server_instance(language_server);
|
||||||
const key = try self.allocator.dupe(u8, file_path);
|
const key = try self.allocator.dupe(u8, file_path);
|
||||||
|
@ -289,7 +292,7 @@ fn get_or_start_language_server(self: *Self, file_path: []const u8, language_ser
|
||||||
return lsp;
|
return lsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_language_server(self: *Self, file_path: []const u8) LspError!LSP {
|
fn get_language_server(self: *Self, file_path: []const u8) LspError!*const LSP {
|
||||||
const lsp = self.file_language_server.get(file_path) orelse return error.NoLsp;
|
const lsp = self.file_language_server.get(file_path) orelse return error.NoLsp;
|
||||||
if (lsp.pid.expired()) {
|
if (lsp.pid.expired()) {
|
||||||
if (self.file_language_server.fetchRemove(file_path)) |kv|
|
if (self.file_language_server.fetchRemove(file_path)) |kv|
|
||||||
|
@ -1510,7 +1513,7 @@ pub fn send_lsp_response(self: *Self, from: tp.pid_ref, cbor_id: []const u8, res
|
||||||
from.send_raw(.{ .buf = cb.items }) catch return error.ClientFailed;
|
from.send_raw(.{ .buf = cb.items }) catch return error.ClientFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_lsp_init_request(self: *Self, lsp: 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) !void {
|
||||||
const handler: struct {
|
const handler: struct {
|
||||||
language_server: []const u8,
|
language_server: []const u8,
|
||||||
lsp: LSP,
|
lsp: LSP,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue