summaryrefslogtreecommitdiff
path: root/src/locations.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/locations.zig')
-rw-r--r--src/locations.zig27
1 files changed, 17 insertions, 10 deletions
diff --git a/src/locations.zig b/src/locations.zig
index 97caf1d9..b34f7a6f 100644
--- a/src/locations.zig
+++ b/src/locations.zig
@@ -158,17 +158,19 @@ const Pending = struct {
}
};
-fn sourceText(p: *pardes.Pardes, arena: std.mem.Allocator, dir: []const u8, path: []const u8) ?[]const u8 {
+const Source = struct { path: []const u8, bytes: []const u8 };
+
+fn sourceText(p: *pardes.Pardes, arena: std.mem.Allocator, dir: []const u8, path: []const u8) ?Source {
if (std.ascii.eqlIgnoreCase(std.fs.path.extension(path), ".pdf")) return null;
const lexical = std.fs.path.resolvePosix(arena, &.{ dir, path }) catch return null;
var pathbuf: [4096]u8 = undefined;
const full = if (filesystem.resolve(p, path, dir, &pathbuf)) |resolved| resolved.path else lexical;
for (p.panes) |slot| if (slot) |pane| {
- if (pane.file) |file| if (file.output == null and (std.mem.eql(u8, file.path, full) or std.mem.eql(u8, file.path, lexical))) return file.content;
+ if (pane.file) |file| if (file.output == null and (std.mem.eql(u8, file.path, full) or std.mem.eql(u8, file.path, lexical))) return .{ .path = lexical, .bytes = file.content };
};
const bytes = filesystem.read(p, full) catch return null;
defer p.gpa.free(bytes);
- return arena.dupe(u8, bytes) catch null;
+ return .{ .path = lexical, .bytes = arena.dupe(u8, bytes) catch return null };
}
/// Inputs are sorted results. Expand each source group, merge context with
@@ -193,18 +195,22 @@ pub fn format(p: *pardes.Pardes, dir: []const u8, input: []const u8, anchor: ?us
const group_start = pending.items.len;
try pending.appendSlice(arena, matches.items[first..end]);
if (expand and (p.locations_config.context > 0 or p.locations_config.tscontext)) {
- if (sourceText(p, arena, dir, path)) |source| {
+ if (sourceText(p, arena, dir, path)) |text| {
+ const source = text.bytes;
var source_lines: std.ArrayList([]const u8) = .empty;
var source_split = std.mem.splitScalar(u8, source, '\n');
while (source_split.next()) |line| try source_lines.append(arena, line);
const count = source_lines.items.len;
const wanted = try arena.alloc(u8, count);
@memset(wanted, 0);
- const source_colors = syntax.highlightFileRange(arena, path, source, 0, source.len) catch &.{};
- const declarations = if (p.locations_config.tscontext)
- syntax.contextDeclarations(arena, path, source) catch &.{}
- else
- &.{};
+ // Muted declaration headers do not need a source-color pass.
+ // Exact bytes include unsaved edits and virtual/remote sources.
+ var cached = p.locations_cache.get(p.tree_sitter_gpa, text.path, source, p.locations_config.tscontext, p.locations_config.context > 0) catch
+ @import("locations_cache.zig").Result{ .analysis = syntax.analyzeSource(arena, text.path, source, p.locations_config.tscontext, p.locations_config.context > 0) catch .{} };
+ defer cached.deinit(p.tree_sitter_gpa);
+ const analysis = cached.analysis;
+ const source_colors = analysis.colors;
+ const declarations = if (p.locations_config.tscontext) analysis.declarations else &.{};
for (pending.items[group_start..]) |*match| {
const row = match.at.line -| 1;
if (row >= count) continue;
@@ -235,7 +241,8 @@ pub fn format(p: *pardes.Pardes, dir: []const u8, input: []const u8, anchor: ?us
const declaration = kind & declaration_context != 0;
const colors = if (!declaration and offset + line.len <= source_colors.len) source_colors[offset..][0..line.len] else &.{};
const hidden = !declaration or !p.locations_config.tslocations or kind & declaration_start == 0;
- try appendContext(arena, &pending, path, line, row, declaration, hidden, colors);
+ // Later source groups may evict this analysis from the cache.
+ try appendContext(arena, &pending, path, line, row, declaration, hidden, try arena.dupe(u8, colors));
}
}
}