From fc921f10a4a15c9aff6656594b5f22f21864a8bf Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 16 Jun 2020 14:27:00 +0300 Subject: [PATCH] Fix server capabilities, add semantic tokens config option, fix semantic tokens basic implementation --- README.md | 3 ++- src/config.zig | 3 +++ src/main.zig | 32 +++++++++++++++++++------------- src/semantic_tokens.zig | 6 +++--- src/types.zig | 2 +- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d9dd017..9722afd 100644 --- a/README.md +++ b/README.md @@ -52,11 +52,12 @@ The following options are currently available. | Option | Type | Default value | What it Does | | --- | --- | --- | --- | -| `enable_snippets` | `bool` | `false` | Enables snippet completion, set to false for compatibility with language clients that do not support snippets (such as ale). | +| `enable_snippets` | `bool` | `false` | Enables snippet completions when the client also supports them. | | `zig_lib_path` | `?[]const u8` | `null` | zig library path, e.g. `/path/to/zig/lib/zig`, used to analyze std library imports. | | `zig_exe_path` | `?[]const u8` | `null` | zig executable path, e.g. `/path/to/zig/zig`, used to run the custom build runner. If `null`, zig is looked up in `PATH`. Will be used to infer the zig standard library path if none is provided. | | `warn_style` | `bool` | `false` | Enables warnings for style *guideline* mismatches | | `build_runner_path` | `?[]const u8` | `null` | Path to the build_runner.zig file provided by zls. This option must be present in one of the global configuration files to have any effect. `null` is equivalent to `${executable_directory}/build_runner.zig` | +| `enable_semantic_tokens` | `bool` | false | Enables semantic token support when the client also supports it. | ## Usage diff --git a/src/config.zig b/src/config.zig index 2df19cd..efb28f1 100644 --- a/src/config.zig +++ b/src/config.zig @@ -17,3 +17,6 @@ warn_style: bool = false, /// Path to the build_runner.zig file. This option must be present in one of /// the global configuration directories to have any effect. build_runner_path: ?[]const u8 = null, + +/// Semantic token support +enable_semantic_tokens: bool = false, diff --git a/src/main.zig b/src/main.zig index 6c737a7..3a5d0d1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -28,7 +28,7 @@ const ClientCapabilities = struct { var client_capabilities = ClientCapabilities{}; const initialize_response = - \\,"result":{"capabilities":{"signatureHelpProvider":{"triggerCharacters":["(",","]},"textDocumentSync":1,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":","@"]},"documentHighlightProvider":false,"hoverProvider":true,"codeActionProvider":false,"declarationProvider":true,"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":false,"referencesProvider":false,"documentSymbolProvider":true,"colorProvider":false,"documentFormattingProvider":false,"documentRangeFormattingProvider":false,"foldingRangeProvider":false,"selectionRangeProvider":false,"workspaceSymbolProvider":false,"rangeProvider":false,"documentProvider":true},"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":true}},"semanticTokensProvider":{"documentProvider":true, "legend":{"tokenTypes":["type","struct","enum","union","parameter","variable","tagField","field","function","keyword","modifier","comment","string","number","operator","builtin"],"tokenModifiers":["definition","async","documentation"]}}}} + \\,"result": {"capabilities": {"signatureHelpProvider": {"triggerCharacters": ["(",","]},"textDocumentSync": 1,"completionProvider": {"resolveProvider": false,"triggerCharacters": [".",":","@"]},"documentHighlightProvider": false,"hoverProvider": true,"codeActionProvider": false,"declarationProvider": true,"definitionProvider": true,"typeDefinitionProvider": true,"implementationProvider": false,"referencesProvider": false,"documentSymbolProvider": true,"colorProvider": false,"documentFormattingProvider": false,"documentRangeFormattingProvider": false,"foldingRangeProvider": false,"selectionRangeProvider": false,"workspaceSymbolProvider": false,"rangeProvider": false,"documentProvider": true,"workspace": {"workspaceFolders": {"supported": true,"changeNotifications": true}},"semanticTokensProvider": {"documentProvider": true,"legend": {"tokenTypes": ["type","struct","enum","union","parameter","variable","tagField","field","function","keyword","modifier","comment","string","number","operator","builtin"],"tokenModifiers": ["definition","async","documentation"]}}}}} ; const not_implemented_response = @@ -50,6 +50,9 @@ const edit_not_applied_response = const no_completions_response = \\,"result":{"isIncomplete":false,"items":[]}} ; +const no_semantic_tokens_response = + \\,"result":{"data":[]}} +; /// Sends a request or response fn send(reqOrRes: var) !void { @@ -997,20 +1000,23 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config) !v const document = params.getValue("textDocument").?.Object; const uri = document.getValue("uri").?.String; - const handle = document_store.getHandle(uri) orelse { - std.debug.warn("Trying to complete in non existent document {}", .{uri}); - return try respondGeneric(id, no_completions_response); - }; + const this_config = configFromUriOr(uri, config); + if (this_config.enable_semantic_tokens) { + const handle = document_store.getHandle(uri) orelse { + std.debug.warn("Trying to complete in non existent document {}", .{uri}); + return try respondGeneric(id, no_semantic_tokens_response); + }; - // TODO Actually test this in some editor, VSCode won't send me requests -_-'. - const semantic_tokens = @import("semantic_tokens.zig"); - const token_array = try semantic_tokens.writeAllSemanticTokens(allocator, handle.*); - defer allocator.free(token_array); + const semantic_tokens = @import("semantic_tokens.zig"); + const token_array = try semantic_tokens.writeAllSemanticTokens(allocator, handle.*); + defer allocator.free(token_array); - return try send(types.Response{ - .id = id, - .result = .{ .SemanticTokens = .{ .data = token_array } }, - }); + return try send(types.Response{ + .id = id, + .result = .{ .SemanticTokens = .{ .data = token_array } }, + }); + } else + return try respondGeneric(id, no_semantic_tokens_response); } // Autocomplete / Signatures else if (std.mem.eql(u8, method, "textDocument/completion")) { diff --git a/src/semantic_tokens.zig b/src/semantic_tokens.zig index b5a052b..16388a6 100644 --- a/src/semantic_tokens.zig +++ b/src/semantic_tokens.zig @@ -54,15 +54,15 @@ const Builder = struct { fn add(self: *Builder, token: ast.TokenIndex, token_type: TokenType, token_modifiers: TokenModifiers) !void { const start_idx = if (self.current_token) |current_token| - self.tree.token_locs[current_token].start + 1 + self.tree.token_locs[current_token].start else 0; const token_loc = self.tree.token_locs[token]; const delta_loc = self.tree.tokenLocationLoc(start_idx, token_loc); try self.arr.appendSlice(&[_]u32{ - @truncate(u32, if (self.current_token == null) delta_loc.line + 1 else delta_loc.line), - @truncate(u32, delta_loc.column + 1), + @truncate(u32, delta_loc.line), + @truncate(u32, delta_loc.column), @truncate(u32, token_loc.end - token_loc.start), @enumToInt(token_type), token_modifiers.toInt(), diff --git a/src/types.zig b/src/types.zig index 3299c39..5366a4d 100644 --- a/src/types.zig +++ b/src/types.zig @@ -59,7 +59,7 @@ pub const ResponseParams = union(enum) { Location: Location, Hover: Hover, DocumentSymbols: []DocumentSymbol, - SemanticTokens: struct { data: []u32 }, + SemanticTokens: struct { data: []const u32 }, }; /// JSONRPC error