Macro. Build actual augmentation library after the types phase.
Change-Id: Iad7825acbf42d91e0cea4cc974a6be564a2b959d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/326243
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index bd51cdd..cd5dec6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -88,7 +88,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 = 305;
+ static const int DATA_VERSION = 306;
/// 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 70183be..b1723cb 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
+import 'dart:typed_data';
import 'package:_fe_analyzer_shared/src/scanner/string_canonicalizer.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart'
@@ -3951,6 +3952,8 @@
@override
final LibraryOrAugmentationElementImpl augmentationTarget;
+ MacroGenerationAugmentationLibrary? macroGenerated;
+
LibraryAugmentationElementLinkedData? linkedData;
LibraryAugmentationElementImpl({
@@ -4800,6 +4803,17 @@
visitor.visitLocalVariableElement(this);
}
+/// Additional information for a macro generated augmentation library.
+class MacroGenerationAugmentationLibrary {
+ final String code;
+ final Uint8List informativeBytes;
+
+ MacroGenerationAugmentationLibrary({
+ required this.code,
+ required this.informativeBytes,
+ });
+}
+
mixin MacroTargetElement {
/// Errors registered while applying macros to this element.
List<MacroApplicationError> macroApplicationErrors = const [];
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index efb73e7..ecbd9bf 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -633,6 +633,13 @@
required LibraryOrAugmentationElementImpl augmentationTarget,
required Source unitSource,
}) {
+ final macroGenerated = _reader.readOptionalObject((reader) {
+ return MacroGenerationAugmentationLibrary(
+ code: _reader.readStringUtf8(),
+ informativeBytes: _reader.readUint8List(),
+ );
+ });
+
final definingUnit = _readUnitElement(
containerSource: unitSource,
unitSource: unitSource,
@@ -645,6 +652,7 @@
);
augmentation.definingCompilationUnit = definingUnit;
augmentation.reference = definingUnit.reference!;
+ augmentation.macroGenerated = macroGenerated;
final resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
_readLibraryOrAugmentationElement(augmentation);
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 4531795..4619a84 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -140,6 +140,10 @@
}
void _writeAugmentationElement(LibraryAugmentationElementImpl augmentation) {
+ _sink.writeOptionalObject(augmentation.macroGenerated, (macroGenerated) {
+ _sink.writeStringUtf8(macroGenerated.code);
+ _sink.writeUint8List(macroGenerated.informativeBytes);
+ });
_writeUnitElement(augmentation.definingCompilationUnit);
// The offset where resolution for the augmentation starts.
// We need it to skip resolution information from the unit.
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index f0c8cbb..a507142 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -76,8 +76,7 @@
var unitElements = libraryElement.units;
for (var i = 0; i < unitElements.length; i++) {
var unitElement = unitElements[i];
- var unitUri = unitElement.source.uri;
- var unitInfoBytes = _unitsInformativeBytes2[unitUri];
+ var unitInfoBytes = _getInfoUnitBytes(unitElement);
if (unitInfoBytes != null) {
var unitReader = SummaryDataReader(unitInfoBytes);
var unitInfo = _InfoUnit(_infoDeclarationStore, unitReader);
@@ -706,6 +705,20 @@
);
}
+ Uint8List? _getInfoUnitBytes(CompilationUnitElement element) {
+ final uri = element.source.uri;
+ if (_unitsInformativeBytes2[uri] case final bytes?) {
+ return bytes;
+ }
+
+ switch (element.enclosingElement) {
+ case LibraryAugmentationElementImpl(:final macroGenerated?):
+ return macroGenerated.informativeBytes;
+ }
+
+ return null;
+ }
+
void _setupApplyConstantOffsetsForTypeAlias(
TypeAliasElementImpl element,
Uint32List constantOffsets, {
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 045b2ed..0e44db6 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -20,6 +20,7 @@
import 'package:analyzer/src/summary2/default_value_resolver.dart';
import 'package:analyzer/src/summary2/element_builder.dart';
import 'package:analyzer/src/summary2/export.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/macro_application.dart';
import 'package:analyzer/src/summary2/metadata_resolver.dart';
@@ -276,6 +277,31 @@
}
}
+ void buildClassSyntheticConstructors() {
+ bool hasConstructor(ClassElementImpl element) {
+ if (element.constructors.isNotEmpty) return true;
+ if (element.augmentation case final augmentation?) {
+ return hasConstructor(augmentation);
+ }
+ return false;
+ }
+
+ for (final classElement in element.topLevelElements) {
+ if (classElement is! ClassElementImpl) continue;
+ if (classElement.isMixinApplication) continue;
+ if (classElement.isAugmentation) continue;
+ if (hasConstructor(classElement)) continue;
+
+ final constructor = ConstructorElementImpl('', -1)..isSynthetic = true;
+ final containerRef = classElement.reference!.getChild('@constructor');
+ final reference = containerRef.getChild('new');
+ reference.element = constructor;
+ constructor.reference = reference;
+
+ classElement.constructors = [constructor].toFixedList();
+ }
+ }
+
/// Build elements for declarations in the library units, add top-level
/// declarations to the local scope, for combining into export scopes.
void buildElements() {
@@ -296,7 +322,6 @@
}
elementBuilder.buildDeclarationElements(linkingUnit.node);
}
- _buildClassSyntheticConstructors();
_declareDartCoreDynamicNever();
}
@@ -453,74 +478,89 @@
},
);
- final augmentationLibrary = await performance.runAsync(
+ final augmentationCode = await performance.runAsync(
'executeTypesPhase',
(performance) async {
return await macroApplier.executeTypesPhase();
},
);
- if (augmentationLibrary == null) {
+ if (augmentationCode == null) {
return;
}
- var parseResult = parseString(
- content: augmentationLibrary,
+ final libraryFileName = uri.pathSegments.lastOrNull;
+ if (libraryFileName == null) {
+ return;
+ }
+
+ if (!libraryFileName.endsWith('.dart')) {
+ return;
+ }
+
+ final augmentationFileName =
+ '${libraryFileName.substring(0, '.dart'.length - 1)}.macro.dart';
+ final augmentationUri = uri.resolve(augmentationFileName);
+ final augmentationUriStr = '$augmentationUri';
+ final augmentationSource = _sourceFactory.forUri2(augmentationUri)!;
+
+ final parseResult = parseString(
+ content: augmentationCode,
featureSet: element.featureSet,
throwIfDiagnostics: false,
);
- var unitNode = parseResult.unit as ast.CompilationUnitImpl;
+ final unitNode = parseResult.unit as ast.CompilationUnitImpl;
- // For now we model augmentation libraries as parts.
- var unitUri = uri.resolve('_macro_types.dart');
- final unitSource = _sourceFactory.forUri2(unitUri)!;
- var unitElement = CompilationUnitElementImpl(
- source: unitSource,
- librarySource: element.source,
+ final unitElement = CompilationUnitElementImpl(
+ source: augmentationSource,
+ librarySource: augmentationSource,
lineInfo: parseResult.lineInfo,
- )
- ..enclosingElement = element
- ..isSynthetic = true
- ..uri = unitUri.toString();
+ );
+ unitElement.uri = augmentationUriStr;
- var unitReference = reference.getChild('@unit').getChild('$unitUri');
- _bindReference(unitReference, unitElement);
+ final augmentationReference =
+ reference.getChild('@augmentation').getChild(augmentationUriStr);
+ _bindReference(augmentationReference, unitElement);
- element.parts = [
- ...element.parts,
- PartElementImpl(
- uri: DirectiveUriWithUnitImpl(
- relativeUriString: '_macro_types.dart',
- relativeUri: unitUri,
- unit: unitElement,
- ),
+ final augmentation = LibraryAugmentationElementImpl(
+ augmentationTarget: element,
+ nameOffset: -1,
+ );
+ augmentation.definingCompilationUnit = unitElement;
+
+ augmentation.macroGenerated = MacroGenerationAugmentationLibrary(
+ code: augmentationCode,
+ informativeBytes: writeUnitInformative(unitNode),
+ );
+
+ final directiveUri = DirectiveUriWithAugmentationImpl(
+ relativeUriString: augmentationUriStr,
+ relativeUri: augmentationUri,
+ source: augmentationSource,
+ augmentation: augmentation,
+ );
+
+ element.augmentationImports = [
+ ...element.augmentationImports,
+ AugmentationImportElementImpl(
+ importKeywordOffset: -1,
+ uri: directiveUri,
),
];
ElementBuilder(
libraryBuilder: this,
- container: element,
- unitReference: unitReference,
+ container: augmentation,
+ unitReference: augmentationReference,
unitElement: unitElement,
).buildDeclarationElements(unitNode);
- // We move elements, so they don't have real offsets.
- unitElement.accept(_FlushElementOffsets());
-
units.add(
LinkingUnit(
- reference: unitReference,
+ reference: augmentationReference,
node: unitNode,
- container: element,
element: unitElement,
- ),
- );
-
- linker.macroGeneratedUnits.add(
- LinkMacroGeneratedUnit(
- uri: unitUri,
- content: parseResult.content,
- unit: parseResult.unit,
+ container: element,
),
);
}
@@ -692,31 +732,6 @@
);
}
- void _buildClassSyntheticConstructors() {
- bool hasConstructor(ClassElementImpl element) {
- if (element.constructors.isNotEmpty) return true;
- if (element.augmentation case final augmentation?) {
- return hasConstructor(augmentation);
- }
- return false;
- }
-
- for (final classElement in element.topLevelElements) {
- if (classElement is! ClassElementImpl) continue;
- if (classElement.isMixinApplication) continue;
- if (classElement.isAugmentation) continue;
- if (hasConstructor(classElement)) continue;
-
- final constructor = ConstructorElementImpl('', -1)..isSynthetic = true;
- final containerRef = classElement.reference!.getChild('@constructor');
- final reference = containerRef.getChild('new');
- reference.element = constructor;
- constructor.reference = reference;
-
- classElement.constructors = [constructor].toFixedList();
- }
- }
-
List<NamespaceCombinator> _buildCombinators(
List<UnlinkedCombinator> combinators2,
) {
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 4175031..f5b1128 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -42,7 +42,6 @@
);
return LinkResult(
resolutionBytes: linker.resolutionBytes,
- macroGeneratedUnits: linker.macroGeneratedUnits,
);
}
@@ -60,8 +59,6 @@
late Uint8List resolutionBytes;
- final List<LinkMacroGeneratedUnit> macroGeneratedUnits = [];
-
Linker(this.elementFactory, this.macroExecutor);
AnalysisContextImpl get analysisContext {
@@ -181,6 +178,10 @@
},
);
+ for (final library in builders.values) {
+ library.buildClassSyntheticConstructors();
+ }
+
macroDeclarationBuilder.transferToElements();
for (var library in builders.values) {
@@ -319,24 +320,10 @@
}
}
-class LinkMacroGeneratedUnit {
- final Uri uri;
- final String content;
- final ast.CompilationUnit unit;
-
- LinkMacroGeneratedUnit({
- required this.uri,
- required this.content,
- required this.unit,
- });
-}
-
class LinkResult {
final Uint8List resolutionBytes;
- final List<LinkMacroGeneratedUnit> macroGeneratedUnits;
LinkResult({
required this.resolutionBytes,
- required this.macroGeneratedUnits,
});
}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 54a2ab8..df74712 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -671,6 +671,15 @@
_writeElements('exports', e.libraryExports, _writeExportElement);
+ if (e is LibraryAugmentationElementImpl) {
+ if (e.macroGenerated case final macroGenerated?) {
+ _sink.writelnWithIndent('macroGeneratedCode');
+ _sink.writeln('---');
+ _sink.writeln(macroGenerated.code);
+ _sink.writeln('---');
+ }
+ }
+
_sink.writelnWithIndent('definingUnit');
_sink.withIndent(() {
_writeUnitElement(e.definingCompilationUnit);
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index edbe5a6..cbcaa8c 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -103,7 +103,7 @@
class A {}
''');
- configuration.withExportScope = true;
+ configuration.withMetadata = false;
checkElementText(library, r'''
library
imports
@@ -111,29 +111,19 @@
definingUnit
classes
class A @35
- metadata
- Annotation
- atSign: @ @18
- name: SimpleIdentifier
- token: MyMacro @19
- staticElement: package:test/a.dart::@class::MyMacro
- staticType: null
- arguments: ArgumentList
- leftParenthesis: ( @26
- rightParenthesis: ) @27
- element: package:test/a.dart::@class::MyMacro::@constructor::new
constructors
synthetic @-1
- parts
- package:test/_macro_types.dart
- classes
- class MyClass @-1
- exportedReferences
- declared self::@class::MyClass
- declared self::@class::A
- exportNamespace
- A: self::@class::A
- MyClass: self::@class::MyClass
+ augmentationImports
+ package:test/test.macro.dart
+ macroGeneratedCode
+---
+class MyClass {}
+---
+ definingUnit
+ classes
+ class MyClass @6
+ constructors
+ synthetic @-1
''');
}
@@ -161,7 +151,7 @@
class A {}
''');
- configuration.withExportScope = true;
+ configuration.withMetadata = false;
checkElementText(library, r'''
library
imports
@@ -169,37 +159,19 @@
definingUnit
classes
class A @41
- metadata
- Annotation
- atSign: @ @18
- name: PrefixedIdentifier
- prefix: SimpleIdentifier
- token: MyMacro @19
- staticElement: package:test/a.dart::@class::MyMacro
- staticType: null
- period: . @26
- identifier: SimpleIdentifier
- token: named @27
- staticElement: package:test/a.dart::@class::MyMacro::@constructor::named
- staticType: null
- staticElement: package:test/a.dart::@class::MyMacro::@constructor::named
- staticType: null
- arguments: ArgumentList
- leftParenthesis: ( @32
- rightParenthesis: ) @33
- element: package:test/a.dart::@class::MyMacro::@constructor::named
constructors
synthetic @-1
- parts
- package:test/_macro_types.dart
- classes
- class MyClass @-1
- exportedReferences
- declared self::@class::MyClass
- declared self::@class::A
- exportNamespace
- A: self::@class::A
- MyClass: self::@class::MyClass
+ augmentationImports
+ package:test/test.macro.dart
+ macroGeneratedCode
+---
+class MyClass {}
+---
+ definingUnit
+ classes
+ class MyClass @6
+ constructors
+ synthetic @-1
''');
}
@@ -226,7 +198,7 @@
class A {}
''');
- configuration.withExportScope = true;
+ configuration.withMetadata = false;
checkElementText(library, r'''
library
imports
@@ -234,37 +206,19 @@
definingUnit
classes
class A @52
- metadata
- Annotation
- atSign: @ @28
- name: PrefixedIdentifier
- prefix: SimpleIdentifier
- token: prefix @29
- staticElement: self::@prefix::prefix
- staticType: null
- period: . @35
- identifier: SimpleIdentifier
- token: MyMacro @36
- staticElement: package:test/a.dart::@class::MyMacro
- staticType: null
- staticElement: package:test/a.dart::@class::MyMacro
- staticType: null
- arguments: ArgumentList
- leftParenthesis: ( @43
- rightParenthesis: ) @44
- element: package:test/a.dart::@class::MyMacro::@constructor::new
constructors
synthetic @-1
- parts
- package:test/_macro_types.dart
- classes
- class MyClass @-1
- exportedReferences
- declared self::@class::MyClass
- declared self::@class::A
- exportNamespace
- A: self::@class::A
- MyClass: self::@class::MyClass
+ augmentationImports
+ package:test/test.macro.dart
+ macroGeneratedCode
+---
+class MyClass {}
+---
+ definingUnit
+ classes
+ class MyClass @6
+ constructors
+ synthetic @-1
''');
}
@@ -291,7 +245,7 @@
class A {}
''');
- configuration.withExportScope = true;
+ configuration.withMetadata = false;
checkElementText(library, r'''
library
imports
@@ -299,42 +253,19 @@
definingUnit
classes
class A @58
- metadata
- Annotation
- atSign: @ @28
- name: PrefixedIdentifier
- prefix: SimpleIdentifier
- token: prefix @29
- staticElement: self::@prefix::prefix
- staticType: null
- period: . @35
- identifier: SimpleIdentifier
- token: MyMacro @36
- staticElement: package:test/a.dart::@class::MyMacro
- staticType: null
- staticElement: package:test/a.dart::@class::MyMacro
- staticType: null
- period: . @43
- constructorName: SimpleIdentifier
- token: named @44
- staticElement: package:test/a.dart::@class::MyMacro::@constructor::named
- staticType: null
- arguments: ArgumentList
- leftParenthesis: ( @49
- rightParenthesis: ) @50
- element: package:test/a.dart::@class::MyMacro::@constructor::named
constructors
synthetic @-1
- parts
- package:test/_macro_types.dart
- classes
- class MyClass @-1
- exportedReferences
- declared self::@class::MyClass
- declared self::@class::A
- exportNamespace
- A: self::@class::A
- MyClass: self::@class::MyClass
+ augmentationImports
+ package:test/test.macro.dart
+ macroGeneratedCode
+---
+class MyClass {}
+---
+ definingUnit
+ classes
+ class MyClass @6
+ constructors
+ synthetic @-1
''');
}
@@ -1449,8 +1380,9 @@
}
if (expected != null) {
- final partUri = library.parts.single.uri as DirectiveUriWithUnit;
- final x = partUri.unit.topLevelVariables.single;
+ final macroAugmentation = library.augmentations.first;
+ final macroUnit = macroAugmentation.definingCompilationUnit;
+ final x = macroUnit.topLevelVariables.single;
expect(x.name, 'x');
x as ConstTopLevelVariableElementImpl;
final actual = (x.constantInitializer as SimpleStringLiteral).value;
@@ -1506,8 +1438,9 @@
library.definingCompilationUnit.getClass('A'),
);
- final partUri = library.parts.single.uri as DirectiveUriWithUnit;
- final x = partUri.unit.topLevelVariables.single;
+ final macroAugmentation = library.augmentations.first;
+ final macroUnit = macroAugmentation.definingCompilationUnit;
+ final x = macroUnit.topLevelVariables.single;
expect(x.name, 'x');
x as ConstTopLevelVariableElementImpl;
var x_literal = x.constantInitializer as SimpleStringLiteral;