fix: remove blocking project manager call on startup
closes #214 The blocking call get_mru_postion to the project mananger may cause a deadlock if the project manager has not started running yet.
This commit is contained in:
parent
739b2a776f
commit
fc3224137d
3 changed files with 114 additions and 12 deletions
65
src/completion.zig
Normal file
65
src/completion.zig
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const tp = @import("thespian");
|
||||||
|
|
||||||
|
const OutOfMemoryError = error{OutOfMemory};
|
||||||
|
const SpawnError = error{ThespianSpawnFailed};
|
||||||
|
|
||||||
|
pub fn send(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
to: tp.pid_ref,
|
||||||
|
m: anytype,
|
||||||
|
ctx: anytype,
|
||||||
|
) (OutOfMemoryError || SpawnError)!void {
|
||||||
|
return RequestContext(@TypeOf(ctx)).send(allocator, to, ctx, tp.message.fmt(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn RequestContext(T: type) type {
|
||||||
|
return struct {
|
||||||
|
receiver: ReceiverT,
|
||||||
|
ctx: T,
|
||||||
|
to: tp.pid,
|
||||||
|
request: tp.message,
|
||||||
|
response: ?tp.message,
|
||||||
|
a: std.mem.Allocator,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
const ReceiverT = tp.Receiver(*@This());
|
||||||
|
|
||||||
|
fn send(a: std.mem.Allocator, to: tp.pid_ref, ctx: T, request: tp.message) (OutOfMemoryError || SpawnError)!void {
|
||||||
|
const self = try a.create(@This());
|
||||||
|
self.* = .{
|
||||||
|
.receiver = undefined,
|
||||||
|
.ctx = if (@hasDecl(T, "clone")) ctx.clone() else ctx,
|
||||||
|
.to = to.clone(),
|
||||||
|
.request = try request.clone(std.heap.c_allocator),
|
||||||
|
.response = null,
|
||||||
|
.a = a,
|
||||||
|
};
|
||||||
|
self.receiver = ReceiverT.init(receive_, self);
|
||||||
|
const proc = try tp.spawn_link(a, self, start, @typeName(@This()));
|
||||||
|
defer proc.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: *@This()) void {
|
||||||
|
if (@hasDecl(T, "deinit")) self.ctx.deinit();
|
||||||
|
std.heap.c_allocator.free(self.request.buf);
|
||||||
|
self.to.deinit();
|
||||||
|
self.a.destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start(self: *@This()) tp.result {
|
||||||
|
_ = tp.set_trap(true);
|
||||||
|
if (@hasDecl(T, "link")) try self.ctx.link();
|
||||||
|
errdefer self.deinit();
|
||||||
|
try self.to.link();
|
||||||
|
try self.to.send_raw(self.request);
|
||||||
|
tp.receive(&self.receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_(self: *@This(), _: tp.pid_ref, m: tp.message) tp.result {
|
||||||
|
defer self.deinit();
|
||||||
|
self.ctx.receive(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
|
return tp.exit_normal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -232,16 +232,13 @@ pub fn update_mru(file_path: []const u8, row: usize, col: usize, ephemeral: bool
|
||||||
return send(.{ "update_mru", project, file_path, row, col });
|
return send(.{ "update_mru", project, file_path, row, col });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mru_position(allocator: std.mem.Allocator, file_path: []const u8) (ProjectManagerError || ProjectError || CallError || cbor.Error)!?Project.FilePos {
|
pub fn get_mru_position(allocator: std.mem.Allocator, file_path: []const u8, ctx: anytype) (ProjectManagerError || ProjectError)!void {
|
||||||
const frame = tracy.initZone(@src(), .{ .name = "get_mru_position" });
|
|
||||||
defer frame.deinit();
|
|
||||||
const project = tp.env.get().str("project");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return error.NoProject;
|
return error.NoProject;
|
||||||
const rsp = try (try get()).pid.call(allocator, request_timeout, .{ "get_mru_position", project, file_path });
|
|
||||||
defer allocator.free(rsp.buf);
|
const cp = @import("completion.zig");
|
||||||
var pos: Project.FilePos = undefined;
|
return cp.send(allocator, (try get()).pid, .{ "get_mru_position", project, file_path }, ctx);
|
||||||
return if (try cbor.match(rsp.buf, .{ tp.extract(&pos.row), tp.extract(&pos.col) })) pos else null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Process = struct {
|
const Process = struct {
|
||||||
|
|
|
@ -115,6 +115,11 @@ pub fn receive(self: *Self, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
var end_line: usize = undefined;
|
var end_line: usize = undefined;
|
||||||
var end_pos: usize = undefined;
|
var end_pos: usize = undefined;
|
||||||
var lines: []const u8 = undefined;
|
var lines: []const u8 = undefined;
|
||||||
|
var same_file: bool = undefined;
|
||||||
|
var goto_args: []const u8 = undefined;
|
||||||
|
var line: i64 = undefined;
|
||||||
|
var column: i64 = undefined;
|
||||||
|
|
||||||
if (try m.match(.{ "REF", tp.extract(&path), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos), tp.extract(&lines) })) {
|
if (try m.match(.{ "REF", tp.extract(&path), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos), tp.extract(&lines) })) {
|
||||||
try self.add_find_in_files_result(.references, path, begin_line, begin_pos, end_line, end_pos, lines, .Information);
|
try self.add_find_in_files_result(.references, path, begin_line, begin_pos, end_line, end_pos, lines, .Information);
|
||||||
return true;
|
return true;
|
||||||
|
@ -139,6 +144,12 @@ pub fn receive(self: *Self, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
.end = .{ .row = end_line, .col = end_pos },
|
.end = .{ .row = end_line, .col = end_pos },
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
} else if (try m.match(.{ "navigate_complete", tp.extract(&same_file), tp.extract(&path), tp.extract(&goto_args), tp.extract(&line), tp.extract(&column) })) {
|
||||||
|
cmds.navigate_complete(self, same_file, path, goto_args, line, column) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
|
return true;
|
||||||
|
} else if (try m.match(.{ "navigate_complete", tp.extract(&same_file), tp.extract(&path), tp.extract(&goto_args), tp.null_, tp.null_ })) {
|
||||||
|
cmds.navigate_complete(self, same_file, path, goto_args, null, null) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return if (try self.floating_views.send(from_, m)) true else self.widgets.send(from_, m);
|
return if (try self.floating_views.send(from_, m)) true else self.widgets.send(from_, m);
|
||||||
}
|
}
|
||||||
|
@ -371,12 +382,42 @@ const cmds = struct {
|
||||||
const same_file = if (self.get_active_file_path()) |fp| std.mem.eql(u8, fp, f) else false;
|
const same_file = if (self.get_active_file_path()) |fp| std.mem.eql(u8, fp, f) else false;
|
||||||
const have_editor_metadata = if (self.buffer_manager.get_buffer_for_file(f)) |_| true else false;
|
const have_editor_metadata = if (self.buffer_manager.get_buffer_for_file(f)) |_| true else false;
|
||||||
|
|
||||||
if (!same_file and !have_editor_metadata and line == null)
|
if (!same_file and !have_editor_metadata and line == null) {
|
||||||
if (try project_manager.get_mru_position(self.allocator, f)) |pos| {
|
const ctx_: struct {
|
||||||
line = @intCast(pos.row);
|
allocator: std.mem.Allocator,
|
||||||
column = @intCast(pos.col);
|
from: tp.pid,
|
||||||
|
same_file: bool,
|
||||||
|
path: []const u8,
|
||||||
|
goto_args: []const u8,
|
||||||
|
|
||||||
|
pub fn deinit(ctx_: *@This()) void {
|
||||||
|
ctx_.from.deinit();
|
||||||
|
ctx_.allocator.free(ctx_.path);
|
||||||
|
ctx_.allocator.free(ctx_.goto_args);
|
||||||
|
}
|
||||||
|
pub fn receive(ctx_: @This(), rsp: tp.message) !void {
|
||||||
|
var line_: ?i64 = null;
|
||||||
|
var column_: ?i64 = null;
|
||||||
|
_ = try cbor.match(rsp.buf, .{ tp.extract(&line_), tp.extract(&column_) });
|
||||||
|
try ctx_.from.send(.{ "navigate_complete", ctx_.same_file, ctx_.path, ctx_.goto_args, line_, column_ });
|
||||||
|
}
|
||||||
|
} = .{
|
||||||
|
.allocator = self.allocator,
|
||||||
|
.from = tp.self_pid().clone(),
|
||||||
|
.same_file = same_file,
|
||||||
|
.path = try self.allocator.dupe(u8, f),
|
||||||
|
.goto_args = try self.allocator.dupe(u8, goto_args),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try project_manager.get_mru_position(self.allocator, f, ctx_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmds.navigate_complete(self, same_file, f, goto_args, line, column);
|
||||||
|
}
|
||||||
|
pub const navigate_meta: Meta = .{ .arguments = &.{.object} };
|
||||||
|
|
||||||
|
fn navigate_complete(self: *Self, same_file: bool, f: []const u8, goto_args: []const u8, line: ?i64, column: ?i64) Result {
|
||||||
if (!same_file) {
|
if (!same_file) {
|
||||||
if (self.get_active_editor()) |editor| {
|
if (self.get_active_editor()) |editor| {
|
||||||
editor.send_editor_jump_source() catch {};
|
editor.send_editor_jump_source() catch {};
|
||||||
|
@ -395,7 +436,6 @@ const cmds = struct {
|
||||||
}
|
}
|
||||||
tui.need_render();
|
tui.need_render();
|
||||||
}
|
}
|
||||||
pub const navigate_meta: Meta = .{ .arguments = &.{.object} };
|
|
||||||
|
|
||||||
pub fn open_help(self: *Self, _: Ctx) Result {
|
pub fn open_help(self: *Self, _: Ctx) Result {
|
||||||
tui.reset_drag_context();
|
tui.reset_drag_context();
|
||||||
|
|
Loading…
Add table
Reference in a new issue