From 0e3806ab98f65b6cbcc7e57d7551dcfd44821100 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 4 Jun 2025 21:33:19 +0200 Subject: [PATCH 01/13] zig: port log.MsgStore to 0.15.0-dev.703+597dd328e --- src/log.zig | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/log.zig b/src/log.zig index 71d3521..4c4e038 100644 --- a/src/log.zig +++ b/src/log.zig @@ -10,9 +10,14 @@ receiver: Receiver, subscriber: ?tp.pid, heap: [32 + 1024]u8, fba: std.heap.FixedBufferAllocator, -msg_store: MsgStoreT, +msg_store: MsgStore, + +const MsgStore = std.DoublyLinkedList; +const MsgStoreEntry = struct { + data: []u8, + node: MsgStore.Node, +}; -const MsgStoreT = std.DoublyLinkedList([]u8); const Receiver = tp.Receiver(*Self); const StartArgs = struct { @@ -38,7 +43,7 @@ fn init(args: StartArgs) !*Self { .subscriber = null, .heap = undefined, .fba = std.heap.FixedBufferAllocator.init(&p.heap), - .msg_store = MsgStoreT{}, + .msg_store = MsgStore{}, }; return p; } @@ -55,17 +60,18 @@ fn log(msg: []const u8) void { fn store(self: *Self, m: tp.message) void { const allocator: std.mem.Allocator = self.fba.allocator(); const buf: []u8 = allocator.alloc(u8, m.len()) catch return; - var node: *MsgStoreT.Node = allocator.create(MsgStoreT.Node) catch return; - node.data = buf; + var msg: *MsgStoreEntry = allocator.create(MsgStoreEntry) catch return; + msg.data = buf; @memcpy(buf, m.buf); - self.msg_store.append(node); + self.msg_store.append(&msg.node); } fn store_send(self: *Self) void { var node = self.msg_store.first; if (self.subscriber) |sub| { while (node) |node_| { - sub.send_raw(tp.message{ .buf = node_.data }) catch return; + const msg: *MsgStoreEntry = @fieldParentPtr("node", node_); + sub.send_raw(tp.message{ .buf = msg.data }) catch return; node = node_.next; } } @@ -73,7 +79,7 @@ fn store_send(self: *Self) void { } fn store_reset(self: *Self) void { - self.msg_store = MsgStoreT{}; + self.msg_store = MsgStore{}; self.fba.reset(); } From 6fb364d64b087a0df6d6038efe0bd1c4ad3a0e0e Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 4 Jun 2025 22:37:21 +0200 Subject: [PATCH 02/13] zig: update to zig-0.15.0-dev.703+597dd328e --- build.zig.version | 2 +- build.zig.zon | 4 ++-- src/buffer/Buffer.zig | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/build.zig.version b/build.zig.version index 930e300..3cfe6f2 100644 --- a/build.zig.version +++ b/build.zig.version @@ -1 +1 @@ -0.14.1 +0.15.0-dev.703+597dd328e diff --git a/build.zig.zon b/build.zig.zon index feb6ad0..e66f66f 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -27,8 +27,8 @@ .hash = "fuzzig-0.1.1-AAAAALNIAQBmbHr-MPalGuR393Vem2pTQXI7_LXeNJgX", }, .vaxis = .{ - .url = "https://github.com/neurocyte/libvaxis/archive/6137cb4c44a7350996f0946a069739e5075d1f23.tar.gz", - .hash = "vaxis-0.1.0-BWNV_HwOCQCw5wTV63hQGSc1QJzsNcytH6sGf1GBc0hP", + .url = "https://github.com/neurocyte/libvaxis/archive/64a29f4f91292bc79dc9afb9a254cbdfb35e29a6.tar.gz", + .hash = "vaxis-0.1.0-BWNV_KEOCQCzedUR1prWhPUcgsRmw8f-r5JBc3s4DLJf", }, .zeit = .{ .url = "https://github.com/rockorager/zeit/archive/8fd203f85f597f16e0a525c1f1ca1e0bffded809.tar.gz", diff --git a/src/buffer/Buffer.zig b/src/buffer/Buffer.zig index c90bf76..b86af65 100644 --- a/src/buffer/Buffer.zig +++ b/src/buffer/Buffer.zig @@ -1222,6 +1222,7 @@ pub const LoadFromFileError = error{ LockViolation, ProcessNotFound, Canceled, + PermissionDenied, }; pub fn load_from_file( @@ -1327,6 +1328,8 @@ pub const StoreToFileError = error{ SystemResources, Unexpected, WouldBlock, + PermissionDenied, + MessageTooBig, }; pub fn store_to_existing_file_const(self: *const Self, file_path: []const u8) StoreToFileError!void { From 4d608d413ad5db398cc4ce7e93defeefdc9c2561 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 18 Jun 2025 10:41:12 +0200 Subject: [PATCH 03/13] build: update to zig-0.15.0-dev.836+080ee25ec --- build.zig.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig.version b/build.zig.version index 3cfe6f2..3e217e6 100644 --- a/build.zig.version +++ b/build.zig.version @@ -1 +1 @@ -0.15.0-dev.703+597dd328e +0.15.0-dev.836+080ee25ec From e28169458ecdeaef564d6dd17b8968e53a3626a6 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Mon, 30 Jun 2025 16:01:44 +0200 Subject: [PATCH 04/13] build: update to zig-0.15.0-dev.877+0adcfd60f --- build.zig.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig.version b/build.zig.version index 3e217e6..aa1059e 100644 --- a/build.zig.version +++ b/build.zig.version @@ -1 +1 @@ -0.15.0-dev.836+080ee25ec +0.15.0-dev.877+0adcfd60f From 0a4c1a57b128967ae39b69a582c1ca30c39f7499 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Tue, 1 Jul 2025 19:48:48 +0200 Subject: [PATCH 05/13] build: update std/debug.zig to zig-0.15.0-dev.877+0adcfd60f --- src/renderer/vaxis/renderer.zig | 2 +- src/renderer/vaxis/std/debug.zig | 64 ++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/renderer/vaxis/renderer.zig b/src/renderer/vaxis/renderer.zig index 8d3cd1f..08130db 100644 --- a/src/renderer/vaxis/renderer.zig +++ b/src/renderer/vaxis/renderer.zig @@ -124,7 +124,7 @@ pub fn install_crash_handler() void { } const act = std.posix.Sigaction{ .handler = .{ .sigaction = handle_crash }, - .mask = std.posix.empty_sigset, + .mask = std.posix.sigemptyset(), .flags = (std.posix.SA.SIGINFO | std.posix.SA.RESTART), }; diff --git a/src/renderer/vaxis/std/debug.zig b/src/renderer/vaxis/std/debug.zig index d155d5a..8608184 100644 --- a/src/renderer/vaxis/std/debug.zig +++ b/src/renderer/vaxis/std/debug.zig @@ -78,13 +78,9 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type { @branchHint(.cold); call("invalid error code", @returnAddress()); } - pub fn castTruncatedData() noreturn { + pub fn integerOutOfBounds() noreturn { @branchHint(.cold); - call("integer cast truncated bits", @returnAddress()); - } - pub fn negativeToUnsigned() noreturn { - @branchHint(.cold); - call("attempt to cast negative value to unsigned integer", @returnAddress()); + call("integer does not fit in destination type", @returnAddress()); } pub fn integerOverflow() noreturn { @branchHint(.cold); @@ -126,9 +122,9 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type { @branchHint(.cold); call("for loop over objects with non-equal lengths", @returnAddress()); } - pub fn memcpyLenMismatch() noreturn { + pub fn copyLenMismatch() noreturn { @branchHint(.cold); - call("@memcpy arguments have non-equal lengths", @returnAddress()); + call("source and destination arguments have non-equal lengths", @returnAddress()); } pub fn memcpyAlias() noreturn { @branchHint(.cold); @@ -165,9 +161,11 @@ pub const sys_can_stack_trace = switch (builtin.cpu.arch) { // `@returnAddress()` in LLVM 10 gives // "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address". + // On Emscripten, Zig only supports `@returnAddress()` in debug builds + // because Emscripten's implementation is very slow. .wasm32, .wasm64, - => native_os == .emscripten, + => native_os == .emscripten and builtin.mode == .Debug, // `@returnAddress()` is unsupported in LLVM 13. .bpfel, @@ -586,15 +584,20 @@ pub fn defaultPanic( // For backends that cannot handle the language features depended on by the // default panic handler, we have a simpler panic handler: - if (builtin.zig_backend == .stage2_wasm or - builtin.zig_backend == .stage2_arm or - builtin.zig_backend == .stage2_aarch64 or - builtin.zig_backend == .stage2_x86 or - (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or - builtin.zig_backend == .stage2_sparc64 or - builtin.zig_backend == .stage2_spirv64) - { - @trap(); + switch (builtin.zig_backend) { + .stage2_aarch64, + .stage2_arm, + .stage2_powerpc, + .stage2_riscv64, + .stage2_spirv, + .stage2_wasm, + .stage2_x86, + => @trap(), + .stage2_x86_64 => switch (builtin.target.ofmt) { + .elf, .macho => {}, + else => @trap(), + }, + else => {}, } switch (builtin.os.tag) { @@ -615,9 +618,9 @@ pub fn defaultPanic( // isn't visible on actual hardware if directly booted into inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| { if (o) |out| { - _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red); - _ = out.outputString(exit_msg); - _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white); + out.setAttribute(.{ .foreground = .red }) catch {}; + _ = out.outputString(exit_msg) catch {}; + out.setAttribute(.{ .foreground = .white }) catch {}; } } @@ -752,7 +755,7 @@ pub const StackIterator = struct { pub fn init(first_address: ?usize, fp: ?usize) StackIterator { if (native_arch.isSPARC()) { // Flush all the register windows on stack. - asm volatile (if (std.Target.sparc.featureSetHas(builtin.cpu.features, .v9)) + asm volatile (if (builtin.cpu.has(.sparc, .v9)) "flushw" else "ta 3" // ST_FLUSH_WINDOWS @@ -905,6 +908,8 @@ pub const StackIterator = struct { } } + if (builtin.omit_frame_pointer) return null; + const fp = if (comptime native_arch.isSPARC()) // On SPARC the offset is positive. (!) math.add(usize, it.fp, fp_offset) catch return null @@ -1371,12 +1376,11 @@ pub fn attachSegfaultHandler() void { windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); return; } - var act = posix.Sigaction{ + const act = posix.Sigaction{ .handler = .{ .sigaction = handleSegfaultPosix }, - .mask = posix.empty_sigset, + .mask = posix.sigemptyset(), .flags = (posix.SA.SIGINFO | posix.SA.RESTART | posix.SA.RESETHAND), }; - updateSegfaultHandler(&act); } @@ -1388,9 +1392,9 @@ fn resetSegfaultHandler() void { } return; } - var act = posix.Sigaction{ + const act = posix.Sigaction{ .handler = .{ .handler = posix.SIG.DFL }, - .mask = posix.empty_sigset, + .mask = posix.sigemptyset(), .flags = 0, }; updateSegfaultHandler(&act); @@ -1504,6 +1508,12 @@ fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(.winapi) c_ } fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) noreturn { + // For backends that cannot handle the language features used by this segfault handler, we have a simpler one, + switch (builtin.zig_backend) { + .stage2_x86_64 => if (builtin.target.ofmt == .coff) @trap(), + else => {}, + } + comptime assert(windows.CONTEXT != void); nosuspend switch (panic_stage) { 0 => { From e5b20974e851b0795c2c2981ca953fb0a984ed0c Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Mon, 14 Jul 2025 20:40:49 +0200 Subject: [PATCH 06/13] build: update to zig-0.15.0-dev.936+fc2c1883b The last pre-writergate version. --- build.zig.version | 2 +- build.zig.zon | 12 ++++++------ src/syntax/build.zig.zon | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build.zig.version b/build.zig.version index aa1059e..ca633d3 100644 --- a/build.zig.version +++ b/build.zig.version @@ -1 +1 @@ -0.15.0-dev.877+0adcfd60f +0.15.0-dev.936+fc2c1883b diff --git a/build.zig.zon b/build.zig.zon index 000a830..a2e2509 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -15,8 +15,8 @@ .hash = "dizzy-1.0.0-AAAAAM1wAAAiDbx_6RwcVEOBk8p2XOu8t9WPNc3K7kBK", }, .thespian = .{ - .url = "https://github.com/neurocyte/thespian/archive/ccdcbbff09f945eec063ebf889581db3e1312107.tar.gz", - .hash = "thespian-0.0.1-owFOjlgaBgCqc3FCnB4Xyg8-9jyIDWgHSJMGx_nt5Kcc", + .url = "https://github.com/neurocyte/thespian/archive/9af61100d08d79ec52e98fa34ea36611dcc1c361.tar.gz", + .hash = "thespian-0.0.1-owFOjlgaBgAwqxQerLVXpy7blPPZjTqdfH9MLf9_v7dt", }, .themes = .{ .url = "https://github.com/neurocyte/flow-themes/releases/download/master-952f9f630ea9544088fd30293666ee0650b7a690/flow-themes.tar.gz", @@ -27,12 +27,12 @@ .hash = "fuzzig-0.1.1-AAAAALNIAQBmbHr-MPalGuR393Vem2pTQXI7_LXeNJgX", }, .vaxis = .{ - .url = "https://github.com/neurocyte/libvaxis/archive/64a29f4f91292bc79dc9afb9a254cbdfb35e29a6.tar.gz", - .hash = "vaxis-0.1.0-BWNV_KEOCQCzedUR1prWhPUcgsRmw8f-r5JBc3s4DLJf", + .url = "https://github.com/neurocyte/libvaxis/archive/2a4137dadbe560b13b712fd3aa8a1c313fdd8c6e.tar.gz", + .hash = "vaxis-0.1.0-BWNV_KMOCQAe8oPD6cCn62Rg7oIVgF8FEWLpcAi7xDZQ", }, .zeit = .{ - .url = "https://github.com/rockorager/zeit/archive/8fd203f85f597f16e0a525c1f1ca1e0bffded809.tar.gz", - .hash = "zeit-0.0.0-AAAAACVbAgAiIzg1rccZU1qOfO_dKQKme7-37xmEQcqc", + .url = "https://github.com/rockorager/zeit/archive/991f38266f86535e68431675e8feb84efa1f011b.tar.gz", + .hash = "zeit-0.6.0-5I6bk0t7AgCPM_cY1DoqJB2pnmG7MMtpdO5IxNpryJDy", }, .win32 = .{ .url = "https://github.com/marlersoft/zigwin32/archive/e8739b32a33ce48a3286aba31918b26a9dfc6ef0.tar.gz", diff --git a/src/syntax/build.zig.zon b/src/syntax/build.zig.zon index 70ca5d8..d8f5c7a 100644 --- a/src/syntax/build.zig.zon +++ b/src/syntax/build.zig.zon @@ -6,12 +6,12 @@ .dependencies = .{ .tree_sitter = .{ - .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-1c3ad59bd98ee430b166054030dac4c46d641e39/source.tar.gz", - .hash = "N-V-__8AANMzUiemOR2eNnrtlMmAGHFqij6VYtDUiaFfn6Dw", + .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-353313ad92324f2e9edc10082ce4768d49e44e7e/source.tar.gz", + .hash = "N-V-__8AAEU0UidDMndETXNGKGW66b0yAu58jXL5dmLbOcfH", }, .cbor = .{ - .url = "https://github.com/neurocyte/cbor/archive/1fccb83c70cd84e1dff57cc53f7db8fb99909a94.tar.gz", - .hash = "cbor-1.0.0-RcQE_HvqAACcrLH7t3IDZOshgY2xqJA_UX330MvwSepb", + .url = "https://github.com/neurocyte/cbor/archive/5ea4b7319146f29bb1aa9acf65982feaba9edc3d.tar.gz", + .hash = "cbor-1.0.0-RcQE_GDyAABovyRXoYFX8zD_NVOLGDc9l5g09-W-svMR", }, }, .paths = .{ From 891945bab1a720a2fe19101c4d62b5ee76c602d9 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Tue, 15 Jul 2025 17:00:06 +0200 Subject: [PATCH 07/13] build: update flow-syntax for 0.15.0-dev.1034+bd97b6618 --- src/syntax/build.zig | 12 ++++++------ src/syntax/build.zig.zon | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/syntax/build.zig b/src/syntax/build.zig index 2b3a149..e287604 100644 --- a/src/syntax/build.zig +++ b/src/syntax/build.zig @@ -14,10 +14,7 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); - const tree_sitter_host_dep = b.dependency("tree_sitter", .{ - .target = b.graph.host, - .optimize = optimize, - }); + const tree_sitter_host_dep = b.dependency("tree_sitter", .{}); const cbor_dep = b.dependency("cbor", .{ .target = target, @@ -26,8 +23,11 @@ pub fn build(b: *std.Build) void { const ts_bin_query_gen = b.addExecutable(.{ .name = "ts_bin_query_gen", - .target = b.graph.host, - .root_source_file = b.path("src/ts_bin_query_gen.zig"), + .root_module = b.createModule(.{ + .root_source_file = b.path("src/ts_bin_query_gen.zig"), + .target = target, + .optimize = optimize, + }), }); ts_bin_query_gen.linkLibC(); ts_bin_query_gen.root_module.addImport("cbor", cbor_dep.module("cbor")); diff --git a/src/syntax/build.zig.zon b/src/syntax/build.zig.zon index d8f5c7a..218a167 100644 --- a/src/syntax/build.zig.zon +++ b/src/syntax/build.zig.zon @@ -6,12 +6,12 @@ .dependencies = .{ .tree_sitter = .{ - .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-353313ad92324f2e9edc10082ce4768d49e44e7e/source.tar.gz", - .hash = "N-V-__8AAEU0UidDMndETXNGKGW66b0yAu58jXL5dmLbOcfH", + .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-f1f032d24f621e2ee4deab1c424d3bf9fb809f6e/source.tar.gz", + .hash = "tree_sitter-0.22.4-150-g7e3f5726-z0LhyN88UicDHlr22vQnOZ3DW9NWN1gOhDwLuCRXvrh2", }, .cbor = .{ - .url = "https://github.com/neurocyte/cbor/archive/5ea4b7319146f29bb1aa9acf65982feaba9edc3d.tar.gz", - .hash = "cbor-1.0.0-RcQE_GDyAABovyRXoYFX8zD_NVOLGDc9l5g09-W-svMR", + .url = "git+https://github.com/neurocyte/cbor#6eccce0b984296e7d05c20d83933cb31530e4fac", + .hash = "cbor-1.0.0-RcQE_N3yAADXjbyvhsmTQ6lf22l1nYgePq5FT8NaC4ic", }, }, .paths = .{ From 4cb6d0af05a95cf86019d064999045b7415c6f75 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Tue, 15 Jul 2025 17:45:42 +0200 Subject: [PATCH 08/13] build: update to zig-0.15.0-dev.1034+bd97b6618 --- build.zig.version | 2 +- build.zig.zon | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.zig.version b/build.zig.version index ca633d3..2e95286 100644 --- a/build.zig.version +++ b/build.zig.version @@ -1 +1 @@ -0.15.0-dev.936+fc2c1883b +0.15.0-dev.1034+bd97b6618 diff --git a/build.zig.zon b/build.zig.zon index a2e2509..d60a43c 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -15,8 +15,8 @@ .hash = "dizzy-1.0.0-AAAAAM1wAAAiDbx_6RwcVEOBk8p2XOu8t9WPNc3K7kBK", }, .thespian = .{ - .url = "https://github.com/neurocyte/thespian/archive/9af61100d08d79ec52e98fa34ea36611dcc1c361.tar.gz", - .hash = "thespian-0.0.1-owFOjlgaBgAwqxQerLVXpy7blPPZjTqdfH9MLf9_v7dt", + .url = "git+https://github.com/neurocyte/thespian#4d317d7bf02eef26da56eddd2d49e46984b50572", + .hash = "thespian-0.0.1-owFOjuEaBgA9zNohtfOqnA8alObpvYjJNNDjEV8dKvLj", }, .themes = .{ .url = "https://github.com/neurocyte/flow-themes/releases/download/master-952f9f630ea9544088fd30293666ee0650b7a690/flow-themes.tar.gz", From 82c431c952e7f17eee3f1b2e493b09833ebdf3ea Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Thu, 17 Jul 2025 11:57:58 +0200 Subject: [PATCH 09/13] update to zig 0.15.0-dev.1048+f43f89a70 --- src/syntax/build.zig | 4 ++-- src/syntax/build.zig.zon | 2 +- src/syntax/src/file_type.zig | 2 +- src/syntax/src/syntax.zig | 8 ++++---- src/syntax/src/treez_dummy.zig | 4 ++-- src/syntax/src/ts_bin_query_gen.zig | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/syntax/build.zig b/src/syntax/build.zig index e287604..4251ae1 100644 --- a/src/syntax/build.zig +++ b/src/syntax/build.zig @@ -25,8 +25,8 @@ pub fn build(b: *std.Build) void { .name = "ts_bin_query_gen", .root_module = b.createModule(.{ .root_source_file = b.path("src/ts_bin_query_gen.zig"), - .target = target, - .optimize = optimize, + .target = b.graph.host, + .optimize = .Debug, }), }); ts_bin_query_gen.linkLibC(); diff --git a/src/syntax/build.zig.zon b/src/syntax/build.zig.zon index 218a167..5d8194d 100644 --- a/src/syntax/build.zig.zon +++ b/src/syntax/build.zig.zon @@ -2,7 +2,7 @@ .name = .flow_syntax, .version = "0.1.0", .fingerprint = 0x3ba2584ea1cec85f, - .minimum_zig_version = "0.14.1", + .minimum_zig_version = "0.15.0-dev.1048+f43f89a70", .dependencies = .{ .tree_sitter = .{ diff --git a/src/syntax/src/file_type.zig b/src/syntax/src/file_type.zig index 88a1494..9faa6fa 100644 --- a/src/syntax/src/file_type.zig +++ b/src/syntax/src/file_type.zig @@ -87,7 +87,7 @@ fn ft_func_name(comptime lang: []const u8) []const u8 { return &func_name; } -pub const LangFn = *const fn () callconv(.C) ?*const treez.Language; +pub const LangFn = *const fn () callconv(.c) ?*const treez.Language; pub const FirstLineMatch = struct { prefix: ?[]const u8 = null, diff --git a/src/syntax/src/syntax.zig b/src/syntax/src/syntax.zig index bd67ccf..cb54b08 100644 --- a/src/syntax/src/syntax.zig +++ b/src/syntax/src/syntax.zig @@ -45,12 +45,12 @@ pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *Q return self; } -pub fn static_create_file_type(allocator: std.mem.Allocator, lang_name: []const u8, query_cache: *QueryCache) !*Self { +pub fn create_file_type_static(allocator: std.mem.Allocator, lang_name: []const u8, query_cache: *QueryCache) !*Self { const file_type = FileType.get_by_name_static(lang_name) orelse return error.NotFound; return create(file_type, allocator, query_cache); } -pub fn static_create_guess_file_type_static(allocator: std.mem.Allocator, content: []const u8, file_path: ?[]const u8, query_cache: *QueryCache) !*Self { +pub fn create_guess_file_type_static(allocator: std.mem.Allocator, content: []const u8, file_path: ?[]const u8, query_cache: *QueryCache) !*Self { const file_type = FileType.guess_static(file_path, content) orelse return error.NotFound; return create(file_type, allocator, query_cache); } @@ -98,7 +98,7 @@ pub fn refresh_from_buffer(self: *Self, buffer: anytype, metrics: anytype) !void const input: Input = .{ .payload = &state, .read = struct { - fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.C) [*:0]const u8 { + fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.c) [*:0]const u8 { const ctx: *State = @ptrCast(@alignCast(payload orelse return "")); const result = ctx.buffer.get_from_pos(.{ .row = position.row, .col = position.column }, &ctx.result_buf, ctx.metrics); bytes_read.* = @intCast(result.len); @@ -124,7 +124,7 @@ pub fn refresh_from_string(self: *Self, content: [:0]const u8) !void { const input: Input = .{ .payload = &state, .read = struct { - fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.C) [*:0]const u8 { + fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.c) [*:0]const u8 { bytes_read.* = 0; const ctx: *State = @ptrCast(@alignCast(payload orelse return "")); const pos = (find_line_begin(ctx.content, position.row) orelse return "") + position.column; diff --git a/src/syntax/src/treez_dummy.zig b/src/syntax/src/treez_dummy.zig index b73b1f4..bee4c42 100644 --- a/src/syntax/src/treez_dummy.zig +++ b/src/syntax/src/treez_dummy.zig @@ -23,12 +23,12 @@ pub const InputEncoding = enum(c_uint) { }; pub const Input = extern struct { payload: ?*anyopaque, - read: ?*const fn (payload: ?*anyopaque, byte_index: u32, position: Point, bytes_read: *u32) callconv(.C) [*:0]const u8, + read: ?*const fn (payload: ?*anyopaque, byte_index: u32, position: Point, bytes_read: *u32) callconv(.c) [*:0]const u8, encoding: InputEncoding, }; pub const Language = struct { var dummy: @This() = .{}; - pub fn LangFn() callconv(.C) ?*const Language { + pub fn LangFn() callconv(.c) ?*const Language { return &dummy; } }; diff --git a/src/syntax/src/ts_bin_query_gen.zig b/src/syntax/src/ts_bin_query_gen.zig index e32c6ef..2584921 100644 --- a/src/syntax/src/ts_bin_query_gen.zig +++ b/src/syntax/src/ts_bin_query_gen.zig @@ -91,7 +91,7 @@ const FileType = struct { highlights: [:0]const u8, injections: ?[:0]const u8, }; -const LangFn = *const fn () callconv(.C) ?*const treez.Language; +const LangFn = *const fn () callconv(.c) ?*const treez.Language; fn load_file_types(comptime Namespace: type) []const FileType { comptime switch (@typeInfo(Namespace)) { From 05d8fe370881ee1ffec8a3629a0c2eea22885e78 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Thu, 17 Jul 2025 11:57:58 +0200 Subject: [PATCH 10/13] update to zig 0.15.0-dev.1048+f43f89a70 --- src/syntax/build.zig | 4 ++-- src/syntax/build.zig.zon | 2 +- src/syntax/src/file_type.zig | 2 +- src/syntax/src/syntax.zig | 8 ++++---- src/syntax/src/treez_dummy.zig | 4 ++-- src/syntax/src/ts_bin_query_gen.zig | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/syntax/build.zig b/src/syntax/build.zig index e287604..4251ae1 100644 --- a/src/syntax/build.zig +++ b/src/syntax/build.zig @@ -25,8 +25,8 @@ pub fn build(b: *std.Build) void { .name = "ts_bin_query_gen", .root_module = b.createModule(.{ .root_source_file = b.path("src/ts_bin_query_gen.zig"), - .target = target, - .optimize = optimize, + .target = b.graph.host, + .optimize = .Debug, }), }); ts_bin_query_gen.linkLibC(); diff --git a/src/syntax/build.zig.zon b/src/syntax/build.zig.zon index 218a167..5d8194d 100644 --- a/src/syntax/build.zig.zon +++ b/src/syntax/build.zig.zon @@ -2,7 +2,7 @@ .name = .flow_syntax, .version = "0.1.0", .fingerprint = 0x3ba2584ea1cec85f, - .minimum_zig_version = "0.14.1", + .minimum_zig_version = "0.15.0-dev.1048+f43f89a70", .dependencies = .{ .tree_sitter = .{ diff --git a/src/syntax/src/file_type.zig b/src/syntax/src/file_type.zig index 88a1494..9faa6fa 100644 --- a/src/syntax/src/file_type.zig +++ b/src/syntax/src/file_type.zig @@ -87,7 +87,7 @@ fn ft_func_name(comptime lang: []const u8) []const u8 { return &func_name; } -pub const LangFn = *const fn () callconv(.C) ?*const treez.Language; +pub const LangFn = *const fn () callconv(.c) ?*const treez.Language; pub const FirstLineMatch = struct { prefix: ?[]const u8 = null, diff --git a/src/syntax/src/syntax.zig b/src/syntax/src/syntax.zig index bd67ccf..cb54b08 100644 --- a/src/syntax/src/syntax.zig +++ b/src/syntax/src/syntax.zig @@ -45,12 +45,12 @@ pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *Q return self; } -pub fn static_create_file_type(allocator: std.mem.Allocator, lang_name: []const u8, query_cache: *QueryCache) !*Self { +pub fn create_file_type_static(allocator: std.mem.Allocator, lang_name: []const u8, query_cache: *QueryCache) !*Self { const file_type = FileType.get_by_name_static(lang_name) orelse return error.NotFound; return create(file_type, allocator, query_cache); } -pub fn static_create_guess_file_type_static(allocator: std.mem.Allocator, content: []const u8, file_path: ?[]const u8, query_cache: *QueryCache) !*Self { +pub fn create_guess_file_type_static(allocator: std.mem.Allocator, content: []const u8, file_path: ?[]const u8, query_cache: *QueryCache) !*Self { const file_type = FileType.guess_static(file_path, content) orelse return error.NotFound; return create(file_type, allocator, query_cache); } @@ -98,7 +98,7 @@ pub fn refresh_from_buffer(self: *Self, buffer: anytype, metrics: anytype) !void const input: Input = .{ .payload = &state, .read = struct { - fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.C) [*:0]const u8 { + fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.c) [*:0]const u8 { const ctx: *State = @ptrCast(@alignCast(payload orelse return "")); const result = ctx.buffer.get_from_pos(.{ .row = position.row, .col = position.column }, &ctx.result_buf, ctx.metrics); bytes_read.* = @intCast(result.len); @@ -124,7 +124,7 @@ pub fn refresh_from_string(self: *Self, content: [:0]const u8) !void { const input: Input = .{ .payload = &state, .read = struct { - fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.C) [*:0]const u8 { + fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.c) [*:0]const u8 { bytes_read.* = 0; const ctx: *State = @ptrCast(@alignCast(payload orelse return "")); const pos = (find_line_begin(ctx.content, position.row) orelse return "") + position.column; diff --git a/src/syntax/src/treez_dummy.zig b/src/syntax/src/treez_dummy.zig index b73b1f4..bee4c42 100644 --- a/src/syntax/src/treez_dummy.zig +++ b/src/syntax/src/treez_dummy.zig @@ -23,12 +23,12 @@ pub const InputEncoding = enum(c_uint) { }; pub const Input = extern struct { payload: ?*anyopaque, - read: ?*const fn (payload: ?*anyopaque, byte_index: u32, position: Point, bytes_read: *u32) callconv(.C) [*:0]const u8, + read: ?*const fn (payload: ?*anyopaque, byte_index: u32, position: Point, bytes_read: *u32) callconv(.c) [*:0]const u8, encoding: InputEncoding, }; pub const Language = struct { var dummy: @This() = .{}; - pub fn LangFn() callconv(.C) ?*const Language { + pub fn LangFn() callconv(.c) ?*const Language { return &dummy; } }; diff --git a/src/syntax/src/ts_bin_query_gen.zig b/src/syntax/src/ts_bin_query_gen.zig index e32c6ef..2584921 100644 --- a/src/syntax/src/ts_bin_query_gen.zig +++ b/src/syntax/src/ts_bin_query_gen.zig @@ -91,7 +91,7 @@ const FileType = struct { highlights: [:0]const u8, injections: ?[:0]const u8, }; -const LangFn = *const fn () callconv(.C) ?*const treez.Language; +const LangFn = *const fn () callconv(.c) ?*const treez.Language; fn load_file_types(comptime Namespace: type) []const FileType { comptime switch (@typeInfo(Namespace)) { From de68c1a5d40edef2a70e02fa872f154cdad7ab97 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Fri, 18 Jul 2025 10:46:02 +0200 Subject: [PATCH 11/13] fix: remove run_async from flow mode add_cursor_all_matches binding The extra run_async prevents the keybind hint from matching the add_cursor_all_matches command. Not sure why it was bound to run_async anyway so I'll just remove it. --- src/keybind/builtin/flow.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/keybind/builtin/flow.json b/src/keybind/builtin/flow.json index 2a6641b..03f7a9f 100644 --- a/src/keybind/builtin/flow.json +++ b/src/keybind/builtin/flow.json @@ -89,8 +89,8 @@ ["ctrl+shift+d", "dupe_down"], ["ctrl+shift+z", "redo"], ["ctrl+shift+w", "close_file_without_saving"], - ["ctrl+shift+l", "run_async", "add_cursor_all_matches"], - ["ctrl+shift+i", "run_async", "toggle_inspector_view"], + ["ctrl+shift+l", "add_cursor_all_matches"], + ["ctrl+shift+i", "toggle_inspector_view"], ["ctrl+shift+m", "show_diagnostics"], ["ctrl+shift+enter", "smart_insert_line_before"], ["ctrl+shift+end", "select_buffer_end"], From efdad96054b533d954a8c9726eef9e6d2ecc4799 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Sat, 19 Jul 2025 00:03:30 +0200 Subject: [PATCH 12/13] refactor: improve create pattern to avoid leaks --- src/EventHandler.zig | 1 + src/LSP.zig | 1 + src/buffer/Buffer.zig | 3 +++ src/diff.zig | 1 + src/keybind/keybind.zig | 2 +- src/project_manager.zig | 2 ++ src/ripgrep.zig | 1 + src/service_template.zig | 1 + src/shell.zig | 1 + src/syntax/src/QueryCache.zig | 1 + src/syntax/src/syntax.zig | 6 +++++- src/syntax/src/ts_serializer.zig | 1 + src/tui/Button.zig | 2 ++ src/tui/InputBox.zig | 3 ++- src/tui/Menu.zig | 1 + src/tui/ModalBackground.zig | 1 + src/tui/Widget.zig | 1 + src/tui/WidgetList.zig | 9 ++++++--- src/tui/editor.zig | 3 ++- src/tui/editor_gutter.zig | 3 ++- src/tui/filelist_view.zig | 3 ++- src/tui/home.zig | 6 +++++- src/tui/info_view.zig | 3 ++- src/tui/inputview.zig | 3 ++- src/tui/inspector_view.zig | 3 ++- src/tui/logview.zig | 3 ++- src/tui/mainview.zig | 1 + src/tui/mode/mini/buffer.zig | 3 ++- src/tui/mode/mini/file_browser.zig | 3 ++- src/tui/mode/mini/find.zig | 3 ++- src/tui/mode/mini/find_in_files.zig | 3 ++- src/tui/mode/mini/goto.zig | 3 ++- src/tui/mode/mini/move_to_char.zig | 3 ++- src/tui/mode/overlay/open_recent.zig | 3 ++- src/tui/mode/overlay/palette.zig | 3 ++- src/tui/scrollbar_v.zig | 3 ++- src/tui/status/blank.zig | 3 ++- src/tui/status/clock.zig | 3 ++- src/tui/status/keybindstate.zig | 3 ++- src/tui/status/keystate.zig | 3 ++- src/tui/status/minilog.zig | 3 ++- src/tui/status/modstate.zig | 3 ++- src/tui/status/selectionstate.zig | 3 ++- src/tui/status/tabs.zig | 2 ++ src/tui/tui.zig | 3 +++ src/walk_tree.zig | 1 + 46 files changed, 90 insertions(+), 30 deletions(-) diff --git a/src/EventHandler.zig b/src/EventHandler.zig index 879ba12..0d5f1d7 100644 --- a/src/EventHandler.zig +++ b/src/EventHandler.zig @@ -118,6 +118,7 @@ pub fn send(self: Self, from_: tp.pid_ref, m: tp.message) tp.result { pub fn empty(allocator: Allocator) !Self { const child: type = struct {}; const widget = try allocator.create(child); + errdefer allocator.destroy(widget); widget.* = .{}; return .{ .ptr = widget, diff --git a/src/LSP.zig b/src/LSP.zig index b224f4f..4fe9952 100644 --- a/src/LSP.zig +++ b/src/LSP.zig @@ -144,6 +144,7 @@ const Process = struct { return error.InvalidLspCommand; } const self = try allocator.create(Process); + errdefer allocator.destroy(self); var sp_tag_ = std.ArrayList(u8).init(allocator); defer sp_tag_.deinit(); try sp_tag_.appendSlice(tag); diff --git a/src/buffer/Buffer.zig b/src/buffer/Buffer.zig index 0c8e5c4..9e8f09b 100644 --- a/src/buffer/Buffer.zig +++ b/src/buffer/Buffer.zig @@ -159,6 +159,7 @@ pub const Leaf = struct { if (piece.len == 0) return if (!bol and !eol) &empty_leaf else if (bol and !eol) &empty_bol_leaf else if (!bol and eol) &empty_eol_leaf else &empty_line_leaf; const node = try allocator.create(Node); + errdefer allocator.destroy(node); node.* = .{ .leaf = .{ .buf = piece, .bol = bol, .eol = eol } }; return node; } @@ -267,6 +268,7 @@ const Node = union(enum) { fn new(allocator: Allocator, l: *const Node, r: *const Node) !*const Node { const node = try allocator.create(Node); + errdefer allocator.destroy(node); const l_weights_sum = l.weights_sum(); var weights_sum_ = Weights{}; weights_sum_.add(l_weights_sum); @@ -1065,6 +1067,7 @@ const Node = union(enum) { pub fn create(allocator: Allocator) error{OutOfMemory}!*Self { const self = try allocator.create(Self); + errdefer allocator.destroy(self); const arena_a = if (builtin.is_test) allocator else std.heap.page_allocator; self.* = .{ .arena = std.heap.ArenaAllocator.init(arena_a), diff --git a/src/diff.zig b/src/diff.zig index abb2bd6..6c2a970 100644 --- a/src/diff.zig +++ b/src/diff.zig @@ -66,6 +66,7 @@ const Process = struct { pub fn create() !tp.pid { const self = try allocator.create(Process); + errdefer allocator.destroy(self); self.* = .{ .receiver = Receiver.init(Process.receive, self), }; diff --git a/src/keybind/keybind.zig b/src/keybind/keybind.zig index 9ffb43b..f45ef52 100644 --- a/src/keybind/keybind.zig +++ b/src/keybind/keybind.zig @@ -65,7 +65,7 @@ const Handler = struct { bindings: *const BindingSet, fn create(mode_name: []const u8, allocator: std.mem.Allocator, opts: anytype) !Mode { - const self: *@This() = try allocator.create(@This()); + const self = try allocator.create(@This()); errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, diff --git a/src/project_manager.zig b/src/project_manager.zig index 78dde81..c7eadd5 100644 --- a/src/project_manager.zig +++ b/src/project_manager.zig @@ -263,6 +263,7 @@ const Process = struct { fn create() SpawnError!tp.pid { const allocator = std.heap.c_allocator; const self = try allocator.create(Process); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .parent = tp.self_pid().clone(), @@ -755,6 +756,7 @@ fn request_path_files_async(a_: std.mem.Allocator, parent_: tp.pid_ref, project_ fn spawn_link(allocator: std.mem.Allocator, parent: tp.pid_ref, project: *Project, max: usize, path: []const u8) (SpawnError || std.fs.Dir.OpenError)!void { const self = try allocator.create(path_files); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .project_name = try allocator.dupe(u8, project.name), diff --git a/src/ripgrep.zig b/src/ripgrep.zig index c6c14a3..4ea7bd6 100644 --- a/src/ripgrep.zig +++ b/src/ripgrep.zig @@ -85,6 +85,7 @@ const Process = struct { pub fn create(allocator: std.mem.Allocator, query: []const u8, tag: [:0]const u8, stdin_behavior: std.process.Child.StdIo) !tp.pid { const self = try allocator.create(Process); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .query = try allocator.dupe(u8, query), diff --git a/src/service_template.zig b/src/service_template.zig index 17f0a83..92cc265 100644 --- a/src/service_template.zig +++ b/src/service_template.zig @@ -45,6 +45,7 @@ const Process = struct { pub fn create(allocator: std.mem.Allocator) Error!tp.pid { const self = try allocator.create(Process); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .parent = tp.self_pid().clone(), diff --git a/src/shell.zig b/src/shell.zig index cb27221..5869a3d 100644 --- a/src/shell.zig +++ b/src/shell.zig @@ -156,6 +156,7 @@ const Process = struct { return error.InvalidShellArg0; const self = try allocator.create(Process); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .argv = argv, diff --git a/src/syntax/src/QueryCache.zig b/src/syntax/src/QueryCache.zig index 816d8bc..7b011d5 100644 --- a/src/syntax/src/QueryCache.zig +++ b/src/syntax/src/QueryCache.zig @@ -62,6 +62,7 @@ pub const Error = CacheError || QueryParseError || QuerySerializeError; pub fn create(allocator: std.mem.Allocator, opts: struct { lock: bool = false }) !*Self { const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .mutex = if (opts.lock) .{} else null, diff --git a/src/syntax/src/syntax.zig b/src/syntax/src/syntax.zig index bd67ccf..5225155 100644 --- a/src/syntax/src/syntax.zig +++ b/src/syntax/src/syntax.zig @@ -29,9 +29,13 @@ tree: ?*treez.Tree = null, pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *QueryCache) !*Self { const query = try query_cache.get(file_type, .highlights); + errdefer query_cache.release(query, .highlights); const errors_query = try query_cache.get(file_type, .errors); + errdefer query_cache.release(errors_query, .highlights); const injections = try query_cache.get(file_type, .injections); + errdefer if (injections) |injections_| query_cache.release(injections_, .injections); const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .lang = file_type.lang_fn() orelse std.debug.panic("tree-sitter parser function failed for language: {s}", .{file_type.name}), @@ -40,7 +44,6 @@ pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *Q .errors_query = errors_query, .injections = injections, }; - errdefer self.destroy(query_cache); try self.parser.setLanguage(self.lang); return self; } @@ -58,6 +61,7 @@ pub fn static_create_guess_file_type_static(allocator: std.mem.Allocator, conten pub fn destroy(self: *Self, query_cache: *QueryCache) void { if (self.tree) |tree| tree.destroy(); query_cache.release(self.query, .highlights); + query_cache.release(self.errors_query, .highlights); if (self.injections) |injections| query_cache.release(injections, .injections); self.parser.destroy(); self.allocator.destroy(self); diff --git a/src/syntax/src/ts_serializer.zig b/src/syntax/src/ts_serializer.zig index 90c5865..928f60b 100644 --- a/src/syntax/src/ts_serializer.zig +++ b/src/syntax/src/ts_serializer.zig @@ -285,6 +285,7 @@ pub const DeserializeError = error{ pub fn fromCbor(cb: []const u8, allocator: std.mem.Allocator) DeserializeError!struct { *TSQuery, *std.heap.ArenaAllocator } { var arena = try allocator.create(std.heap.ArenaAllocator); + errdefer allocator.destroy(arena); arena.* = std.heap.ArenaAllocator.init(allocator); errdefer arena.deinit(); const query = try arena.allocator().create(TSQuery); diff --git a/src/tui/Button.zig b/src/tui/Button.zig index 60fbc41..1ca9704 100644 --- a/src/tui/Button.zig +++ b/src/tui/Button.zig @@ -48,6 +48,7 @@ pub fn Options(context: type) type { pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts: Options(ctx_type)) error{OutOfMemory}!*State(ctx_type) { const Self = State(ctx_type); const self = try allocator.create(Self); + errdefer allocator.destroy(self); var n = try Plane.init(&opts.pos.opts(@typeName(Self)), parent); errdefer n.deinit(); self.* = .{ @@ -57,6 +58,7 @@ pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts: .opts = opts, }; self.opts.label = try self.allocator.dupe(u8, opts.label); + errdefer allocator.free(self.opts.label); try self.init(); return self; } diff --git a/src/tui/InputBox.zig b/src/tui/InputBox.zig index 71d79b7..1efd3d2 100644 --- a/src/tui/InputBox.zig +++ b/src/tui/InputBox.zig @@ -58,9 +58,10 @@ pub fn Options(context: type) type { pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts: Options(ctx_type)) !Widget { const Self = State(ctx_type); - const self = try allocator.create(Self); var n = try Plane.init(&opts.pos.opts(@typeName(Self)), parent); errdefer n.deinit(); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .parent = parent, .plane = n, diff --git a/src/tui/Menu.zig b/src/tui/Menu.zig index 14f68f1..284dc03 100644 --- a/src/tui/Menu.zig +++ b/src/tui/Menu.zig @@ -56,6 +56,7 @@ pub fn Options(context: type) type { pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts: Options(ctx_type)) !*State(ctx_type) { const self = try allocator.create(State(ctx_type)); + errdefer allocator.destroy(self); const container = try WidgetList.createH(allocator, parent, @typeName(@This()), .dynamic); self.* = .{ .allocator = allocator, diff --git a/src/tui/ModalBackground.zig b/src/tui/ModalBackground.zig index 63444c0..4bc1630 100644 --- a/src/tui/ModalBackground.zig +++ b/src/tui/ModalBackground.zig @@ -59,6 +59,7 @@ pub fn Options(context: type) type { pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Widget, opts: Options(ctx_type)) !*State(ctx_type) { const self = try allocator.create(State(ctx_type)); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .plane = parent.plane.*, diff --git a/src/tui/Widget.zig b/src/tui/Widget.zig index 40060f6..0f0c96f 100644 --- a/src/tui/Widget.zig +++ b/src/tui/Widget.zig @@ -224,6 +224,7 @@ pub fn hover(self: *Self) bool { pub fn empty(allocator: Allocator, parent: Plane, layout_: Layout) !Self { const child: type = struct { plane: Plane, layout: Layout }; const widget = try allocator.create(child); + errdefer allocator.destroy(widget); const n = try Plane.init(&(Box{}).opts("empty"), parent); widget.* = .{ .plane = n, .layout = layout_ }; return .{ diff --git a/src/tui/WidgetList.zig b/src/tui/WidgetList.zig index 98808a9..1024ece 100644 --- a/src/tui/WidgetList.zig +++ b/src/tui/WidgetList.zig @@ -32,21 +32,24 @@ after_render: *const fn (ctx: ?*anyopaque, theme: *const Widget.Theme) void = on on_resize: *const fn (ctx: ?*anyopaque, self: *Self, pos_: Widget.Box) void = on_resize_default, pub fn createH(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout) error{OutOfMemory}!*Self { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = try init(allocator, parent, name, .horizontal, layout_, Box{}); self.plane.hide(); return self; } pub fn createV(allocator: Allocator, parent: Plane, name: [:0]const u8, layout_: Layout) !*Self { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = try init(allocator, parent, name, .vertical, layout_, Box{}); self.plane.hide(); return self; } pub fn createBox(allocator: Allocator, parent: Plane, name: [:0]const u8, dir: Direction, layout_: Layout, box: Box) !*Self { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = try init(allocator, parent, name, dir, layout_, box); self.plane.hide(); return self; diff --git a/src/tui/editor.zig b/src/tui/editor.zig index c4bd75b..dd4c0b4 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -5941,7 +5941,8 @@ pub const EditorWidget = struct { fn create(allocator: Allocator, parent: Plane, buffer_manager: *Buffer.Manager) !Widget { const container = try WidgetList.createH(allocator, parent, "editor.container", .dynamic); - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); try self.init(allocator, container.plane, buffer_manager); try self.commands.init(&self.editor); const editorWidget = Widget.to(self); diff --git a/src/tui/editor_gutter.zig b/src/tui/editor_gutter.zig index f8045d8..77ed19b 100644 --- a/src/tui/editor_gutter.zig +++ b/src/tui/editor_gutter.zig @@ -43,7 +43,8 @@ const Kind = enum { insert, modified, delete }; const Symbol = struct { kind: Kind, line: usize }; pub fn create(allocator: Allocator, parent: Widget, event_source: Widget, editor: *ed.Editor) !Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent.plane.*), diff --git a/src/tui/filelist_view.zig b/src/tui/filelist_view.zig index 4465e8a..6f4e824 100644 --- a/src/tui/filelist_view.zig +++ b/src/tui/filelist_view.zig @@ -47,7 +47,8 @@ const Entry = struct { }; pub fn create(allocator: Allocator, parent: Plane) !Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .plane = try Plane.init(&(Widget.Box{}).opts(name), parent), diff --git a/src/tui/home.zig b/src/tui/home.zig index 42406d0..e00a16a 100644 --- a/src/tui/home.zig +++ b/src/tui/home.zig @@ -81,7 +81,8 @@ const Self = @This(); pub fn create(allocator: std.mem.Allocator, parent: Widget) !Widget { const logger = log.logger("home"); - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); var n = try Plane.init(&(Widget.Box{}).opts("editor"), parent.plane.*); errdefer n.deinit(); @@ -303,6 +304,8 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool { self.position_menu(self.v_center(5, self.menu_len, 5), self.center(x, self.menu_w)); } + if (self.plane.dim_y() < 3 or self.plane.dim_x() < root.version.len + 4) return false; + self.plane.cursor_move_yx( @intCast(self.plane.dim_y() - 2), @intCast(@max(self.plane.dim_x(), root.version.len + 3) - root.version.len - 3), @@ -311,6 +314,7 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool { _ = self.plane.print("{s}", .{root.version}) catch return false; if (builtin.mode == .Debug) { const debug_warning_text = "debug build"; + if (self.plane.dim_y() < 4 or self.plane.dim_x() < debug_warning_text.len + 4) return false; self.plane.cursor_move_yx( @intCast(self.plane.dim_y() - 3), @intCast(@max(self.plane.dim_x(), debug_warning_text.len + 3) - debug_warning_text.len - 3), diff --git a/src/tui/info_view.zig b/src/tui/info_view.zig index de43f50..f67e2df 100644 --- a/src/tui/info_view.zig +++ b/src/tui/info_view.zig @@ -14,7 +14,8 @@ view_rows: usize = 0, lines: std.ArrayList([]const u8), pub fn create(allocator: Allocator, parent: Plane) !Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .plane = try Plane.init(&(Widget.Box{}).opts(name), parent), diff --git a/src/tui/inputview.zig b/src/tui/inputview.zig index a8be882..a955189 100644 --- a/src/tui/inputview.zig +++ b/src/tui/inputview.zig @@ -30,9 +30,10 @@ const Entry = struct { const Buffer = ArrayList(Entry); pub fn create(allocator: Allocator, parent: Plane) !Widget { - const self: *Self = try allocator.create(Self); var n = try Plane.init(&(Widget.Box{}).opts_vscroll(@typeName(Self)), parent); errdefer n.deinit(); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .parent = parent, diff --git a/src/tui/inspector_view.zig b/src/tui/inspector_view.zig index 967648e..6d314d7 100644 --- a/src/tui/inspector_view.zig +++ b/src/tui/inspector_view.zig @@ -26,7 +26,8 @@ const Self = @This(); pub fn create(allocator: Allocator, parent: Plane) !Widget { const editor = tui.get_active_editor() orelse return error.NotFound; - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts_vscroll(name), parent), .editor = editor, diff --git a/src/tui/logview.zig b/src/tui/logview.zig index 02776e0..4c70457 100644 --- a/src/tui/logview.zig +++ b/src/tui/logview.zig @@ -38,7 +38,8 @@ const Level = enum { }; pub fn create(allocator: Allocator, parent: Plane) !Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(name), parent) }; return Widget.to(self); } diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 7fafc9d..f32b90a 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -66,6 +66,7 @@ pub const CreateError = error{ OutOfMemory, ThespianSpawnFailed }; pub fn create(allocator: std.mem.Allocator) CreateError!Widget { const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .plane = tui.plane(), diff --git a/src/tui/mode/mini/buffer.zig b/src/tui/mode/mini/buffer.zig index 35af902..3875d1a 100644 --- a/src/tui/mode/mini/buffer.zig +++ b/src/tui/mode/mini/buffer.zig @@ -21,7 +21,8 @@ pub fn Create(options: type) type { const Self = @This(); pub fn create(allocator: std.mem.Allocator, _: command.Context) !struct { tui.Mode, tui.MiniMode } { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .input = std.ArrayList(u8).init(allocator), diff --git a/src/tui/mode/mini/file_browser.zig b/src/tui/mode/mini/file_browser.zig index 4b5da15..ea6fee7 100644 --- a/src/tui/mode/mini/file_browser.zig +++ b/src/tui/mode/mini/file_browser.zig @@ -35,7 +35,8 @@ pub fn Create(options: type) type { }; pub fn create(allocator: std.mem.Allocator, _: command.Context) !struct { tui.Mode, tui.MiniMode } { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .file_path = std.ArrayList(u8).init(allocator), diff --git a/src/tui/mode/mini/find.zig b/src/tui/mode/mini/find.zig index 30b4976..e04adc0 100644 --- a/src/tui/mode/mini/find.zig +++ b/src/tui/mode/mini/find.zig @@ -28,7 +28,8 @@ commands: Commands = undefined, pub fn create(allocator: Allocator, _: command.Context) !struct { tui.Mode, tui.MiniMode } { const editor = tui.get_active_editor() orelse return error.NotFound; - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .input_ = ArrayList(u8).init(allocator), diff --git a/src/tui/mode/mini/find_in_files.zig b/src/tui/mode/mini/find_in_files.zig index 4680d22..839cd1b 100644 --- a/src/tui/mode/mini/find_in_files.zig +++ b/src/tui/mode/mini/find_in_files.zig @@ -25,7 +25,8 @@ last_input: []u8 = "", commands: Commands = undefined, pub fn create(allocator: Allocator, _: command.Context) !struct { tui.Mode, tui.MiniMode } { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator }; try self.commands.init(self); if (tui.get_active_selection(self.allocator)) |text| { diff --git a/src/tui/mode/mini/goto.zig b/src/tui/mode/mini/goto.zig index c71a0bd..94d5c6d 100644 --- a/src/tui/mode/mini/goto.zig +++ b/src/tui/mode/mini/goto.zig @@ -24,8 +24,9 @@ start: usize, commands: Commands = undefined, pub fn create(allocator: Allocator, _: command.Context) !struct { tui.Mode, tui.MiniMode } { - const self: *Self = try allocator.create(Self); const editor = tui.get_active_editor() orelse return error.NotFound; + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .start = editor.get_primary().cursor.row + 1, diff --git a/src/tui/mode/mini/move_to_char.zig b/src/tui/mode/mini/move_to_char.zig index 950b35e..d32f00c 100644 --- a/src/tui/mode/mini/move_to_char.zig +++ b/src/tui/mode/mini/move_to_char.zig @@ -38,7 +38,8 @@ pub fn create(allocator: Allocator, ctx: command.Context) !struct { tui.Mode, tu const direction: Direction = if (std.mem.indexOf(u8, operation_command, "_left")) |_| .left else .right; const operation: Operation = if (tui.get_active_editor()) |editor| if (editor.get_primary().selection) |_| .select else .move else .move; - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .direction = direction, diff --git a/src/tui/mode/overlay/open_recent.zig b/src/tui/mode/overlay/open_recent.zig index e6a22e9..0c5d687 100644 --- a/src/tui/mode/overlay/open_recent.zig +++ b/src/tui/mode/overlay/open_recent.zig @@ -38,7 +38,8 @@ buffer_manager: ?*BufferManager, pub fn create(allocator: std.mem.Allocator) !tui.Mode { const mv = tui.mainview() orelse return error.NotFound; - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .modal = try ModalBackground.create(*Self, allocator, tui.mainview_widget(), .{ .ctx = self }), diff --git a/src/tui/mode/overlay/palette.zig b/src/tui/mode/overlay/palette.zig index bde1217..926dc65 100644 --- a/src/tui/mode/overlay/palette.zig +++ b/src/tui/mode/overlay/palette.zig @@ -47,7 +47,8 @@ pub fn Create(options: type) type { pub fn create(allocator: std.mem.Allocator) !tui.Mode { const mv = tui.mainview() orelse return error.NotFound; - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .modal = try ModalBackground.create(*Self, allocator, tui.mainview_widget(), .{ diff --git a/src/tui/scrollbar_v.zig b/src/tui/scrollbar_v.zig index 4f83b1b..8f0911a 100644 --- a/src/tui/scrollbar_v.zig +++ b/src/tui/scrollbar_v.zig @@ -27,7 +27,8 @@ style_factory: ?*const fn (self: *Self, theme: *const Widget.Theme) Widget.Theme const Self = @This(); pub fn create(allocator: Allocator, parent: Plane, event_source: ?Widget, event_sink: EventHandler) !Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .event_sink = event_sink, diff --git a/src/tui/status/blank.zig b/src/tui/status/blank.zig index 8901fd0..50e143b 100644 --- a/src/tui/status/blank.zig +++ b/src/tui/status/blank.zig @@ -20,7 +20,8 @@ pub fn Create(comptime layout_: Widget.Layout) @import("widget.zig").CreateFunct break :blk Widget.Layout{ .static = size }; } else break :blk layout_; } else layout_; - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .layout_ = layout__, diff --git a/src/tui/status/clock.zig b/src/tui/status/clock.zig index d6e8391..fe5b6cd 100644 --- a/src/tui/status/clock.zig +++ b/src/tui/status/clock.zig @@ -30,7 +30,8 @@ pub fn create(allocator: std.mem.Allocator, parent: Plane, event_handler: ?Event return error.WidgetInitFailed; }; defer env.deinit(); - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), diff --git a/src/tui/status/keybindstate.zig b/src/tui/status/keybindstate.zig index 3253c19..ea6e709 100644 --- a/src/tui/status/keybindstate.zig +++ b/src/tui/status/keybindstate.zig @@ -12,7 +12,8 @@ plane: Plane, const Self = @This(); pub fn create(allocator: std.mem.Allocator, parent: Plane, _: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), diff --git a/src/tui/status/keystate.zig b/src/tui/status/keystate.zig index ca674a8..afa9ff3 100644 --- a/src/tui/status/keystate.zig +++ b/src/tui/status/keystate.zig @@ -31,7 +31,8 @@ pub const width = idle_msg.len + 20; pub fn create(allocator: Allocator, parent: Plane, _: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget { const frame_rate = tp.env.get().num("frame-rate"); - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .wipe_after_frames = @divTrunc(frame_rate, 2), diff --git a/src/tui/status/minilog.zig b/src/tui/status/minilog.zig index a2644fb..400ac60 100644 --- a/src/tui/status/minilog.zig +++ b/src/tui/status/minilog.zig @@ -27,7 +27,8 @@ const Level = enum { }; pub fn create(allocator: std.mem.Allocator, parent: Plane, event_handler: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .msg = std.ArrayList(u8).init(allocator), diff --git a/src/tui/status/modstate.zig b/src/tui/status/modstate.zig index 4555cef..2136e7c 100644 --- a/src/tui/status/modstate.zig +++ b/src/tui/status/modstate.zig @@ -20,7 +20,8 @@ const Self = @This(); pub const width = 8; pub fn create(allocator: Allocator, parent: Plane, _: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), }; diff --git a/src/tui/status/selectionstate.zig b/src/tui/status/selectionstate.zig index f606a5c..6e0fec9 100644 --- a/src/tui/status/selectionstate.zig +++ b/src/tui/status/selectionstate.zig @@ -19,7 +19,8 @@ on_event: ?EventHandler, const Self = @This(); pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget { - const self: *Self = try allocator.create(Self); + const self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .on_event = event_handler, diff --git a/src/tui/status/tabs.zig b/src/tui/status/tabs.zig index 45a2b69..f3af3d1 100644 --- a/src/tui/status/tabs.zig +++ b/src/tui/status/tabs.zig @@ -54,6 +54,7 @@ pub const Style = @"style.config"; pub fn create(allocator: std.mem.Allocator, parent: Plane, event_handler: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget { const self = try allocator.create(TabBar); + errdefer allocator.destroy(self); self.* = try TabBar.init(allocator, parent, event_handler); return Widget.to(self); } @@ -447,6 +448,7 @@ const spacer = struct { event_handler: ?EventHandler, ) @import("widget.zig").CreateError!Widget { const self: *Self = try allocator.create(Self); + errdefer allocator.destroy(self); self.* = .{ .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .layout_ = .{ .static = self.plane.egc_chunk_width(content, 0, 1) }, diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 6472742..9b82887 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -120,6 +120,9 @@ fn init(allocator: Allocator) InitError!*Self { const frame_clock = try tp.metronome.init(frame_time); var self = try allocator.create(Self); + // don't destroy + // if tui fails it is catastrophic anyway and we don't want to cause nock-on errors + // errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .config_ = conf, diff --git a/src/walk_tree.zig b/src/walk_tree.zig index 5b9a264..ee10d22 100644 --- a/src/walk_tree.zig +++ b/src/walk_tree.zig @@ -21,6 +21,7 @@ pub fn start(a_: std.mem.Allocator, root_path_: []const u8) (SpawnError || std.f fn spawn_link(allocator: std.mem.Allocator, root_path: []const u8) (SpawnError || std.fs.Dir.OpenError)!tp.pid { const self = try allocator.create(tree_walker); + errdefer allocator.destroy(self); self.* = .{ .allocator = allocator, .root_path = try allocator.dupe(u8, root_path), From 5d256413dad6e75da1c71aede6be6c4e3a069a95 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Sat, 19 Jul 2025 00:05:02 +0200 Subject: [PATCH 13/13] refactor: dynamically allocate LSP client handles --- src/LSP.zig | 26 +++++++++++++++++++------- src/Project.zig | 25 ++++++++++++++----------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/LSP.zig b/src/LSP.zig index 4fe9952..2afae60 100644 --- a/src/LSP.zig +++ b/src/LSP.zig @@ -17,22 +17,34 @@ const OutOfMemoryError = error{OutOfMemory}; const SendError = error{SendFailed}; const SpawnError = error{ThespianSpawnFailed}; -pub fn open(allocator: std.mem.Allocator, project: []const u8, cmd: tp.message) (error{ ThespianSpawnFailed, InvalidLspCommand } || cbor.Error)!Self { - return .{ .allocator = allocator, .pid = try Process.create(allocator, project, cmd) }; +pub fn open( + 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.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.deinit(); + self.allocator.destroy(self); } pub fn send_request( - self: Self, + self: *const Self, allocator: std.mem.Allocator, method: []const u8, 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 })); } -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); defer cb.deinit(); try cbor.writeValue(cb.writer(), m); 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; } diff --git a/src/Project.zig b/src/Project.zig index 19e4399..2306d78 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -19,8 +19,8 @@ files: std.ArrayListUnmanaged(File) = .empty, pending: std.ArrayListUnmanaged(File) = .empty, longest_file_path: usize = 0, open_time: i64, -language_servers: std.StringHashMap(LSP), -file_language_server: std.StringHashMap(LSP), +language_servers: std.StringHashMap(*const LSP), +file_language_server: std.StringHashMap(*const LSP), tasks: std.ArrayList(Task), persistent: bool = false, logger: log.Logger, @@ -74,8 +74,8 @@ pub fn init(allocator: std.mem.Allocator, name: []const u8) OutOfMemoryError!Sel .allocator = allocator, .name = try allocator.dupe(u8, name), .open_time = std.time.milliTimestamp(), - .language_servers = std.StringHashMap(LSP).init(allocator), - .file_language_server = std.StringHashMap(LSP).init(allocator), + .language_servers = std.StringHashMap(*const LSP).init(allocator), + .file_language_server = std.StringHashMap(*const LSP).init(allocator), .tasks = std.ArrayList(Task).init(allocator), .logger = log.logger("project"), .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 (!lsp.pid.expired()) return lsp; - lsp.deinit(); - _ = self.language_servers.remove(language_server); + if (lsp.pid.expired()) { + _ = self.language_servers.remove(language_server); + lsp.deinit(); + } else { + return lsp; + } } const lsp = try LSP.open(self.allocator, self.name, .{ .buf = language_server }); errdefer lsp.deinit(); @@ -279,7 +282,7 @@ fn get_language_server_instance(self: *Self, language_server: []const u8) StartL 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 new_lsp = try self.get_language_server_instance(language_server); 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; } -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; if (lsp.pid.expired()) { 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; } -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 { language_server: []const u8, lsp: LSP,