[cfe] Support json_serializable macro

This refactors and update the cfe macro implementation to support
macro annotations generated by macros.

Change-Id: I6a4b669f2f01b1f2fec4efbc87271eecf397205d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/346841
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2024-01-23 12:24:49 +00:00 committed by Commit Queue
parent 64b03d1998
commit 694c2911e2
20 changed files with 1555 additions and 1067 deletions

View file

@ -7,28 +7,84 @@ part of 'declaration_builders.dart';
const Uri? noUri = null;
abstract class ClassMemberAccess {
/// [Iterator] for all members declared in this class or any of its
/// [Iterator] for all constructors declared in this class or any of its
/// augmentations.
///
/// Duplicates and augmenting constructor are _not_ included.
///
/// For instance:
///
/// class Class {
/// Class(); // declared, so it is included
/// Class.named(); // declared, so it is included
/// Class.named(); // duplicate, so it is *not* included
/// }
///
/// augment class Class {
/// augment Class(); // augmenting, so it is *not* included
/// Class.extra(); // declared, so it is included
/// }
///
Iterator<T> fullConstructorIterator<T extends MemberBuilder>();
/// [NameIterator] for all constructors declared in this class or any of its
/// augmentations.
///
/// Duplicates and augmenting constructors are _not_ included.
///
/// For instance:
///
/// class Class {
/// Class(); // declared, so it is included
/// Class.named(); // declared, so it is included
/// Class.named(); // duplicate, so it is *not* included
/// }
///
/// augment class Class {
/// augment Class(); // augmenting, so it is *not* included
/// Class.extra(); // declared, so it is included
/// }
///
NameIterator<T> fullConstructorNameIterator<T extends MemberBuilder>();
/// [Iterator] for all members declared in this class or any of its
/// augmentations.
///
/// Duplicates and augmenting members are _not_ included.
///
/// For instance:
///
/// class Class {
/// method() {} // Declared, so it is included.
/// method2() {} // Declared, so it is included.
/// method2() {} // Duplicate, so it is *not* included.
/// }
///
/// augment class Class {
/// augment method() {} // Augmenting, so it is *not* included.
/// extra() {} // Declared, so it is included.
/// }
///
Iterator<T> fullMemberIterator<T extends Builder>();
/// [NameIterator] for all members declared in this class or any of its
/// augmentations.
///
/// Duplicates and augmenting members are _not_ included.
///
/// For instance:
///
/// class Class {
/// method() {} // Declared, so it is included.
/// method2() {} // Declared, so it is included.
/// method2() {} // Duplicate, so it is *not* included.
/// }
///
/// augment class Class {
/// augment method() {} // Augmenting, so it is *not* included.
/// extra() {} // Declared, so it is included.
/// }
///
NameIterator<T> fullMemberNameIterator<T extends Builder>();
}

View file

