diff --git a/src/DocumentStore.zig b/src/DocumentStore.zig index d78d809..318bd1a 100644 --- a/src/DocumentStore.zig +++ b/src/DocumentStore.zig @@ -921,7 +921,7 @@ pub fn uriFromImportStr(self: *const DocumentStore, allocator: std.mem.Allocator } } -fn tagStoreCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle, comptime name: []const u8) ![]types.CompletionItem { +fn tagStoreCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle, comptime name: []const u8) error{OutOfMemory}![]types.CompletionItem { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -944,11 +944,11 @@ fn tagStoreCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle return result_set.entries.items(.key); } -pub fn errorCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle) ![]types.CompletionItem { +pub fn errorCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle) error{OutOfMemory}![]types.CompletionItem { return try self.tagStoreCompletionItems(arena, handle, "error_completions"); } -pub fn enumCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle) ![]types.CompletionItem { +pub fn enumCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle) error{OutOfMemory}![]types.CompletionItem { return try self.tagStoreCompletionItems(arena, handle, "enum_completions"); } diff --git a/src/Server.zig b/src/Server.zig index 5f750c4..265f823 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -66,8 +66,7 @@ const ClientCapabilities = packed struct { supports_configuration: bool = false, }; -/// TODO remove anyerror -pub const Error = anyerror || std.mem.Allocator.Error || error{ +pub const Error = std.mem.Allocator.Error || error{ ParseError, InvalidRequest, MethodNotFound, @@ -138,7 +137,7 @@ fn sendInternal( maybe_err: ?types.ResponseError, extra_name: []const u8, extra: anytype, -) !void { +) error{OutOfMemory}!void { var buffer = std.ArrayListUnmanaged(u8){}; var writer = buffer.writer(server.allocator); try writer.writeAll( @@ -191,7 +190,7 @@ fn showMessage( }); } -fn generateDiagnostics(server: *Server, handle: DocumentStore.Handle) !types.PublishDiagnosticsParams { +fn generateDiagnostics(server: *Server, handle: DocumentStore.Handle) error{OutOfMemory}!types.PublishDiagnosticsParams { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -205,7 +204,7 @@ fn generateDiagnostics(server: *Server, handle: DocumentStore.Handle) !types.Pub for (tree.errors) |err| { var mem_buffer: [256]u8 = undefined; var fbs = std.io.fixedBufferStream(&mem_buffer); - try tree.renderError(err, fbs.writer()); + tree.renderError(err, fbs.writer()) catch if (std.debug.runtime_safety) unreachable else continue; // if an error occurs here increase buffer size try diagnostics.append(allocator, .{ .range = offsets.tokenToRange(tree, err.token, server.offset_encoding), @@ -218,7 +217,9 @@ fn generateDiagnostics(server: *Server, handle: DocumentStore.Handle) !types.Pub } if (server.config.enable_ast_check_diagnostics and tree.errors.len == 0) { - try getAstCheckDiagnostics(server, handle, &diagnostics); + getAstCheckDiagnostics(server, handle, &diagnostics) catch |err| { + log.err("failed to run ast-check: {}", .{err}); + }; } if (server.config.warn_style) { @@ -485,12 +486,14 @@ fn getAutofixMode(server: *Server) enum { } /// caller owns returned memory. -fn autofix(server: *Server, allocator: std.mem.Allocator, handle: *const DocumentStore.Handle) !std.ArrayListUnmanaged(types.TextEdit) { +fn autofix(server: *Server, allocator: std.mem.Allocator, handle: *const DocumentStore.Handle) error{OutOfMemory}!std.ArrayListUnmanaged(types.TextEdit) { if (!server.config.enable_ast_check_diagnostics) return .{}; if (handle.tree.errors.len != 0) return .{}; var diagnostics = std.ArrayListUnmanaged(types.Diagnostic){}; - try getAstCheckDiagnostics(server, handle.*, &diagnostics); + getAstCheckDiagnostics(server, handle.*, &diagnostics) catch |err| { + log.err("failed to run ast-check: {}", .{err}); + }; var builder = code_actions.Builder{ .arena = server.arena, @@ -1086,7 +1089,7 @@ fn getSymbolFieldAccess( handle: *const DocumentStore.Handle, source_index: usize, loc: offsets.Loc, -) !?analysis.DeclWithHandle { +) error{OutOfMemory}!?analysis.DeclWithHandle { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1167,7 +1170,7 @@ const DeclToCompletionContext = struct { parent_is_type_val: ?bool = null, }; -fn declToCompletion(context: DeclToCompletionContext, decl_handle: analysis.DeclWithHandle) !void { +fn declToCompletion(context: DeclToCompletionContext, decl_handle: analysis.DeclWithHandle) error{OutOfMemory}!void { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1227,7 +1230,7 @@ fn completeLabel( server: *Server, pos_index: usize, handle: *const DocumentStore.Handle, -) ![]types.CompletionItem { +) error{OutOfMemory}![]types.CompletionItem { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1267,7 +1270,7 @@ fn populateSnippedCompletions( } } -fn completeGlobal(server: *Server, pos_index: usize, handle: *const DocumentStore.Handle) ![]types.CompletionItem { +fn completeGlobal(server: *Server, pos_index: usize, handle: *const DocumentStore.Handle) error{OutOfMemory}![]types.CompletionItem { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1290,7 +1293,7 @@ fn completeGlobal(server: *Server, pos_index: usize, handle: *const DocumentStor return completions.toOwnedSlice(server.arena.allocator()); } -fn completeFieldAccess(server: *Server, handle: *const DocumentStore.Handle, source_index: usize, loc: offsets.Loc) !?[]types.CompletionItem { +fn completeFieldAccess(server: *Server, handle: *const DocumentStore.Handle, source_index: usize, loc: offsets.Loc) error{OutOfMemory}!?[]types.CompletionItem { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1312,7 +1315,7 @@ fn completeFieldAccess(server: *Server, handle: *const DocumentStore.Handle, sou return try completions.toOwnedSlice(allocator); } -fn formatDetailledLabel(item: *types.CompletionItem, alloc: std.mem.Allocator) !void { +fn formatDetailledLabel(item: *types.CompletionItem, alloc: std.mem.Allocator) error{OutOfMemory}!void { // NOTE: this is not ideal, we should build a detailled label like we do for label/detail // because this implementation is very loose, nothing is formated properly so we need to clean // things a little bit, wich is quite messy @@ -1478,7 +1481,7 @@ fn formatDetailledLabel(item: *types.CompletionItem, alloc: std.mem.Allocator) ! // logger.info("labelDetails: {s} :: {s}", .{item.labelDetails.?.detail, item.labelDetails.?.description}); } -fn completeError(server: *Server, handle: *const DocumentStore.Handle) ![]types.CompletionItem { +fn completeError(server: *Server, handle: *const DocumentStore.Handle) error{OutOfMemory}![]types.CompletionItem { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1513,7 +1516,7 @@ fn kindToSortScore(kind: types.CompletionItemKind) ?[]const u8 { }; } -fn completeDot(server: *Server, handle: *const DocumentStore.Handle) ![]types.CompletionItem { +fn completeDot(server: *Server, handle: *const DocumentStore.Handle) error{OutOfMemory}![]types.CompletionItem { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1578,7 +1581,7 @@ fn completeFileSystemStringLiteral(allocator: std.mem.Allocator, store: *const D return completions.toOwnedSlice(allocator); } -fn initializeHandler(server: *Server, request: types.InitializeParams) !types.InitializeResult { +fn initializeHandler(server: *Server, request: types.InitializeParams) Error!types.InitializeResult { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1794,7 +1797,7 @@ fn initializeHandler(server: *Server, request: types.InitializeParams) !types.In }; } -fn initializedHandler(server: *Server, notification: types.InitializedParams) !void { +fn initializedHandler(server: *Server, notification: types.InitializedParams) Error!void { _ = notification; if (server.status != .initializing) { @@ -1807,7 +1810,7 @@ fn initializedHandler(server: *Server, notification: types.InitializedParams) !v try server.requestConfiguration(); } -fn shutdownHandler(server: *Server, _: void) !?void { +fn shutdownHandler(server: *Server, _: void) Error!?void { if (server.status != .initialized) return error.InvalidRequest; // received a shutdown request but the server is not initialized! // Technically we should deinitialize first and send possible errors to the client @@ -1826,13 +1829,13 @@ fn exitHandler(server: *Server, _: void) noreturn { std.os.exit(error_code); } -fn cancelRequestHandler(server: *Server, request: types.CancelParams) !void { +fn cancelRequestHandler(server: *Server, request: types.CancelParams) Error!void { _ = server; _ = request; // TODO implement $/cancelRequest } -fn registerCapability(server: *Server, method: []const u8) !void { +fn registerCapability(server: *Server, method: []const u8) Error!void { const allocator = server.arena.allocator(); const id = try std.fmt.allocPrint(allocator, "register-{s}", .{method}); @@ -1851,7 +1854,7 @@ fn registerCapability(server: *Server, method: []const u8) !void { ); } -fn requestConfiguration(server: *Server) !void { +fn requestConfiguration(server: *Server) Error!void { if (server.recording_enabled) { log.info("workspace/configuration are disabled during a recording session!", .{}); return; @@ -1938,7 +1941,7 @@ fn handleConfiguration(server: *Server, json: std.json.Value) error{OutOfMemory} }; } -fn openDocumentHandler(server: *Server, notification: types.DidOpenTextDocumentParams) !void { +fn openDocumentHandler(server: *Server, notification: types.DidOpenTextDocumentParams) Error!void { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1950,7 +1953,7 @@ fn openDocumentHandler(server: *Server, notification: types.DidOpenTextDocumentP } } -fn changeDocumentHandler(server: *Server, notification: types.DidChangeTextDocumentParams) !void { +fn changeDocumentHandler(server: *Server, notification: types.DidChangeTextDocumentParams) Error!void { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -1966,7 +1969,7 @@ fn changeDocumentHandler(server: *Server, notification: types.DidChangeTextDocum } } -fn saveDocumentHandler(server: *Server, notification: types.DidSaveTextDocumentParams) !void { +fn saveDocumentHandler(server: *Server, notification: types.DidSaveTextDocumentParams) Error!void { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2000,7 +2003,7 @@ fn closeDocumentHandler(server: *Server, notification: types.DidCloseTextDocumen server.document_store.closeDocument(notification.textDocument.uri); } -fn willSaveWaitUntilHandler(server: *Server, request: types.WillSaveTextDocumentParams) !?[]types.TextEdit { +fn willSaveWaitUntilHandler(server: *Server, request: types.WillSaveTextDocumentParams) Error!?[]types.TextEdit { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2015,7 +2018,7 @@ fn willSaveWaitUntilHandler(server: *Server, request: types.WillSaveTextDocument return try text_edits.toOwnedSlice(allocator); } -fn semanticTokensFullHandler(server: *Server, request: types.SemanticTokensParams) !?types.SemanticTokens { +fn semanticTokensFullHandler(server: *Server, request: types.SemanticTokensParams) Error!?types.SemanticTokens { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2028,7 +2031,7 @@ fn semanticTokensFullHandler(server: *Server, request: types.SemanticTokensParam return .{ .data = token_array }; } -fn completionHandler(server: *Server, request: types.CompletionParams) !?types.CompletionList { +fn completionHandler(server: *Server, request: types.CompletionParams) Error!?types.CompletionList { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2056,7 +2059,10 @@ fn completionHandler(server: *Server, request: types.CompletionParams) !?types.C const completing = offsets.locToSlice(handle.tree.source, loc); const is_import = pos_context == .import_string_literal; - break :blk try completeFileSystemStringLiteral(server.arena.allocator(), &server.document_store, handle, completing, is_import); + break :blk completeFileSystemStringLiteral(server.arena.allocator(), &server.document_store, handle, completing, is_import) catch |err| { + log.err("failed to get file system completions: {}", .{err}); + return null; + }; }, else => null, }; @@ -2082,7 +2088,7 @@ fn completionHandler(server: *Server, request: types.CompletionParams) !?types.C return .{ .isIncomplete = false, .items = completions }; } -fn signatureHelpHandler(server: *Server, request: types.SignatureHelpParams) !?types.SignatureHelp { +fn signatureHelpHandler(server: *Server, request: types.SignatureHelpParams) Error!?types.SignatureHelp { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2111,7 +2117,7 @@ fn signatureHelpHandler(server: *Server, request: types.SignatureHelpParams) !?t }; } -fn gotoHandler(server: *Server, request: types.TextDocumentPositionParams, resolve_alias: bool) !?types.Location { +fn gotoHandler(server: *Server, request: types.TextDocumentPositionParams, resolve_alias: bool) Error!?types.Location { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2134,7 +2140,7 @@ fn gotoHandler(server: *Server, request: types.TextDocumentPositionParams, resol fn gotoDefinitionHandler( server: *Server, request: types.TextDocumentPositionParams, -) !?types.Location { +) Error!?types.Location { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2144,14 +2150,14 @@ fn gotoDefinitionHandler( fn gotoDeclarationHandler( server: *Server, request: types.TextDocumentPositionParams, -) !?types.Location { +) Error!?types.Location { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); return try server.gotoHandler(request, false); } -fn hoverHandler(server: *Server, request: types.HoverParams) !?types.Hover { +fn hoverHandler(server: *Server, request: types.HoverParams) Error!?types.Hover { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2179,7 +2185,7 @@ fn hoverHandler(server: *Server, request: types.HoverParams) !?types.Hover { return response; } -fn documentSymbolsHandler(server: *Server, request: types.DocumentSymbolParams) !?[]types.DocumentSymbol { +fn documentSymbolsHandler(server: *Server, request: types.DocumentSymbolParams) Error!?[]types.DocumentSymbol { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2188,7 +2194,7 @@ fn documentSymbolsHandler(server: *Server, request: types.DocumentSymbolParams) return try analysis.getDocumentSymbols(server.arena.allocator(), handle.tree, server.offset_encoding); } -fn formattingHandler(server: *Server, request: types.DocumentFormattingParams) !?[]types.TextEdit { +fn formattingHandler(server: *Server, request: types.DocumentFormattingParams) Error!?[]types.TextEdit { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2224,7 +2230,7 @@ fn formattingHandler(server: *Server, request: types.DocumentFormattingParams) ! return text_edits.items; } -fn didChangeConfigurationHandler(server: *Server, request: configuration.DidChangeConfigurationParams) !void { +fn didChangeConfigurationHandler(server: *Server, request: configuration.DidChangeConfigurationParams) Error!void { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2244,13 +2250,15 @@ fn didChangeConfigurationHandler(server: *Server, request: configuration.DidChan } } - try configuration.configChanged(server.config, server.allocator, null); + configuration.configChanged(server.config, server.allocator, null) catch |err| { + log.err("failed to update config: {}", .{err}); + }; } else if (server.client_capabilities.supports_configuration) { try server.requestConfiguration(); } } -fn renameHandler(server: *Server, request: types.RenameParams) !?types.WorkspaceEdit { +fn renameHandler(server: *Server, request: types.RenameParams) Error!?types.WorkspaceEdit { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2258,7 +2266,7 @@ fn renameHandler(server: *Server, request: types.RenameParams) !?types.Workspace return if (response) |rep| rep.rename else null; } -fn referencesHandler(server: *Server, request: types.ReferenceParams) !?[]types.Location { +fn referencesHandler(server: *Server, request: types.ReferenceParams) Error!?[]types.Location { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2266,7 +2274,7 @@ fn referencesHandler(server: *Server, request: types.ReferenceParams) !?[]types. return if (response) |rep| rep.references else null; } -fn documentHighlightHandler(server: *Server, request: types.DocumentHighlightParams) !?[]types.DocumentHighlight { +fn documentHighlightHandler(server: *Server, request: types.DocumentHighlightParams) Error!?[]types.DocumentHighlight { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2302,7 +2310,7 @@ const GeneralReferencesResponse = union { highlight: []types.DocumentHighlight, }; -fn generalReferencesHandler(server: *Server, request: GeneralReferencesRequest) !?GeneralReferencesResponse { +fn generalReferencesHandler(server: *Server, request: GeneralReferencesRequest) Error!?GeneralReferencesResponse { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2387,7 +2395,7 @@ fn isPositionBefore(lhs: types.Position, rhs: types.Position) bool { } } -fn inlayHintHandler(server: *Server, request: types.InlayHintParams) !?[]types.InlayHint { +fn inlayHintHandler(server: *Server, request: types.InlayHintParams) Error!?[]types.InlayHint { const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); @@ -2429,7 +2437,7 @@ fn inlayHintHandler(server: *Server, request: types.InlayHintParams) !?[]types.I return visible_hints; } -fn codeActionHandler(server: *Server, request: types.CodeActionParams) !?[]types.CodeAction { +fn codeActionHandler(server: *Server, request: types.CodeActionParams) Error!?[]types.CodeAction { const handle = server.document_store.getHandle(request.textDocument.uri) orelse return null; var builder = code_actions.Builder{ @@ -2442,7 +2450,10 @@ fn codeActionHandler(server: *Server, request: types.CodeActionParams) !?[]types // as of right now, only ast-check errors may get a code action var diagnostics = std.ArrayListUnmanaged(types.Diagnostic){}; if (server.config.enable_ast_check_diagnostics and handle.tree.errors.len == 0) { - try getAstCheckDiagnostics(server, handle.*, &diagnostics); + getAstCheckDiagnostics(server, handle.*, &diagnostics) catch |err| { + log.err("failed to run ast-check: {}", .{err}); + return error.InternalError; + }; } var actions = std.ArrayListUnmanaged(types.CodeAction){}; @@ -2453,7 +2464,7 @@ fn codeActionHandler(server: *Server, request: types.CodeActionParams) !?[]types return actions.items; } -fn foldingRangeHandler(server: *Server, request: types.FoldingRangeParams) !?[]types.FoldingRange { +fn foldingRangeHandler(server: *Server, request: types.FoldingRangeParams) Error!?[]types.FoldingRange { const Token = std.zig.Token; const Node = Ast.Node; const allocator = server.arena.allocator(); @@ -2716,7 +2727,7 @@ pub const SelectionRange = struct { parent: ?*SelectionRange, }; -fn selectionRangeHandler(server: *Server, request: types.SelectionRangeParams) !?[]*SelectionRange { +fn selectionRangeHandler(server: *Server, request: types.SelectionRangeParams) Error!?[]*SelectionRange { const allocator = server.arena.allocator(); const handle = server.document_store.getHandle(request.textDocument.uri) orelse return null; @@ -2906,26 +2917,23 @@ pub fn processJsonRpc( var parser = std.json.Parser.init(server.arena.allocator(), false); defer parser.deinit(); - var tree = parser.parse(json) catch { - log.err("failed to parse message!", .{}); + var tree = parser.parse(json) catch |err| { + log.err("failed to parse message: {}", .{err}); return; // maybe panic? }; defer tree.deinit(); - const message = Message.fromJsonValueTree(tree) catch { - log.err("failed to parse message!", .{}); + const message = Message.fromJsonValueTree(tree) catch |err| { + log.err("failed to parse message: {}", .{err}); return; // maybe panic? }; - server.processMessage(message) catch |err| { - log.err("got {} while processing message!", .{err}); // TODO include message information - switch (message) { - .RequestMessage => |request| server.sendResponseError(request.id, .{ - .code = @errorToInt(err), - .message = @errorName(err), - }), - else => {}, - } + server.processMessage(message) catch |err| switch (message) { + .RequestMessage => |request| server.sendResponseError(request.id, .{ + .code = @errorToInt(err), + .message = @errorName(err), + }), + else => {}, }; } @@ -3039,7 +3047,10 @@ fn processMessage(server: *Server, message: Message) Error!void { const ParamsType = handler_info.params[1].type.?; // TODO add error message on null const params: ParamsType = tres.parse(ParamsType, message.params().?, server.arena.allocator()) catch return error.InternalError; - const response = handler(server, params) catch return error.InternalError; + const response = handler(server, params) catch |err| { + log.err("got {} error while handling {s}", .{ err, method }); + return error.InternalError; + }; if (@TypeOf(response) == void) return; diff --git a/src/analysis.zig b/src/analysis.zig index 7c1879f..c7dca19 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -1680,7 +1680,7 @@ pub fn getPositionContext(allocator: std.mem.Allocator, text: []const u8, doc_in return if (tok.tag == .identifier) PositionContext{ .var_access = tok.loc } else .empty; } -fn addOutlineNodes(allocator: std.mem.Allocator, tree: Ast, child: Ast.Node.Index, context: *GetDocumentSymbolsContext) anyerror!void { +fn addOutlineNodes(allocator: std.mem.Allocator, tree: Ast, child: Ast.Node.Index, context: *GetDocumentSymbolsContext) error{OutOfMemory}!void { switch (tree.nodes.items(.tag)[child]) { .string_literal, .number_literal, @@ -1825,7 +1825,7 @@ const GetDocumentSymbolsContext = struct { encoding: offsets.Encoding, }; -fn getDocumentSymbolsInternal(allocator: std.mem.Allocator, tree: Ast, node: Ast.Node.Index, context: *GetDocumentSymbolsContext) anyerror!void { +fn getDocumentSymbolsInternal(allocator: std.mem.Allocator, tree: Ast, node: Ast.Node.Index, context: *GetDocumentSymbolsContext) error{OutOfMemory}!void { const name = getDeclName(tree, node) orelse return; if (name.len == 0) return; diff --git a/src/configuration.zig b/src/configuration.zig index ebab2e8..908b21c 100644 --- a/src/configuration.zig +++ b/src/configuration.zig @@ -240,4 +240,4 @@ pub fn findZig(allocator: std.mem.Allocator) !?[]const u8 { return try allocator.dupe(u8, full_path); } return null; -} \ No newline at end of file +}