diff --git a/src/LSP.zig b/src/LSP.zig index 58012a3..2afae60 100644 --- a/src/LSP.zig +++ b/src/LSP.zig @@ -67,45 +67,6 @@ pub fn send_notification_raw(self: *const Self, method: []const u8, cb: []const self.pid.send(.{ "NTFY", method, cb }) catch return error.SendFailed; } -pub const ErrorCode = enum(i32) { - - // Defined by JSON-RPC - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603, - - // Defined by LSP - RequestFailed = -32803, - ServerCancelled = -32802, - ContentModified = -32801, - RequestCancelled = -32800, -}; - -pub fn send_response(allocator: std.mem.Allocator, to: tp.pid_ref, cbor_id: []const u8, result: anytype) (SendError || OutOfMemoryError)!void { - var cb = std.ArrayList(u8).init(allocator); - defer cb.deinit(); - const writer = cb.writer(); - try cbor.writeArrayHeader(writer, 3); - try cbor.writeValue(writer, "RSP"); - try writer.writeAll(cbor_id); - try cbor.writeValue(cb.writer(), result); - to.send_raw(.{ .buf = cb.items }) catch return error.SendFailed; -} - -pub fn send_error_response(allocator: std.mem.Allocator, to: tp.pid_ref, cbor_id: []const u8, code: ErrorCode, message: []const u8) (SendError || OutOfMemoryError)!void { - var cb = std.ArrayList(u8).init(allocator); - defer cb.deinit(); - const writer = cb.writer(); - try cbor.writeArrayHeader(writer, 4); - try cbor.writeValue(writer, "ERR"); - try writer.writeAll(cbor_id); - try cbor.writeValue(cb.writer(), code); - try cbor.writeValue(cb.writer(), message); - to.send_raw(.{ .buf = cb.items }) catch return error.SendFailed; -} - pub fn close(self: *Self) void { self.deinit(); } @@ -291,8 +252,6 @@ const Process = struct { var err: []const u8 = ""; var code: u32 = 0; var cbor_id: []const u8 = ""; - var error_code: ErrorCode = undefined; - var message: []const u8 = ""; if (try cbor.match(m.buf, .{ "REQ", "initialize", tp.extract(&bytes) })) { try self.send_request(from, "initialize", bytes); @@ -303,8 +262,6 @@ const Process = struct { } } else if (try cbor.match(m.buf, .{ "RSP", tp.extract_cbor(&cbor_id), tp.extract_cbor(&bytes) })) { try self.send_response(cbor_id, bytes); - } else if (try cbor.match(m.buf, .{ "ERR", tp.extract_cbor(&cbor_id), tp.extract(&error_code), tp.extract(&message) })) { - try self.send_error_response(cbor_id, error_code, message); } else if (try cbor.match(m.buf, .{ "NTFY", "initialized", tp.extract(&bytes) })) { self.state = .running; try self.send_notification("initialized", bytes); @@ -525,39 +482,6 @@ const Process = struct { self.write_log("### SEND response:\n{s}\n###\n", .{output.items}); } - fn send_error_response(self: *Process, cbor_id: []const u8, error_code: ErrorCode, message: []const u8) (error{Closed} || SendError || cbor.Error || cbor.JsonEncodeError)!void { - const sp = if (self.sp) |*sp| sp else return error.Closed; - - var msg = std.ArrayList(u8).init(self.allocator); - defer msg.deinit(); - const msg_writer = msg.writer(); - try cbor.writeMapHeader(msg_writer, 3); - try cbor.writeValue(msg_writer, "jsonrpc"); - try cbor.writeValue(msg_writer, "2.0"); - try cbor.writeValue(msg_writer, "id"); - try msg_writer.writeAll(cbor_id); - try cbor.writeValue(msg_writer, "error"); - try cbor.writeMapHeader(msg_writer, 2); - try cbor.writeValue(msg_writer, "code"); - try cbor.writeValue(msg_writer, @intFromEnum(error_code)); - try cbor.writeValue(msg_writer, "message"); - try cbor.writeValue(msg_writer, message); - - const json = try cbor.toJsonAlloc(self.allocator, msg.items); - defer self.allocator.free(json); - var output = std.ArrayList(u8).init(self.allocator); - defer output.deinit(); - const writer = output.writer(); - const terminator = "\r\n"; - const content_length = json.len + terminator.len; - try writer.print("Content-Length: {d}\r\nContent-Type: application/vscode-jsonrpc; charset=utf-8\r\n\r\n", .{content_length}); - _ = try writer.write(json); - _ = try writer.write(terminator); - - sp.send(output.items) catch return error.SendFailed; - self.write_log("### SEND error response:\n{s}\n###\n", .{output.items}); - } - fn send_notification(self: *Process, method: []const u8, params_cb: []const u8) Error!void { const sp = if (self.sp) |*sp| sp else return error.Closed; diff --git a/src/Project.zig b/src/Project.zig index f9da66c..2306d78 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -1494,16 +1494,23 @@ pub fn show_message(self: *Self, _: tp.pid_ref, params_cb: []const u8) !void { pub fn register_capability(self: *Self, from: tp.pid_ref, cbor_id: []const u8, params_cb: []const u8) ClientError!void { _ = params_cb; - return LSP.send_response(self.allocator, from, cbor_id, null) catch error.ClientFailed; + return self.send_lsp_response(from, cbor_id, null); } pub fn workDoneProgress_create(self: *Self, from: tp.pid_ref, cbor_id: []const u8, params_cb: []const u8) ClientError!void { _ = params_cb; - return LSP.send_response(self.allocator, from, cbor_id, null) catch error.ClientFailed; + return self.send_lsp_response(from, cbor_id, null); } -pub fn unsupported_lsp_request(self: *Self, from: tp.pid_ref, cbor_id: []const u8, method: []const u8) ClientError!void { - return LSP.send_error_response(self.allocator, from, cbor_id, LSP.ErrorCode.MethodNotFound, method) catch error.ClientFailed; +pub fn send_lsp_response(self: *Self, from: tp.pid_ref, cbor_id: []const u8, result: anytype) ClientError!void { + var cb = std.ArrayList(u8).init(self.allocator); + defer cb.deinit(); + const writer = cb.writer(); + try cbor.writeArrayHeader(writer, 3); + try cbor.writeValue(writer, "RSP"); + try writer.writeAll(cbor_id); + try cbor.writeValue(cb.writer(), result); + from.send_raw(.{ .buf = cb.items }) catch return error.ClientFailed; } 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 { diff --git a/src/project_manager.zig b/src/project_manager.zig index a179c1e..c7eadd5 100644 --- a/src/project_manager.zig +++ b/src/project_manager.zig @@ -620,11 +620,11 @@ const Process = struct { project.register_capability(from, cbor_id, params_cb) else if (std.mem.eql(u8, method, "window/workDoneProgress/create")) project.workDoneProgress_create(from, cbor_id, params_cb) - else { + else blk: { const params = try cbor.toJsonAlloc(self.allocator, params_cb); defer self.allocator.free(params); - self.logger.print("unsupported LSP request: {s} -> {s}", .{ method, params }); - project.unsupported_lsp_request(from, cbor_id, method) catch {}; + self.logger.print_err("lsp", "unsupported LSP request: {s} -> {s}", .{ method, params }); + break :blk error.Unsupported; }; }