@@ -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
14291420pub fn loadDirectoryRecursive (store : * DocumentStore , directory_uri : Uri ) ! usize {
0 commit comments