Correctly handle utf16 offsets for semantic tokens
This commit is contained in:
parent
78a7d79c39
commit
9bed369797
11
src/main.zig
11
src/main.zig
@ -86,6 +86,7 @@ const ClientCapabilities = struct {
|
||||
};
|
||||
|
||||
var client_capabilities = ClientCapabilities{};
|
||||
var offset_encoding = offsets.Encoding.utf16;
|
||||
|
||||
const initialize_response =
|
||||
\\,"result": {"capabilities": {"signatureHelpProvider": {"triggerCharacters": ["(",","]},"textDocumentSync": 1,"renameProvider":true,"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": true,"documentRangeFormattingProvider": false,"foldingRangeProvider": false,"selectionRangeProvider": false,"workspaceSymbolProvider": false,"rangeProvider": false,"documentProvider": true,"workspace": {"workspaceFolders": {"supported": true,"changeNotifications": true}},"semanticTokensProvider": {"documentProvider": true,"legend": {"tokenTypes": ["namespace","type","struct","enum","union","parameter","variable","tagField","field","errorTag","function","keyword","comment","string","number","operator","builtin","label"],"tokenModifiers": ["definition","async","documentation", "generic"]}}}}}
|
||||
@ -1067,7 +1068,7 @@ fn semanticTokensHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, r
|
||||
};
|
||||
|
||||
const semantic_tokens = @import("semantic_tokens.zig");
|
||||
const token_array = try semantic_tokens.writeAllSemanticTokens(arena, &document_store, handle);
|
||||
const token_array = try semantic_tokens.writeAllSemanticTokens(arena, &document_store, handle, offset_encoding);
|
||||
defer allocator.free(token_array);
|
||||
|
||||
return try send(arena, types.Response{
|
||||
@ -1085,7 +1086,7 @@ fn completionHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req:
|
||||
};
|
||||
|
||||
if (req.params.position.character >= 0) {
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, .utf16);
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, offset_encoding);
|
||||
const pos_context = try analysis.documentPositionContext(arena, handle.document, doc_position);
|
||||
|
||||
const this_config = configFromUriOr(req.params.textDocument.uri, config);
|
||||
@ -1142,7 +1143,7 @@ fn gotoHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: reques
|
||||
};
|
||||
|
||||
if (req.params.position.character >= 0) {
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, .utf16);
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, offset_encoding);
|
||||
const pos_context = try analysis.documentPositionContext(arena, handle.document, doc_position);
|
||||
|
||||
const this_config = configFromUriOr(req.params.textDocument.uri, config);
|
||||
@ -1173,7 +1174,7 @@ fn hoverHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: reque
|
||||
};
|
||||
|
||||
if (req.params.position.character >= 0) {
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, .utf16);
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, offset_encoding);
|
||||
const pos_context = try analysis.documentPositionContext(arena, handle.document, doc_position);
|
||||
|
||||
const this_config = configFromUriOr(req.params.textDocument.uri, config);
|
||||
@ -1246,7 +1247,7 @@ fn renameHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requ
|
||||
};
|
||||
|
||||
if (req.params.position.character >= 0) {
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, .utf16);
|
||||
const doc_position = try offsets.documentPosition(handle.document, req.params.position, offset_encoding);
|
||||
const pos_context = try analysis.documentPositionContext(arena, handle.document, doc_position);
|
||||
|
||||
const this_config = configFromUriOr(req.params.textDocument.uri, config);
|
||||
|
@ -52,3 +52,64 @@ pub fn documentPosition(doc: types.TextDocument, position: types.Position, encod
|
||||
return DocumentPosition{ .line = line, .absolute_index = line_start_idx + utf8_idx, .line_index = utf8_idx };
|
||||
}
|
||||
}
|
||||
|
||||
pub const TokenLocation = struct {
|
||||
line: usize,
|
||||
column: usize,
|
||||
};
|
||||
|
||||
pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token: std.zig.ast.TokenIndex, encoding: Encoding) !TokenLocation {
|
||||
const token_loc = tree.token_locs[token];
|
||||
|
||||
var loc = TokenLocation{
|
||||
.line = 0,
|
||||
.column = 0,
|
||||
};
|
||||
const token_start = token_loc.start;
|
||||
const source = tree.source[start_index..];
|
||||
var i: usize = 0;
|
||||
while (i < token_start - start_index) {
|
||||
const c = source[i];
|
||||
if (c == '\n') {
|
||||
loc.line += 1;
|
||||
loc.column = 0;
|
||||
i += 1;
|
||||
} else {
|
||||
if (encoding == .utf16) {
|
||||
const n = try std.unicode.utf8ByteSequenceLength(c);
|
||||
const codepoint = try std.unicode.utf8Decode(source[i..i + n]);
|
||||
if (codepoint < 0x10000) {
|
||||
loc.column += 1;
|
||||
} else {
|
||||
loc.column += 2;
|
||||
}
|
||||
i += n;
|
||||
} else {
|
||||
loc.column += 1;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
/// Asserts the token is comprised of valid utf8
|
||||
pub fn tokenLength(tree: *std.zig.ast.Tree, token: std.zig.ast.TokenIndex, encoding: Encoding) usize {
|
||||
const token_loc = tree.token_locs[token];
|
||||
if (encoding == .utf8)
|
||||
return token_loc.end - token_loc.start;
|
||||
|
||||
var i: usize = token_loc.start;
|
||||
var utf16_len: usize = 0;
|
||||
while (i < token_loc.end) {
|
||||
const n = std.unicode.utf8ByteSequenceLength(tree.source[i]) catch unreachable;
|
||||
const codepoint = std.unicode.utf8Decode(tree.source[i..i + n]) catch unreachable;
|
||||
if (codepoint < 0x10000) {
|
||||
utf16_len += 1;
|
||||
} else {
|
||||
utf16_len += 2;
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
return utf16_len;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const offsets = @import("offsets.zig");
|
||||
const DocumentStore = @import("document_store.zig");
|
||||
const analysis = @import("analysis.zig");
|
||||
const ast = std.zig.ast;
|
||||
@ -43,12 +44,14 @@ const Builder = struct {
|
||||
handle: *DocumentStore.Handle,
|
||||
current_token: ?ast.TokenIndex,
|
||||
arr: std.ArrayList(u32),
|
||||
encoding: offsets.Encoding,
|
||||
|
||||
fn init(allocator: *std.mem.Allocator, handle: *DocumentStore.Handle) Builder {
|
||||
fn init(allocator: *std.mem.Allocator, handle: *DocumentStore.Handle, encoding: offsets.Encoding) Builder {
|
||||
return Builder{
|
||||
.handle = handle,
|
||||
.current_token = null,
|
||||
.arr = std.ArrayList(u32).init(allocator),
|
||||
.encoding = encoding,
|
||||
};
|
||||
}
|
||||
|
||||
@ -57,13 +60,11 @@ const Builder = struct {
|
||||
self.handle.tree.token_locs[current_token].start
|
||||
else
|
||||
0;
|
||||
|
||||
const token_loc = self.handle.tree.token_locs[token];
|
||||
const delta_loc = self.handle.tree.tokenLocationLoc(start_idx, token_loc);
|
||||
const delta_loc = offsets.tokenRelativeLocation(self.handle.tree, start_idx, token, self.encoding) catch return;
|
||||
try self.arr.appendSlice(&[_]u32{
|
||||
@truncate(u32, delta_loc.line),
|
||||
@truncate(u32, delta_loc.column),
|
||||
@truncate(u32, token_loc.end - token_loc.start),
|
||||
@truncate(u32, offsets.tokenLength(self.handle.tree, token, self.encoding)),
|
||||
@enumToInt(token_type),
|
||||
token_modifiers.toInt(),
|
||||
});
|
||||
@ -722,8 +723,8 @@ fn writeNodeTokens(builder: *Builder, arena: *std.heap.ArenaAllocator, store: *D
|
||||
}
|
||||
|
||||
// TODO Range version, edit version.
|
||||
pub fn writeAllSemanticTokens(arena: *std.heap.ArenaAllocator, store: *DocumentStore, handle: *DocumentStore.Handle) ![]u32 {
|
||||
var builder = Builder.init(arena.child_allocator, handle);
|
||||
pub fn writeAllSemanticTokens(arena: *std.heap.ArenaAllocator, store: *DocumentStore, handle: *DocumentStore.Handle, encoding: offsets.Encoding) ![]u32 {
|
||||
var builder = Builder.init(arena.child_allocator, handle, encoding);
|
||||
try writeNodeTokens(&builder, arena, store, &handle.tree.root_node.base);
|
||||
return builder.toOwnedSlice();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user