@@ -192,23 +192,54 @@ class FileState {
192192
193193 /// Return the set of all directly referenced files - imported, exported or
194194 /// parted.
195- Set <FileState > get directReferencedFiles => _directReferencedFiles;
195+ Set <FileState > get directReferencedFiles {
196+ return _directReferencedFiles ?? = < FileState > {
197+ ...importedFiles,
198+ ...exportedFiles,
199+ ...partedFiles,
200+ };
201+ }
196202
197203 /// Return the set of all directly referenced libraries - imported or
198204 /// exported.
199- Set <FileState > get directReferencedLibraries => _directReferencedLibraries;
205+ Set <FileState > get directReferencedLibraries {
206+ return _directReferencedLibraries ?? = < FileState > {
207+ ...importedFiles,
208+ ...exportedFiles,
209+ };
210+ }
200211
201212 /// Return `true` if the file exists.
202213 bool get exists => _exists;
203214
204215 /// The list of files this file exports.
205- List <FileState > get exportedFiles => _exportedFiles;
216+ List <FileState > get exportedFiles {
217+ if (_exportedFiles == null ) {
218+ _exportedFiles = < FileState > [];
219+ for (var directive in _unlinked2.exports) {
220+ var uri = _selectRelativeUri (directive);
221+ var file = _fileForRelativeUri (uri);
222+ _exportedFiles.add (file);
223+ }
224+ }
225+ return _exportedFiles;
226+ }
206227
207228 @override
208229 int get hashCode => uri.hashCode;
209230
210231 /// The list of files this file imports.
211- List <FileState > get importedFiles => _importedFiles;
232+ List <FileState > get importedFiles {
233+ if (_importedFiles == null ) {
234+ _importedFiles = < FileState > [];
235+ for (var directive in _unlinked2.imports) {
236+ var uri = _selectRelativeUri (directive);
237+ var file = _fileForRelativeUri (uri);
238+ _importedFiles.add (file);
239+ }
240+ }
241+ return _importedFiles;
242+ }
212243
213244 LibraryCycle get internal_libraryCycle => _libraryCycle;
214245
@@ -237,6 +268,7 @@ class FileState {
237268 /// of. Return `null` if a library is not known, for example because we have
238269 /// not processed a library file yet.
239270 FileState get library {
271+ _fsState.readPartsForLibraries ();
240272 List <FileState > libraries = _fsState._partToLibraries[this ];
241273 if (libraries == null || libraries.isEmpty) {
242274 return null ;
@@ -264,13 +296,27 @@ class FileState {
264296
265297 /// The list of files files that this library consists of, i.e. this library
266298 /// file itself and its [partedFiles] .
267- List <FileState > get libraryFiles => _libraryFiles;
299+ List <FileState > get libraryFiles {
300+ return _libraryFiles ?? = [this , ...partedFiles];
301+ }
268302
269303 /// Return information about line in the file.
270304 LineInfo get lineInfo => _lineInfo;
271305
272306 /// The list of files this library file references as parts.
273- List <FileState > get partedFiles => _partedFiles;
307+ List <FileState > get partedFiles {
308+ if (_partedFiles == null ) {
309+ _partedFiles = < FileState > [];
310+ for (var uri in _unlinked2.parts) {
311+ var file = _fileForRelativeUri (uri);
312+ _partedFiles.add (file);
313+ _fsState._partToLibraries
314+ .putIfAbsent (file, () => < FileState > [])
315+ .add (this );
316+ }
317+ }
318+ return _partedFiles;
319+ }
274320
275321 /// The external names referenced by the file.
276322 Set <String > get referencedNames {
@@ -287,7 +333,7 @@ class FileState {
287333
288334 void appendReferenced (FileState file) {
289335 if (transitiveFiles.add (file)) {
290- file._directReferencedFiles ? .forEach (appendReferenced);
336+ file.directReferencedFiles .forEach (appendReferenced);
291337 }
292338 }
293339
@@ -436,39 +482,16 @@ class FileState {
436482 }
437483 }
438484
439- // Build the graph.
440- _importedFiles = < FileState > [];
441- _exportedFiles = < FileState > [];
442- _partedFiles = < FileState > [];
443- for (var directive in _unlinked2.imports) {
444- var uri = _selectRelativeUri (directive);
445- var file = _fileForRelativeUri (uri);
446- _importedFiles.add (file);
447- }
448- for (var directive in _unlinked2.exports) {
449- var uri = _selectRelativeUri (directive);
450- var file = _fileForRelativeUri (uri);
451- _exportedFiles.add (file);
452- }
453- for (var uri in _unlinked2.parts) {
454- var file = _fileForRelativeUri (uri);
455- _partedFiles.add (file);
456- _fsState._partToLibraries
457- .putIfAbsent (file, () => < FileState > [])
458- .add (this );
459- }
460- _libraryFiles = [this , ..._partedFiles];
485+ // Read imports/exports on demand.
486+ _importedFiles = null ;
487+ _exportedFiles = null ;
488+ _directReferencedFiles = null ;
489+ _directReferencedLibraries = null ;
461490
462- // Compute referenced files.
463- _directReferencedFiles = < FileState > {
464- ..._importedFiles,
465- ..._exportedFiles,
466- ..._partedFiles,
467- };
468- _directReferencedLibraries = < FileState > {
469- ..._importedFiles,
470- ..._exportedFiles,
471- };
491+ // Read parts on demand.
492+ _fsState._librariesWithoutPartsRead.add (this );
493+ _partedFiles = null ;
494+ _libraryFiles = null ;
472495
473496 // Update mapping from subtyped names to files.
474497 for (var name in _driverUnlinkedUnit.subtypedNames) {
@@ -748,6 +771,11 @@ class FileSystemState {
748771 /// Mapping from a path to the corresponding canonical [FileState] .
749772 final Map <String , FileState > _pathToCanonicalFile = {};
750773
774+ /// We don't read parts until requested, but if we need to know the
775+ /// library for a file, we need to read parts of every file to know
776+ /// which libraries reference this part.
777+ final List <FileState > _librariesWithoutPartsRead = [];
778+
751779 /// Mapping from a part to the libraries it is a part of.
752780 final Map <FileState , List <FileState >> _partToLibraries = {};
753781
@@ -950,6 +978,19 @@ class FileSystemState {
950978 _fileContentCache.remove (path);
951979 }
952980
981+ void readPartsForLibraries () {
982+ // Make a copy, because reading new files will update it.
983+ var libraryToProcess = _librariesWithoutPartsRead.toList ();
984+
985+ // We will process these files, so clear it now.
986+ // It will be filled with new files during the loop below.
987+ _librariesWithoutPartsRead.clear ();
988+
989+ for (var library in libraryToProcess) {
990+ library.partedFiles;
991+ }
992+ }
993+
953994 /// Remove the file with the given [path] .
954995 void removeFile (String path) {
955996 markFileForReading (path);
0 commit comments