fix: crash on failed language server startup
This commit is contained in:
parent
724543f7a1
commit
4c156aa4b1
1 changed files with 23 additions and 22 deletions
|
@ -21,7 +21,7 @@ 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(*const LSP),
|
language_servers: std.StringHashMap(*const LSP),
|
||||||
file_language_server: std.StringHashMap(*const LSP),
|
file_language_server_name: std.StringHashMap([]const u8),
|
||||||
tasks: std.ArrayList(Task),
|
tasks: std.ArrayList(Task),
|
||||||
persistent: bool = false,
|
persistent: bool = false,
|
||||||
logger: log.Logger,
|
logger: log.Logger,
|
||||||
|
@ -79,7 +79,7 @@ pub fn init(allocator: std.mem.Allocator, name: []const u8) OutOfMemoryError!Sel
|
||||||
.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(*const LSP).init(allocator),
|
.language_servers = std.StringHashMap(*const LSP).init(allocator),
|
||||||
.file_language_server = std.StringHashMap(*const LSP).init(allocator),
|
.file_language_server_name = std.StringHashMap([]const u8).init(allocator),
|
||||||
.tasks = .empty,
|
.tasks = .empty,
|
||||||
.logger = log.logger("project"),
|
.logger = log.logger("project"),
|
||||||
.logger_lsp = log.logger("lsp"),
|
.logger_lsp = log.logger("lsp"),
|
||||||
|
@ -91,9 +91,10 @@ pub fn deinit(self: *Self) void {
|
||||||
if (self.walker) |pid| pid.send(.{"stop"}) catch {};
|
if (self.walker) |pid| pid.send(.{"stop"}) catch {};
|
||||||
if (self.workspace) |p| self.allocator.free(p);
|
if (self.workspace) |p| self.allocator.free(p);
|
||||||
if (self.branch) |p| self.allocator.free(p);
|
if (self.branch) |p| self.allocator.free(p);
|
||||||
var i_ = self.file_language_server.iterator();
|
var i_ = self.file_language_server_name.iterator();
|
||||||
while (i_.next()) |p| {
|
while (i_.next()) |p| {
|
||||||
self.allocator.free(p.key_ptr.*);
|
self.allocator.free(p.key_ptr.*);
|
||||||
|
self.allocator.free(p.value_ptr.*);
|
||||||
}
|
}
|
||||||
var i = self.language_servers.iterator();
|
var i = self.language_servers.iterator();
|
||||||
while (i.next()) |p| {
|
while (i.next()) |p| {
|
||||||
|
@ -274,15 +275,19 @@ pub fn restore_state_v0(self: *Self, data: []const u8) error{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_language_server_instance(self: *Self, language_server: []const u8) StartLspError!*const LSP {
|
fn get_existing_language_server(self: *Self, language_server: []const u8) ?*const LSP {
|
||||||
if (self.language_servers.get(language_server)) |lsp| {
|
if (self.language_servers.get(language_server)) |lsp| {
|
||||||
if (lsp.pid.expired()) {
|
if (!lsp.pid.expired()) return lsp;
|
||||||
_ = self.language_servers.remove(language_server);
|
if (self.language_servers.fetchRemove(language_server)) |kv| {
|
||||||
lsp.deinit();
|
self.allocator.free(kv.key);
|
||||||
} else {
|
kv.value.deinit();
|
||||||
return lsp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_language_server_instance(self: *Self, language_server: []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 });
|
const lsp = try LSP.open(self.allocator, self.name, .{ .buf = language_server });
|
||||||
errdefer lsp.deinit();
|
errdefer lsp.deinit();
|
||||||
const uri = try self.make_URI(null);
|
const uri = try self.make_URI(null);
|
||||||
|
@ -290,29 +295,25 @@ fn get_language_server_instance(self: *Self, language_server: []const u8) StartL
|
||||||
const basename_begin = std.mem.lastIndexOfScalar(u8, self.name, std.fs.path.sep);
|
const basename_begin = std.mem.lastIndexOfScalar(u8, self.name, std.fs.path.sep);
|
||||||
const basename = if (basename_begin) |begin| self.name[begin + 1 ..] else self.name;
|
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);
|
||||||
try self.language_servers.put(try self.allocator.dupe(u8, language_server), lsp);
|
try self.language_servers.put(try self.allocator.dupe(u8, language_server), lsp);
|
||||||
return 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) StartLspError!*const LSP {
|
||||||
const lsp = self.file_language_server.get(file_path) orelse blk: {
|
if (self.file_language_server_name.get(file_path)) |lsp_name|
|
||||||
const new_lsp = try self.get_language_server_instance(language_server);
|
return self.get_existing_language_server(lsp_name) orelse error.LspFailed;
|
||||||
const key = try self.allocator.dupe(u8, file_path);
|
const lsp = try self.get_language_server_instance(language_server);
|
||||||
try self.file_language_server.put(key, new_lsp);
|
const key = try self.allocator.dupe(u8, file_path);
|
||||||
break :blk new_lsp;
|
const value = try self.allocator.dupe(u8, language_server);
|
||||||
};
|
try self.file_language_server_name.put(key, value);
|
||||||
return lsp;
|
return lsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_language_server(self: *Self, file_path: []const u8) LspError!*const 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_name = self.file_language_server_name.get(file_path) orelse return error.NoLsp;
|
||||||
if (lsp.pid.expired()) {
|
return self.get_existing_language_server(lsp_name) orelse error.LspFailed;
|
||||||
if (self.file_language_server.fetchRemove(file_path)) |kv|
|
|
||||||
self.allocator.free(kv.key);
|
|
||||||
return error.LspFailed;
|
|
||||||
}
|
|
||||||
return lsp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_URI(self: *Self, file_path: ?[]const u8) LspError![]const u8 {
|
fn make_URI(self: *Self, file_path: ?[]const u8) LspError![]const u8 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue