@@ -178,8 +178,6 @@ pub const BuildFile = struct {
178178pub const Handle = struct {
179179 uri : Uri ,
180180 tree : Ast ,
181- /// Contains one entry for every import in the document
182- import_uris : std .ArrayListUnmanaged (Uri ),
183181 /// Contains one entry for every cimport in the document
184182 cimports : std .MultiArrayList (CImportHandle ),
185183
@@ -194,6 +192,7 @@ pub const Handle = struct {
194192 /// See `getLazy`
195193 lazy_condition : std.Thread.Condition = .{},
196194
195+ import_uris : ? []Uri = null ,
197196 document_scope : DocumentScope = undefined ,
198197 zzoiir : ZirOrZoir = undefined ,
199198
@@ -245,7 +244,7 @@ pub const Handle = struct {
245244 _ : u27 = 0 ,
246245 };
247246
248- /// Takes ownership of `text` on success. The `import_uris` be initialized to `.empty`.
247+ /// Takes ownership of `text` on success.
249248 pub fn init (
250249 allocator : std.mem.Allocator ,
251250 uri : Uri ,
@@ -263,7 +262,6 @@ pub const Handle = struct {
263262 return .{
264263 .uri = uri ,
265264 .tree = tree ,
266- .import_uris = .empty ,
267265 .cimports = cimports ,
268266 .impl = .{
269267 .status = .init (@bitCast (Status {
@@ -291,8 +289,10 @@ pub const Handle = struct {
291289 allocator .free (self .tree .source );
292290 self .tree .deinit (allocator );
293291
294- for (self .import_uris .items ) | uri | allocator .free (uri );
295- self .import_uris .deinit (allocator );
292+ if (self .impl .import_uris ) | import_uris | {
293+ for (import_uris ) | uri | allocator .free (uri );
294+ allocator .free (import_uris );
295+ }
296296
297297 for (self .cimports .items (.source )) | source | allocator .free (source );
298298 self .cimports .deinit (allocator );
@@ -305,6 +305,42 @@ pub const Handle = struct {
305305 self .* = undefined ;
306306 }
307307
308+ pub fn getImportUris (self : * Handle ) error {OutOfMemory }! []const Uri {
309+ self .impl .lock .lock ();
310+ defer self .impl .lock .unlock ();
311+
312+ const allocator = self .impl .allocator ;
313+
314+ if (self .impl .import_uris ) | import_uris | return import_uris ;
315+
316+ var imports = try analysis .collectImports (allocator , self .tree );
317+
318+ var i : usize = 0 ;
319+ errdefer {
320+ // only free the uris
321+ for (imports .items [0.. i ]) | uri | allocator .free (uri );
322+ imports .deinit (allocator );
323+ }
324+
325+ // Convert to URIs
326+ while (i < imports .items .len ) {
327+ const import_str = imports .items [i ];
328+ if (! std .mem .endsWith (u8 , import_str , ".zig" )) {
329+ _ = imports .swapRemove (i );
330+ continue ;
331+ }
332+ // The raw import strings are owned by the document and do not need to be freed here.
333+ imports .items [i ] = try uriFromFileImportStr (allocator , self , import_str ) orelse {
334+ _ = imports .swapRemove (i );
335+ continue ;
336+ };
337+ i += 1 ;
338+ }
339+
340+ self .impl .import_uris = try imports .toOwnedSlice (allocator );
341+ return self .impl .import_uris .? ;
342+ }
343+
308344 pub fn getDocumentScope (self : * Handle ) error {OutOfMemory }! DocumentScope {
309345 if (self .getStatus ().has_document_scope ) return self .impl .document_scope ;
310346 return try self .getLazy (DocumentScope , "document_scope" , struct {
@@ -1285,7 +1321,7 @@ fn uriInImports(
12851321 return std .mem .eql (u8 , associated_build_file_uri , build_file_uri );
12861322 }
12871323
1288- for (handle .import_uris . items ) | import_uri | {
1324+ for (try handle .getImportUris () ) | import_uri | {
12891325 if (try self .uriInImports (checked_uris , build_file_uri , import_uri , uri ))
12901326 return true ;
12911327 }
@@ -1346,37 +1382,6 @@ fn createAndStoreDocument(
13461382 return gop .value_ptr .* ;
13471383}
13481384
1349- /// Caller owns returned memory.
1350- /// **Thread safe** takes a shared lock
1351- fn collectImportUris (self : * DocumentStore , handle : * Handle ) error {OutOfMemory }! std .ArrayListUnmanaged (Uri ) {
1352- const tracy_zone = tracy .trace (@src ());
1353- defer tracy_zone .end ();
1354-
1355- var imports = try analysis .collectImports (self .allocator , handle .tree );
1356-
1357- var i : usize = 0 ;
1358- errdefer {
1359- // only free the uris
1360- for (imports .items [0.. i ]) | uri | self .allocator .free (uri );
1361- imports .deinit (self .allocator );
1362- }
1363-
1364- // Convert to URIs
1365- while (i < imports .items .len ) {
1366- const maybe_uri = try self .uriFromImportStr (self .allocator , handle , imports .items [i ]);
1367-
1368- if (maybe_uri ) | uri | {
1369- // The raw import strings are owned by the document and do not need to be freed here.
1370- imports .items [i ] = uri ;
1371- i += 1 ;
1372- } else {
1373- _ = imports .swapRemove (i );
1374- }
1375- }
1376-
1377- return imports ;
1378- }
1379-
13801385pub const CImportHandle = struct {
13811386 /// the `@cImport` node
13821387 node : Ast.Node.Index ,
@@ -1438,8 +1443,10 @@ pub fn collectDependencies(
14381443 store .lock .lockShared ();
14391444 defer store .lock .unlockShared ();
14401445
1441- try dependencies .ensureUnusedCapacity (allocator , handle .import_uris .items .len + handle .cimports .len );
1442- for (handle .import_uris .items ) | uri | {
1446+ const import_uris = try handle .getImportUris ();
1447+
1448+ try dependencies .ensureUnusedCapacity (allocator , import_uris .len + handle .cimports .len );
1449+ for (import_uris ) | uri | {
14431450 dependencies .appendAssumeCapacity (try allocator .dupe (u8 , uri ));
14441451 }
14451452
@@ -1746,18 +1753,22 @@ pub fn uriFromImportStr(self: *DocumentStore, allocator: std.mem.Allocator, hand
17461753 }
17471754 return null ;
17481755 } else {
1749- const base_path = URI .toFsPath (allocator , handle .uri ) catch | err | switch (err ) {
1750- error .OutOfMemory = > return error .OutOfMemory ,
1751- else = > return null ,
1752- };
1753- defer allocator .free (base_path );
1756+ return try uriFromFileImportStr (allocator , handle , import_str );
1757+ }
1758+ }
17541759
1755- const joined_path = std .fs .path .resolve (allocator , &.{ base_path , ".." , import_str }) catch | err | switch (err ) {
1756- error .OutOfMemory = > return error .OutOfMemory ,
1757- else = > return null ,
1758- };
1759- defer allocator .free (joined_path );
1760+ fn uriFromFileImportStr (allocator : std.mem.Allocator , handle : * Handle , import_str : []const u8 ) error {OutOfMemory }! ? Uri {
1761+ const base_path = URI .toFsPath (allocator , handle .uri ) catch | err | switch (err ) {
1762+ error .OutOfMemory = > return error .OutOfMemory ,
1763+ else = > return null ,
1764+ };
1765+ defer allocator .free (base_path );
17601766
1761- return try URI .fromPath (allocator , joined_path );
1762- }
1767+ const joined_path = std .fs .path .resolve (allocator , &.{ base_path , ".." , import_str }) catch | err | switch (err ) {
1768+ error .OutOfMemory = > return error .OutOfMemory ,
1769+ else = > return null ,
1770+ };
1771+ defer allocator .free (joined_path );
1772+
1773+ return try URI .fromPath (allocator , joined_path );
17631774}
0 commit comments