Implement semantic tokens for regular comments
This commit is contained in:
		
							parent
							
								
									ac8a00342e
								
							
						
					
					
						commit
						e2f4bbf2f3
					
				| @ -1785,8 +1785,19 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: ast.Tree, nod | ||||
|     if (name.len == 0) | ||||
|         return; | ||||
| 
 | ||||
|     const start_loc = context.prev_loc.add(try offsets.tokenRelativeLocation(tree, context.prev_loc.offset, tree.firstToken(node), context.encoding)); | ||||
|     const end_loc = start_loc.add(try offsets.tokenRelativeLocation(tree, start_loc.offset, tree.lastToken(node), context.encoding)); | ||||
|     const starts = tree.tokens.items(.start); | ||||
|     const start_loc = context.prev_loc.add(try offsets.tokenRelativeLocation( | ||||
|         tree, | ||||
|         context.prev_loc.offset, | ||||
|         starts[tree.firstToken(node)], | ||||
|         context.encoding, | ||||
|     )); | ||||
|     const end_loc = start_loc.add(try offsets.tokenRelativeLocation( | ||||
|         tree, | ||||
|         start_loc.offset, | ||||
|         starts[tree.lastToken(node)], | ||||
|         context.encoding, | ||||
|     )); | ||||
|     context.prev_loc = end_loc; | ||||
|     const range = types.Range{ | ||||
|         .start = .{ | ||||
| @ -1908,7 +1919,7 @@ pub const DeclWithHandle = struct { | ||||
| 
 | ||||
|     pub fn location(self: DeclWithHandle, encoding: offsets.Encoding) !offsets.TokenLocation { | ||||
|         const tree = self.handle.tree; | ||||
|         return try offsets.tokenRelativeLocation(tree, 0, self.nameToken(), encoding); | ||||
|         return try offsets.tokenRelativeLocation(tree, 0, tree.tokens.items(.start)[self.nameToken()], encoding); | ||||
|     } | ||||
| 
 | ||||
|     fn isPublic(self: DeclWithHandle) bool { | ||||
|  | ||||
| @ -28,4 +28,4 @@ operator_completions: bool = true, | ||||
| 
 | ||||
| /// Skips references to std. This will improve lookup speeds. | ||||
| /// Going to definition however will continue to work | ||||
| skip_std_references: bool = true, | ||||
| skip_std_references: bool = false, | ||||
|  | ||||
| @ -554,7 +554,7 @@ fn gotoDefinitionSymbol(id: types.RequestId, arena: *std.heap.ArenaAllocator, de | ||||
| 
 | ||||
|             const name_token = analysis.getDeclNameToken(handle.tree, node) orelse | ||||
|                 return try respondGeneric(id, null_result_response); | ||||
|             break :block offsets.tokenRelativeLocation(handle.tree, 0, name_token, offset_encoding) catch return; | ||||
|             break :block offsets.tokenRelativeLocation(handle.tree, 0, handle.tree.tokens.items(.start)[name_token], offset_encoding) catch return; | ||||
|         }, | ||||
|         else => decl_handle.location(offset_encoding) catch return, | ||||
|     }; | ||||
|  | ||||
| @ -71,8 +71,8 @@ pub const TokenLocation = struct { | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| pub fn tokenRelativeLocation(tree: ast.Tree, start_index: usize, token: ast.TokenIndex, encoding: Encoding) !TokenLocation { | ||||
|     const start = tree.tokens.items(.start)[token]; | ||||
| pub fn tokenRelativeLocation(tree: ast.Tree, start_index: usize, next_token_index: usize, encoding: Encoding) !TokenLocation { | ||||
|     const start = next_token_index; | ||||
| 
 | ||||
|     var loc = TokenLocation{ | ||||
|         .line = 0, | ||||
|  | ||||
| @ -14,7 +14,7 @@ fn tokenReference( | ||||
|     context: anytype, | ||||
|     comptime handler: anytype, | ||||
| ) !void { | ||||
|     const loc = offsets.tokenRelativeLocation(handle.tree, 0, tok, encoding) catch return; | ||||
|     const loc = offsets.tokenRelativeLocation(handle.tree, 0, handle.tree.tokens.items(.start)[tok], encoding) catch return; | ||||
|     try handler(context, types.Location{ | ||||
|         .uri = handle.uri(), | ||||
|         .range = .{ | ||||
|  | ||||
| @ -48,11 +48,21 @@ pub const TokenModifiers = packed struct { | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| const Comment = struct { | ||||
|     /// Length of the comment | ||||
|     length: u32, | ||||
|     /// Source index of the comment | ||||
|     start: u32, | ||||
| }; | ||||
| 
 | ||||
| const CommentList = std.ArrayList(Comment); | ||||
| 
 | ||||
| const Builder = struct { | ||||
|     handle: *DocumentStore.Handle, | ||||
|     current_token: ?ast.TokenIndex, | ||||
|     arr: std.ArrayList(u32), | ||||
|     encoding: offsets.Encoding, | ||||
|     comments: CommentList, | ||||
| 
 | ||||
|     fn init(allocator: *std.mem.Allocator, handle: *DocumentStore.Handle, encoding: offsets.Encoding) Builder { | ||||
|         return Builder{ | ||||
| @ -60,6 +70,7 @@ const Builder = struct { | ||||
|             .current_token = null, | ||||
|             .arr = std.ArrayList(u32).init(allocator), | ||||
|             .encoding = encoding, | ||||
|             .comments = CommentList.init(allocator), | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
| @ -73,7 +84,21 @@ const Builder = struct { | ||||
|         if (start_idx > starts[token]) | ||||
|             return; | ||||
| 
 | ||||
|         const delta_loc = offsets.tokenRelativeLocation(self.handle.tree, start_idx, token, self.encoding) catch return; | ||||
|         const delta_loc = if (self.findCommentBetween(start_idx, starts[token])) |comment| blk: { | ||||
|             const old_loc = self.handle.tree.tokenLocation(0, self.current_token orelse 0); | ||||
|             const comment_delta = offsets.tokenRelativeLocation(self.handle.tree, start_idx, comment.start, self.encoding) catch return; | ||||
| 
 | ||||
|             try self.arr.appendSlice(&[_]u32{ | ||||
|                 @truncate(u32, comment_delta.line), | ||||
|                 @truncate(u32, comment_delta.column), | ||||
|                 comment.length, | ||||
|                 @enumToInt(TokenType.comment), | ||||
|                 0, | ||||
|             }); | ||||
| 
 | ||||
|             break :blk offsets.tokenRelativeLocation(self.handle.tree, comment.start, starts[token], self.encoding) catch return; | ||||
|         } else offsets.tokenRelativeLocation(self.handle.tree, start_idx, starts[token], self.encoding) catch return; | ||||
| 
 | ||||
|         try self.arr.appendSlice(&[_]u32{ | ||||
|             @truncate(u32, delta_loc.line), | ||||
|             @truncate(u32, delta_loc.column), | ||||
| @ -87,6 +112,15 @@ const Builder = struct { | ||||
|     fn toOwnedSlice(self: *Builder) []u32 { | ||||
|         return self.arr.toOwnedSlice(); | ||||
|     } | ||||
| 
 | ||||
|     /// Based on a given start and end index, returns a `Comment` between the positions | ||||
|     /// Returns `null` if none was fone | ||||
|     fn findCommentBetween(self: Builder, from: u32, to: u32) ?Comment { | ||||
|         return for (self.comments.items) |comment| { | ||||
|             if (comment.start > from and comment.start < to) | ||||
|                 break comment; | ||||
|         } else null; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| fn writeToken( | ||||
| @ -1011,8 +1045,12 @@ fn writeNodeTokens( | ||||
| 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); | ||||
| 
 | ||||
|     // as line comments are not nodes, we parse the text then generate the tokens for them | ||||
|     try findComments(&builder, handle.tree.source, encoding); | ||||
| 
 | ||||
|     // reverse the ast from the root declarations | ||||
|     var gap_highlighter = GapHighlighter.init(&builder, 0); | ||||
| 
 | ||||
|     var buf: [2]ast.Node.Index = undefined; | ||||
|     for (analysis.declMembers(handle.tree, .root, 0, &buf)) |child| { | ||||
|         try gap_highlighter.next(child); | ||||
| @ -1020,7 +1058,57 @@ pub fn writeAllSemanticTokens(arena: *std.heap.ArenaAllocator, store: *DocumentS | ||||
|     } | ||||
| 
 | ||||
|     try gap_highlighter.end(@truncate(u32, handle.tree.tokens.len) - 1); | ||||
|     // pass root node, which always has index '0' | ||||
|     // try writeNodeTokens(&builder, arena, store, 0); | ||||
| 
 | ||||
|     return builder.toOwnedSlice(); | ||||
| } | ||||
| 
 | ||||
| /// As the AST does not contain nodes for comments | ||||
| /// this will parse through the entire file to search for comments | ||||
| /// and generate semantic tokens for them | ||||
| fn findComments(builder: *Builder, source: []const u8, encoding: offsets.Encoding) !void { | ||||
|     var state: enum { none, comment, doc_comment } = .none; | ||||
| 
 | ||||
|     var prev: u8 = 0; | ||||
|     var start: usize = 0; | ||||
|     for (source) |c, i| { | ||||
|         if (state == .comment and c == '/') { | ||||
|             state = .none; | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (state == .none and c == '/' and prev == '/') { | ||||
|             state = .comment; | ||||
|             start = i - 1; | ||||
|         } | ||||
| 
 | ||||
|         if (c == '\n') { | ||||
|             if (state == .comment) { | ||||
|                 state = .none; | ||||
| 
 | ||||
|                 const len = if (encoding == .utf8) | ||||
|                     i - start | ||||
|                 else blk: { | ||||
|                     var index: usize = start; | ||||
|                     var utf16_len: usize = 0; | ||||
|                     while (index < i) { | ||||
|                         const n = std.unicode.utf8ByteSequenceLength(source[index]) catch unreachable; | ||||
|                         const codepoint = std.unicode.utf8Decode(source[index .. index + n]) catch unreachable; | ||||
|                         if (codepoint < 0x10000) { | ||||
|                             utf16_len += 1; | ||||
|                         } else { | ||||
|                             utf16_len += 2; | ||||
|                         } | ||||
|                         index += n; | ||||
|                     } | ||||
|                     break :blk utf16_len; | ||||
|                 }; | ||||
| 
 | ||||
|                 try builder.comments.append(.{ | ||||
|                     .length = @truncate(u32, len), | ||||
|                     .start = @truncate(u32, start), | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|         prev = c; | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user