Add LibraryOrAugmentationFileKind.augmentations
Change-Id: Id339b36d37ae904693c27173cd606856b0114eec
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250182
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index e7c3225..1164841 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -60,6 +60,9 @@
// TODO(scheglov): implement asLibrary
throw UnimplementedError();
}
+
+ /// Returns `true` if the `library augment` directive confirms [container].
+ bool isAugmentationOf(LibraryOrAugmentationFileKind container);
}
/// The URI of the [directive] can be resolved.
@@ -100,6 +103,11 @@
}
return null;
}
+
+ @override
+ bool isAugmentationOf(LibraryOrAugmentationFileKind container) {
+ return uriFile == container.file;
+ }
}
/// The URI of the [directive] can not be resolved.
@@ -111,6 +119,9 @@
@override
LibraryFileStateKind? get library => null;
+
+ @override
+ bool isAugmentationOf(LibraryOrAugmentationFileKind container) => false;
}
/// Information about a single `import` directive.
@@ -278,7 +289,6 @@
/// Files that reference this file.
final Set<FileState> referencingFiles = {};
- List<FileState?> _augmentationFiles = [];
List<FileState?>? _importedFiles;
List<FileState?>? _exportedFiles;
@@ -306,11 +316,6 @@
/// The unlinked API signature of the file.
Uint8List get apiSignature => _apiSignature!;
- /// The list of imported augmentations.
- List<FileState?> get augmentationFiles {
- return _augmentationFiles;
- }
-
/// The content of the file.
String get content => _fileContent!.content;
@@ -568,7 +573,6 @@
// Read parts eagerly to link parts to libraries.
_updateKind();
- _updateAugmentationFiles();
// Update mapping from subtyped names to files.
for (var name in _driverUnlinkedUnit!.subtypedNames) {
@@ -743,23 +747,10 @@
}
}
- removeForOne(_augmentationFiles);
removeForOne(_exportedFiles);
removeForOne(_importedFiles);
}
- void _updateAugmentationFiles() {
- _augmentationFiles = unlinked2.augmentations.map((directive) {
- return _fileForRelativeUri(directive.uri).map(
- (augmentation) {
- augmentation?.referencingFiles.add(this);
- return augmentation;
- },
- (_) => null,
- );
- }).toList();
- }
-
void _updateKind() {
_kind?.dispose();
@@ -1026,6 +1017,7 @@
/// Returns the library in which this file should be analyzed.
LibraryFileStateKind? get library;
+ @mustCallSuper
void dispose() {}
}
@@ -1502,6 +1494,47 @@
bool get isSrc => (_flags & _isSrc) != 0;
}
+/// Information about a single `import augment` directive.
+class ImportAugmentationDirectiveState {
+ final LibraryOrAugmentationFileKind container;
+ final UnlinkedImportAugmentationDirective directive;
+
+ ImportAugmentationDirectiveState({
+ required this.container,
+ required this.directive,
+ });
+
+ /// Returns a [Source] that is referenced by this directive.
+ ///
+ /// Returns `null` if the URI cannot be resolved into a [Source].
+ Source? get importedSource => null;
+}
+
+/// [PartDirectiveState] that has a valid URI that references a file.
+class ImportAugmentationDirectiveWithFile
+ extends ImportAugmentationDirectiveState {
+ final FileState importedFile;
+
+ ImportAugmentationDirectiveWithFile({
+ required super.container,
+ required super.directive,
+ required this.importedFile,
+ });
+
+ /// If [importedFile] is a [AugmentationFileStateKind], and it confirms that
+ /// it is an augmentation of the [container], returns the [importedFile].
+ AugmentationFileStateKind? get importedAugmentation {
+ final kind = importedFile.kind;
+ if (kind is AugmentationFileStateKind && kind.isAugmentationOf(container)) {
+ return kind;
+ }
+ return null;
+ }
+
+ @override
+ Source? get importedSource => importedFile.source;
+}
+
/// Information about a single `import` directive.
class ImportDirectiveState {
final UnlinkedNamespaceDirective directive;
@@ -1673,23 +1706,7 @@
}
}
- final imports = _imports;
- if (imports != null) {
- for (final import in imports) {
- if (import is ImportDirectiveWithFile) {
- import.importedFile.referencingFiles.remove(file);
- }
- }
- }
-
- final exports = _exports;
- if (exports != null) {
- for (final export in exports) {
- if (export is ExportDirectiveWithFile) {
- export.exportedFile.referencingFiles.remove(file);
- }
- }
- }
+ super.dispose();
}
bool hasPart(PartFileStateKind partKind) {
@@ -1714,6 +1731,7 @@
}
abstract class LibraryOrAugmentationFileKind extends FileStateKind {
+ List<ImportAugmentationDirectiveState>? _augmentations;
List<ExportDirectiveState>? _exports;
List<ImportDirectiveState>? _imports;
@@ -1721,6 +1739,34 @@
required super.file,
});
+ List<ImportAugmentationDirectiveState> get augmentations {
+ return _augmentations ??= file.unlinked2.augmentations.map((directive) {
+ return file._fileForRelativeUri(directive.uri).map(
+ (refFile) {
+ if (refFile != null) {
+ refFile.referencingFiles.add(file);
+ return ImportAugmentationDirectiveWithFile(
+ container: this,
+ directive: directive,
+ importedFile: refFile,
+ );
+ } else {
+ return ImportAugmentationDirectiveState(
+ container: this,
+ directive: directive,
+ );
+ }
+ },
+ (externalLibrary) {
+ return ImportAugmentationDirectiveState(
+ container: this,
+ directive: directive,
+ );
+ },
+ );
+ }).toList();
+ }
+
List<ExportDirectiveState> get exports {
return _exports ??= file.unlinked2.exports.map((directive) {
final uriStr = file._selectRelativeUri(directive);
@@ -1782,12 +1828,56 @@
/// we register available objects.
@visibleForTesting
void discoverReferencedFiles() {
- imports;
exports;
+ imports;
+ for (final import in augmentations) {
+ if (import is ImportAugmentationDirectiveWithFile) {
+ import.importedAugmentation?.discoverReferencedFiles();
+ }
+ }
+ }
+
+ @override
+ void dispose() {
+ final augmentations = _augmentations;
+ if (augmentations != null) {
+ for (final import in augmentations) {
+ if (import is ImportAugmentationDirectiveWithFile) {
+ import.importedFile.referencingFiles.remove(file);
+ }
+ }
+ }
+
+ final exports = _exports;
+ if (exports != null) {
+ for (final export in exports) {
+ if (export is ExportDirectiveWithFile) {
+ export.exportedFile.referencingFiles.remove(file);
+ }
+ }
+ }
+
+ final imports = _imports;
+ if (imports != null) {
+ for (final import in imports) {
+ if (import is ImportDirectiveWithFile) {
+ import.importedFile.referencingFiles.remove(file);
+ }
+ }
+ }
+
+ super.dispose();
}
bool hasAugmentation(AugmentationFileStateKind augmentation) {
- return file.augmentationFiles.contains(augmentation.file);
+ for (final import in augmentations) {
+ if (import is ImportAugmentationDirectiveWithFile) {
+ if (import.importedFile == augmentation.file) {
+ return true;
+ }
+ }
+ }
+ return false;
}
}
diff --git a/pkg/analyzer/test/src/dart/analysis/analyzer_state_printer.dart b/pkg/analyzer/test/src/dart/analysis/analyzer_state_printer.dart
index b11d66d..242801d 100644
--- a/pkg/analyzer/test/src/dart/analysis/analyzer_state_printer.dart
+++ b/pkg/analyzer/test/src/dart/analysis/analyzer_state_printer.dart
@@ -92,13 +92,31 @@
_indent = indent;
}
- /// TODO(scheglov) Support unresolved URIs, not augmentations, etc.
- void _writeAugmentations(LibraryOrAugmentationFileKind kind) {
- final files = kind.file.augmentationFiles.whereNotNull();
- if (files.isNotEmpty) {
- final keys = files.map(idProvider.fileState).join(' ');
- _writelnWithIndent('augmentations: $keys');
- }
+ void _writeAugmentations(LibraryOrAugmentationFileKind container) {
+ _writeElements<ImportAugmentationDirectiveState>(
+ 'augmentations',
+ container.augmentations,
+ (augmentation) {
+ expect(augmentation.container, same(container));
+ if (augmentation is ImportAugmentationDirectiveWithFile) {
+ final file = augmentation.importedFile;
+ sink.write(_indent);
+
+ final importedAugmentation = augmentation.importedAugmentation;
+ if (importedAugmentation != null) {
+ expect(importedAugmentation.file, file);
+ sink.write(idProvider.fileStateKind(importedAugmentation));
+ } else {
+ sink.write('notAugmentation ${idProvider.fileState(file)}');
+ }
+ sink.writeln();
+ } else {
+ sink.write(_indent);
+ sink.write('uri: ${_stringOfUriStr(augmentation.directive.uri)}');
+ sink.writeln();
+ }
+ },
+ );
}
void _writeByteStore() {
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index b121f74..5ac5829 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -686,7 +686,8 @@
kind: library_0
imports
library_3 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -701,7 +702,8 @@
library: library_0
imports
library_3 dart:core synthetic
- augmentations: file_2
+ augmentations
+ augmentation_2
referencingFiles: file_0
unlinkedKey: k01
/home/test/lib/c.dart
@@ -756,7 +758,8 @@
uriFile: file_0
imports
library_3 dart:core synthetic
- augmentations: file_2
+ augmentations
+ augmentation_2
unlinkedKey: k01
/home/test/lib/c.dart
uri: package:test/c.dart
@@ -799,7 +802,8 @@
kind: library_0
imports
library_3 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -853,7 +857,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -867,7 +872,8 @@
augmented: augmentation_1
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
referencingFiles: file_0 file_1
unlinkedKey: k01
libraryCycles
@@ -901,7 +907,8 @@
kind: library_0
imports
library_3 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -916,7 +923,8 @@
library: library_0
imports
library_3 dart:core synthetic
- augmentations: file_2
+ augmentations
+ augmentation_2
referencingFiles: file_0 file_2
unlinkedKey: k01
/home/test/lib/c.dart
@@ -928,7 +936,8 @@
library: library_0
imports
library_3 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
referencingFiles: file_1
unlinkedKey: k02
libraryCycles
@@ -936,7 +945,7 @@
''');
}
- test_newFile_augmentation_invalid() async {
+ test_newFile_augmentation_invalidRelativeUri() async {
final a = newFile('$testPackageLibPath/a.dart', r'''
library augment 'da:';
''');
@@ -978,7 +987,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -1130,7 +1140,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -1162,7 +1173,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -1175,7 +1187,8 @@
kind: library_7
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_2
dependencies: dart:core
libraries: library_7
@@ -1207,7 +1220,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -1220,7 +1234,8 @@
kind: library_8
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_3
dependencies: dart:core
libraries: library_8
@@ -1266,7 +1281,8 @@
kind: library_8
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_3
dependencies: dart:core
libraries: library_8
@@ -1354,7 +1370,8 @@
kind: library_11
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_6
dependencies: dart:core
libraries: library_11
@@ -1388,7 +1405,8 @@
kind: library_12
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_7
dependencies: dart:core
libraries: library_12
@@ -1401,7 +1419,8 @@
kind: library_11
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_6
dependencies: dart:core
libraries: library_11
@@ -1451,6 +1470,62 @@
''');
}
+ test_newFile_library_augmentations_invalidRelativeUri() async {
+ final a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'da:';
+''');
+
+ fileStateFor(a);
+
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: library_0
+ imports
+ library_1 dart:core synthetic
+ augmentations
+ uri: da:
+ cycle_0
+ dependencies: dart:core
+ libraries: library_0
+ apiSignature_0
+ unlinkedKey: k00
+libraryCycles
+elementFactory
+''');
+ }
+
+ test_newFile_library_augmentations_invalidRelativeUri_empty() {
+ final a = newFile('$testPackageLibPath/a.dart', r'''
+import augment '';
+''');
+
+ fileStateFor(a);
+
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: library_0
+ imports
+ library_1 dart:core synthetic
+ augmentations
+ uri: ''
+ cycle_0
+ dependencies: dart:core
+ libraries: library_0
+ apiSignature_0
+ unlinkedKey: k00
+libraryCycles
+elementFactory
+''');
+ }
+
test_newFile_library_dartCore() async {
final core = fsStateFor(testFile).getFileForUri(
Uri.parse('dart:core'),
@@ -3900,7 +3975,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -3927,6 +4003,7 @@
// Not an augmentation anymore, but a library.
// But `a.dart` still uses `b.dart` as an augmentation.
+ // TODO(scheglov) Any `augmentation_to_X` should change the signature.
assertDriverStateString(testFile, r'''
files
/home/test/lib/a.dart
@@ -3936,7 +4013,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -3970,7 +4048,8 @@
kind: library_8
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_3
dependencies: dart:core
libraries: library_8
@@ -4016,7 +4095,8 @@
name: my.lib
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -4059,7 +4139,8 @@
name: my.lib
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -4090,7 +4171,8 @@
name: my.lib
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_2
dependencies: dart:core
libraries: library_8
@@ -4167,7 +4249,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -4206,7 +4289,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -4235,7 +4319,8 @@
kind: library_8
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_2
dependencies: dart:core
libraries: library_8
@@ -4511,7 +4596,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ notAugmentation file_1
cycle_0
dependencies: dart:core
libraries: library_0
@@ -4551,7 +4637,8 @@
kind: library_0
imports
library_2 dart:core synthetic
- augmentations: file_1
+ augmentations
+ augmentation_7
cycle_0
dependencies: dart:core
libraries: library_0