mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 17:35:46 +00:00
[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:
parent
64b03d1998
commit
694c2911e2
|
@ -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>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.'));
|
||||
}
|
||||
|
|
637
pkg/front_end/lib/src/fasta/kernel/macro/introspectors.dart
Normal file
637
pkg/front_end/lib/src/fasta/kernel/macro/introspectors.dart
Normal 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
187
pkg/front_end/lib/src/fasta/kernel/macro/types.dart
Normal file
187
pkg/front_end/lib/src/fasta/kernel/macro/types.dart
Normal 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);
|
||||
}
|
|
@ -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})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
'();'
|
||||
]));
|
||||
}
|
||||
}
|
|
@ -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 {}
|
|
@ -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 {}
|
||||
}
|
|
@ -981,6 +981,7 @@ lives
|
|||
ll
|
||||
llub
|
||||
lm
|
||||
loadable
|
||||
locationd
|
||||
logged
|
||||
logically
|
||||
|
|
|
@ -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(';');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();',
|
||||
]));
|
||||
|
|
Loading…
Reference in a new issue