@ -348,18 +348,21 @@ class KernelTarget extends TargetImplementation {
/// Builds [augmentationLibraries] to the state expected after applying phase
/// 1 macros.
Future<void> _buildForPhase1(
Future<void> _buildForPhase1(MacroApplications macroApplications,
Iterable<SourceLibraryBuilder> augmentationLibraries) async {
await loader.buildOutlines();
// Normally patch libraries are applied in [SourceLoader.resolveParts].
// For augmentation libraries we instead apply them directly here.
for (SourceLibraryBuilder augmentationLibrary in augmentationLibraries) {
augmentationLibrary.applyPatches();
if (augmentationLibraries.isNotEmpty) {
// Normally patch libraries are applied in [SourceLoader.resolveParts].
// For augmentation libraries we instead apply them directly here.
for (SourceLibraryBuilder augmentationLibrary in augmentationLibraries) {
augmentationLibrary.applyPatches();
}
loader.computeLibraryScopes(augmentationLibraries);
loader.resolveTypes(augmentationLibraries);
await loader.computeAdditionalMacroApplications(
macroApplications, augmentationLibraries);
}
loader.computeLibraryScopes(augmentationLibraries);
// TODO(johnniwinther): Support computation of macro applications in
// augmentation libraries?
loader.resolveTypes(augmentationLibraries);
}
/// Builds [augmentationLibraries] to the state expected after applying phase
@ -374,6 +377,32 @@ class KernelTarget extends TargetImplementation {
loader.resolveConstructors(augmentationLibraries);
}
Future<void> _applyMacroPhase2(MacroApplications macroApplications,
List<SourceClassBuilder> sortedSourceClassBuilders) async {
benchmarker?.enterPhase(BenchmarkPhases.outline_applyDeclarationMacros);
macroApplications.enterDeclarationsMacroPhase(loader.hierarchyBuilder);
Future<void> applyDeclarationMacros() async {
await macroApplications.applyDeclarationsMacros(sortedSourceClassBuilders,
(SourceLibraryBuilder augmentationLibrary) async {
List<SourceLibraryBuilder> augmentationLibraries = [
augmentationLibrary
];
// TODO(johnniwinther): How should we use the benchmarker here?
benchmarker?.enterPhase(
BenchmarkPhases.outline_buildMacroDeclarationsForPhase1);
await _buildForPhase1(macroApplications, augmentationLibraries);
benchmarker?.enterPhase(
BenchmarkPhases.outline_buildMacroDeclarationsForPhase2);
_buildForPhase2(augmentationLibraries);
await applyDeclarationMacros();
});
}
await applyDeclarationMacros();
}
/// Builds [augmentationLibraries] to the state expected after applying phase
/// 3 macros.
void _buildForPhase3(List<SourceLibraryBuilder> augmentationLibraries) {
@ -420,11 +449,12 @@ class KernelTarget extends TargetImplementation {
if (macroApplications != null) {
benchmarker?.enterPhase(BenchmarkPhases.outline_applyTypeMacros);
macroApplications.enterTypeMacroPhase();
List<SourceLibraryBuilder> augmentationLibraries =
await macroApplications.applyTypeMacros(loader);
await macroApplications.applyTypeMacros();
benchmarker
?.enterPhase(BenchmarkPhases.outline_buildMacroTypesForPhase1);
await _buildForPhase1(augmentationLibraries);
await _buildForPhase1(macroApplications, augmentationLibraries);
}
benchmarker?.enterPhase(BenchmarkPhases.outline_checkSemantics);
@ -468,20 +498,7 @@ class KernelTarget extends TargetImplementation {
underscoreEnumClass);
if (macroApplications != null) {
benchmarker?.enterPhase(BenchmarkPhases.outline_applyDeclarationMacros);
await macroApplications.applyDeclarationsMacros(
loader.hierarchyBuilder, sortedSourceClassBuilders,
(SourceLibraryBuilder augmentationLibrary) async {
List<SourceLibraryBuilder> augmentationLibraries = [
augmentationLibrary
];
benchmarker?.enterPhase(
BenchmarkPhases.outline_buildMacroDeclarationsForPhase1);
await _buildForPhase1(augmentationLibraries);
benchmarker?.enterPhase(
BenchmarkPhases.outline_buildMacroDeclarationsForPhase2);
_buildForPhase2(augmentationLibraries);
});
await _applyMacroPhase2(macroApplications, sortedSourceClassBuilders);
}
benchmarker
@ -581,11 +598,12 @@ class KernelTarget extends TargetImplementation {
if (macroApplications != null) {
benchmarker?.enterPhase(BenchmarkPhases.body_applyDefinitionMacros);
macroApplications.enterDefinitionMacroPhase();
List<SourceLibraryBuilder> augmentationLibraries =
await macroApplications.applyDefinitionMacros();
benchmarker
?.enterPhase(BenchmarkPhases.body_buildMacroDefinitionsForPhase1);
await _buildForPhase1(augmentationLibraries);
await _buildForPhase1(macroApplications, augmentationLibraries);
benchmarker
?.enterPhase(BenchmarkPhases.body_buildMacroDefinitionsForPhase2);
_buildForPhase2(augmentationLibraries);

View file

@ -15,7 +15,7 @@ import '../../builder/member_builder.dart';
import '../../builder/nullability_builder.dart';
import '../../builder/type_builder.dart';
import '../../uris.dart';
import 'macro.dart';
import 'introspectors.dart';
abstract class IdentifierImpl extends macro.IdentifierImpl {
IdentifierImpl({
@ -26,7 +26,7 @@ abstract class IdentifierImpl extends macro.IdentifierImpl {
macro.ResolvedIdentifier resolveIdentifier();
Future<macro.TypeDeclaration> resolveTypeDeclaration(
MacroApplications macroApplications);
MacroIntrospection macroIntrospection);
DartType buildType(
NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments);
@ -37,9 +37,9 @@ abstract class IdentifierImpl extends macro.IdentifierImpl {
Uri? uri;
switch (typeDeclarationBuilder) {
case ClassBuilder():
uri = typeDeclarationBuilder.libraryBuilder.importUri;
uri = typeDeclarationBuilder.libraryBuilder.origin.importUri;
case TypeAliasBuilder():
uri = typeDeclarationBuilder.libraryBuilder.importUri;
uri = typeDeclarationBuilder.libraryBuilder.origin.importUri;
case NominalVariableBuilder():
// TODO(johnniwinther): Handle this case.
case StructuralVariableBuilder():
@ -56,7 +56,6 @@ abstract class IdentifierImpl extends macro.IdentifierImpl {
// TODO(johnniwinther): How should we handle this case?
case OmittedTypeDeclarationBuilder():
}
return new macro.ResolvedIdentifier(
kind: macro.IdentifierKind.topLevelMember,
name: name,
@ -67,16 +66,15 @@ abstract class IdentifierImpl extends macro.IdentifierImpl {
}
}
Future<macro.TypeDeclaration> _resolveTypeDeclaration(
MacroApplications macroApplications,
macro.TypeDeclaration _resolveTypeDeclaration(
MacroIntrospection macroIntrospection,
TypeDeclarationBuilder? typeDeclarationBuilder) {
switch (typeDeclarationBuilder) {
case ClassBuilder():
return new Future.value(
macroApplications.getClassDeclaration(typeDeclarationBuilder));
return macroIntrospection.getClassDeclaration(typeDeclarationBuilder);
case TypeAliasBuilder():
return new Future.value(
macroApplications.getTypeAliasDeclaration(typeDeclarationBuilder));
return macroIntrospection
.getTypeAliasDeclaration(typeDeclarationBuilder);
case NominalVariableBuilder():
case StructuralVariableBuilder():
case ExtensionBuilder():
@ -87,10 +85,13 @@ abstract class IdentifierImpl extends macro.IdentifierImpl {
case OmittedTypeDeclarationBuilder():
case null:
// TODO(johnniwinther): Handle these cases.
return new Future.error(
new ArgumentError('Unable to resolve identifier $this'));
throw new ArgumentError('Unable to resolve identifier $this');
}
}
macro.Declaration resolveDeclaration(MacroIntrospection macroIntrospection) {
throw new UnimplementedError('${runtimeType}.resolveDeclaration');
}
}
class TypeBuilderIdentifier extends IdentifierImpl {
@ -126,8 +127,20 @@ class TypeBuilderIdentifier extends IdentifierImpl {
@override
Future<macro.TypeDeclaration> resolveTypeDeclaration(
MacroApplications macroApplications) {
return _resolveTypeDeclaration(macroApplications, typeBuilder.declaration);
MacroIntrospection macroIntrospection) {
return new Future.value(
_resolveTypeDeclaration(macroIntrospection, typeBuilder.declaration));
}
@override
macro.Declaration resolveDeclaration(MacroIntrospection macroIntrospection) {
return _resolveTypeDeclaration(macroIntrospection, typeBuilder.declaration);
}
@override
String toString() {
return "TypeBuilderIdentifier("
"typeBuilder=$typeBuilder,libraryBuilder=$libraryBuilder)";
}
}
@ -149,8 +162,14 @@ class TypeDeclarationBuilderIdentifier extends IdentifierImpl {
@override
Future<macro.TypeDeclaration> resolveTypeDeclaration(
MacroApplications macroApplications) {
return _resolveTypeDeclaration(macroApplications, typeDeclarationBuilder);
MacroIntrospection macroIntrospection) {
return new Future.value(
_resolveTypeDeclaration(macroIntrospection, typeDeclarationBuilder));
}
@override
macro.Declaration resolveDeclaration(MacroIntrospection macroIntrospection) {
return _resolveTypeDeclaration(macroIntrospection, typeDeclarationBuilder);
}
@override
@ -182,12 +201,12 @@ class MemberBuilderIdentifier extends IdentifierImpl {
String? staticScope;
macro.IdentifierKind kind;
if (memberBuilder.isTopLevel) {
uri = memberBuilder.libraryBuilder.importUri;
uri = memberBuilder.libraryBuilder.origin.importUri;
kind = macro.IdentifierKind.topLevelMember;
} else if (memberBuilder.isStatic || memberBuilder.isConstructor) {
ClassBuilder classBuilder = memberBuilder.classBuilder!;
staticScope = classBuilder.name;
uri = classBuilder.libraryBuilder.importUri;
uri = classBuilder.libraryBuilder.origin.importUri;
kind = macro.IdentifierKind.staticInstanceMember;
} else {
kind = macro.IdentifierKind.instanceMember;
@ -204,7 +223,7 @@ class MemberBuilderIdentifier extends IdentifierImpl {
@override
Future<macro.TypeDeclaration> resolveTypeDeclaration(
MacroApplications macroApplications) {
MacroIntrospection macroIntrospection) {
return new Future.error(
new ArgumentError('Cannot resolve type declaration from member.'));
}
@ -238,7 +257,7 @@ class FormalParameterBuilderIdentifier extends IdentifierImpl {
@override
Future<macro.TypeDeclaration> resolveTypeDeclaration(
MacroApplications macroApplications) {
MacroIntrospection macroIntrospection) {
throw new ArgumentError(
'Cannot resolve type declaration from formal parameter.');
}
@ -264,7 +283,7 @@ class OmittedTypeIdentifier extends IdentifierImpl {
@override
Future<macro.TypeDeclaration> resolveTypeDeclaration(
MacroApplications macroApplications) {
MacroIntrospection macroIntrospection) {
return new Future.error(new ArgumentError(
'Cannot resolve type declaration from omitted type.'));
}

View file

@ -0,0 +1,637 @@
// Copyright (c) 2024, 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:kernel/ast.dart';
import '../../builder/builder.dart';
import '../../builder/declaration_builders.dart';
import '../../builder/formal_parameter_builder.dart';
import '../../builder/library_builder.dart';
import '../../builder/member_builder.dart';
import '../../builder/type_builder.dart';
import '../../source/source_constructor_builder.dart';
import '../../source/source_factory_builder.dart';
import '../../source/source_field_builder.dart';
import '../../source/source_loader.dart';
import '../../source/source_procedure_builder.dart';
import '../hierarchy/hierarchy_builder.dart';
import 'identifiers.dart';
import 'types.dart';
class MacroIntrospection {
final SourceLoader _sourceLoader;
final MacroTypes types;
late final ClassHierarchyBuilder _classHierarchy;
late final macro.TypePhaseIntrospector typePhaseIntrospector;
late final macro.DeclarationPhaseIntrospector declarationPhaseIntrospector;
late final macro.DefinitionPhaseIntrospector definitionPhaseIntrospector;
Map<ClassBuilder, macro.ParameterizedTypeDeclaration> _classDeclarations = {};
Map<macro.ParameterizedTypeDeclaration, ClassBuilder> _classBuilders = {};
Map<TypeAliasBuilder, macro.TypeAliasDeclaration> _typeAliasDeclarations = {};
Map<MemberBuilder, macro.Declaration?> _memberDeclarations = {};
Map<LibraryBuilder, macro.LibraryImpl> _libraries = {};
MacroIntrospection(this._sourceLoader)
: types = new MacroTypes(_sourceLoader);
void enterTypeMacroPhase() {
typePhaseIntrospector = new _TypePhaseIntrospector(_sourceLoader);
}
void enterDeclarationsMacroPhase(ClassHierarchyBuilder classHierarchy) {
_classHierarchy = classHierarchy;
declarationPhaseIntrospector =
new _DeclarationPhaseIntrospector(this, _classHierarchy, _sourceLoader);
types.enterDeclarationsMacroPhase(classHierarchy);
}
void enterDefinitionMacroPhase() {
definitionPhaseIntrospector =
new _DefinitionPhaseIntrospector(this, _classHierarchy, _sourceLoader);
}
void clear() {
types.clear();
}
macro.Declaration getMemberDeclaration(MemberBuilder memberBuilder) {
memberBuilder = memberBuilder.origin as MemberBuilder;
return _memberDeclarations[memberBuilder] ??=
_createMemberDeclaration(memberBuilder);
}
macro.ParameterizedTypeDeclaration getClassDeclaration(ClassBuilder builder) {
builder = builder.origin;
return _classDeclarations[builder] ??= _createClassDeclaration(builder);
}
macro.TypeAliasDeclaration getTypeAliasDeclaration(TypeAliasBuilder builder) {
return _typeAliasDeclarations[builder] ??=
_createTypeAliasDeclaration(builder);
}
ClassBuilder _getClassBuilder(
macro.ParameterizedTypeDeclaration declaration) {
return _classBuilders[declaration]!;
}
macro.Declaration _createMemberDeclaration(MemberBuilder memberBuilder) {
if (memberBuilder is SourceProcedureBuilder) {
return _createFunctionDeclaration(memberBuilder);
} else if (memberBuilder is SourceFieldBuilder) {
return _createVariableDeclaration(memberBuilder);
} else if (memberBuilder is SourceConstructorBuilder) {
return _createConstructorDeclaration(memberBuilder);
} else if (memberBuilder is SourceFactoryBuilder) {
return _createFactoryDeclaration(memberBuilder);
} else {
// TODO(johnniwinther): Throw when all members are supported.
throw new UnimplementedError(
'Unsupported member ${memberBuilder} (${memberBuilder.runtimeType})');
}
}
macro.TypeDeclaration resolveDeclaration(macro.Identifier identifier) {
if (identifier is MemberBuilderIdentifier) {
return getClassDeclaration(identifier.memberBuilder.classBuilder!);
} else if (identifier is TypeDeclarationBuilderIdentifier) {
final TypeDeclarationBuilder typeDeclarationBuilder =
identifier.typeDeclarationBuilder;
switch (typeDeclarationBuilder) {
case ClassBuilder():
return getClassDeclaration(typeDeclarationBuilder);
case TypeAliasBuilder():
case NominalVariableBuilder():
case StructuralVariableBuilder():
case ExtensionBuilder():
case ExtensionTypeDeclarationBuilder():
case InvalidTypeDeclarationBuilder():
case BuiltinTypeDeclarationBuilder():
// TODO(johnniwinther): How should we handle this case?
case OmittedTypeDeclarationBuilder():
}
throw new UnimplementedError(
'Resolving declarations is only supported for classes');
} else {
throw new UnimplementedError(
'Resolving declarations not supported for $identifier');
}
}
macro.ResolvedIdentifier resolveIdentifier(macro.Identifier identifier) {
if (identifier is IdentifierImpl) {
return identifier.resolveIdentifier();
} else {
throw new UnsupportedError(
'Unsupported identifier ${identifier} (${identifier.runtimeType})');
}
}
macro.LibraryImpl _libraryFor(LibraryBuilder builder) {
return _libraries[builder] ??= () {
final Version version = builder.library.languageVersion;
return new macro.LibraryImpl(
id: macro.RemoteInstance.uniqueId,
uri: builder.importUri,
languageVersion:
new macro.LanguageVersionImpl(version.major, version.minor),
// TODO: Provide metadata annotations.
metadata: const []);
}();
}
macro.ParameterizedTypeDeclaration _createClassDeclaration(
ClassBuilder builder) {
assert(
!builder.isAnonymousMixinApplication,
"Trying to create a ClassDeclaration for the mixin application "
"${builder}.");
TypeBuilder? supertypeBuilder = builder.supertypeBuilder;
List<TypeBuilder>? mixins;
while (supertypeBuilder != null) {
TypeDeclarationBuilder? declaration = supertypeBuilder.declaration;
if (declaration is ClassBuilder &&
declaration.isAnonymousMixinApplication) {
(mixins ??= []).add(declaration.mixedInTypeBuilder!);
supertypeBuilder = declaration.supertypeBuilder;
} else {
break;
}
}
if (mixins != null) {
mixins = mixins.reversed.toList();
}
final TypeDeclarationBuilderIdentifier identifier =
new TypeDeclarationBuilderIdentifier(
typeDeclarationBuilder: builder,
libraryBuilder: builder.libraryBuilder,
id: macro.RemoteInstance.uniqueId,
name: builder.name);
// TODO(johnniwinther): Support typeParameters
final List<macro.TypeParameterDeclarationImpl> typeParameters = [];
final List<macro.NamedTypeAnnotationImpl> interfaces =
types.typeBuildersToAnnotations(
builder.libraryBuilder, builder.interfaceBuilders);
final macro.LibraryImpl library = _libraryFor(builder.libraryBuilder);
macro.ParameterizedTypeDeclaration declaration = builder.isMixinDeclaration
? new macro.MixinDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: identifier,
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
typeParameters: typeParameters,
hasBase: builder.isBase,
interfaces: interfaces,
superclassConstraints: types.typeBuildersToAnnotations(
builder.libraryBuilder, builder.onTypes))
// This cast is not necessary but LUB doesn't give the desired type
// without it.
as macro.ParameterizedTypeDeclaration
: new macro.ClassDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: identifier,
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
typeParameters: typeParameters,
interfaces: interfaces,
hasAbstract: builder.isAbstract,
hasBase: builder.isBase,
hasExternal: builder.isExternal,
hasFinal: builder.isFinal,
hasInterface: builder.isInterface,
hasMixin: builder.isMixinClass,
hasSealed: builder.isSealed,
mixins:
types.typeBuildersToAnnotations(builder.libraryBuilder, mixins),
superclass: supertypeBuilder != null
? types.computeTypeAnnotation(
builder.libraryBuilder, supertypeBuilder)
as macro.NamedTypeAnnotationImpl
: null);
_classBuilders[declaration] = builder;
return declaration;
}
macro.TypeAliasDeclaration _createTypeAliasDeclaration(
TypeAliasBuilder builder) {
final macro.LibraryImpl library = _libraryFor(builder.libraryBuilder);
macro.TypeAliasDeclaration declaration = new macro.TypeAliasDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new TypeDeclarationBuilderIdentifier(
typeDeclarationBuilder: builder,
libraryBuilder: builder.libraryBuilder,
id: macro.RemoteInstance.uniqueId,
name: builder.name),
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
// TODO(johnniwinther): Support typeParameters
typeParameters: [],
aliasedType:
types.computeTypeAnnotation(builder.libraryBuilder, builder.type));
return declaration;
}
List<List<macro.ParameterDeclarationImpl>> _createParameters(
MemberBuilder builder, List<FormalParameterBuilder>? formals) {
List<macro.ParameterDeclarationImpl>? positionalParameters;
List<macro.ParameterDeclarationImpl>? namedParameters;
if (formals == null) {
positionalParameters = namedParameters = const [];
} else {
positionalParameters = [];
namedParameters = [];
final macro.LibraryImpl library = _libraryFor(builder.libraryBuilder);
for (FormalParameterBuilder formal in formals) {
macro.TypeAnnotationImpl type =
types.computeTypeAnnotation(builder.libraryBuilder, formal.type);
macro.IdentifierImpl identifier = new FormalParameterBuilderIdentifier(
id: macro.RemoteInstance.uniqueId,
name: formal.name,
parameterBuilder: formal,
libraryBuilder: builder.libraryBuilder);
if (formal.isNamed) {
namedParameters.add(new macro.ParameterDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: identifier,
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
isRequired: formal.isRequiredNamed,
isNamed: true,
type: type,
));
} else {
positionalParameters.add(new macro.ParameterDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: identifier,
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
isRequired: formal.isRequiredPositional,
isNamed: false,
type: type,
));
}
}
}
return [positionalParameters, namedParameters];
}
macro.ConstructorDeclaration _createConstructorDeclaration(
SourceConstructorBuilder builder) {
List<FormalParameterBuilder>? formals = null;
// TODO(johnniwinther): Support formals for other constructors.
if (builder is DeclaredSourceConstructorBuilder) {
formals = builder.formals;
}
List<List<macro.ParameterDeclarationImpl>> parameters =
_createParameters(builder, formals);
macro.ParameterizedTypeDeclaration definingClass =
getClassDeclaration(builder.classBuilder!);
return new macro.ConstructorDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new MemberBuilderIdentifier(
memberBuilder: builder,
id: macro.RemoteInstance.uniqueId,
name: builder.name),
library: _libraryFor(builder.libraryBuilder),
// TODO: Provide metadata annotations.
metadata: const [],
definingType: definingClass.identifier as macro.IdentifierImpl,
isFactory: builder.isFactory,
// TODO(johnniwinther): Real implementation of hasBody.
hasBody: true,
hasExternal: builder.isExternal,
positionalParameters: parameters[0],
namedParameters: parameters[1],
// TODO(johnniwinther): Support constructor return type.
returnType: types.computeTypeAnnotation(builder.libraryBuilder, null),
// TODO(johnniwinther): Support typeParameters
typeParameters: const [],
);
}
macro.ConstructorDeclaration _createFactoryDeclaration(
SourceFactoryBuilder builder) {
List<List<macro.ParameterDeclarationImpl>> parameters =
_createParameters(builder, builder.formals);
macro.ParameterizedTypeDeclaration definingClass =
// TODO(johnniwinther): Support extension type factories.
getClassDeclaration(builder.classBuilder!);
return new macro.ConstructorDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new MemberBuilderIdentifier(
memberBuilder: builder,
id: macro.RemoteInstance.uniqueId,
name: builder.name),
library: _libraryFor(builder.libraryBuilder),
// TODO: Provide metadata annotations.
metadata: const [],
definingType: definingClass.identifier as macro.IdentifierImpl,
isFactory: builder.isFactory,
// TODO(johnniwinther): Real implementation of hasBody.
hasBody: true,
hasExternal: builder.isExternal,
positionalParameters: parameters[0],
namedParameters: parameters[1],
// TODO(johnniwinther): Support constructor return type.
returnType: types.computeTypeAnnotation(builder.libraryBuilder, null),
// TODO(johnniwinther): Support typeParameters
typeParameters: const [],
);
}
macro.FunctionDeclaration _createFunctionDeclaration(
SourceProcedureBuilder builder) {
List<List<macro.ParameterDeclarationImpl>> parameters =
_createParameters(builder, builder.formals);
macro.ParameterizedTypeDeclaration? definingClass = null;
if (builder.classBuilder != null) {
definingClass = getClassDeclaration(builder.classBuilder!);
}
final macro.LibraryImpl library = _libraryFor(builder.libraryBuilder);
if (definingClass != null) {
// TODO(johnniwinther): Should static fields be field or variable
// declarations?
return new macro.MethodDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new MemberBuilderIdentifier(
memberBuilder: builder,
id: macro.RemoteInstance.uniqueId,
name: builder.name),
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
definingType: definingClass.identifier as macro.IdentifierImpl,
// TODO(johnniwinther): Real implementation of hasBody.
hasBody: true,
hasExternal: builder.isExternal,
isGetter: builder.isGetter,
isOperator: builder.isOperator,
isSetter: builder.isSetter,
isStatic: builder.isStatic,
positionalParameters: parameters[0],
namedParameters: parameters[1],
returnType: types.computeTypeAnnotation(
builder.libraryBuilder, builder.returnType),
// TODO(johnniwinther): Support typeParameters
typeParameters: const []);
} else {
return new macro.FunctionDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new MemberBuilderIdentifier(
memberBuilder: builder,
id: macro.RemoteInstance.uniqueId,
name: builder.name),
library: library,
// TODO(johnniwinther): Provide metadata annotations.
metadata: const [],
// TODO(johnniwinther): Real implementation of hasBody.
hasBody: true,
hasExternal: builder.isExternal,
isGetter: builder.isGetter,
isOperator: builder.isOperator,
isSetter: builder.isSetter,
positionalParameters: parameters[0],
namedParameters: parameters[1],
returnType: types.computeTypeAnnotation(
builder.libraryBuilder, builder.returnType),
// TODO(johnniwinther): Support typeParameters
typeParameters: const []);
}
}
macro.VariableDeclaration _createVariableDeclaration(
SourceFieldBuilder builder) {
macro.ParameterizedTypeDeclaration? definingClass = null;
if (builder.classBuilder != null) {
definingClass = getClassDeclaration(builder.classBuilder!);
}
final macro.LibraryImpl library = _libraryFor(builder.libraryBuilder);
if (definingClass != null) {
// TODO(johnniwinther): Should static fields be field or variable
// declarations?
return new macro.FieldDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new MemberBuilderIdentifier(
memberBuilder: builder,
id: macro.RemoteInstance.uniqueId,
name: builder.name),
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
definingType: definingClass.identifier as macro.IdentifierImpl,
hasAbstract: builder.isAbstract,
hasExternal: builder.isExternal,
hasFinal: builder.isFinal,
hasLate: builder.isLate,
isStatic: builder.isStatic,
type: types.computeTypeAnnotation(
builder.libraryBuilder, builder.type));
} else {
return new macro.VariableDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new MemberBuilderIdentifier(
memberBuilder: builder,
id: macro.RemoteInstance.uniqueId,
name: builder.name),
library: library,
// TODO: Provide metadata annotations.
metadata: const [],
hasExternal: builder.isExternal,
hasFinal: builder.isFinal,
hasLate: builder.isLate,
type: types.computeTypeAnnotation(
builder.libraryBuilder, builder.type));
}
}
}
class _TypePhaseIntrospector implements macro.TypePhaseIntrospector {
final SourceLoader sourceLoader;
_TypePhaseIntrospector(this.sourceLoader);
@override
Future<macro.Identifier> resolveIdentifier(Uri library, String name) {
LibraryBuilder? libraryBuilder = sourceLoader.lookupLibraryBuilder(library);
if (libraryBuilder == null) {
return new Future.error(
new ArgumentError('Library at uri $library could not be resolved.'),
StackTrace.current);
}
bool isSetter = false;
String memberName = name;
if (name.endsWith('=')) {
memberName = name.substring(0, name.length - 1);
isSetter = true;
}
Builder? builder =
libraryBuilder.scope.lookupLocalMember(memberName, setter: isSetter);
if (builder == null) {
return new Future.error(
new ArgumentError(
'Unable to find top level identifier "$name" in $library'),
StackTrace.current);
} else if (builder is TypeDeclarationBuilder) {
return new Future.value(new TypeDeclarationBuilderIdentifier(
typeDeclarationBuilder: builder,
libraryBuilder: libraryBuilder,
id: macro.RemoteInstance.uniqueId,
name: name));
} else if (builder is MemberBuilder) {
return new Future.value(new MemberBuilderIdentifier(
memberBuilder: builder,
id: macro.RemoteInstance.uniqueId,
name: name));
} else {
return new Future.error(
new UnsupportedError('Unsupported identifier kind $builder'),
StackTrace.current);
}
}
}
class _DeclarationPhaseIntrospector extends _TypePhaseIntrospector
implements macro.DeclarationPhaseIntrospector {
final ClassHierarchyBuilder classHierarchy;
final MacroIntrospection _introspection;
_DeclarationPhaseIntrospector(
this._introspection, this.classHierarchy, super.sourceLoader);
@override
Future<macro.TypeDeclaration> typeDeclarationOf(macro.Identifier identifier) {
if (identifier is IdentifierImpl) {
return identifier.resolveTypeDeclaration(_introspection);
}
throw new UnsupportedError(
'Unsupported identifier $identifier (${identifier.runtimeType})');
}
@override
Future<List<macro.ConstructorDeclaration>> constructorsOf(
macro.TypeDeclaration type) {
if (type is! macro.ClassDeclaration) {
throw new UnsupportedError('Only introspection on classes is supported');
}
ClassBuilder classBuilder = _introspection
._getClassBuilder(type as macro.ParameterizedTypeDeclaration);
List<macro.ConstructorDeclaration> result = [];
Iterator<MemberBuilder> iterator = classBuilder.fullConstructorIterator();
while (iterator.moveNext()) {
MemberBuilder memberBuilder = iterator.current;
if (memberBuilder is DeclaredSourceConstructorBuilder) {
// TODO(johnniwinther): Should we support synthesized constructors?
result.add(_introspection.getMemberDeclaration(memberBuilder)
as macro.ConstructorDeclaration);
} else if (memberBuilder is SourceFactoryBuilder) {
result.add(_introspection.getMemberDeclaration(memberBuilder)
as macro.ConstructorDeclaration);
}
}
return new Future.value(result);
}
@override
Future<List<macro.EnumValueDeclaration>> valuesOf(
covariant macro.EnumDeclaration enumType) {
// TODO: implement valuesOf
throw new UnimplementedError();
}
@override
Future<List<macro.FieldDeclaration>> fieldsOf(macro.TypeDeclaration type) {
if (type is! macro.ClassDeclaration) {
throw new UnsupportedError('Only introspection on classes is supported');
}
ClassBuilder classBuilder = _introspection._getClassBuilder(type);
List<macro.FieldDeclaration> result = [];
Iterator<SourceFieldBuilder> iterator =
classBuilder.fullMemberIterator<SourceFieldBuilder>();
while (iterator.moveNext()) {
result.add(_introspection.getMemberDeclaration(iterator.current)
as macro.FieldDeclaration);
}
return new Future.value(result);
}
@override
Future<List<macro.MethodDeclaration>> methodsOf(macro.TypeDeclaration type) {
if (type is! macro.ClassDeclaration && type is! macro.MixinDeclaration) {
throw new UnsupportedError(
'Only introspection on classes and mixins is supported');
}
ClassBuilder classBuilder = _introspection
._getClassBuilder(type as macro.ParameterizedTypeDeclaration);
List<macro.MethodDeclaration> result = [];
Iterator<SourceProcedureBuilder> iterator =
classBuilder.fullMemberIterator<SourceProcedureBuilder>();
while (iterator.moveNext()) {
result.add(_introspection.getMemberDeclaration(iterator.current)
as macro.MethodDeclaration);
}
return new Future.value(result);
}
@override
Future<List<macro.TypeDeclaration>> typesOf(covariant macro.Library library) {
// TODO: implement typesOf
throw new UnimplementedError();
}
@override
Future<macro.StaticType> resolve(macro.TypeAnnotationCode typeAnnotation) {
return new Future.value(
_introspection.types.resolveTypeAnnotation(typeAnnotation));
}
}
class _DefinitionPhaseIntrospector extends _DeclarationPhaseIntrospector
implements macro.DefinitionPhaseIntrospector {
_DefinitionPhaseIntrospector(
super.macroIntrospection, super.classHierarchy, super.sourceLoader);
@override
Future<macro.TypeDeclaration> typeDeclarationOf(
macro.Identifier identifier) async =>
(await super.typeDeclarationOf(identifier));
@override
Future<macro.TypeAnnotation> inferType(
macro.OmittedTypeAnnotation omittedType) =>
new Future.value(_introspection.types.inferOmittedType(omittedType)!);
@override
Future<List<macro.Declaration>> topLevelDeclarationsOf(
macro.Library library) {
// TODO: implement topLevelDeclarationsOf
throw new UnimplementedError();
}
@override
Future<macro.Declaration> declarationOf(
covariant macro.Identifier identifier) {
if (identifier is IdentifierImpl) {
return new Future.value(identifier.resolveDeclaration(_introspection));
} else {
throw new UnsupportedError(
'Unsupported identifier ${identifier} (${identifier.runtimeType})');
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,187 @@
// Copyright (c) 2024, 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/introspection_impls.dart'
as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
as macro;
import 'package:kernel/ast.dart';
import 'package:kernel/src/types.dart';
import 'package:kernel/type_environment.dart' show SubtypeCheckMode;
import '../../builder/library_builder.dart';
import '../../builder/nullability_builder.dart';
import '../../builder/type_builder.dart';
import '../../source/source_loader.dart';
import '../hierarchy/hierarchy_builder.dart';
import 'identifiers.dart';
final IdentifierImpl omittedTypeIdentifier =
new OmittedTypeIdentifier(id: macro.RemoteInstance.uniqueId);
class MacroTypes {
final SourceLoader _sourceLoader;
late Types _types;
Map<TypeBuilder?, macro.TypeAnnotationImpl> _typeAnnotationCache = {};
Map<DartType, _StaticTypeImpl> _staticTypeCache = {};
MacroTypes(this._sourceLoader);
void enterDeclarationsMacroPhase(ClassHierarchyBuilder classHierarchy) {
_types = new Types(classHierarchy);
}
void clear() {
_staticTypeCache.clear();
_typeAnnotationCache.clear();
}
List<macro.TypeAnnotationImpl> computeTypeAnnotations(
LibraryBuilder library, List<TypeBuilder>? typeBuilders) {
if (typeBuilders == null) return const [];
return new List.generate(typeBuilders.length,
(int index) => computeTypeAnnotation(library, typeBuilders[index]));
}
macro.TypeAnnotationImpl _computeTypeAnnotation(
LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
switch (typeBuilder) {
case NamedTypeBuilder():
List<macro.TypeAnnotationImpl> typeArguments =
computeTypeAnnotations(libraryBuilder, typeBuilder.typeArguments);
bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
return new macro.NamedTypeAnnotationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new TypeBuilderIdentifier(
typeBuilder: typeBuilder,
libraryBuilder: libraryBuilder,
id: macro.RemoteInstance.uniqueId,
name: typeBuilder.typeName.name),
typeArguments: typeArguments,
isNullable: isNullable);
case OmittedTypeBuilder():
return new _OmittedTypeAnnotationImpl(typeBuilder,
id: macro.RemoteInstance.uniqueId);
case FunctionTypeBuilder():
case InvalidTypeBuilder():
case RecordTypeBuilder():
case FixedTypeBuilder():
case null:
// TODO(johnniwinther): Should this only be for `null`? Can the other
// type builders be observed here?
return new macro.NamedTypeAnnotationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: omittedTypeIdentifier,
isNullable: false,
typeArguments: const []);
}
}
macro.TypeAnnotationImpl computeTypeAnnotation(
LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
return _typeAnnotationCache[typeBuilder] ??=
_computeTypeAnnotation(libraryBuilder, typeBuilder);
}
DartType _typeForAnnotation(macro.TypeAnnotationCode typeAnnotation) {
NullabilityBuilder nullabilityBuilder;
if (typeAnnotation is macro.NullableTypeAnnotationCode) {
nullabilityBuilder = const NullabilityBuilder.nullable();
typeAnnotation = typeAnnotation.underlyingType;
} else {
nullabilityBuilder = const NullabilityBuilder.omitted();
}
if (typeAnnotation is macro.NamedTypeAnnotationCode) {
macro.NamedTypeAnnotationCode namedTypeAnnotation = typeAnnotation;
IdentifierImpl typeIdentifier = typeAnnotation.name as IdentifierImpl;
List<DartType> arguments = new List<DartType>.generate(
namedTypeAnnotation.typeArguments.length,
(int index) =>
_typeForAnnotation(namedTypeAnnotation.typeArguments[index]));
return typeIdentifier.buildType(nullabilityBuilder, arguments);
}
// TODO: Implement support for function types.
throw new UnimplementedError(
'Unimplemented type annotation kind ${typeAnnotation.kind}');
}
macro.StaticType resolveTypeAnnotation(
macro.TypeAnnotationCode typeAnnotation) {
return createStaticType(_typeForAnnotation(typeAnnotation));
}
macro.StaticType createStaticType(DartType dartType) {
return _staticTypeCache[dartType] ??= new _StaticTypeImpl(_types, dartType);
}
List<macro.NamedTypeAnnotationImpl> typeBuildersToAnnotations(
LibraryBuilder libraryBuilder, List<TypeBuilder>? typeBuilders) {
return typeBuilders == null
? []
: typeBuilders
.map((TypeBuilder typeBuilder) =>
computeTypeAnnotation(libraryBuilder, typeBuilder)
as macro.NamedTypeAnnotationImpl)
.toList();
}
macro.TypeAnnotation? inferOmittedType(
macro.OmittedTypeAnnotation omittedType) {
if (omittedType is _OmittedTypeAnnotationImpl) {
OmittedTypeBuilder typeBuilder = omittedType.typeBuilder;
if (typeBuilder.hasType) {
return computeTypeAnnotation(
_sourceLoader.coreLibrary,
_sourceLoader.target.dillTarget.loader
.computeTypeBuilder(typeBuilder.type));
}
}
return null;
}
Map<String, OmittedTypeBuilder>? computeOmittedTypeBuilders(
Map<macro.OmittedTypeAnnotation, String> omittedTypes) {
if (omittedTypes.isEmpty) {
return null;
}
Map<String, OmittedTypeBuilder> omittedTypeBuilders = {};
for (MapEntry<macro.OmittedTypeAnnotation, String> entry
in omittedTypes.entries) {
_OmittedTypeAnnotationImpl omittedType =
entry.key as _OmittedTypeAnnotationImpl;
omittedTypeBuilders[entry.value] = omittedType.typeBuilder;
}
return omittedTypeBuilders;
}
}
class _StaticTypeImpl implements macro.StaticType {
final Types types;
final DartType type;
_StaticTypeImpl(this.types, this.type);
@override
Future<bool> isExactly(covariant _StaticTypeImpl other) {
return new Future.value(type == other.type);
}
@override
Future<bool> isSubtypeOf(covariant _StaticTypeImpl other) {
return new Future.value(types.isSubtypeOf(
type, other.type, SubtypeCheckMode.withNullabilities));
}
}
// ignore: missing_override_of_must_be_overridden
class _OmittedTypeAnnotationImpl extends macro.OmittedTypeAnnotationImpl {
final OmittedTypeBuilder typeBuilder;
_OmittedTypeAnnotationImpl(this.typeBuilder, {required int id})
: super(id: id);
}

View file

@ -179,7 +179,7 @@ class ClassDeclarationMemberIterator<D extends ClassDeclaration,
Iterator<D>? augmentationBuilders;
final bool includeDuplicates;
factory ClassDeclarationMemberIterator(
factory ClassDeclarationMemberIterator.full(
ClassDeclarationAugmentationAccess<D> patching, D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationMemberIterator._(
@ -188,6 +188,12 @@ class ClassDeclarationMemberIterator<D extends ClassDeclaration,
includeDuplicates: includeDuplicates);
}
factory ClassDeclarationMemberIterator.local(D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationMemberIterator._(classBuilder, null,
includeDuplicates: includeDuplicates);
}
ClassDeclarationMemberIterator._(
D classDeclaration, this.augmentationBuilders,
{required this.includeDuplicates})
@ -280,7 +286,7 @@ class ClassDeclarationConstructorIterator<D extends ClassDeclaration,
Iterator<D>? augmentationBuilders;
final bool includeDuplicates;
factory ClassDeclarationConstructorIterator(
factory ClassDeclarationConstructorIterator.full(
ClassDeclarationAugmentationAccess<D> patching, D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationConstructorIterator._(
@ -289,6 +295,12 @@ class ClassDeclarationConstructorIterator<D extends ClassDeclaration,
includeDuplicates: includeDuplicates);
}
factory ClassDeclarationConstructorIterator.local(D classBuilder,
{required bool includeDuplicates}) {
return new ClassDeclarationConstructorIterator._(classBuilder, null,
includeDuplicates: includeDuplicates);
}
ClassDeclarationConstructorIterator._(
D classDeclaration, this.augmentationBuilders,
{required this.includeDuplicates})

View file

@ -547,8 +547,12 @@ class DietListener extends StackListenerImpl {
if (importUri.startsWith("dart-ext:")) return;
Library libraryNode = libraryBuilder.library;
LibraryDependency dependency =
libraryNode.dependencies[importExportDirectiveIndex++];
LibraryDependency? dependency;
if (importExportDirectiveIndex < libraryNode.dependencies.length) {
// TODO(johnniwinther): Include dependencies from macro libraries in
// library dependencies.
dependency = libraryNode.dependencies[importExportDirectiveIndex++];
}
parseMetadata(libraryBuilder.bodyBuilderContext, libraryBuilder, metadata,
dependency);
}

View file

@ -358,9 +358,67 @@ class SourceClassBuilder extends ClassBuilderImpl
.forEach(build);
}
/// [Iterator] for all members declared directly in this class, including
/// augmenting members.
///
/// Duplicates are _not_ included.
///
/// For instance:
///
/// class Class {
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// method() {}
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// method2() {}
/// method2() {} // Duplicate, so it is *not* included.
/// }
///
/// augment class Class {
/// // Augmenting, so it is included for this augmentation class but
/// // not for the origin class above.
/// augment method() {}
/// // Declared, so it is included for this augmentation class but not
/// // for the origin class above.
/// extra() {}
/// }
///
Iterator<T> localMemberIterator<T extends Builder>() =>
new ClassDeclarationMemberIterator<SourceClassBuilder, T>.local(this,
includeDuplicates: false);
/// [Iterator] for all constructors declared directly in this class, including
/// augmenting constructors.
///
/// For instance:
///
/// class Class {
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// Class();
/// // Declared, so it is included for this class but not for the
/// // augmentation class below.
/// Class.named();
/// Class.named(); // Duplicate, so it is *not* included.
/// }
///
/// augment class Class {
/// // Augmenting, so it is included for this augmentation class but
/// // not for the origin class above.
/// augment Class();
/// // Declared, so it is included for this augmentation class but not
/// // for the origin class above.
/// Class.extra();
/// }
///
Iterator<T> localConstructorIterator<T extends MemberBuilder>() =>
new ClassDeclarationConstructorIterator<SourceClassBuilder, T>.local(this,
includeDuplicates: false);
@override
Iterator<T> fullMemberIterator<T extends Builder>() =>
new ClassDeclarationMemberIterator<SourceClassBuilder, T>(
new ClassDeclarationMemberIterator<SourceClassBuilder, T>.full(
const _SourceClassBuilderAugmentationAccess(), this,
includeDuplicates: false);
@ -372,7 +430,7 @@ class SourceClassBuilder extends ClassBuilderImpl
@override
Iterator<T> fullConstructorIterator<T extends MemberBuilder>() =>
new ClassDeclarationConstructorIterator<SourceClassBuilder, T>(
new ClassDeclarationConstructorIterator<SourceClassBuilder, T>.full(
const _SourceClassBuilderAugmentationAccess(), this,
includeDuplicates: false);

View file

@ -735,7 +735,7 @@ class SourceExtensionTypeDeclarationBuilder
@override
Iterator<T> fullMemberIterator<T extends Builder>() =>
new ClassDeclarationMemberIterator<SourceExtensionTypeDeclarationBuilder,
T>(
T>.full(
const _SourceExtensionTypeDeclarationBuilderAugmentationAccess(),
this,
includeDuplicates: false);
@ -751,7 +751,7 @@ class SourceExtensionTypeDeclarationBuilder
@override
Iterator<T> fullConstructorIterator<T extends MemberBuilder>() =>
new ClassDeclarationConstructorIterator<
SourceExtensionTypeDeclarationBuilder, T>(
SourceExtensionTypeDeclarationBuilder, T>.full(
const _SourceExtensionTypeDeclarationBuilderAugmentationAccess(),
this,
includeDuplicates: false);

View file

@ -498,9 +498,21 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
/// unparsed library on the [loader].
SourceLibraryBuilder createAugmentationLibrary(String source,
{Map<String, OmittedTypeBuilder>? omittedTypes}) {
assert(!isPatch,
"createAugmentationLibrary is only supported on the origin library.");
int index = _patchLibraries?.length ?? 0;
Uri uri =
new Uri(scheme: augmentationScheme, path: '${fileUri.path}-$index');
// TODO(johnniwinther): Add support for printing the generated macro
// libraries when running `fasta compile`.
/*
print('==================================================================');
print('Origin library: ${importUri}');
print('Augmentation library: $uri');
print('-----------------------------source-------------------------------');
print(source);
print('==================================================================');
*/
Map<String, Builder>? omittedTypeDeclarationBuilders;
if (omittedTypes != null && omittedTypes.isNotEmpty) {
omittedTypeDeclarationBuilders = {};

View file

@ -23,10 +23,6 @@ import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
ScannerResult,
Token,
scan;
import 'package:front_end/src/fasta/kernel/benchmarker.dart'
show BenchmarkSubdivides;
import 'package:front_end/src/fasta/kernel/exhaustiveness.dart';
import 'package:front_end/src/fasta/source/source_type_alias_builder.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
@ -50,7 +46,6 @@ import '../builder/name_iterator.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/omitted_type_builder.dart';
import '../builder/prefix_builder.dart';
import '../builder/type_builder.dart';
import '../builder_graph.dart';
import '../denylisted_classes.dart'
@ -59,8 +54,10 @@ import '../dill/dill_library_builder.dart';
import '../export.dart' show Export;
import '../fasta_codes.dart';
import '../import_chains.dart';
import '../kernel/benchmarker.dart' show BenchmarkSubdivides;
import '../kernel/body_builder.dart' show BodyBuilder;
import '../kernel/body_builder_context.dart';
import '../kernel/exhaustiveness.dart';
import '../kernel/hierarchy/class_member.dart';
import '../kernel/hierarchy/delayed.dart';
import '../kernel/hierarchy/hierarchy_builder.dart';
@ -69,7 +66,6 @@ import '../kernel/hierarchy/members_builder.dart';
import '../kernel/kernel_helper.dart'
show DelayedDefaultValueCloner, TypeDependency;
import '../kernel/kernel_target.dart' show KernelTarget;
import '../kernel/macro/annotation_parser.dart';
import '../kernel/macro/macro.dart';
import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
import '../loader.dart' show Loader, untranslatableUriScheme;
@ -88,10 +84,7 @@ import 'outline_builder.dart' show OutlineBuilder;
import 'source_class_builder.dart' show SourceClassBuilder;
import 'source_constructor_builder.dart';
import 'source_enum_builder.dart';
import 'source_extension_builder.dart';
import 'source_extension_type_declaration_builder.dart';
import 'source_factory_builder.dart';
import 'source_field_builder.dart';
import 'source_library_builder.dart'
show
ImplicitLanguageVersion,
@ -1680,143 +1673,35 @@ severity: $severity
return null;
}
Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
for (SourceLibraryBuilder libraryBuilder in sourceLibraryBuilders) {
// TODO(johnniwinther): Handle patch libraries.
LibraryMacroApplicationData libraryMacroApplicationData =
new LibraryMacroApplicationData();
Iterator<Builder> iterator = libraryBuilder.localMembersIterator;
while (iterator.moveNext()) {
Builder builder = iterator.current;
if (builder is SourceClassBuilder) {
SourceClassBuilder classBuilder = builder;
ClassMacroApplicationData classMacroApplicationData =
new ClassMacroApplicationData();
List<MacroApplication>? classMacroApplications = prebuildAnnotations(
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: classBuilder.fileUri,
metadataBuilders: classBuilder.metadata);
if (classMacroApplications != null) {
classMacroApplicationData.classApplications = new ApplicationData(
libraryBuilder, classBuilder, classMacroApplications);
}
Iterator<Builder> memberIterator = classBuilder.fullMemberIterator();
while (memberIterator.moveNext()) {
Builder memberBuilder = memberIterator.current;
if (memberBuilder is SourceProcedureBuilder) {
List<MacroApplication>? macroApplications = prebuildAnnotations(
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new ApplicationData(
libraryBuilder, memberBuilder, macroApplications);
}
} else if (memberBuilder is SourceFieldBuilder) {
List<MacroApplication>? macroApplications = prebuildAnnotations(
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new ApplicationData(
libraryBuilder, memberBuilder, macroApplications);
}
} else {
throw new UnsupportedError("Unexpected class member "
"$memberBuilder (${memberBuilder.runtimeType})");
}
}
Iterator<MemberBuilder> constructorIterator =
classBuilder.fullConstructorIterator();
while (constructorIterator.moveNext()) {
MemberBuilder memberBuilder = constructorIterator.current;
if (memberBuilder is DeclaredSourceConstructorBuilder) {
List<MacroApplication>? macroApplications = prebuildAnnotations(
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new ApplicationData(
libraryBuilder, memberBuilder, macroApplications);
}
} else if (memberBuilder is SourceFactoryBuilder) {
List<MacroApplication>? macroApplications = prebuildAnnotations(
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new ApplicationData(
libraryBuilder, memberBuilder, macroApplications);
}
} else {
throw new UnsupportedError("Unexpected constructor "
"$memberBuilder (${memberBuilder.runtimeType})");
}
}
if (classMacroApplicationData.classApplications != null ||
classMacroApplicationData.memberApplications.isNotEmpty) {
libraryMacroApplicationData.classData[builder] =
classMacroApplicationData;
}
} else if (builder is SourceProcedureBuilder) {
List<MacroApplication>? macroApplications = prebuildAnnotations(
enclosingLibrary: libraryBuilder,
scope: libraryBuilder.scope,
fileUri: builder.fileUri,
metadataBuilders: builder.metadata);
if (macroApplications != null) {
libraryMacroApplicationData.memberApplications[builder] =
new ApplicationData(libraryBuilder, builder, macroApplications);
}
} else if (builder is SourceFieldBuilder) {
List<MacroApplication>? macroApplications = prebuildAnnotations(
enclosingLibrary: libraryBuilder,
scope: libraryBuilder.scope,
fileUri: builder.fileUri,
metadataBuilders: builder.metadata);
if (macroApplications != null) {
libraryMacroApplicationData.memberApplications[builder] =
new ApplicationData(libraryBuilder, builder, macroApplications);
}
} else if (builder is PrefixBuilder ||
builder is SourceExtensionBuilder ||
builder is SourceTypeAliasBuilder) {
// Macro applications are not supported.
} else {
throw new UnsupportedError("Unexpected library member "
"$builder (${builder.runtimeType})");
}
}
if (libraryMacroApplicationData.classData.isNotEmpty ||
libraryMacroApplicationData.memberApplications.isNotEmpty) {
libraryData[libraryBuilder] = libraryMacroApplicationData;
}
}
if (libraryData.isNotEmpty) {
MacroApplications macroApplications = new MacroApplications(
this,
target.context.options.macroExecutor,
dataForTesting?.macroApplicationData);
macroApplications
.computeLibrariesMacroApplicationData(sourceLibraryBuilders);
if (macroApplications.hasLoadableMacroIds) {
target.benchmarker?.beginSubdivide(
BenchmarkSubdivides.computeMacroApplications_macroExecutorProvider);
await macroApplications.loadMacroIds(target.benchmarker);
target.benchmarker?.endSubdivide();
MacroApplications result = await MacroApplications.loadMacroIds(
target.context.options.macroExecutor,
libraryData,
dataForTesting?.macroApplicationData,
target.benchmarker);
return result;
return macroApplications;
}
return null;
}
Future<void> computeAdditionalMacroApplications(
MacroApplications macroApplications,
Iterable<SourceLibraryBuilder> sourceLibraryBuilders) async {
macroApplications
.computeLibrariesMacroApplicationData(sourceLibraryBuilders);
if (macroApplications.hasLoadableMacroIds) {
target.benchmarker?.beginSubdivide(
BenchmarkSubdivides.computeMacroApplications_macroExecutorProvider);
await macroApplications.loadMacroIds(target.benchmarker);
target.benchmarker?.endSubdivide();
}
}
void finishDeferredLoadTearoffs() {
int count = 0;
for (SourceLibraryBuilder library in sourceLibraryBuilders) {

View file

@ -0,0 +1,37 @@
// Copyright (c) 2024, 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class CreateMacro implements ClassDeclarationsMacro {
const CreateMacro();
FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz,
MemberDeclarationBuilder builder) async {
Uri myUri = Uri.parse('package:macro/cascade.dart');
builder.declareInType(DeclarationCode.fromParts([
' @',
await builder.resolveIdentifier(myUri, 'CreateMethodMacro'),
'()\n external ',
NamedTypeAnnotationCode(name: clazz.identifier),
' create();',
]));
}
}
macro class CreateMethodMacro implements MethodDefinitionMacro {
const CreateMethodMacro();
FutureOr<void> buildDefinitionForMethod(
MethodDeclaration method, FunctionDefinitionBuilder builder) {
builder.augment(FunctionBodyCode.fromParts([
' => ',
method.definingType,
'();'
]));
}
}

View file

@ -0,0 +1,30 @@
// Copyright (c) 2024, 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.
/*library:
Declarations Order:
Class:CreateMacro.new()
Definition Order:
Class.create:CreateMethodMacro.new()
Definitions:
import 'org-dartlang-test:///a/b/c/main.dart' as prefix0;
augment class Class {
augment prefix0.Class create() => prefix0.Class();
}*/
import 'package:macro/cascade.dart';
@CreateMacro()
/*class: Class:
declarations:
import 'package:macro/cascade.dart' as prefix0;
import 'org-dartlang-test:///a/b/c/main.dart' as prefix1;
augment class Class {
@prefix0.CreateMethodMacro()
external prefix1.Class create();
}
*/
class Class {}

View file

@ -0,0 +1,21 @@
library;
import self as self;
import "package:macro/cascade.dart" as cas;
import "dart:core" as core;
import "package:macro/cascade.dart";
@#C1
class Class extends core::Object {
synthetic constructor •() → self::Class
: super core::Object::•()
;
@#C2
method /* from org-dartlang-augmentation:/a/b/c/main.dart-1 */ create() → self::Class
return new self::Class::•();
}
constants {
#C1 = cas::CreateMacro {}
#C2 = cas::CreateMethodMacro {}
}

View file

@ -981,6 +981,7 @@ lives
ll
llub
lm
loadable
locationd
logged
logically

View file

@ -753,7 +753,16 @@ class LibraryDependency extends TreeNode implements Annotatable {
@override
void toTextInternal(AstPrinter printer) {
// TODO(johnniwinther): Implement this.
if (isExport) {
printer.write('export ');
} else {
printer.write('import ');
}
if (isDeferred) {
printer.write('deferred ');
}
printer.writeLibraryReference(importedLibraryReference);
printer.write(';');
}
}

View file

@ -160,6 +160,10 @@ class AstPrinter {
}
}
void writeLibraryReference(Reference reference) {
_sb.write(libraryReferenceToString(reference));
}
void writeName(Name? name) {
_sb.write(nameToString(name,
includeLibraryName: _strategy.includeLibraryNamesInMembers));

View file

@ -31,6 +31,25 @@ String libraryNameToString(Library? node) {
return node == null ? 'null' : node.name ?? 'library ${node.importUri}';
}
String libraryReferenceToString(Reference? reference) {
if (reference == null) {
return '<missing-library-reference>';
} else {
Library? node = reference.node as Library?;
if (node != null) {
return node.importUri.toString();
} else {
CanonicalName? canonicalName = reference.canonicalName;
if (canonicalName != null) {
return qualifiedCanonicalNameToString(canonicalName,
includeLibraryName: false);
} else {
return '<unlinked-library-reference>';
}
}
}
}
String qualifiedClassNameToString(Class node,
{bool includeLibraryName = false}) {
TreeNode? parent = node.parent;

View file

@ -35,9 +35,10 @@ macro class JsonSerializable implements ClassDeclarationsMacro {
clazz.library.uri.resolve('json_serializable.dart');
builder.declareInType(DeclarationCode.fromParts([
'@',
' @',
await builder.resolveIdentifier(jsonSerializableUri, 'FromJson'),
'()\n ',
// TODO(language#3580): Remove/replace 'external'?
'()\n external ',
clazz.identifier.name,
'.fromJson(',
mapStringObject,
@ -45,9 +46,10 @@ macro class JsonSerializable implements ClassDeclarationsMacro {
]));
builder.declareInType(DeclarationCode.fromParts([
'@',
' @',
await builder.resolveIdentifier(jsonSerializableUri, 'ToJson'),
'()\n ',
// TODO(language#3580): Remove/replace 'external'?
'()\n external ',
mapStringObject,
' toJson();',
]));