Restore building types from macros.

Now that we can be async during linking, we can re-apply it.

Change-Id: I6a5bfb1881e4e04028fcaa75c43407699483d5d5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/240781
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov
2022-04-11 17:48:51 +00:00
committed by Commit Bot
parent cd005ecdd4
commit 425fb22638
12 changed files with 412 additions and 25 deletions
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
as macro;
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/context_locator.dart';
import 'package:analyzer/dart/analysis/declared_variables.dart';
@@ -22,6 +24,9 @@ class AnalysisContextCollectionImpl implements AnalysisContextCollection {
/// The resource provider used to access the file system.
final ResourceProvider resourceProvider;
/// The instance of macro executor that is used for all macros.
final macro.MultiMacroExecutor? macroExecutor = macro.MultiMacroExecutor();
/// The list of analysis contexts.
@override
final List<DriverBasedAnalysisContext> contexts = [];
@@ -77,6 +82,7 @@ class AnalysisContextCollectionImpl implements AnalysisContextCollection {
updateAnalysisOptions: updateAnalysisOptions,
fileContentCache: fileContentCache,
macroKernelBuilder: macroKernelBuilder,
macroExecutor: macroExecutor,
);
contexts.add(context);
}
@@ -109,6 +115,13 @@ class AnalysisContextCollectionImpl implements AnalysisContextCollection {
throw StateError('Unable to find the context to $path');
}
void dispose() {
for (var analysisContext in contexts) {
analysisContext.driver.dispose();
}
macroExecutor?.close();
}
/// Check every element with [_throwIfNotAbsoluteNormalizedPath].
void _throwIfAnyNotAbsoluteNormalizedPath(List<String> paths) {
for (var path in paths) {
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
as macro;
import 'package:analyzer/dart/analysis/context_builder.dart';
import 'package:analyzer/dart/analysis/context_root.dart';
import 'package:analyzer/dart/analysis/declared_variables.dart';
@@ -60,6 +62,7 @@ class ContextBuilderImpl implements ContextBuilder {
void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
FileContentCache? fileContentCache,
MacroKernelBuilder? macroKernelBuilder,
macro.MultiMacroExecutor? macroExecutor,
}) {
// TODO(scheglov) Remove this, and make `sdkPath` required.
sdkPath ??= getSdkPath();
@@ -118,6 +121,7 @@ class ContextBuilderImpl implements ContextBuilder {
retainDataForTesting: retainDataForTesting,
fileContentCache: fileContentCache,
macroKernelBuilder: macroKernelBuilder,
macroExecutor: macroExecutor,
);
if (declaredVariables != null) {
@@ -5,6 +5,8 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
as macro;
import 'package:analyzer/dart/analysis/analysis_context.dart' as api;
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/results.dart';
@@ -124,6 +126,9 @@ class AnalysisDriver implements AnalysisDriverGeneric {
final MacroKernelBuilder? macroKernelBuilder;
/// The instance of macro executor that is used for all macros.
final macro.MultiMacroExecutor? macroExecutor;
/// The declared environment variables.
DeclaredVariables declaredVariables = DeclaredVariables();
@@ -258,6 +263,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
required AnalysisOptionsImpl analysisOptions,
required Packages packages,
this.macroKernelBuilder,
this.macroExecutor,
FileContentCache? fileContentCache,
this.enableIndex = false,
SummaryDataStore? externalSummaries,
@@ -325,6 +331,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
declaredVariables: declaredVariables,
sourceFactory: _sourceFactory,
macroKernelBuilder: macroKernelBuilder,
macroExecutor: macroExecutor,
externalSummaries: _externalSummaries,
fileSystemState: _fsState,
);
@@ -525,6 +532,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
/// periodically.
@visibleForTesting
void clearLibraryContext() {
_libraryContext?.dispose();
_libraryContext = null;
}
@@ -578,6 +586,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
@override
void dispose() {
_scheduler.remove(this);
clearLibraryContext();
}
/// Return the cached [ResolvedUnitResult] for the Dart file with the given
@@ -4,6 +4,8 @@
import 'dart:typed_data';
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
as macro;
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/element/element.dart'
show CompilationUnitElement, LibraryElement;
@@ -43,6 +45,7 @@ class LibraryContext {
final ByteStore byteStore;
final FileSystemState fileSystemState;
final MacroKernelBuilder? macroKernelBuilder;
final macro.MultiMacroExecutor? macroExecutor;
final SummaryDataStore store = SummaryDataStore();
late final AnalysisContextImpl analysisContext;
@@ -57,7 +60,8 @@ class LibraryContext {
required AnalysisOptionsImpl analysisOptions,
required DeclaredVariables declaredVariables,
required SourceFactory sourceFactory,
this.macroKernelBuilder,
required this.macroKernelBuilder,
required this.macroExecutor,
required SummaryDataStore? externalSummaries,
}) {
var synchronousSession =
@@ -92,6 +96,10 @@ class LibraryContext {
return element as CompilationUnitElement;
}
void dispose() {
elementFactory.dispose();
}
/// Get the [LibraryElement] for the given library.
LibraryElement getLibraryElement(Uri uri) {
_createElementFactoryTypeProvider();
@@ -206,7 +214,8 @@ class LibraryContext {
LinkResult linkResult;
try {
timerLinking.start();
linkResult = await link(elementFactory, inputLibraries);
linkResult = await link(elementFactory, inputLibraries,
macroExecutor: macroExecutor);
librariesLinked += cycle.libraries.length;
counterLinkedLibraries += inputLibraries.length;
timerLinking.stop();
@@ -236,12 +245,31 @@ class LibraryContext {
final macroKernelBuilder = this.macroKernelBuilder;
if (macroKernelBuilder != null && macroLibraries.isNotEmpty) {
var macroKernelKey = cycle.transitiveSignature + '.macro_kernel';
var macroKernelBytes = macroKernelBuilder.build(
fileSystem: _MacroFileSystem(fileSystemState),
libraries: macroLibraries,
);
byteStore.put(macroKernelKey, macroKernelBytes);
bytesPut += macroKernelBytes.length;
var macroKernelBytes = byteStore.get(macroKernelKey);
if (macroKernelBytes == null) {
macroKernelBytes = macroKernelBuilder.build(
fileSystem: _MacroFileSystem(fileSystemState),
libraries: macroLibraries,
);
byteStore.put(macroKernelKey, macroKernelBytes);
bytesPut += macroKernelBytes.length;
} else {
bytesGet += macroKernelBytes.length;
}
final macroExecutor = this.macroExecutor;
if (macroExecutor != null) {
var bundleMacroExecutor = BundleMacroExecutor(
macroExecutor: macroExecutor,
kernelBytes: macroKernelBytes,
libraries: cycle.libraries.map((e) => e.uri).toSet(),
);
for (var libraryFile in cycle.libraries) {
var libraryUriStr = libraryFile.uriStr;
var libraryElement = elementFactory.libraryOfUri2(libraryUriStr);
libraryElement.bundleMacroExecutor = bundleMacroExecutor;
}
}
}
}
@@ -40,6 +40,7 @@ import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/inference_error.dart';
import 'package:collection/collection.dart';
@@ -3678,6 +3679,9 @@ class LibraryElementImpl extends _ExistingElementImpl
/// The scope of this library, `null` if it has not been created yet.
LibraryScope? _scope;
/// The macro executor for the bundle to which this library belongs.
BundleMacroExecutor? bundleMacroExecutor;
/// Initialize a newly created library element in the given [context] to have
/// the given [name] and [offset].
LibraryElementImpl(this.context, this.session, String name, int offset,
@@ -2,18 +2,22 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart' as ast;
import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary2/combinator.dart';
import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
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/link.dart';
import 'package:analyzer/src/summary2/macro_application.dart';
import 'package:analyzer/src/summary2/metadata_resolver.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/reference_resolver.dart';
@@ -57,6 +61,10 @@ class LibraryBuilder {
required this.units,
});
SourceFactory get _sourceFactory {
return linker.elementFactory.analysisContext.sourceFactory;
}
void addExporters() {
for (var element in element.exports) {
var exportedLibrary = element.exportedLibrary;
@@ -169,6 +177,55 @@ class LibraryBuilder {
}
}
Future<void> executeMacroTypesPhase() async {
if (!element.featureSet.isEnabled(Feature.macros)) {
return;
}
var applier = LibraryMacroApplier(this);
var augmentationLibrary = await applier.executeMacroTypesPhase();
if (augmentationLibrary == null) {
return;
}
var parseResult = parseString(
content: augmentationLibrary,
featureSet: element.featureSet,
throwIfDiagnostics: false,
);
var unitNode = parseResult.unit as ast.CompilationUnitImpl;
// For now we model augmentation libraries as parts.
var unitUri = uri.resolve('_macro_types.dart');
var unitElement = CompilationUnitElementImpl(
source: _sourceFactory.forUri2(unitUri)!,
librarySource: element.source,
lineInfo: parseResult.lineInfo,
)
..enclosingElement = element
..isSynthetic = true;
var unitReference = reference.getChild('@unit').getChild('$unitUri');
_bindReference(unitReference, unitElement);
element.parts.add(unitElement);
ElementBuilder(
libraryBuilder: this,
unitReference: unitReference,
unitElement: unitElement,
).buildDeclarationElements(unitNode);
units.add(
LinkingUnit(
isDefiningUnit: false,
reference: unitReference,
node: unitNode,
element: unitElement,
),
);
}
void resolveConstructors() {
ConstructorInitializerResolver(linker, element).resolve();
}
@@ -281,7 +338,6 @@ class LibraryBuilder {
unitElements.add(unitElement);
linkingUnits.add(
LinkingUnit(
input: inputUnit,
isDefiningUnit: isDefiningUnit,
reference: unitReference,
node: unitNode,
@@ -312,14 +368,12 @@ class LibraryBuilder {
}
class LinkingUnit {
final LinkInputUnit input;
final bool isDefiningUnit;
final Reference reference;
final ast.CompilationUnitImpl node;
final CompilationUnitElementImpl element;
LinkingUnit({
required this.input,
required this.isDefiningUnit,
required this.reference,
required this.node,
+18 -10
View File
@@ -4,6 +4,8 @@
import 'dart:typed_data';
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
as macro;
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
@@ -28,10 +30,11 @@ var timerLinkingLinkingBundle = Stopwatch();
/// Note that AST units and tokens of [inputLibraries] will be damaged.
Future<LinkResult> link(
LinkedElementFactory elementFactory,
List<LinkInputLibrary> inputLibraries,
) async {
var linker = Linker(elementFactory);
linker.link(inputLibraries);
List<LinkInputLibrary> inputLibraries, {
macro.MultiMacroExecutor? macroExecutor,
}) async {
var linker = Linker(elementFactory, macroExecutor);
await linker.link(inputLibraries);
return LinkResult(
resolutionBytes: linker.resolutionBytes,
);
@@ -48,6 +51,7 @@ Future<LinkResult> link2(
class Linker {
final LinkedElementFactory elementFactory;
final macro.MultiMacroExecutor? macroExecutor;
/// Libraries that are being linked.
final Map<Uri, LibraryBuilder> builders = {};
@@ -58,7 +62,7 @@ class Linker {
late Uint8List resolutionBytes;
Linker(this.elementFactory);
Linker(this.elementFactory, this.macroExecutor);
AnalysisContextImpl get analysisContext {
return elementFactory.analysisContext;
@@ -81,12 +85,12 @@ class Linker {
return elementNodes[element];
}
void link(List<LinkInputLibrary> inputLibraries) {
Future<void> link(List<LinkInputLibrary> inputLibraries) async {
for (var inputLibrary in inputLibraries) {
LibraryBuilder.build(this, inputLibrary);
}
_buildOutlines();
await _buildOutlines();
timerLinkingLinkingBundle.start();
_writeLibraries();
@@ -99,9 +103,9 @@ class Linker {
}
}
void _buildOutlines() {
Future<void> _buildOutlines() async {
_createTypeSystemIfNotLinkingDartCore();
_computeLibraryScopes();
await _computeLibraryScopes();
_createTypeSystem();
_resolveTypes();
_buildEnumChildren();
@@ -121,11 +125,15 @@ class Linker {
}
}
void _computeLibraryScopes() {
Future<void> _computeLibraryScopes() async {
for (var library in builders.values) {
library.buildElements();
}
for (var library in builders.values) {
await library.executeMacroTypesPhase();
}
for (var library in builders.values) {
library.buildInitialExportScope();
}
@@ -114,6 +114,12 @@ class LinkedElementFactory {
}
}
void dispose() {
for (var libraryReference in rootReference.children) {
_disposeLibrary(libraryReference.element);
}
}
Element? elementOfReference(Reference reference) {
if (reference.element != null) {
return reference.element;
@@ -184,7 +190,8 @@ class LinkedElementFactory {
void removeLibraries(Set<String> uriStrSet) {
for (var uriStr in uriStrSet) {
_libraryReaders.remove(uriStr);
rootReference.removeChild(uriStr);
var libraryReference = rootReference.removeChild(uriStr);
_disposeLibrary(libraryReference?.element);
}
analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
@@ -238,4 +245,10 @@ class LinkedElementFactory {
libraryElement.createLoadLibraryFunction();
}
void _disposeLibrary(Element? libraryElement) {
if (libraryElement is LibraryElementImpl) {
libraryElement.bundleMacroExecutor?.dispose();
}
}
}
+82
View File
@@ -2,10 +2,72 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:isolate';
import 'dart:typed_data';
import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
as isolated_executor;
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart'
as macro;
import 'package:path/path.dart' as package_path;
export 'package:_fe_analyzer_shared/src/macros/executor.dart' show Arguments;
class BundleMacroExecutor {
final macro.MultiMacroExecutor macroExecutor;
late final macro.ExecutorFactoryToken _executorFactoryToken;
final Uint8List kernelBytes;
Uri? _kernelUriCached;
BundleMacroExecutor({
required this.macroExecutor,
required Uint8List kernelBytes,
required Set<Uri> libraries,
}) : kernelBytes = Uint8List.fromList(kernelBytes) {
_executorFactoryToken = macroExecutor.registerExecutorFactory(
() => isolated_executor.start(
macro.SerializationMode.byteDataServer,
_kernelUri,
),
libraries,
);
}
Uri get _kernelUri {
return _kernelUriCached ??=
// ignore: avoid_dynamic_calls
(Isolate.current as dynamic).createUriForKernelBlob(kernelBytes);
}
void dispose() {
macroExecutor.unregisterExecutorFactory(_executorFactoryToken);
final kernelUriCached = _kernelUriCached;
if (kernelUriCached != null) {
// ignore: avoid_dynamic_calls
(Isolate.current as dynamic).unregisterKernelBlobUri(kernelUriCached);
_kernelUriCached = null;
}
}
Future<MacroClassInstance> instantiate({
required Uri libraryUri,
required String className,
required String constructorName,
required macro.Arguments arguments,
required macro.Declaration declaration,
required macro.IdentifierResolver identifierResolver,
}) async {
var instanceIdentifier = await macroExecutor.instantiateMacro(
libraryUri, className, constructorName, arguments);
return MacroClassInstance._(
this, identifierResolver, declaration, instanceIdentifier);
}
}
class MacroClass {
final String name;
final List<String> constructors;
@@ -16,6 +78,26 @@ class MacroClass {
});
}
class MacroClassInstance {
final BundleMacroExecutor _bundleExecutor;
final macro.IdentifierResolver _identifierResolver;
final macro.Declaration _declaration;
final macro.MacroInstanceIdentifier _instanceIdentifier;
MacroClassInstance._(
this._bundleExecutor,
this._identifierResolver,
this._declaration,
this._instanceIdentifier,
);
Future<macro.MacroExecutionResult> executeTypesPhase() async {
macro.MacroExecutor executor = _bundleExecutor.macroExecutor;
return await executor.executeTypesPhase(
_instanceIdentifier, _declaration, _identifierResolver);
}
}
abstract class MacroFileEntry {
String get content;
@@ -0,0 +1,147 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart'
as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
as macro;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/macro.dart';
class LibraryMacroApplier {
final LibraryBuilder libraryBuilder;
final Map<ClassDeclaration, macro.ClassDeclaration> _classDeclarations = {};
LibraryMacroApplier(this.libraryBuilder);
/// TODO(scheglov) check `shouldExecute`.
/// TODO(scheglov) check `supportsDeclarationKind`.
Future<String?> executeMacroTypesPhase() async {
var macroResults = <macro.MacroExecutionResult>[];
for (var unitElement in libraryBuilder.element.units) {
for (var classElement in unitElement.classes) {
var classNode = libraryBuilder.linker.elementNodes[classElement];
// TODO(scheglov) support other declarations
if (classNode is ClassDeclaration) {
for (var annotation in classNode.metadata) {
var annotationNameNode = annotation.name;
if (annotationNameNode is SimpleIdentifier &&
annotation.arguments != null) {
// TODO(scheglov) Create a Scope.
for (var import in libraryBuilder.element.imports) {
var importedLibrary = import.importedLibrary;
if (importedLibrary is LibraryElementImpl) {
var importedUri = importedLibrary.source.uri;
if (!libraryBuilder.linker.builders
.containsKey(importedUri)) {
var lookupResult = importedLibrary.scope.lookup(
annotationNameNode.name,
);
var getter = lookupResult.getter;
if (getter is ClassElementImpl && getter.isMacro) {
var macroExecutor = importedLibrary.bundleMacroExecutor;
if (macroExecutor != null) {
var macroResult = await _runSingleMacro(
macroExecutor,
getClassDeclaration(classNode),
getter,
);
if (macroResult.isNotEmpty) {
macroResults.add(macroResult);
}
}
}
}
}
}
}
}
}
}
}
var macroExecutor = libraryBuilder.linker.macroExecutor;
if (macroExecutor != null && macroResults.isNotEmpty) {
return macroExecutor.buildAugmentationLibrary(
macroResults,
_resolveIdentifier,
_inferOmittedType,
);
}
return null;
}
macro.ClassDeclaration getClassDeclaration(ClassDeclaration node) {
return _classDeclarations[node] ??= _createClassDeclaration(node);
}
macro.ClassDeclaration _createClassDeclaration(ClassDeclaration node) {
return macro.ClassDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: _IdentifierImpl(
id: macro.RemoteInstance.uniqueId,
name: node.name.name,
),
// TODO(scheglov): Support typeParameters
typeParameters: [],
// TODO(scheglov): Support interfaces
interfaces: [],
isAbstract: node.abstractKeyword != null,
isExternal: false,
// TODO(scheglov): Support mixins
mixins: [],
// TODO(scheglov): Support superclass
superclass: null,
);
}
macro.TypeAnnotation _inferOmittedType(
macro.OmittedTypeAnnotation omittedType,
) {
throw UnimplementedError();
}
macro.ResolvedIdentifier _resolveIdentifier(macro.Identifier identifier) {
throw UnimplementedError();
}
Future<macro.MacroExecutionResult> _runSingleMacro(
BundleMacroExecutor macroExecutor,
macro.Declaration declaration,
ClassElementImpl classElement,
) async {
var macroInstance = await macroExecutor.instantiate(
libraryUri: classElement.librarySource.uri,
className: classElement.name,
constructorName: '', // TODO
arguments: Arguments([], {}), // TODO
declaration: declaration,
identifierResolver: _FakeIdentifierResolver(),
);
return await macroInstance.executeTypesPhase();
}
}
class _FakeIdentifierResolver extends macro.IdentifierResolver {
@override
Future<macro.Identifier> resolveIdentifier(Uri library, String name) {
// TODO: implement resolveIdentifier
throw UnimplementedError();
}
}
class _IdentifierImpl extends macro.IdentifierImpl {
_IdentifierImpl({required int id, required String name})
: super(id: id, name: name);
}
extension on macro.MacroExecutionResult {
bool get isNotEmpty =>
libraryAugmentations.isNotEmpty || classAugmentations.isNotEmpty;
}
@@ -177,7 +177,9 @@ abstract class ContextResolutionTest
}
void disposeAnalysisContextCollection() {
if (_analysisContextCollection != null) {
final analysisContextCollection = _analysisContextCollection;
if (analysisContextCollection != null) {
analysisContextCollection.dispose();
_analysisContextCollection = null;
}
}
@@ -216,6 +218,10 @@ abstract class ContextResolutionTest
);
}
Future<void> tearDown() async {
disposeAnalysisContextCollection();
}
/// Override this method to update [analysisOptions] for every context root,
/// the default or already updated with `analysis_options.yaml` file.
void updateAnalysisOptions(AnalysisOptionsImpl analysisOptions) {}
@@ -34,6 +34,9 @@ class MacroResolutionTest extends PubPackageResolutionTest {
void setUp() {
super.setUp();
// TODO(scheglov) Dependency tracking for macros is not right yet.
useEmptyByteStore();
writeTestPackageConfig(
PackageConfigFileBuilder(),
macrosEnvironment: MacrosEnvironment.instance,
@@ -41,14 +44,30 @@ class MacroResolutionTest extends PubPackageResolutionTest {
}
test_0() async {
await assertNoErrorsInCode(r'''
newFile2('$testPackageLibPath/a.dart', r'''
import 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class EmptyMacro implements ClassTypesMacro {
const EmptyMacro();
FutureOr<void> buildTypesForClass(clazz, builder) {}
FutureOr<void> buildTypesForClass(clazz, builder) {
var targetName = clazz.identifier.name;
builder.declareType(
'${targetName}_Macro',
DeclarationCode.fromString('class ${targetName}_Macro {}'),
);
}
}
''');
await assertNoErrorsInCode('''
import 'a.dart';
@EmptyMacro()
class A {}
void f(A_Macro a) {}
''');
}
}