Skip to content

Commit 815230e

Browse files
committed
lazily resolve potential build files
1 parent 62ad636 commit 815230e

File tree

1 file changed

+51
-60
lines changed

1 file changed

+51
-60
lines changed

src/DocumentStore.zig

Lines changed: 51 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,11 @@ pub const Handle = struct {
203203
zoir: std.zig.Zoir = undefined,
204204

205205
associated_build_file: union(enum) {
206-
/// The Handle has no associated build file (build.zig).
207-
none,
208-
/// The associated build file (build.zig) has not been resolved yet.
209-
/// Uris that come first have higher priority.
206+
/// The initial state. The associated build file (build.zig) is resolved lazily.
207+
init,
208+
/// The associated build file (build.zig) has been requested but has not yet been resolved.
210209
unresolved: struct {
210+
/// The build files are ordered in decreasing priority.
211211
potential_build_files: []const *BuildFile,
212212
/// to avoid checking build files multiple times, a bitset stores whether or
213213
/// not the build file should be skipped because it has previously been
@@ -220,9 +220,11 @@ pub const Handle = struct {
220220
self.* = undefined;
221221
}
222222
},
223+
/// The Handle has no associated build file (build.zig).
224+
none,
223225
/// The associated build file (build.zig) has been successfully resolved.
224226
resolved: *BuildFile,
225-
} = .none,
227+
} = .init,
226228
},
227229

228230
const Status = packed struct(u32) {
@@ -310,7 +312,7 @@ pub const Handle = struct {
310312
self.cimports.deinit(allocator);
311313

312314
switch (self.impl.associated_build_file) {
313-
.none, .resolved => {},
315+
.init, .none, .resolved => {},
314316
.unresolved => |*payload| payload.deinit(allocator),
315317
}
316318

@@ -425,8 +427,26 @@ pub const Handle = struct {
425427
defer self.impl.lock.unlock();
426428

427429
const unresolved = switch (self.impl.associated_build_file) {
428-
.none => return .none,
430+
.init => blk: {
431+
const potential_build_files = document_store.collectPotentialBuildFiles(self.uri) catch {
432+
log.err("failed to collect potential build files of '{s}'", .{self.uri});
433+
self.impl.associated_build_file = .none;
434+
return .none;
435+
};
436+
errdefer document_store.allocator.free(potential_build_files);
437+
438+
var has_been_checked: std.DynamicBitSetUnmanaged = try .initEmpty(document_store.allocator, potential_build_files.len);
439+
errdefer has_been_checked.deinit(document_store.allocator);
440+
441+
self.impl.associated_build_file = .{ .unresolved = .{
442+
.has_been_checked = has_been_checked,
443+
.potential_build_files = potential_build_files,
444+
} };
445+
446+
break :blk &self.impl.associated_build_file.unresolved;
447+
},
429448
.unresolved => |*unresolved| unresolved,
449+
.none => return .none,
430450
.resolved => |build_file| return .{ .resolved = build_file },
431451
};
432452

@@ -1361,69 +1381,40 @@ fn createAndStoreDocument(
13611381
const tracy_zone = tracy.trace(@src());
13621382
defer tracy_zone.end();
13631383

1364-
const gop = gop: {
1365-
var new_handle: Handle = try .init(self.allocator, uri, text, lsp_synced);
1384+
var new_handle: Handle = try .init(self.allocator, uri, text, lsp_synced);
13661385

1367-
self.lock.lock();
1368-
defer self.lock.unlock();
1386+
self.lock.lock();
1387+
defer self.lock.unlock();
13691388

1370-
errdefer self.allocator.free(text);
1389+
errdefer self.allocator.free(text);
13711390

1372-
const gop = try self.handles.getOrPut(self.allocator, uri);
1373-
errdefer if (!gop.found_existing) std.debug.assert(self.handles.swapRemove(uri));
1391+
const gop = try self.handles.getOrPut(self.allocator, uri);
1392+
errdefer if (!gop.found_existing) std.debug.assert(self.handles.swapRemove(uri));
13741393

1375-
if (gop.found_existing) {
1376-
new_handle.uri = gop.key_ptr.*;
1377-
new_handle.impl.associated_build_file = gop.value_ptr.*.impl.associated_build_file;
1378-
gop.value_ptr.*.impl.associated_build_file = .none;
1394+
if (gop.found_existing) {
1395+
new_handle.impl.associated_build_file = gop.value_ptr.*.impl.associated_build_file;
1396+
gop.value_ptr.*.impl.associated_build_file = .init;
13791397

1380-
gop.value_ptr.*.deinit();
1381-
gop.value_ptr.*.* = new_handle;
1382-
} else {
1383-
gop.value_ptr.* = try self.allocator.create(Handle);
1384-
errdefer self.allocator.destroy(gop.value_ptr.*);
1385-
1386-
gop.key_ptr.* = try self.allocator.dupe(u8, uri);
1387-
errdefer self.allocator.free(gop.key_ptr.*);
1388-
1389-
new_handle.uri = gop.key_ptr.*;
1390-
gop.value_ptr.*.* = new_handle;
1391-
// The `associated_build_file` field is not yet set.
1392-
}
1393-
errdefer comptime unreachable; // would double free `text` on error
1394-
1395-
if (self.currently_loading_uris.swapRemove(uri)) {
1396-
self.wait_for_currently_loading_uri.broadcast();
1397-
}
1398-
1399-
break :gop gop;
1400-
};
1401-
const handle = gop.value_ptr.*;
1402-
1403-
if (gop.found_existing or !supports_build_system or isInStd(uri)) {
1404-
// nothing to do
1405-
} else if (isBuildFile(uri)) {
1406-
_ = self.getOrLoadBuildFile(uri);
1407-
} else blk: {
1408-
const potential_build_files = self.collectPotentialBuildFiles(uri) catch {
1409-
log.err("failed to collect potential build files of '{s}'", .{handle.uri});
1410-
break :blk;
1411-
};
1412-
errdefer self.allocator.free(potential_build_files);
1398+
new_handle.uri = gop.key_ptr.*;
1399+
gop.value_ptr.*.deinit();
1400+
gop.value_ptr.*.* = new_handle;
1401+
} else {
1402+
gop.value_ptr.* = try self.allocator.create(Handle);
1403+
errdefer self.allocator.destroy(gop.value_ptr.*);
14131404

1414-
var has_been_checked: std.DynamicBitSetUnmanaged = try .initEmpty(self.allocator, potential_build_files.len);
1415-
errdefer has_been_checked.deinit(self.allocator);
1405+
gop.key_ptr.* = try self.allocator.dupe(u8, uri);
1406+
errdefer self.allocator.free(gop.key_ptr.*);
14161407

1417-
handle.impl.lock.lock();
1418-
defer handle.impl.lock.unlock();
1408+
new_handle.uri = gop.key_ptr.*;
1409+
gop.value_ptr.*.* = new_handle;
1410+
}
1411+
errdefer comptime unreachable; // would double free `text` on error
14191412

1420-
handle.impl.associated_build_file = .{ .unresolved = .{
1421-
.has_been_checked = has_been_checked,
1422-
.potential_build_files = potential_build_files,
1423-
} };
1413+
if (self.currently_loading_uris.swapRemove(uri)) {
1414+
self.wait_for_currently_loading_uri.broadcast();
14241415
}
14251416

1426-
return handle;
1417+
return gop.value_ptr.*;
14271418
}
14281419

14291420
pub fn loadDirectoryRecursive(store: *DocumentStore, directory_uri: Uri) !usize {

0 commit comments

Comments
 (0)