Support for metadata on augmentation directives.
Change-Id: Id05c1e2bbee6f3adc3399168065bb31f7ddeebfe
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251589
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index fde98ef..eacb5ab 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -85,7 +85,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 234;
+ static const int DATA_VERSION = 235;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index cbe272d..687f6f6 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3933,13 +3933,12 @@
@override
List<AugmentationImportElement> get augmentationImports {
- linkedData?.read(this);
+ _readLinkedData();
return super.augmentationImports;
}
@override
List<ExportElement2> get exports2 {
- linkedData?.read(this);
return _exports2;
}
@@ -3948,7 +3947,7 @@
@override
List<ImportElement2> get imports2 {
- linkedData?.read(this);
+ _readLinkedData();
return _imports2;
}
@@ -3978,6 +3977,11 @@
T? accept<T>(ElementVisitor<T> visitor) {
return visitor.visitLibraryAugmentationElement(this);
}
+
+ @override
+ void _readLinkedData() {
+ augmented._readLinkedData();
+ }
}
/// A concrete implementation of a [LibraryElement].
@@ -4050,7 +4054,7 @@
@override
List<AugmentationImportElement> get augmentationImports {
- linkedData?.read(this);
+ _readLinkedData();
return super.augmentationImports;
}
@@ -4061,7 +4065,7 @@
@override
FunctionElement? get entryPoint {
- linkedData?.read(this);
+ _readLinkedData();
return _entryPoint;
}
@@ -4108,7 +4112,7 @@
@override
List<ExportElement2> get exports2 {
- linkedData?.read(this);
+ _readLinkedData();
return _exports2;
}
@@ -4142,7 +4146,7 @@
@override
List<ImportElement2> get imports2 {
- linkedData?.read(this);
+ _readLinkedData();
return _imports2;
}
@@ -4221,7 +4225,7 @@
@override
List<ElementAnnotation> get metadata {
- linkedData?.read(this);
+ _readLinkedData();
return super.metadata;
}
@@ -4446,6 +4450,11 @@
}
}
+ @override
+ void _readLinkedData() {
+ linkedData?.read(this);
+ }
+
static List<PrefixElement> buildPrefixesFromImports(
List<ImportElement2> imports) {
HashSet<PrefixElement> prefixes = HashSet<PrefixElement>();
@@ -4602,6 +4611,8 @@
safelyVisitChildren(imports2, visitor);
}
+ void _readLinkedData();
+
static List<PrefixElement> buildPrefixesFromImports(
List<ImportElement2> imports) {
HashSet<PrefixElement> prefixes = HashSet<PrefixElement>();
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 841cead..40c321b 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -350,55 +350,23 @@
}
}
-class LibraryAugmentationElementLinkedData
- extends LibraryOrAugmentationElementLinkedData<
- LibraryAugmentationElementImpl> {
+/// Not a [ElementLinkedData], just a bundle with data.
+class LibraryAugmentationElementLinkedData {
+ final int offset;
+ ApplyConstantOffsets? applyConstantOffsets;
+
LibraryAugmentationElementLinkedData({
- required super.reference,
- required super.libraryReader,
- required super.unitElement,
- required super.offset,
+ required this.offset,
});
-
- @override
- void read(ElementImpl element) {
- final libraryData = element.library?.linkedData;
- if (libraryData != null && !libraryData._isLocked) {
- super.read(element);
- }
- }
}
-class LibraryElementLinkedData
- extends LibraryOrAugmentationElementLinkedData<LibraryElementImpl> {
- LibraryElementLinkedData({
- required super.reference,
- required super.libraryReader,
- required super.unitElement,
- required super.offset,
- });
-
- @override
- void _readAdditional(element, reader) {
- for (final part in element.parts2) {
- part as PartElementImpl;
- part.metadata = reader._readAnnotationList(
- unitElement: unitElement,
- );
- }
-
- element.entryPoint = reader.readElement() as FunctionElement?;
- }
-}
-
-class LibraryOrAugmentationElementLinkedData<
- E extends LibraryOrAugmentationElementImpl> extends ElementLinkedData<E> {
+class LibraryElementLinkedData extends ElementLinkedData<LibraryElementImpl> {
ApplyConstantOffsets? applyConstantOffsets;
/// When we are applying offsets to a library, we want to lock it.
bool _isLocked = false;
- LibraryOrAugmentationElementLinkedData({
+ LibraryElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
@@ -428,6 +396,23 @@
@override
void _read(element, reader) {
+ _readLibraryOrAugmentation(element, reader);
+ for (final part in element.parts2) {
+ part as PartElementImpl;
+ part.metadata = reader._readAnnotationList(
+ unitElement: unitElement,
+ );
+ }
+
+ element.entryPoint = reader.readElement() as FunctionElement?;
+
+ applyConstantOffsets?.perform();
+ }
+
+ void _readLibraryOrAugmentation(
+ LibraryOrAugmentationElementImpl element,
+ ResolutionReader reader,
+ ) {
element.metadata = reader._readAnnotationList(
unitElement: unitElement,
);
@@ -454,14 +439,21 @@
}
}
- // TODO(scheglov) metadata on augmentation imports
-
- _readAdditional(element, reader);
-
- applyConstantOffsets?.perform();
+ for (var import in element.augmentationImports) {
+ import as AugmentationImportElementImpl;
+ import.metadata = reader._readAnnotationList(
+ // TODO(scheglov) Here and for parts, unit is not valid. Test and fix.
+ unitElement: unitElement,
+ );
+ final importedAugmentation = import.importedAugmentation;
+ if (importedAugmentation != null) {
+ final linkedData = importedAugmentation.linkedData!;
+ reader.setOffset(linkedData.offset);
+ _readLibraryOrAugmentation(importedAugmentation, reader);
+ linkedData.applyConstantOffsets?.perform();
+ }
+ }
}
-
- void _readAdditional(E element, ResolutionReader reader) {}
}
class LibraryReader {
@@ -570,9 +562,6 @@
_readLibraryOrAugmentationElement(augmentation);
augmentation.linkedData = LibraryAugmentationElementLinkedData(
- reference: _reference,
- libraryReader: this,
- unitElement: definingUnit,
offset: resolutionOffset,
);
@@ -1758,6 +1747,10 @@
return _reader.readUInt32();
}
+ void setOffset(int offset) {
+ _reader.offset = offset;
+ }
+
void _addFormalParameters(List<ParameterElement> parameters) {
for (var parameter in parameters) {
_localElements.add(parameter);
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 43a2151..d44e85a 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -124,6 +124,8 @@
void _writeAugmentationElement(LibraryAugmentationElement augmentation) {
augmentation as LibraryAugmentationElementImpl;
_writeUnitElement(augmentation.definingCompilationUnit);
+ // The offset where resolution for the augmentation starts.
+ // We need it to skip resolution information from the unit.
_sink.writeUInt30(_resolutionSink.offset);
_writeLibraryOrAugmentationElement(augmentation);
}
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index c21d763..1912980 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -751,8 +751,7 @@
@override
void visitLibraryAugmentationDirective(LibraryAugmentationDirective node) {
- // TODO: implement visitLibraryAugmentationDirective
- // super.visitLibraryAugmentationDirective(node);
+ _container.metadata = _buildAnnotations(node.metadata);
}
@override
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 95cb3b4..39e50e1 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -78,8 +78,13 @@
var unitReader = SummaryDataReader(unitInfoBytes);
var unitInfo = _InfoUnit(unitReader);
- if (i == 0) {
- _applyToLibrary(libraryElement, unitInfo);
+ final enclosing = unitElement.enclosingElement2;
+ if (enclosing is LibraryElementImpl) {
+ if (identical(enclosing.definingCompilationUnit, unitElement)) {
+ _applyToLibrary(enclosing, unitInfo);
+ }
+ } else if (enclosing is LibraryAugmentationElementImpl) {
+ _applyToAugmentation(enclosing, unitInfo);
}
unitElement.setCodeRange(unitInfo.codeOffset, unitInfo.codeLength);
@@ -176,6 +181,29 @@
);
}
+ void _applyToAugmentation(
+ LibraryAugmentationElementImpl element,
+ _InfoUnit info,
+ ) {
+ if (info.docComment.isNotEmpty) {
+ element.documentationComment = info.docComment;
+ }
+
+ _applyToImports(element, info);
+ _applyToExports(element, info);
+
+ var linkedData = element.linkedData as LibraryAugmentationElementLinkedData;
+ linkedData.applyConstantOffsets = ApplyConstantOffsets(
+ info.libraryConstantOffsets,
+ (applier) {
+ applier.applyToMetadata(element);
+ applier.applyToImports(element.imports2);
+ applier.applyToExports(element.exports2);
+ applier.applyToAugmentationImports(element.augmentationImports);
+ },
+ );
+ }
+
void _applyToClassDeclaration(
ClassElement element,
_InfoClassDeclaration info,
@@ -305,6 +333,21 @@
);
}
+ void _applyToExports(
+ LibraryOrAugmentationElementImpl element,
+ _InfoUnit info,
+ ) {
+ forCorrespondingPairs<ExportElement2, _InfoExport>(
+ element.exports_unresolved,
+ info.exports,
+ (element, info) {
+ element as ExportElement2Impl;
+ element.nameOffset = info.nameOffset;
+ _applyToCombinators(element.combinators, info.combinators);
+ },
+ );
+ }
+
void _applyToExtensionDeclaration(
ExtensionElement element,
_InfoClassDeclaration info,
@@ -442,14 +485,10 @@
);
}
- void _applyToLibrary(LibraryElementImpl element, _InfoUnit info) {
- element.nameOffset = info.libraryName.offset;
- element.nameLength = info.libraryName.length;
-
- if (info.docComment.isNotEmpty) {
- element.documentationComment = info.docComment;
- }
-
+ void _applyToImports(
+ LibraryOrAugmentationElementImpl element,
+ _InfoUnit info,
+ ) {
forCorrespondingPairs<ImportElement2, _InfoImport>(
element.imports_unresolved,
info.imports,
@@ -465,16 +504,18 @@
_applyToCombinators(element.combinators, info.combinators);
},
);
+ }
- forCorrespondingPairs<ExportElement2, _InfoExport>(
- element.exports_unresolved,
- info.exports,
- (element, info) {
- element as ExportElement2Impl;
- element.nameOffset = info.nameOffset;
- _applyToCombinators(element.combinators, info.combinators);
- },
- );
+ void _applyToLibrary(LibraryElementImpl element, _InfoUnit info) {
+ element.nameOffset = info.libraryName.offset;
+ element.nameLength = info.libraryName.length;
+
+ if (info.docComment.isNotEmpty) {
+ element.documentationComment = info.docComment;
+ }
+
+ _applyToImports(element, info);
+ _applyToExports(element, info);
forCorrespondingPairs<PartElement, _InfoPart>(
element.parts2,
@@ -491,6 +532,7 @@
applier.applyToMetadata(element);
applier.applyToImports(element.imports2);
applier.applyToExports(element.exports2);
+ applier.applyToAugmentationImports(element.augmentationImports);
applier.applyToPartDirectives(element.parts2);
},
);
@@ -1392,6 +1434,8 @@
metadata: firstDirective?.metadata,
importDirectives: unit.directives.whereType<ImportDirective>(),
exportDirectives: unit.directives.whereType<ExportDirective>(),
+ augmentationImportDirectives:
+ unit.directives.whereType<AugmentationImportDirective>(),
partDirectives: unit.directives.whereType<PartDirective>(),
);
}
@@ -1422,6 +1466,7 @@
NodeList<Annotation>? metadata,
Iterable<ImportDirective>? importDirectives,
Iterable<ExportDirective>? exportDirectives,
+ Iterable<AugmentationImportDirective>? augmentationImportDirectives,
Iterable<PartDirective>? partDirectives,
TypeParameterList? typeParameters,
FormalParameterList? formalParameters,
@@ -1468,6 +1513,7 @@
metadata?.accept(collector);
addDirectives(importDirectives);
addDirectives(exportDirectives);
+ addDirectives(augmentationImportDirectives);
addDirectives(partDirectives);
addTypeParameters(typeParameters);
addFormalParameters(formalParameters);
@@ -1588,7 +1634,6 @@
libraryName: _InfoLibraryName(reader),
libraryConstantOffsets: reader.readUInt30List(),
docComment: reader.readStringUtf8(),
- // TODO(scheglov)
imports: reader.readTypedList(
() => _InfoImport(reader),
),
@@ -1659,6 +1704,12 @@
_OffsetsApplier(this._iterator);
+ void applyToAugmentationImports(List<AugmentationImportElement> elements) {
+ for (var element in elements) {
+ applyToMetadata(element);
+ }
+ }
+
void applyToConstantInitializer(Element element) {
if (element is ConstFieldElementImpl && element.isEnumConstant) {
_applyToEnumConstantInitializer(element);
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index c9bab89..1c9331c 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -78,6 +78,24 @@
''');
}
+ test_augmentation_documented() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+/// My documentation.
+library augment 'test.dart';
+''');
+ final library = await buildLibrary(r'''
+import augment 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/a.dart
+ documentationComment: /// My documentation.
+ definingUnit
+ definingUnit
+''');
+ }
+
test_augmentation_libraryExports_library() async {
newFile('$testPackageLibPath/a.dart', r'''
library augment 'test.dart';
@@ -26283,6 +26301,149 @@
''');
}
+ test_metadata_augmentation_class() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+@deprecated
+class A {}
+''');
+ var library = await buildLibrary('''
+import augment 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/a.dart
+ definingUnit
+ classes
+ class A @47
+ metadata
+ Annotation
+ atSign: @ @29
+ name: SimpleIdentifier
+ token: deprecated @30
+ staticElement: dart:core::@getter::deprecated
+ staticType: null
+ element: dart:core::@getter::deprecated
+ constructors
+ synthetic @-1
+ definingUnit
+''');
+ }
+
+ test_metadata_augmentation_directive() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+@deprecated
+library augment 'test.dart';
+''');
+ var library = await buildLibrary(r'''
+import augment 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/a.dart
+ metadata
+ Annotation
+ atSign: @ @0
+ name: SimpleIdentifier
+ token: deprecated @1
+ staticElement: dart:core::@getter::deprecated
+ staticType: null
+ element: dart:core::@getter::deprecated
+ definingUnit
+ definingUnit
+''');
+ }
+
+ test_metadata_augmentation_exportLibrary() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+@deprecated
+export 'dart:math';
+''');
+ var library = await buildLibrary('''
+import augment 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/a.dart
+ exports
+ dart:math
+ metadata
+ Annotation
+ atSign: @ @29
+ name: SimpleIdentifier
+ token: deprecated @30
+ staticElement: dart:core::@getter::deprecated
+ staticType: null
+ element: dart:core::@getter::deprecated
+ definingUnit
+ definingUnit
+''');
+ }
+
+ test_metadata_augmentation_importAugmentation() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'b.dart';
+''');
+ newFile('$testPackageLibPath/b.dart', r'''
+library augment 'test.dart';
+@deprecated
+import augment 'a.dart';
+''');
+ var library = await buildLibrary('''
+import augment 'b.dart';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/b.dart
+ augmentationImports
+ package:test/a.dart
+ metadata
+ Annotation
+ atSign: @ @29
+ name: SimpleIdentifier
+ token: deprecated @30
+ staticElement: dart:core::@getter::deprecated
+ staticType: null
+ element: dart:core::@getter::deprecated
+ definingUnit
+ definingUnit
+ definingUnit
+''');
+ }
+
+ test_metadata_augmentation_importLibrary() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+@deprecated
+import 'dart:math';
+''');
+ var library = await buildLibrary('''
+import augment 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/a.dart
+ imports
+ dart:math
+ metadata
+ Annotation
+ atSign: @ @29
+ name: SimpleIdentifier
+ token: deprecated @30
+ staticElement: dart:core::@getter::deprecated
+ staticType: null
+ element: dart:core::@getter::deprecated
+ definingUnit
+ definingUnit
+''');
+ }
+
test_metadata_class_field_first() async {
var library = await buildLibrary(r'''
const a = 0;
@@ -28841,6 +29002,53 @@
''');
}
+ test_metadata_library_importAugmentation_augmentation() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+''');
+ var library = await buildLibrary('''
+@deprecated
+import augment 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/a.dart
+ metadata
+ Annotation
+ atSign: @ @0
+ name: SimpleIdentifier
+ token: deprecated @1
+ staticElement: dart:core::@getter::deprecated
+ staticType: null
+ element: dart:core::@getter::deprecated
+ definingUnit
+ definingUnit
+''');
+ }
+
+ /// Even though the target is not an augmentation, metadata is available.
+ test_metadata_library_importAugmentation_notAugmentation_library() async {
+ var library = await buildLibrary('''
+@deprecated
+import augment 'dart:math';
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ source 'dart:math'
+ metadata
+ Annotation
+ atSign: @ @0
+ name: SimpleIdentifier
+ token: deprecated @1
+ staticElement: dart:core::@getter::deprecated
+ staticType: null
+ element: dart:core::@getter::deprecated
+ definingUnit
+''');
+ }
+
test_metadata_libraryDirective() async {
var library = await buildLibrary('@a library L; const a = null;');
checkElementText(library, r'''