From ee5edccf68c1d9d269acdb6e4f7bed3f9cb1c94e Mon Sep 17 00:00:00 2001 From: xdBronch <51252236+xdBronch@users.noreply.github.com> Date: Thu, 7 May 2026 20:04:24 -0400 Subject: [PATCH] fix inefficient semanticTokens/range at the end of files Co-authored-by: Techatrix --- src/features/inlay_hints.zig | 14 ++++++-------- src/features/semantic_tokens.zig | 18 +++++++++++------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/features/inlay_hints.zig b/src/features/inlay_hints.zig index 9ec3873e2..de5cae796 100644 --- a/src/features/inlay_hints.zig +++ b/src/features/inlay_hints.zig @@ -565,15 +565,13 @@ pub fn writeRangeInlayHint( .hover_kind = hover_kind, }; - const nodes = try ast.nodesAtLoc(arena, &handle.tree, loc); - - for (nodes) |child| { - try writeNodeInlayHint(&builder, &handle.tree, child); - - var walker: ast.Walker = try .init(arena, &handle.tree, child); - defer walker.deinit(arena); - while (try walker.nextIgnoreClose(arena, &handle.tree)) |node| { + var walker: ast.Walker = try .init(arena, &handle.tree, .root); + defer walker.deinit(arena); + while (try walker.nextIgnoreClose(arena, &handle.tree)) |node| { + if (offsets.locIntersect(loc, offsets.nodeToLoc(&handle.tree, node))) { try writeNodeInlayHint(&builder, &handle.tree, node); + } else { + walker.skip(); } } diff --git a/src/features/semantic_tokens.zig b/src/features/semantic_tokens.zig index 696b4ab66..909ccbe76 100644 --- a/src/features/semantic_tokens.zig +++ b/src/features/semantic_tokens.zig @@ -89,6 +89,8 @@ const Builder = struct { encoding: offsets.Encoding, limited: bool, overlappingTokenSupport: bool, + /// Only emit tokens for the given source range. + loc: ?offsets.Loc, fn add(self: *Builder, token: Ast.TokenIndex, token_type: TokenType, token_modifiers: TokenModifiers) error{OutOfMemory}!void { const tree = &self.handle.tree; @@ -285,6 +287,10 @@ fn writeNodeTokens(builder: *Builder, node: Ast.Node.Index) Analyser.Error!void const handle = builder.handle; const tree = &handle.tree; + if (builder.loc) |loc| { + if (!offsets.locIntersect(loc, offsets.nodeToLoc(tree, node))) return; + } + const main_token = tree.nodeMainToken(node); switch (tree.nodeTag(node)) { @@ -1164,22 +1170,20 @@ pub fn writeSemanticTokens( limited: bool, overlappingTokenSupport: bool, ) Analyser.Error!types.semantic_tokens.Result { - var builder = Builder{ + const tree = &handle.tree; + + var builder: Builder = .{ .arena = arena, .analyser = analyser, .handle = handle, .encoding = encoding, .limited = limited, .overlappingTokenSupport = overlappingTokenSupport, + .loc = loc, }; - var nodes = if (loc) |l| try ast.nodesAtLoc(arena, &handle.tree, l) else handle.tree.rootDecls(); - if (nodes.len == 1 and nodes[0] == .root) { - nodes = handle.tree.rootDecls(); - } - // reverse the ast from the root declarations - for (nodes) |child| { + for (tree.rootDecls()) |child| { try writeNodeTokens(&builder, child); }