[cfe] Apply phase 2 macro results

Results of Phase 2 macros are now applied. The macro application code
has been refactored to support that Phase 1 can apply all macro
applications within a library in bulk, but Phase 2 can apply each
macro application in sequence.

The later is to prepare for making added member visible to subsequent
macro applications within Phase 2. This functionality has not been
completed yet.

Change-Id: Idaf2702e21bde75aedb1509d88e02f270196af5e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233380
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2022-02-18 11:00:31 +00:00
committed by Commit Bot
parent 0a275f6e97
commit 931fd976c6
21 changed files with 407 additions and 95 deletions
@@ -7010,6 +7010,34 @@ const MessageCode messageLoadLibraryTakesNoArguments = const MessageCode(
analyzerCodes: <String>["LOAD_LIBRARY_TAKES_NO_ARGUMENTS"],
problemMessage: r"""'loadLibrary' takes no arguments.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
String
name)> templateMacroClassNotDeclaredMacro = const Template<
Message Function(String name)>(
problemMessageTemplate:
r"""Non-abstract class '#name' implements 'Macro' but isn't declared as a macro class.""",
correctionMessageTemplate: r"""Try adding the 'macro' class modifier.""",
withArguments: _withArgumentsMacroClassNotDeclaredMacro);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)> codeMacroClassNotDeclaredMacro =
const Code<Message Function(String name)>(
"MacroClassNotDeclaredMacro",
);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsMacroClassNotDeclaredMacro(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeMacroClassNotDeclaredMacro,
problemMessage:
"""Non-abstract class '${name}' implements 'Macro' but isn't declared as a macro class.""",
correctionMessage: """Try adding the 'macro' class modifier.""",
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeMainNotFunctionDeclaration =
messageMainNotFunctionDeclaration;
@@ -1749,6 +1749,7 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
loader: lastGoodKernelTarget.loader,
nameOrigin: libraryBuilder,
isUnsupported: libraryBuilder.isUnsupported,
isAugmentation: false,
);
libraryBuilder.scope.forEachLocalMember((name, member) {
debugLibrary.scope.addLocalMember(name, member, setter: false);
@@ -1803,6 +1804,7 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
scope: debugLibrary.scope.createNestedScope("expression"),
nameOrigin: libraryBuilder,
isUnsupported: libraryBuilder.isUnsupported,
isAugmentation: false,
);
HybridFileSystem hfs =
@@ -427,12 +427,25 @@ class KernelTarget extends TargetImplementation {
Future<void> _buildForPhase1(
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();
}
loader.computeLibraryScopes(augmentationLibraries);
// TODO(johnniwinther): Support computation of macro applications in
// augmentation libraries?
loader.resolveTypes(augmentationLibraries);
}
/// Builds [augmentationLibrary] to the state expected after applying phase
/// 2 macros.
void _buildForPhase2(SourceLibraryBuilder augmentationLibrary) {
augmentationLibrary.finishTypeVariables(objectClassBuilder, dynamicType);
augmentationLibrary.build(loader.coreLibrary, modifyTarget: false);
augmentationLibrary.resolveConstructors();
}
Future<BuildResult> buildOutlines({CanonicalName? nameRoot}) async {
if (loader.first == null) return new BuildResult();
return withCrashReporting<BuildResult>(() async {
@@ -483,7 +496,8 @@ class KernelTarget extends TargetImplementation {
loader.checkSemantics(objectClassBuilder);
benchmarker?.enterPhase(BenchmarkPhases.outline_finishTypeVariables);
loader.finishTypeVariables(objectClassBuilder, dynamicType);
loader.finishTypeVariables(
loader.sourceLibraryBuilders, objectClassBuilder, dynamicType);
benchmarker
?.enterPhase(BenchmarkPhases.outline_createTypeInferenceEngine);
@@ -500,7 +514,7 @@ class KernelTarget extends TargetImplementation {
installSyntheticConstructors(sourceClassBuilders);
benchmarker?.enterPhase(BenchmarkPhases.outline_resolveConstructors);
loader.resolveConstructors();
loader.resolveConstructors(loader.sourceLibraryBuilders);
benchmarker?.enterPhase(BenchmarkPhases.outline_link);
component =
@@ -517,8 +531,11 @@ class KernelTarget extends TargetImplementation {
if (macroApplications != null) {
benchmarker?.enterPhase(BenchmarkPhases.outline_applyDeclarationMacros);
await macroApplications
.applyDeclarationsMacros(loader.hierarchyBuilder);
await macroApplications.applyDeclarationsMacros(loader.hierarchyBuilder,
(SourceLibraryBuilder augmentationLibrary) async {
await _buildForPhase1([augmentationLibrary]);
_buildForPhase2(augmentationLibrary);
});
}
benchmarker
+88 -59
View File
@@ -116,6 +116,7 @@ class MacroApplications {
final macro.MacroExecutor _macroExecutor;
final Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData;
final MacroApplicationDataForTesting? dataForTesting;
List<_ApplicationData>? _applicationDataCache;
MacroApplications(
this._macroExecutor, this.libraryData, this.dataForTesting) {
@@ -272,60 +273,57 @@ class MacroApplications {
}
}
Future<Map<SourceLibraryBuilder, List<macro.MacroExecutionResult>>>
_applyMacros(
Future<List<macro.MacroExecutionResult>> Function(
Builder, macro.Declaration, List<MacroApplication>)
applyMacros) async {
Map<SourceLibraryBuilder, List<macro.MacroExecutionResult>> libraryResults =
{};
for (MapEntry<SourceLibraryBuilder,
LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
SourceLibraryBuilder libraryBuilder = libraryEntry.key;
List<macro.MacroExecutionResult> results = [];
LibraryMacroApplicationData libraryMacroApplicationData =
libraryEntry.value;
for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
in libraryMacroApplicationData.memberApplications.entries) {
MemberBuilder memberBuilder = memberEntry.key;
macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
if (declaration != null) {
results.addAll(
await applyMacros(memberBuilder, declaration, memberEntry.value));
}
}
for (MapEntry<SourceClassBuilder, ClassMacroApplicationData> classEntry
in libraryMacroApplicationData.classData.entries) {
SourceClassBuilder classBuilder = classEntry.key;
ClassMacroApplicationData classData = classEntry.value;
List<MacroApplication>? classApplications = classData.classApplications;
if (classApplications != null) {
macro.ClassDeclaration classDeclaration =
_getClassDeclaration(classBuilder);
results.addAll(await applyMacros(
classBuilder, classDeclaration, classApplications));
}
Iterable<_ApplicationData> get _applicationData {
if (_applicationDataCache == null) {
List<_ApplicationData> data = _applicationDataCache = [];
for (MapEntry<SourceLibraryBuilder,
LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
SourceLibraryBuilder libraryBuilder = libraryEntry.key;
LibraryMacroApplicationData libraryMacroApplicationData =
libraryEntry.value;
for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
in classData.memberApplications.entries) {
in libraryMacroApplicationData.memberApplications.entries) {
MemberBuilder memberBuilder = memberEntry.key;
macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
if (declaration != null) {
results.addAll(await applyMacros(
memberBuilder, declaration, memberEntry.value));
data.add(new _ApplicationData(
libraryBuilder, memberBuilder, declaration, memberEntry.value));
}
}
for (MapEntry<SourceClassBuilder, ClassMacroApplicationData> classEntry
in libraryMacroApplicationData.classData.entries) {
SourceClassBuilder classBuilder = classEntry.key;
ClassMacroApplicationData classData = classEntry.value;
List<MacroApplication>? classApplications =
classData.classApplications;
if (classApplications != null) {
macro.ClassDeclaration classDeclaration =
_getClassDeclaration(classBuilder);
data.add(new _ApplicationData(libraryBuilder, classBuilder,
classDeclaration, classApplications));
}
for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
in classData.memberApplications.entries) {
MemberBuilder memberBuilder = memberEntry.key;
macro.Declaration? declaration =
_getMemberDeclaration(memberBuilder);
if (declaration != null) {
data.add(new _ApplicationData(libraryBuilder, memberBuilder,
declaration, memberEntry.value));
}
}
}
}
libraryResults[libraryBuilder] = results;
}
return libraryResults;
return _applicationDataCache!;
}
Future<List<macro.MacroExecutionResult>> _applyTypeMacros(
Builder builder,
macro.Declaration declaration,
List<MacroApplication> macroApplications) async {
_ApplicationData applicationData) async {
macro.Declaration declaration = applicationData.declaration;
List<macro.MacroExecutionResult> results = [];
for (MacroApplication macroApplication in macroApplications) {
for (MacroApplication macroApplication
in applicationData.macroApplications) {
if (macroApplication.instanceIdentifier
.shouldExecute(_declarationKind(declaration), macro.Phase.types)) {
macro.MacroExecutionResult result =
@@ -336,6 +334,7 @@ class MacroApplications {
}
if (retainDataForTesting) {
Builder builder = applicationData.builder;
if (builder is SourceClassBuilder) {
dataForTesting?.classTypesResults[builder] = results;
} else {
@@ -347,8 +346,13 @@ class MacroApplications {
Future<List<SourceLibraryBuilder>> applyTypeMacros() async {
List<SourceLibraryBuilder> augmentationLibraries = [];
Map<SourceLibraryBuilder, List<macro.MacroExecutionResult>> results =
await _applyMacros(_applyTypeMacros);
Map<SourceLibraryBuilder, List<macro.MacroExecutionResult>> results = {};
for (_ApplicationData macroApplication in _applicationData) {
List<macro.MacroExecutionResult> executionResults =
await _applyTypeMacros(macroApplication);
(results[macroApplication.libraryBuilder] ??= [])
.addAll(executionResults);
}
for (MapEntry<SourceLibraryBuilder, List<macro.MacroExecutionResult>> entry
in results.entries) {
SourceLibraryBuilder sourceLibraryBuilder = entry.key;
@@ -363,12 +367,12 @@ class MacroApplications {
return augmentationLibraries;
}
Future<List<macro.MacroExecutionResult>> _applyDeclarationsMacros(
Builder builder,
macro.Declaration declaration,
List<MacroApplication> macroApplications) async {
Future<void> _applyDeclarationsMacros(_ApplicationData applicationData,
Future<void> Function(SourceLibraryBuilder) onAugmentationLibrary) async {
List<macro.MacroExecutionResult> results = [];
for (MacroApplication macroApplication in macroApplications) {
macro.Declaration declaration = applicationData.declaration;
for (MacroApplication macroApplication
in applicationData.macroApplications) {
if (macroApplication.instanceIdentifier.shouldExecute(
_declarationKind(declaration), macro.Phase.declarations)) {
macro.MacroExecutionResult result =
@@ -377,10 +381,19 @@ class MacroApplications {
declaration,
typeResolver,
classIntrospector);
results.add(result);
String source = _macroExecutor
.buildAugmentationLibrary([result], _resolveIdentifier);
SourceLibraryBuilder augmentationLibrary = await applicationData
.libraryBuilder
.createAugmentationLibrary(source);
await onAugmentationLibrary(augmentationLibrary);
if (retainDataForTesting) {
results.add(result);
}
}
}
if (retainDataForTesting) {
Builder builder = applicationData.builder;
if (builder is SourceClassBuilder) {
dataForTesting?.classDeclarationsResults[builder] = results;
} else {
@@ -388,27 +401,28 @@ class MacroApplications {
results;
}
}
return results;
}
late Types types;
late macro.TypeResolver typeResolver;
late macro.ClassIntrospector classIntrospector;
Future<void> applyDeclarationsMacros(
ClassHierarchyBase classHierarchy) async {
Future<void> applyDeclarationsMacros(ClassHierarchyBase classHierarchy,
Future<void> Function(SourceLibraryBuilder) onAugmentationLibrary) async {
types = new Types(classHierarchy);
typeResolver = new _TypeResolver(this);
classIntrospector = new _ClassIntrospector(this);
await _applyMacros(_applyDeclarationsMacros);
for (_ApplicationData macroApplication in _applicationData) {
await _applyDeclarationsMacros(macroApplication, onAugmentationLibrary);
}
}
Future<List<macro.MacroExecutionResult>> _applyDefinitionMacros(
Builder builder,
macro.Declaration declaration,
List<MacroApplication> macroApplications) async {
_ApplicationData applicationData) async {
List<macro.MacroExecutionResult> results = [];
for (MacroApplication macroApplication in macroApplications) {
macro.Declaration declaration = applicationData.declaration;
for (MacroApplication macroApplication
in applicationData.macroApplications) {
if (macroApplication.instanceIdentifier.shouldExecute(
_declarationKind(declaration), macro.Phase.definitions)) {
macro.MacroExecutionResult result =
@@ -422,6 +436,7 @@ class MacroApplications {
}
}
if (retainDataForTesting) {
Builder builder = applicationData.builder;
if (builder is SourceClassBuilder) {
dataForTesting?.classDefinitionsResults[builder] = results;
} else {
@@ -436,13 +451,16 @@ class MacroApplications {
Future<void> applyDefinitionMacros() async {
typeDeclarationResolver = new _TypeDeclarationResolver();
await _applyMacros(_applyDefinitionMacros);
for (_ApplicationData macroApplication in _applicationData) {
await _applyDefinitionMacros(macroApplication);
}
}
void close() {
_macroExecutor.close();
_staticTypeCache.clear();
_typeAnnotationCache.clear();
_applicationDataCache?.clear();
}
macro.ClassDeclaration _createClassDeclaration(SourceClassBuilder builder) {
@@ -951,3 +969,14 @@ macro.DeclarationKind _declarationKind(macro.Declaration declaration) {
throw new UnsupportedError(
"Unexpected declaration ${declaration} (${declaration.runtimeType})");
}
/// Data needed to apply a list of macro applications to a class or member.
class _ApplicationData {
final SourceLibraryBuilder libraryBuilder;
final Builder builder;
final macro.Declaration declaration;
final List<MacroApplication> macroApplications;
_ApplicationData(this.libraryBuilder, this.builder, this.declaration,
this.macroApplications);
}
@@ -618,8 +618,11 @@ class SourceClassBuilder extends ClassBuilderImpl
}
}
void checkSupertypes(CoreTypes coreTypes,
ClassHierarchyBuilder hierarchyBuilder, Class enumClass) {
void checkSupertypes(
CoreTypes coreTypes,
ClassHierarchyBuilder hierarchyBuilder,
Class enumClass,
Class? macroClass) {
// This method determines whether the class (that's being built) its super
// class appears both in 'extends' and 'implements' clauses and whether any
// interface appears multiple times in the 'implements' clause.
@@ -679,6 +682,27 @@ class SourceClassBuilder extends ClassBuilderImpl
}
}
}
if (macroClass != null && !cls.isMacro && !cls.isAbstract) {
// TODO(johnniwinther): Merge this check with the loop above.
bool isMacroFound = false;
List<Supertype> interfaces =
hierarchyBuilder.getNodeFromClass(cls).superclasses;
for (int i = 0; !isMacroFound && i < interfaces.length; i++) {
if (interfaces[i].classNode == macroClass) {
isMacroFound = true;
}
}
interfaces = hierarchyBuilder.getNodeFromClass(cls).interfaces;
for (int i = 0; !isMacroFound && i < interfaces.length; i++) {
if (interfaces[i].classNode == macroClass) {
isMacroFound = true;
}
}
if (isMacroFound) {
addProblem(templateMacroClassNotDeclaredMacro.withArguments(name),
charOffset, noLength);
}
}
void fail(NamedTypeBuilder target, Message message,
TypeAliasBuilder? aliasBuilder) {
@@ -243,6 +243,9 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
List<SourceLibraryBuilder>? _patchLibraries;
/// `true` if this is an augmentation library.
final bool isAugmentation;
SourceLibraryBuilder.internal(
SourceLoader loader,
Uri fileUri,
@@ -253,8 +256,9 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
Library library,
LibraryBuilder? nameOrigin,
Library? referencesFrom,
bool? referenceIsPartOwner,
bool isUnsupported)
{bool? referenceIsPartOwner,
required bool isUnsupported,
required bool isAugmentation})
: this.fromScopes(
loader,
fileUri,
@@ -266,7 +270,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
library,
nameOrigin,
referencesFrom,
isUnsupported);
isUnsupported: isUnsupported,
isAugmentation: isAugmentation);
SourceLibraryBuilder.fromScopes(
this.loader,
@@ -279,7 +284,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
this.library,
this._nameOrigin,
this.referencesFrom,
this.isUnsupported)
{required this.isUnsupported,
required this.isAugmentation})
: _languageVersion = packageLanguageVersion,
currentTypeParameterScopeBuilder = _libraryTypeParameterScopeBuilder,
referencesFromIndexed =
@@ -469,7 +475,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
LibraryBuilder? nameOrigin,
Library? referencesFrom,
bool? referenceIsPartOwner,
required bool isUnsupported})
required bool isUnsupported,
required bool isAugmentation})
: this.internal(
loader,
fileUri,
@@ -487,8 +494,9 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
..setLanguageVersion(packageLanguageVersion.version)),
nameOrigin,
referencesFrom,
referenceIsPartOwner,
isUnsupported);
referenceIsPartOwner: referenceIsPartOwner,
isUnsupported: isUnsupported,
isAugmentation: isAugmentation);
@override
bool get isPart => partOfName != null || partOfUri != null;
@@ -520,7 +528,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
loader: loader,
isUnsupported: false,
target: library,
origin: this);
origin: this,
isAugmentation: true);
addPatchLibrary(augmentationLibrary);
loader.registerUnparsedLibrarySource(augmentationLibrary, source);
return augmentationLibrary;
@@ -3896,9 +3905,11 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
Builder member = patchDeclarations.current;
// We need to inject all non-patch members into the origin library. This
// should only apply to private members.
// For augmentation libraries, all members are injected into the origin
// library, regardless of privacy.
if (member.isPatch) {
// Ignore patches.
} else if (name.startsWith("_")) {
} else if (name.startsWith("_") || isAugmentation) {
origin.injectMemberFromPatch(name, member);
} else {
origin.exportMemberFromPatch(name, member);
@@ -328,7 +328,8 @@ class SourceLoader extends Loader {
referenceIsPartOwner: referenceIsPartOwner,
isUnsupported: origin?.library.isUnsupported ??
importUri.isScheme('dart') &&
!target.uriTranslator.isLibrarySupported(importUri.path));
!target.uriTranslator.isLibrarySupported(importUri.path),
isAugmentation: false);
}
/// Return `"true"` if the [dottedName] is a 'dart.library.*' qualifier for a
@@ -1689,9 +1690,9 @@ severity: $severity
ticker.logMs("Finished forwarders for $count procedures");
}
void resolveConstructors() {
void resolveConstructors(List<SourceLibraryBuilder> libraryBuilders) {
int count = 0;
for (SourceLibraryBuilder library in sourceLibraryBuilders) {
for (SourceLibraryBuilder library in libraryBuilders) {
count += library.resolveConstructors();
}
ticker.logMs("Resolved $count constructors");
@@ -1705,9 +1706,10 @@ severity: $severity
}
}
void finishTypeVariables(ClassBuilder object, TypeBuilder dynamicType) {
void finishTypeVariables(Iterable<SourceLibraryBuilder> libraryBuilders,
ClassBuilder object, TypeBuilder dynamicType) {
int count = 0;
for (SourceLibraryBuilder library in sourceLibraryBuilders) {
for (SourceLibraryBuilder library in libraryBuilders) {
count += library.finishTypeVariables(object, dynamicType);
}
ticker.logMs("Resolved $count type-variable bounds");
@@ -2065,7 +2067,8 @@ severity: $severity
List<SourceClassBuilder> sourceClasses, Class enumClass) {
for (SourceClassBuilder builder in sourceClasses) {
if (builder.library.loader == this && !builder.isPatch) {
builder.checkSupertypes(coreTypes, hierarchyBuilder, enumClass);
builder.checkSupertypes(
coreTypes, hierarchyBuilder, enumClass, _macroClassBuilder?.cls);
}
}
ticker.logMs("Checked supertypes");
+2
View File
@@ -578,6 +578,8 @@ LibraryDirectiveNotFirst/script2: Fail
LibraryDirectiveNotFirst/script3: Fail
ListLiteralTooManyTypeArguments/example: Fail
LoadLibraryTakesNoArguments/example: Fail
MacroClassNotDeclaredMacro/analyzerCode: Fail
MacroClassNotDeclaredMacro/example: Fail
MainNotFunctionDeclaration/analyzerCode: Fail
MainNotFunctionDeclarationExported/analyzerCode: Fail
MainNotFunctionDeclarationExported/part_wrapped_script: Fail
+4
View File
@@ -5479,3 +5479,7 @@ EnumContainsValuesDeclaration:
EnumImplementerContainsValuesDeclaration:
problemMessage: "'#name' has 'Enum' as a superinterface and can't contain non-static member with name 'values'."
MacroClassNotDeclaredMacro:
problemMessage: "Non-abstract class '#name' implements 'Macro' but isn't declared as a macro class."
correctionMessage: "Try adding the 'macro' class modifier."
@@ -95,7 +95,8 @@ Future<void> main() async {
new NoneTarget(new TargetFlags())),
uriTranslator)
.loader,
isUnsupported: false);
isUnsupported: false,
isAugmentation: false);
libraryBuilder.markLanguageVersionFinal();
LoadLibraryBuilder loadLibraryBuilder =
new LoadLibraryBuilder(libraryBuilder, dummyLibraryDependency, -1);
@@ -51,7 +51,8 @@ class FunctionTypesMacro1 implements FunctionTypesMacro {
name, new DeclarationCode.fromParts(['''
class $name {
external ''', function.returnType.code, ''' method();
}''']));
}'''
]));
}
}
@@ -129,8 +130,14 @@ class MethodDeclarationsMacro1 implements MethodDeclarationsMacro {
if (method.isSetter) {
sb.write('s');
}
String name;
if (method.isOperator) {
name = 'operator';
} else {
name = method.identifier.name;
}
builder.declareInLibrary(new DeclarationCode.fromString('''
void ${method.definingClass.name}_${method.identifier.name}GeneratedMethod_${sb}() {}
void ${method.definingClass.name}_${name}GeneratedMethod_${sb}() {}
'''));
}
}
@@ -288,3 +295,31 @@ void ${constructor.definingClass.name}_${constructor.identifier
'''));
}
}
macro
class ToStringMacro implements ClassDeclarationsMacro {
const ToStringMacro();
FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz,
ClassMemberDeclarationBuilder builder) async {
Iterable<MethodDeclaration> methods = await builder.methodsOf(clazz);
if (!methods.any((m) => m.identifier.name == 'toString')) {
Iterable<FieldDeclaration> fields = await builder.fieldsOf(clazz);
List<Object> parts = ['''
toString() {
return "${clazz.identifier.name}('''];
String comma = '';
for (FieldDeclaration field in fields) {
parts.add(comma);
parts.add('${field.identifier.name}=\${');
parts.add(field.identifier.name);
parts.add('}');
comma = ',';
}
parts.add(''')";
}''');
builder.declareInClass(new DeclarationCode.fromParts(parts));
}
}
}
@@ -112,7 +112,7 @@ void Class1_instanceSetter1GeneratedMethod_s() {}
void set instanceSetter1(int? value) {}
/*member: Class1.[]:
void Class1_[]GeneratedMethod_o() {}
void Class1_operatorGeneratedMethod_o() {}
*/
@MethodDeclarationsMacro1()
int operator [](int i) => i;
@@ -19,6 +19,9 @@ class Class1 extends core::Object {
constructor •() → self::Class1
: super core::Object::•()
;
method /* from org-dartlang-augmentation:/a/b/c/main.dart-18 */ Class1_GeneratedMethod_() → void {}
method /* from org-dartlang-augmentation:/a/b/c/main.dart-19 */ Class1_redirectGeneratedMethod_f() → void {}
method /* from org-dartlang-augmentation:/a/b/c/main.dart-20 */ Class1_factGeneratedMethod_f() → void {}
@#C5
static factory redirect() → self::Class1
return new self::Class1::•();
@@ -68,6 +71,35 @@ static get topLevelGetter1() → core::int?
return null;
@#C8
static set topLevelSetter1(core::int? value) → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-1 */ topLevelFunction1GeneratedMethod_() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-2 */ topLevelFunction2GeneratedMethod_e() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-3 */ topLevelField1GeneratedMethod_() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-4 */ topLevelField2GeneratedMethod_e() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-5 */ topLevelField3GeneratedMethod_f() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-6 */ topLevelField4GeneratedMethod_l() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-7 */ topLevelGetter1GeneratedMethod_g() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-8 */ topLevelSetter1GeneratedMethod_s() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-9 */ Class1GeneratedMethod_() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-10 */ Class1Introspection() → void {
core::print("constructors=''");
core::print("fields='instanceField1','instanceField2','instanceField3'");
core::print("methods='instanceMethod1','instanceGetter1','[]','instanceSetter1'");
}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-11 */ Class1_instanceMethod1GeneratedMethod_() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-12 */ Class1_instanceGetter1GeneratedMethod_g() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-13 */ Class1_operatorGeneratedMethod_o() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-14 */ Class1_instanceField1GeneratedMethod_() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-15 */ Class1_instanceField2GeneratedMethod_f() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-16 */ Class1_instanceField3GeneratedMethod_fl() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-17 */ Class1_instanceSetter1GeneratedMethod_s() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-21 */ Class2GeneratedMethod_a() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-22 */ Class2Introspection() → void {
core::print("constructors=");
core::print("fields='instanceField1'");
core::print("methods='instanceMethod1'");
}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-23 */ Class2_instanceMethod1GeneratedMethod_a() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-24 */ Class2_instanceField1GeneratedMethod_() → void {}
constants {
#C1 = mac::ClassDeclarationsMacro1 {}
@@ -52,6 +52,10 @@ external static method topLevelFunction3(self::C1 a) → self::C2;
@#C1
@#C2
external static method topLevelFunction4(self::D1 a) → self::D2;
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-1 */ topLevelFunction1GeneratedMethod_es() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-2 */ topLevelFunction2GeneratedMethod_s() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-3 */ topLevelFunction3GeneratedMethod_() → void {}
static method /* from org-dartlang-augmentation:/a/b/c/main.dart-4 */ topLevelFunction4GeneratedMethod_() → void {}
constants {
#C1 = mac::FunctionDeclarationsMacro2 {}
@@ -0,0 +1,47 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/*library:
*/
import 'package:macro/macro.dart';
@ToStringMacro()
/*class: A:
augment class A {
toString() {
return "A(a=${a},b=${b})";
}
}*/
class A {
var a;
var b;
}
@ToStringMacro()
/*class: B:
augment class B {
toString() {
return "B(c=${c},d=${d},e=${e})";
}
}*/
class B {
var c, d;
var e;
}
@ToStringMacro()
class C {
var f;
@override
String toString() => 'C()';
}
class D {
var g;
var h;
}
@@ -0,0 +1,52 @@
library /*isNonNullableByDefault*/;
import self as self;
import "package:macro/macro.dart" as mac;
import "dart:core" as core;
import "package:macro/macro.dart";
@#C1
class A extends core::Object {
field dynamic a = null;
field dynamic b = null;
synthetic constructor •() → self::A
: super core::Object::•()
;
method /* from org-dartlang-augmentation:/a/b/c/main.dart-1 */ toString() → dynamic {
return "A(a=${this.{self::A::a}{dynamic}},b=${this.{self::A::b}{dynamic}})";
}
}
@#C1
class B extends core::Object {
field dynamic c = null;
field dynamic d = null;
field dynamic e = null;
synthetic constructor •() → self::B
: super core::Object::•()
;
method /* from org-dartlang-augmentation:/a/b/c/main.dart-2 */ toString() → dynamic {
return "B(c=${this.{self::B::c}{dynamic}},d=${this.{self::B::d}{dynamic}},e=${this.{self::B::e}{dynamic}})";
}
}
@#C1
class C extends core::Object {
field dynamic f = null;
synthetic constructor •() → self::C
: super core::Object::•()
;
@#C2
method toString() → core::String
return "C()";
}
class D extends core::Object {
field dynamic g = null;
field dynamic h = null;
synthetic constructor •() → self::D
: super core::Object::•()
;
}
constants {
#C1 = mac::ToStringMacro {}
#C2 = core::_Override {}
}
@@ -184,7 +184,9 @@ class MacroDataComputer extends DataComputer<String> {
in macroApplicationData.classTypesResults.entries) {
if (entry.key.cls == cls) {
for (MacroExecutionResult result in entry.value) {
sb.write('\n${codeToString(result.augmentations.first)}');
if (result.augmentations.isNotEmpty) {
sb.write('\n${codeToString(result.augmentations.first)}');
}
}
}
}
@@ -192,7 +194,9 @@ class MacroDataComputer extends DataComputer<String> {
in macroApplicationData.classDeclarationsResults.entries) {
if (entry.key.cls == cls) {
for (MacroExecutionResult result in entry.value) {
sb.write('\n${codeToString(result.augmentations.first)}');
if (result.augmentations.isNotEmpty) {
sb.write('\n${codeToString(result.augmentations.first)}');
}
}
}
}
@@ -200,7 +204,9 @@ class MacroDataComputer extends DataComputer<String> {
in macroApplicationData.classDefinitionsResults.entries) {
if (entry.key.cls == cls) {
for (MacroExecutionResult result in entry.value) {
sb.write('\n${codeToString(result.augmentations.first)}');
if (result.augmentations.isNotEmpty) {
sb.write('\n${codeToString(result.augmentations.first)}');
}
}
}
}
@@ -38,20 +38,20 @@ macro class ImplementsAlias implements Alias {}
macro class MixinAlias with Alias {}
class ExtendsNoKeyword extends Macro {}
class /*error: error=MacroClassNotDeclaredMacro*/ExtendsNoKeyword extends Macro {}
class ImplementsNoKeyword implements Macro {}
class /*error: error=MacroClassNotDeclaredMacro*/ImplementsNoKeyword implements Macro {}
class MixinNoKeyword with Macro {}
class /*error: error=MacroClassNotDeclaredMacro*/MixinNoKeyword with Macro {}
class ExtendsAliasNoKeyword extends Alias {}
class /*error: error=MacroClassNotDeclaredMacro*/ExtendsAliasNoKeyword extends Alias {}
class ImplementsAliasNoKeyword implements Alias {}
class /*error: error=MacroClassNotDeclaredMacro*/ImplementsAliasNoKeyword implements Alias {}
class MixinAliasNoKeyword with Alias {}
class /*error: error=MacroClassNotDeclaredMacro*/MixinAliasNoKeyword with Alias {}
class NamedMixin1NoKeyword = Macro with _Mixin;
class /*error: error=MacroClassNotDeclaredMacro*/NamedMixin1NoKeyword = Macro with _Mixin;
class NamedMixin2NoKeyword = Object with Macro;
class /*error: error=MacroClassNotDeclaredMacro*/NamedMixin2NoKeyword = Object with Macro;
void main() {}
+13
View File
@@ -17,6 +17,7 @@ import 'package:front_end/src/fasta/builder/library_builder.dart';
import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/kernel/macro.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart' hide Arguments;
Future<void> main(List<String> args) async {
@@ -77,6 +78,17 @@ class MacroDataComputer extends DataComputer<Features> {
.computeForLibrary(library);
}
@override
bool get supportsErrors => true;
@override
Features? computeErrorData(
TestResultData testResultData, Id id, List<FormattedMessage> errors) {
Features features = new Features();
features[Tags.error] = errorsToText(errors, useCodes: true);
return features;
}
@override
DataInterpreter<Features> get dataValidator =>
const FeaturesDataInterpreter();
@@ -91,6 +103,7 @@ class Tags {
static const String appliedMacros = 'appliedMacros';
static const String macroClassIds = 'macroClassIds';
static const String macroInstanceIds = 'macroInstanceIds';
static const String error = 'error';
}
String constructorNameToString(String constructorName) {
@@ -45,6 +45,7 @@ js_util
libraries.json
list.filled
loadlibrary
macro
migrate
name.#name
name.stack
@@ -834,6 +834,7 @@ class DocTestIncrementalCompiler extends IncrementalCompiler {
scope: libraryBuilder.scope.createNestedScope("dartdoctest"),
nameOrigin: libraryBuilder,
isUnsupported: false,
isAugmentation: false,
);
if (libraryBuilder is DillLibraryBuilder) {