Version 2.17.0-25.0.dev
Merge commit '24ee012ce3705795914c64d2dc0be962a08a014a' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
index 7706af7..a3f6fb4 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
@@ -32,7 +32,8 @@
name,
if (typeArguments.isNotEmpty) ...[
'<',
- for (TypeAnnotation arg in typeArguments) ...[arg, ','],
+ typeArguments.first,
+ for (TypeAnnotation arg in typeArguments.skip(1)) ...[', ', arg],
'>',
],
if (isNullable) '?',
@@ -79,10 +80,15 @@
'Function',
if (typeParameters.isNotEmpty) ...[
'<',
- for (TypeParameterDeclaration arg in typeParameters) ...[
+ typeParameters.first.name,
+ if (typeParameters.first.bounds != null) ...[
+ ' extends ',
+ typeParameters.first.bounds!
+ ],
+ for (TypeParameterDeclaration arg in typeParameters.skip(1)) ...[
+ ', ',
arg.name,
if (arg.bounds != null) ...[' extends ', arg.bounds!],
- ','
],
'>',
],
@@ -158,7 +164,10 @@
}
abstract class DeclarationImpl extends RemoteInstance implements Declaration {
- DeclarationImpl(int id) : super(id);
+ final String name;
+
+ DeclarationImpl({required int id, required this.name}) : super(id);
+
@override
void serialize(Serializer serializer) {
super.serialize(serializer);
@@ -174,9 +183,6 @@
class ParameterDeclarationImpl extends DeclarationImpl
implements ParameterDeclaration {
@override
- final String name;
-
- @override
final Code? defaultValue;
@override
@@ -193,12 +199,12 @@
ParameterDeclarationImpl({
required int id,
- required this.name,
+ required String name,
required this.defaultValue,
required this.isNamed,
required this.isRequired,
required this.type,
- }) : super(id);
+ }) : super(id: id, name: name);
@override
void serialize(Serializer serializer) {
@@ -222,17 +228,16 @@
class TypeParameterDeclarationImpl extends DeclarationImpl
implements TypeParameterDeclaration {
@override
- final String name;
-
- @override
final TypeAnnotationImpl? bounds;
@override
RemoteInstanceKind get kind => RemoteInstanceKind.typeParameterDeclaration;
- TypeParameterDeclarationImpl(
- {required int id, required this.name, required this.bounds})
- : super(id);
+ TypeParameterDeclarationImpl({
+ required int id,
+ required String name,
+ required this.bounds,
+ }) : super(id: id, name: name);
@override
void serialize(Serializer serializer) {
@@ -254,9 +259,6 @@
class FunctionDeclarationImpl extends DeclarationImpl
implements FunctionDeclaration {
@override
- final String name;
-
- @override
final bool isAbstract;
@override
@@ -285,7 +287,7 @@
FunctionDeclarationImpl({
required int id,
- required this.name,
+ required String name,
required this.isAbstract,
required this.isExternal,
required this.isGetter,
@@ -294,7 +296,7 @@
required this.positionalParameters,
required this.returnType,
required this.typeParameters,
- }) : super(id);
+ }) : super(id: id, name: name);
@override
void serialize(Serializer serializer) {
@@ -328,3 +330,304 @@
serializer.endList();
}
}
+
+class MethodDeclarationImpl extends FunctionDeclarationImpl
+ implements MethodDeclaration {
+ @override
+ final TypeAnnotationImpl definingClass;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.methodDeclaration;
+
+ MethodDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required String name,
+ // Function fields
+ required bool isAbstract,
+ required bool isExternal,
+ required bool isGetter,
+ required bool isSetter,
+ required List<ParameterDeclarationImpl> namedParameters,
+ required List<ParameterDeclarationImpl> positionalParameters,
+ required TypeAnnotationImpl returnType,
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // Method fields
+ required this.definingClass,
+ }) : super(
+ id: id,
+ name: name,
+ isAbstract: isAbstract,
+ isExternal: isExternal,
+ isGetter: isGetter,
+ isSetter: isSetter,
+ namedParameters: namedParameters,
+ positionalParameters: positionalParameters,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ );
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode == SerializationMode.client) {
+ return;
+ }
+
+ definingClass.serialize(serializer);
+ }
+}
+
+class ConstructorDeclarationImpl extends MethodDeclarationImpl
+ implements ConstructorDeclaration {
+ @override
+ final bool isFactory;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.constructorDeclaration;
+
+ ConstructorDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required String name,
+ // Function fields
+ required bool isAbstract,
+ required bool isExternal,
+ required bool isGetter,
+ required bool isSetter,
+ required List<ParameterDeclarationImpl> namedParameters,
+ required List<ParameterDeclarationImpl> positionalParameters,
+ required TypeAnnotationImpl returnType,
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // Method fields
+ required TypeAnnotationImpl definingClass,
+ // Constructor fields
+ required this.isFactory,
+ }) : super(
+ id: id,
+ name: name,
+ isAbstract: isAbstract,
+ isExternal: isExternal,
+ isGetter: isGetter,
+ isSetter: isSetter,
+ namedParameters: namedParameters,
+ positionalParameters: positionalParameters,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ definingClass: definingClass,
+ );
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode == SerializationMode.client) {
+ return;
+ }
+
+ serializer.addBool(isFactory);
+ }
+}
+
+class VariableDeclarationImpl extends DeclarationImpl
+ implements VariableDeclaration {
+ @override
+ final Code? initializer;
+
+ @override
+ final bool isAbstract;
+
+ @override
+ final bool isExternal;
+
+ @override
+ final TypeAnnotationImpl type;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.variableDeclaration;
+
+ VariableDeclarationImpl({
+ required int id,
+ required String name,
+ required this.initializer,
+ required this.isAbstract,
+ required this.isExternal,
+ required this.type,
+ }) : super(id: id, name: name);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode == SerializationMode.client) {
+ return;
+ }
+
+ initializer.serializeNullable(serializer);
+ serializer
+ ..addBool(isAbstract)
+ ..addBool(isExternal);
+ type.serialize(serializer);
+ }
+}
+
+class FieldDeclarationImpl extends VariableDeclarationImpl
+ implements FieldDeclaration {
+ @override
+ final TypeAnnotationImpl definingClass;
+
+ FieldDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required String name,
+ // Variable fields
+ required Code? initializer,
+ required bool isAbstract,
+ required bool isExternal,
+ required TypeAnnotationImpl type,
+ // Field fields
+ required this.definingClass,
+ }) : super(
+ id: id,
+ name: name,
+ initializer: initializer,
+ isAbstract: isAbstract,
+ isExternal: isExternal,
+ type: type);
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.fieldDeclaration;
+
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode == SerializationMode.client) {
+ return;
+ }
+
+ definingClass.serialize(serializer);
+ }
+}
+
+abstract class TypeDeclarationImpl extends DeclarationImpl
+ implements TypeDeclaration {
+ @override
+ final List<TypeParameterDeclarationImpl> typeParameters;
+
+ TypeDeclarationImpl({
+ required int id,
+ required String name,
+ required this.typeParameters,
+ }) : super(id: id, name: name);
+
+ @override
+ Future<StaticType> instantiate(
+ {required List<StaticType> typeArguments, required bool isNullable}) {
+ // TODO: implement instantiate
+ throw new UnimplementedError('instantiate');
+ }
+
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode == SerializationMode.client) {
+ return;
+ }
+
+ serializer..startList();
+ for (TypeParameterDeclarationImpl param in typeParameters) {
+ param.serialize(serializer);
+ }
+ serializer.endList();
+ }
+}
+
+class ClassDeclarationImpl extends TypeDeclarationImpl
+ implements ClassDeclaration {
+ @override
+ final List<TypeAnnotationImpl> interfaces;
+
+ @override
+ final bool isAbstract;
+
+ @override
+ final bool isExternal;
+
+ @override
+ final List<TypeAnnotationImpl> mixins;
+
+ @override
+ final TypeAnnotationImpl? superclass;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.classDeclaration;
+
+ ClassDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required String name,
+ // TypeDeclaration fields
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // ClassDeclaration fields
+ required this.interfaces,
+ required this.isAbstract,
+ required this.isExternal,
+ required this.mixins,
+ required this.superclass,
+ }) : super(id: id, name: name, typeParameters: typeParameters);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode == SerializationMode.client) {
+ return;
+ }
+
+ serializer.startList();
+ for (TypeAnnotationImpl interface in interfaces) {
+ interface.serialize(serializer);
+ }
+ serializer
+ ..endList()
+ ..addBool(isAbstract)
+ ..addBool(isExternal)
+ ..startList();
+ for (TypeAnnotationImpl mixin in mixins) {
+ mixin.serialize(serializer);
+ }
+ serializer..endList();
+ superclass.serializeNullable(serializer);
+ }
+}
+
+class TypeAliasDeclarationImpl extends TypeDeclarationImpl
+ implements TypeAliasDeclaration {
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.typeAliasDeclaration;
+
+ @override
+ final TypeAnnotationImpl type;
+
+ TypeAliasDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required String name,
+ // TypeDeclaration fields
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // TypeAlias fields
+ required this.type,
+ }) : super(id: id, name: name, typeParameters: typeParameters);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode == SerializationMode.client) {
+ return;
+ }
+
+ type.serialize(serializer);
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
index 3f9e55c..820c899 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
@@ -369,7 +369,7 @@
/// TODO: Implement this
class ClientClassIntrospector implements ClassIntrospector {
- /// The actual remote instance of this type resolver.
+ /// The actual remote instance of this class introspector.
final RemoteInstanceImpl remoteInstance;
/// The ID of the zone in which to find the original type resolver.
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
index c950279..e341b91 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
@@ -12,161 +12,174 @@
moveNext();
RemoteInstanceKind kind = RemoteInstanceKind.values[expectNum()];
switch (kind) {
- case RemoteInstanceKind.namedTypeAnnotation:
+ case RemoteInstanceKind.classDeclaration:
moveNext();
- return _expectNamedTypeAnnotation(id) as T;
- case RemoteInstanceKind.functionTypeAnnotation:
+ return _expectClassDeclaration(id) as T;
+ case RemoteInstanceKind.constructorDeclaration:
moveNext();
- return _expectFunctionTypeAnnotation(id) as T;
+ return _expectConstructorDeclaration(id) as T;
+ case RemoteInstanceKind.fieldDeclaration:
+ moveNext();
+ return _expectFieldDeclaration(id) as T;
case RemoteInstanceKind.functionDeclaration:
moveNext();
return _expectFunctionDeclaration(id) as T;
+ case RemoteInstanceKind.functionTypeAnnotation:
+ moveNext();
+ return _expectFunctionTypeAnnotation(id) as T;
+ case RemoteInstanceKind.instance:
+ return new RemoteInstanceImpl(id: id) as T;
+ case RemoteInstanceKind.methodDeclaration:
+ moveNext();
+ return _expectMethodDeclaration(id) as T;
+ case RemoteInstanceKind.namedTypeAnnotation:
+ moveNext();
+ return _expectNamedTypeAnnotation(id) as T;
case RemoteInstanceKind.parameterDeclaration:
moveNext();
return _expectParameterDeclaration(id) as T;
+ case RemoteInstanceKind.typeAliasDeclaration:
+ moveNext();
+ return _expectTypeAliasDeclaration(id) as T;
case RemoteInstanceKind.typeParameterDeclaration:
moveNext();
return _expectTypeParameterDeclaration(id) as T;
- case RemoteInstanceKind.instance:
- return new RemoteInstanceImpl(id: id) as T;
- default:
- throw new UnsupportedError('Unsupported remote object kind: $kind');
+ case RemoteInstanceKind.variableDeclaration:
+ moveNext();
+ return _expectVariableDeclaration(id) as T;
}
case SerializationMode.server:
return RemoteInstance.cached(id) as T;
}
}
- NamedTypeAnnotation _expectNamedTypeAnnotation(int id) {
- bool isNullable = expectBool();
- moveNext();
- String name = expectString();
- moveNext();
+ /// Helper method to read a list of [RemoteInstance]s.
+ List<T> _expectRemoteInstanceList<T extends RemoteInstance>() {
expectList();
- List<TypeAnnotationImpl> typeArguments = [
+ return [
for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
expectRemoteInstance(),
];
- return new NamedTypeAnnotationImpl(
+ }
+
+ NamedTypeAnnotation _expectNamedTypeAnnotation(int id) =>
+ new NamedTypeAnnotationImpl(
id: id,
- isNullable: isNullable,
- name: name,
- typeArguments: typeArguments);
- }
+ isNullable: expectBool(),
+ name: (this..moveNext()).expectString(),
+ typeArguments: (this..moveNext())._expectRemoteInstanceList(),
+ );
- FunctionTypeAnnotation _expectFunctionTypeAnnotation(int id) {
- bool isNullable = expectBool();
-
- TypeAnnotationImpl returnType = RemoteInstance.deserialize(this);
-
- moveNext();
- expectList();
- List<ParameterDeclarationImpl> positionalParameters = [
- for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
- expectRemoteInstance(),
- ];
-
- moveNext();
- expectList();
- List<ParameterDeclarationImpl> namedParameters = [
- for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
- expectRemoteInstance(),
- ];
-
- moveNext();
- expectList();
- List<TypeParameterDeclarationImpl> typeParameters = [
- for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
- expectRemoteInstance(),
- ];
-
- return new FunctionTypeAnnotationImpl(
- id: id,
- isNullable: isNullable,
- returnType: returnType,
- positionalParameters: positionalParameters,
- namedParameters: namedParameters,
- typeParameters: typeParameters,
- );
- }
-
- ParameterDeclaration _expectParameterDeclaration(int id) {
- String name = expectString();
- moveNext();
- Code? defaultValue;
- if (!checkNull()) {
- defaultValue = expectCode();
- }
- bool isNamed = expectBool();
- moveNext();
- bool isRequired = expectBool();
-
- TypeAnnotationImpl type = RemoteInstance.deserialize(this);
-
- return new ParameterDeclarationImpl(
+ FunctionTypeAnnotation _expectFunctionTypeAnnotation(int id) =>
+ new FunctionTypeAnnotationImpl(
id: id,
- defaultValue: defaultValue,
- isNamed: isNamed,
- isRequired: isRequired,
- name: name,
- type: type);
- }
+ isNullable: expectBool(),
+ returnType: RemoteInstance.deserialize(this),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ );
- TypeParameterDeclaration _expectTypeParameterDeclaration(int id) {
- String name = expectString();
- moveNext();
- TypeAnnotationImpl? bounds;
- if (!checkNull()) {
- bounds = expectRemoteInstance();
- }
- return new TypeParameterDeclarationImpl(id: id, name: name, bounds: bounds);
- }
-
- FunctionDeclaration _expectFunctionDeclaration(int id) {
- String name = expectString();
- moveNext();
- bool isAbstract = expectBool();
- moveNext();
- bool isExternal = expectBool();
- moveNext();
- bool isGetter = expectBool();
- moveNext();
- bool isSetter = expectBool();
-
- moveNext();
- expectList();
- List<ParameterDeclarationImpl> namedParameters = [
- for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
- expectRemoteInstance(),
- ];
-
- moveNext();
- expectList();
- List<ParameterDeclarationImpl> positionalParameters = [
- for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
- expectRemoteInstance(),
- ];
-
- TypeAnnotationImpl returnType = RemoteInstance.deserialize(this);
-
- moveNext();
- expectList();
- List<TypeParameterDeclarationImpl> typeParameters = [
- for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
- expectRemoteInstance(),
- ];
- return new FunctionDeclarationImpl(
+ ParameterDeclaration _expectParameterDeclaration(int id) =>
+ new ParameterDeclarationImpl(
id: id,
- name: name,
- isAbstract: isAbstract,
- isExternal: isExternal,
- isGetter: isGetter,
- isSetter: isSetter,
- namedParameters: namedParameters,
- positionalParameters: positionalParameters,
- returnType: returnType,
- typeParameters: typeParameters);
- }
+ name: expectString(),
+ defaultValue: (this..moveNext()).checkNull() ? null : expectCode(),
+ isNamed: (this..moveNext()).expectBool(),
+ isRequired: (this..moveNext()).expectBool(),
+ type: RemoteInstance.deserialize(this),
+ );
+
+ TypeParameterDeclaration _expectTypeParameterDeclaration(int id) =>
+ new TypeParameterDeclarationImpl(
+ id: id,
+ name: expectString(),
+ bounds: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
+ );
+
+ FunctionDeclaration _expectFunctionDeclaration(int id) =>
+ new FunctionDeclarationImpl(
+ id: id,
+ name: expectString(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ isGetter: (this..moveNext()).expectBool(),
+ isSetter: (this..moveNext()).expectBool(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ returnType: RemoteInstance.deserialize(this),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ );
+
+ MethodDeclaration _expectMethodDeclaration(int id) =>
+ new MethodDeclarationImpl(
+ id: id,
+ name: expectString(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ isGetter: (this..moveNext()).expectBool(),
+ isSetter: (this..moveNext()).expectBool(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ returnType: RemoteInstance.deserialize(this),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ definingClass: RemoteInstance.deserialize(this),
+ );
+
+ ConstructorDeclaration _expectConstructorDeclaration(int id) =>
+ new ConstructorDeclarationImpl(
+ id: id,
+ name: expectString(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ isGetter: (this..moveNext()).expectBool(),
+ isSetter: (this..moveNext()).expectBool(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ returnType: RemoteInstance.deserialize(this),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ definingClass: RemoteInstance.deserialize(this),
+ isFactory: (this..moveNext()).expectBool(),
+ );
+
+ VariableDeclaration _expectVariableDeclaration(int id) =>
+ new VariableDeclarationImpl(
+ id: id,
+ name: expectString(),
+ initializer: (this..moveNext()).expectNullableCode(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ type: RemoteInstance.deserialize(this),
+ );
+
+ FieldDeclaration _expectFieldDeclaration(int id) => new FieldDeclarationImpl(
+ id: id,
+ name: expectString(),
+ initializer: (this..moveNext()).expectNullableCode(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ type: RemoteInstance.deserialize(this),
+ definingClass: RemoteInstance.deserialize(this),
+ );
+
+ ClassDeclaration _expectClassDeclaration(int id) => new ClassDeclarationImpl(
+ id: id,
+ name: expectString(),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ interfaces: (this..moveNext())._expectRemoteInstanceList(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ mixins: (this..moveNext())._expectRemoteInstanceList(),
+ superclass: RemoteInstance.deserialize(this),
+ );
+
+ TypeAliasDeclaration _expectTypeAliasDeclaration(int id) =>
+ new TypeAliasDeclarationImpl(
+ id: id,
+ name: expectString(),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ type: RemoteInstance.deserialize(this),
+ );
T expectCode<T extends Code>() {
CodeKind kind = CodeKind.values[expectNum()];
@@ -210,6 +223,35 @@
return new StatementCode.fromParts(parts) as T;
}
}
+
+ T? expectNullableCode<T extends Code>() {
+ if (checkNull()) return null;
+ return expectCode();
+ }
+}
+
+extension SerializeNullable on Serializable? {
+ /// Either serializes a `null` literal or the object.
+ void serializeNullable(Serializer serializer) {
+ Serializable? self = this;
+ if (self == null) {
+ serializer.addNull();
+ } else {
+ self.serialize(serializer);
+ }
+ }
+}
+
+extension SerializeNullableCode on Code? {
+ /// Either serializes a `null` literal or the code object.
+ void serializeNullable(Serializer serializer) {
+ Code? self = this;
+ if (self == null) {
+ serializer.addNull();
+ } else {
+ self.serialize(serializer);
+ }
+ }
}
extension SerializeCode on Code {
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
index fd2ed54..e1596e1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
@@ -358,7 +358,7 @@
'offset=$offset,object=$objectText)';
}
-abstract class DataRegistry<T> {
+mixin DataRegistry<T> {
Map<Id, ActualData<T>> get actualMap;
/// Registers [value] with [id] in [actualMap].
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
index 9faf079..6a3807b 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
@@ -2,11 +2,15 @@
// 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';
import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization_extensions.dart';
import 'package:test/test.dart';
+import '../util.dart';
+
void main() {
group('json serializer', () {
test('can serialize and deserialize basic data', () {
@@ -100,11 +104,196 @@
expect(instance, foo);
});
});
+
+ group('declarations', () {
+ final barType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ name: 'Bar',
+ typeArguments: []);
+ final fooType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: true,
+ name: 'Foo',
+ typeArguments: [barType]);
+
+ test('NamedTypeAnnotation', () {
+ expectSerializationEquality(fooType);
+ });
+
+ final fooNamedParam = ParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ defaultValue: null,
+ isNamed: true,
+ isRequired: true,
+ name: 'foo',
+ type: fooType);
+
+ final barPositionalParam = ParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ defaultValue: Code.fromString('const Bar()'),
+ isNamed: false,
+ isRequired: false,
+ name: 'bar',
+ type: barType);
+
+ final zapTypeParam = TypeParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId, name: 'Zap', bounds: barType);
+
+ // Transitively tests `TypeParameterDeclaration` and
+ // `ParameterDeclaration`.
+ test('FunctionTypeAnnotation', () {
+ var functionType = FunctionTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: true,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ );
+ expectSerializationEquality(functionType);
+ });
+
+ test('FunctionDeclaration', () {
+ var function = FunctionDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'name',
+ isAbstract: true,
+ isExternal: false,
+ isGetter: true,
+ isSetter: false,
+ namedParameters: [],
+ positionalParameters: [],
+ returnType: fooType,
+ typeParameters: []);
+ expectSerializationEquality(function);
+ });
+
+ test('MethodDeclaration', () {
+ var method = MethodDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'zorp',
+ isAbstract: false,
+ isExternal: false,
+ isGetter: false,
+ isSetter: true,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ definingClass: fooType);
+ expectSerializationEquality(method);
+ });
+
+ test('ConstructorDeclaration', () {
+ var constructor = ConstructorDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'new',
+ isAbstract: false,
+ isExternal: false,
+ isGetter: false,
+ isSetter: false,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ definingClass: fooType,
+ isFactory: true,
+ );
+ expectSerializationEquality(constructor);
+ });
+
+ test('VariableDeclaration', () {
+ var bar = VariableDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'bar',
+ isAbstract: false,
+ isExternal: true,
+ initializer: Code.fromString('Bar()'),
+ type: barType,
+ );
+ expectSerializationEquality(bar);
+ });
+
+ test('FieldDeclaration', () {
+ var bar = FieldDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'bar',
+ isAbstract: false,
+ isExternal: false,
+ initializer: null,
+ type: barType,
+ definingClass: fooType,
+ );
+ expectSerializationEquality(bar);
+ });
+
+ var objectType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'Object',
+ isNullable: false,
+ typeArguments: [],
+ );
+ var serializableType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'Serializable',
+ isNullable: false,
+ typeArguments: [],
+ );
+
+ test('ClassDeclaration', () {
+ var fooClass = ClassDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'Foo',
+ interfaces: [barType],
+ isAbstract: true,
+ isExternal: false,
+ mixins: [serializableType],
+ superclass: objectType,
+ typeParameters: [zapTypeParam],
+ );
+ expectSerializationEquality(fooClass);
+ });
+
+ test('TypeAliasDeclaration', () {
+ var typeAlias = TypeAliasDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ name: 'FooOfBar',
+ type: NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ name: 'Foo',
+ typeArguments: [barType]),
+ typeParameters: [zapTypeParam],
+ );
+ expectSerializationEquality(typeAlias);
+ });
+ });
+ });
+}
+
+/// Serializes [serializable] in server mode, then deserializes it in client
+/// mode, and checks that all the fields are the same.
+void expectSerializationEquality(Serializable serializable) {
+ var serializer = JsonSerializer();
+ withSerializationMode(SerializationMode.server, () {
+ serializable.serialize(serializer);
+ });
+ withSerializationMode(SerializationMode.client, () {
+ var deserializer = JsonDeserializer(serializer.result);
+ var deserialized = (deserializer..moveNext()).expectRemoteInstance();
+ if (deserialized is Declaration) {
+ expect(serializable, deepEqualsDeclaration(deserialized));
+ } else if (deserialized is TypeAnnotation) {
+ expect(serializable, deepEqualsTypeAnnotation(deserialized));
+ } else {
+ throw new UnsupportedError('Unsupported object type $deserialized');
+ }
});
}
/// Deserializes [serialized] in client mode and sends it back.
-Object? roundTrip(Object? serialized) {
+Object? roundTrip<Declaration>(Object? serialized) {
return withSerializationMode(SerializationMode.client, () {
var deserializer = JsonDeserializer(serialized as List<Object?>);
var instance =
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
index 179f50b..d92c884 100644
--- a/pkg/_fe_analyzer_shared/test/macros/util.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -2,9 +2,12 @@
// 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:mirrors';
+
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'package:test/fake.dart';
+import 'package:test/test.dart';
class FakeClassIntrospector with Fake implements ClassIntrospector {}
@@ -58,3 +61,96 @@
return buffer;
}
}
+
+/// Checks if two [Code] objectss are of the same type and all their fields are
+/// equal.
+Matcher deepEqualsCode(Code other) => _DeepEqualityMatcher(other);
+
+/// Checks if two [Declaration]s are of the same type and all their fields are
+/// equal.
+Matcher deepEqualsDeclaration(Declaration declaration) =>
+ _DeepEqualityMatcher(declaration);
+
+/// Checks if two [TypeAnnotation]s are of the same type and all their fields are
+/// equal.
+Matcher deepEqualsTypeAnnotation(TypeAnnotation declaration) =>
+ _DeepEqualityMatcher(declaration);
+
+/// Checks if two [Declaration]s, [TypeAnnotation]s, or [Code] objects are of
+/// the same type and all their fields are equal.
+class _DeepEqualityMatcher extends Matcher {
+ final Object? instance;
+
+ _DeepEqualityMatcher(this.instance);
+
+ @override
+ Description describe(Description description) => description;
+
+ @override
+ bool matches(item, Map matchState) {
+ if (item.runtimeType != instance.runtimeType) {
+ return false;
+ }
+
+ if (instance is Declaration || instance is TypeAnnotation) {
+ var instanceReflector = reflect(instance);
+ var itemReflector = reflect(item);
+
+ var type = instanceReflector.type;
+ for (var getter
+ in type.instanceMembers.values.where((member) => member.isGetter)) {
+ // We only care about synthetic field getters
+ if (!getter.isSynthetic) continue;
+
+ var instanceField = instanceReflector.getField(getter.simpleName);
+ var itemField = itemReflector.getField(getter.simpleName);
+ var instanceValue = instanceField.reflectee;
+ var itemValue = itemField.reflectee;
+
+ // Handle lists of things
+ if (instanceValue is List) {
+ if (!_listEquals(instanceValue, itemValue, matchState)) {
+ return false;
+ }
+ } else if (instanceValue is Declaration ||
+ instanceValue is Code ||
+ instanceValue is TypeAnnotation) {
+ // Handle nested declarations and code objects
+ if (!_DeepEqualityMatcher(instanceValue)
+ .matches(itemValue, matchState)) {
+ return false;
+ }
+ } else {
+ // Handles basic values and identity
+ if (instanceValue != itemValue) {
+ return false;
+ }
+ }
+ }
+ } else if (instance is Code) {
+ if (!_listEquals(
+ (instance as Code).parts, (item as Code).parts, matchState)) {
+ return false;
+ }
+ } else {
+ // Handles basic values and identity
+ if (instance != item) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool _listEquals(List instanceValue, List itemValue, Map matchState) {
+ if (instanceValue.length != itemValue.length) {
+ return false;
+ }
+ for (var i = 0; i < instanceValue.length; i++) {
+ if (!_DeepEqualityMatcher(instanceValue[i])
+ .matches(itemValue[i], matchState)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 02aaf4e..50cb925 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -329,8 +329,12 @@
}
}
-class RtiClassNeedIrComputer extends DataRegistry<String>
- with ComputeValueMixin, IrMixin, IrDataRegistryMixin<String> {
+class RtiClassNeedIrComputer
+ with
+ DataRegistry<String>,
+ ComputeValueMixin,
+ IrMixin,
+ IrDataRegistryMixin<String> {
@override
final Compiler compiler;
final JsToElementMap _elementMap;
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index cc832b8..c1cae63 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -12,6 +12,7 @@
- test/extensions/data/**
- test/id_testing/data/**
- test/language_versioning/data/**
+ - test/macro_application/data/**
- test/macros/data/**
- test/patching/data/**
- test/predicates/data/**
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 39a7a01..a8355e8 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -18,6 +18,7 @@
import '../base/nnbd_mode.dart';
+import '../fasta/kernel/macro.dart';
import 'experimental_flags.dart'
show
AllowedExperimentalFlags,
@@ -116,6 +117,12 @@
Future<MacroExecutor> Function() macroExecutorProvider =
() async => throw 'Macro execution is not supported.';
+ /// Map from [MacroClass] to [Uri] for the precompiled dill that contains
+ /// the macro code.
+ ///
+ /// This is an experimental feature.
+ Map<MacroClass, Uri>? precompiledMacroUris;
+
/// Whether to generate code for the SDK.
///
/// By default the front end resolves components using a prebuilt SDK summary.
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index db25cec..f8a8de9 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -70,6 +70,7 @@
templateSdkSpecificationNotFound,
templateSdkSummaryNotFound;
+import '../fasta/kernel/macro.dart';
import '../fasta/messages.dart' show getLocation;
import '../fasta/problems.dart' show DebugAbort, unimplemented;
@@ -857,6 +858,9 @@
Future<MacroExecutor> Function() get macroExecutorProvider =>
_raw.macroExecutorProvider;
+ Map<MacroClass, Uri> get precompiledMacroUris =>
+ _raw.precompiledMacroUris ?? const {};
+
CompilerOptions get rawOptionsForTesting => _raw;
}
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 306c9aa..e66b50a 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -114,7 +114,8 @@
NamedTypeBuilder(this.name, this.nullabilityBuilder, this.arguments,
this.fileUri, this.charOffset,
- {required this.instanceTypeVariableAccess});
+ {required this.instanceTypeVariableAccess})
+ : assert(name is String || name is QualifiedName);
NamedTypeBuilder.fromTypeDeclarationBuilder(
TypeDeclarationBuilder this.declaration, this.nullabilityBuilder,
diff --git a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
index e9920a6..d2f1000 100644
--- a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
@@ -19,6 +19,9 @@
/// Used when the type is declared without any nullability suffixes.
omitted,
+
+ /// Used when the type is nullable without any nullability suffix.
+ inherent,
}
class NullabilityBuilder {
@@ -30,8 +33,15 @@
const NullabilityBuilder.omitted()
: _syntacticNullability = SyntacticNullability.omitted;
+ const NullabilityBuilder.inherent()
+ : _syntacticNullability = SyntacticNullability.inherent;
+
bool get isOmitted => _syntacticNullability == SyntacticNullability.omitted;
+ bool get isInherent => _syntacticNullability == SyntacticNullability.inherent;
+
+ bool get isNullable => _syntacticNullability == SyntacticNullability.nullable;
+
factory NullabilityBuilder.fromNullability(Nullability nullability) {
switch (nullability) {
case Nullability.nullable:
@@ -55,6 +65,7 @@
case SyntacticNullability.legacy:
return Nullability.legacy;
case SyntacticNullability.nullable:
+ case SyntacticNullability.inherent:
return Nullability.nullable;
case SyntacticNullability.omitted:
return ifOmitted;
@@ -70,6 +81,7 @@
sb.write("?");
return;
case SyntacticNullability.omitted:
+ case SyntacticNullability.inherent:
// Do nothing.
return;
}
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 8152374..76ab9eb8 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -126,7 +126,7 @@
import 'kernel/internal_ast.dart' show VariableDeclarationImpl;
-import 'kernel/kernel_target.dart' show KernelTarget;
+import 'kernel/kernel_target.dart' show BuildResult, KernelTarget;
import 'library_graph.dart' show LibraryGraph;
@@ -351,13 +351,17 @@
// Technically, it's the combination of
// `currentKernelTarget.loader.libraries` and
// `_dillLoadedData.loader.libraries`.
- Component? componentWithDill = await currentKernelTarget.buildOutlines();
+ BuildResult buildResult = await currentKernelTarget.buildOutlines();
+ Component? componentWithDill = buildResult.component;
if (!outlineOnly) {
// Checkpoint: Build the actual bodies.
- componentWithDill =
- await currentKernelTarget.buildComponent(verify: c.options.verify);
+ buildResult = await currentKernelTarget.buildComponent(
+ macroApplications: buildResult.macroApplications,
+ verify: c.options.verify);
+ componentWithDill = buildResult.component;
}
+ buildResult.macroApplications?.macroExecutor.close();
hierarchy ??= currentKernelTarget.loader.hierarchy;
if (currentKernelTarget.classHierarchyChanges != null) {
hierarchy.applyTreeChanges(
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index fe74b48..ea31b84 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -4039,7 +4039,7 @@
push(new NamedTypeBuilder.fromTypeDeclarationBuilder(
new VoidTypeDeclarationBuilder(
const VoidType(), libraryBuilder, offset),
- const NullabilityBuilder.nullable(),
+ const NullabilityBuilder.inherent(),
fileUri: uri,
charOffset: offset,
instanceTypeVariableAccess:
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 72fefca..4576ec6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -81,6 +81,7 @@
ConstantEvaluationData;
import 'kernel_constants.dart' show KernelConstantErrorReporter;
import 'kernel_helper.dart';
+import 'macro.dart';
import 'verifier.dart' show verifyComponent, verifyGetStaticType;
class KernelTarget extends TargetImplementation {
@@ -102,7 +103,7 @@
// TODO(johnniwinther): Why isn't this using a FixedTypeBuilder?
final TypeBuilder dynamicType = new NamedTypeBuilder(
"dynamic",
- const NullabilityBuilder.nullable(),
+ const NullabilityBuilder.inherent(),
/* arguments = */ null,
/* fileUri = */ null,
/* charOffset = */ null,
@@ -121,7 +122,7 @@
// have NullType?
final TypeBuilder nullType = new NamedTypeBuilder(
"Null",
- const NullabilityBuilder.nullable(),
+ const NullabilityBuilder.inherent(),
/* arguments = */ null,
/* fileUri = */ null,
/* charOffset = */ null,
@@ -373,20 +374,26 @@
builder.mixedInTypeBuilder = null;
}
- Future<Component?> buildOutlines({CanonicalName? nameRoot}) async {
- if (loader.first == null) return null;
- return withCrashReporting<Component?>(() async {
+ Future<BuildResult> buildOutlines({CanonicalName? nameRoot}) async {
+ if (loader.first == null) return new BuildResult();
+ return withCrashReporting<BuildResult>(() async {
await loader.buildOutlines();
loader.coreLibrary.becomeCoreLibrary();
loader.resolveParts();
loader.computeMacroDeclarations();
loader.computeLibraryScopes();
- await loader.computeMacroApplications();
+ MacroApplications? macroApplications =
+ await loader.computeMacroApplications();
setupTopAndBottomTypes();
loader.resolveTypes();
loader.computeVariances();
loader.computeDefaultTypes(
dynamicType, nullType, bottomType, objectClassBuilder);
+ // TODO(johnniwinther): Enable this when supported in the isolate-based
+ // macro executor.
+ /*if (macroApplications != null) {
+ await macroApplications.applyTypeMacros();
+ }*/
List<SourceClassBuilder> sourceClassBuilders =
loader.checkSemantics(objectClassBuilder);
loader.finishTypeVariables(objectClassBuilder, dynamicType);
@@ -399,6 +406,12 @@
link(new List<Library>.from(loader.libraries), nameRoot: nameRoot);
computeCoreTypes();
loader.buildClassHierarchy(sourceClassBuilders, objectClassBuilder);
+ // TODO(johnniwinther): Enable this when supported in the isolate-based
+ // macro executor.
+ /*if (macroApplications != null) {
+ await macroApplications.applyDeclarationMacros();
+ }*/
+ loader.buildClassHierarchyMembers(sourceClassBuilders);
loader.computeHierarchy();
loader.computeShowHideElements();
loader.installTypedefTearOffs();
@@ -416,7 +429,8 @@
loader.checkMainMethods();
installAllComponentProblems(loader.allComponentProblems);
loader.allComponentProblems.clear();
- return component;
+ return new BuildResult(
+ component: component, macroApplications: macroApplications);
}, () => loader.currentUriForCrashReporting);
}
@@ -428,15 +442,22 @@
///
/// If [verify], run the default kernel verification on the resulting
/// component.
- Future<Component?> buildComponent({bool verify: false}) async {
- if (loader.first == null) return null;
- return withCrashReporting<Component?>(() async {
+ Future<BuildResult> buildComponent(
+ {required MacroApplications? macroApplications,
+ bool verify: false}) async {
+ if (loader.first == null) {
+ return new BuildResult(macroApplications: macroApplications);
+ }
+ return withCrashReporting<BuildResult>(() async {
ticker.logMs("Building component");
await loader.buildBodies();
finishSynthesizedParameters();
loader.finishDeferredLoadTearoffs();
loader.finishNoSuchMethodForwarders();
List<SourceClassBuilder> sourceClasses = loader.collectSourceClasses();
+ if (macroApplications != null) {
+ await macroApplications.applyDefinitionMacros();
+ }
loader.finishNativeMethods();
loader.finishPatchMethods();
finishAllConstructors(sourceClasses);
@@ -444,7 +465,8 @@
if (verify) this.verify();
installAllComponentProblems(loader.allComponentProblems);
- return component;
+ return new BuildResult(
+ component: component, macroApplications: macroApplications);
}, () => loader.currentUriForCrashReporting);
}
@@ -1529,3 +1551,10 @@
loader.addProblem(message, charOffset, noLength, fileUri, context: context);
}
}
+
+class BuildResult {
+ final Component? component;
+ final MacroApplications? macroApplications;
+
+ BuildResult({this.component, this.macroApplications});
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 3055eea..6d95bbf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -2,12 +2,19 @@
// 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' hide TypeBuilder;
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
import '../builder/class_builder.dart';
+import '../builder/formal_parameter_builder.dart';
import '../builder/member_builder.dart';
+import '../builder/named_type_builder.dart';
+import '../builder/type_builder.dart';
+import '../identifiers.dart';
import '../source/source_class_builder.dart';
import '../source/source_library_builder.dart';
+import '../source/source_procedure_builder.dart';
bool enableMacros = false;
@@ -21,30 +28,60 @@
List<List<Uri>>? compilationSequence;
}
-class MacroApplicationData {
- Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
+class MacroClass {
+ final Uri importUri;
+ final String className;
- Future<void> loadMacroIds(
- Future<MacroExecutor> Function() macroExecutorProvider) async {
- MacroExecutor macroExecutor = await macroExecutorProvider();
+ const MacroClass(this.importUri, this.className);
+ @override
+ int get hashCode => importUri.hashCode * 13 + className.hashCode * 17;
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ return other is MacroClass &&
+ importUri == other.importUri &&
+ className == other.className;
+ }
+}
+
+class MacroApplications {
+ final MacroExecutor macroExecutor;
+ final Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData;
+ final MacroApplicationDataForTesting? dataForTesting;
+
+ MacroApplications(this.macroExecutor, this.libraryData, this.dataForTesting) {
+ dataForTesting?.libraryData.addAll(libraryData);
+ }
+
+ static Future<MacroApplications> loadMacroIds(
+ MacroExecutor macroExecutor,
+ Map<MacroClass, Uri> precompiledMacroUris,
+ Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData,
+ MacroApplicationDataForTesting? dataForTesting) async {
Map<ClassBuilder, MacroClassIdentifier> classIdCache = {};
Map<MacroApplication, MacroInstanceIdentifier> instanceIdCache = {};
- Future<void> ensureMacroClassIds(MacroApplications? applications) async {
+ Future<void> ensureMacroClassIds(
+ List<MacroApplication>? applications) async {
if (applications != null) {
- for (MacroApplication application in applications.macros) {
- MacroClassIdentifier macroClass =
- classIdCache[application.classBuilder] ??=
- await macroExecutor.loadMacro(
- application.classBuilder.library.importUri,
- application.classBuilder.name);
- instanceIdCache[application] = await macroExecutor.instantiateMacro(
- macroClass,
- application.constructorName,
- // TODO(johnniwinther): Support macro arguments.
- new Arguments([], {}));
+ for (MacroApplication application in applications) {
+ MacroClass macroClass = new MacroClass(
+ application.classBuilder.library.importUri,
+ application.classBuilder.name);
+ Uri? precompiledMacroUri = precompiledMacroUris[macroClass];
+ MacroClassIdentifier macroClassIdentifier =
+ classIdCache[application.classBuilder] ??= await macroExecutor
+ .loadMacro(macroClass.importUri, macroClass.className,
+ precompiledKernelUri: precompiledMacroUri);
+ application.instanceIdentifier = instanceIdCache[application] =
+ await macroExecutor.instantiateMacro(
+ macroClassIdentifier,
+ application.constructorName,
+ // TODO(johnniwinther): Support macro arguments.
+ new Arguments([], {}));
}
}
}
@@ -53,23 +90,138 @@
for (ClassMacroApplicationData classData
in libraryData.classData.values) {
await ensureMacroClassIds(classData.classApplications);
- for (MacroApplications applications
+ for (List<MacroApplication> applications
in classData.memberApplications.values) {
await ensureMacroClassIds(applications);
}
}
- for (MacroApplications applications
+ for (List<MacroApplication> applications
in libraryData.memberApplications.values) {
await ensureMacroClassIds(applications);
}
}
+ return new MacroApplications(macroExecutor, libraryData, dataForTesting);
}
-}
-class MacroApplications {
- final List<MacroApplication> macros;
+ Map<MemberBuilder, Declaration?> _memberDeclarations = {};
- MacroApplications(this.macros);
+ // TODO(johnniwinther): Support all members.
+ Declaration? _getMemberDeclaration(MemberBuilder memberBuilder) {
+ return _memberDeclarations[memberBuilder] ??=
+ _createMemberDeclaration(memberBuilder);
+ }
+
+ Declaration? _createMemberDeclaration(MemberBuilder memberBuilder) {
+ if (memberBuilder is SourceProcedureBuilder) {
+ return createTopLevelFunctionDeclaration(memberBuilder);
+ } else {
+ // TODO(johnniwinther): Throw when all members are supported.
+ //throw new UnimplementedError('Unsupported member ${memberBuilder}');
+ return null;
+ }
+ }
+
+ Future<void> _applyTypeMacros(
+ Declaration declaration, List<MacroApplication> macroApplications) async {
+ for (MacroApplication macroApplication in macroApplications) {
+ await macroExecutor.executeTypesPhase(
+ macroApplication.instanceIdentifier, declaration);
+ }
+ }
+
+ Future<void> applyTypeMacros() async {
+ for (MapEntry<SourceLibraryBuilder,
+ LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
+ LibraryMacroApplicationData libraryMacroApplicationData =
+ libraryEntry.value;
+ for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
+ in libraryMacroApplicationData.memberApplications.entries) {
+ MemberBuilder memberBuilder = memberEntry.key;
+ Declaration? declaration = _getMemberDeclaration(memberBuilder);
+ if (declaration != null) {
+ await _applyTypeMacros(declaration, memberEntry.value);
+ }
+ }
+ }
+ }
+
+ Future<void> _applyDeclarationMacros(
+ Declaration declaration,
+ List<MacroApplication> macroApplications,
+ TypeResolver typeResolver,
+ ClassIntrospector classIntrospector) async {
+ for (MacroApplication macroApplication in macroApplications) {
+ await macroExecutor.executeDeclarationsPhase(
+ macroApplication.instanceIdentifier,
+ declaration,
+ typeResolver,
+ classIntrospector);
+ }
+ }
+
+ Future<void> applyDeclarationMacros() async {
+ TypeResolver typeResolver = new _TypeResolver();
+ ClassIntrospector classIntrospector = new _ClassIntrospector();
+ for (MapEntry<SourceLibraryBuilder,
+ LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
+ LibraryMacroApplicationData libraryMacroApplicationData =
+ libraryEntry.value;
+ for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
+ in libraryMacroApplicationData.memberApplications.entries) {
+ MemberBuilder memberBuilder = memberEntry.key;
+ Declaration? declaration = _getMemberDeclaration(memberBuilder);
+ if (declaration != null) {
+ await _applyDeclarationMacros(
+ declaration, memberEntry.value, typeResolver, classIntrospector);
+ }
+ }
+ }
+ }
+
+ Future<List<MacroExecutionResult>> _applyDefinitionMacros(
+ Declaration declaration,
+ List<MacroApplication> macroApplications,
+ TypeResolver typeResolver,
+ ClassIntrospector classIntrospector,
+ TypeDeclarationResolver typeDeclarationResolver) async {
+ List<MacroExecutionResult> results = [];
+ for (MacroApplication macroApplication in macroApplications) {
+ MacroExecutionResult result = await macroExecutor.executeDefinitionsPhase(
+ macroApplication.instanceIdentifier,
+ declaration,
+ typeResolver,
+ classIntrospector,
+ typeDeclarationResolver);
+ results.add(result);
+ }
+ return results;
+ }
+
+ Future<void> applyDefinitionMacros() async {
+ TypeResolver typeResolver = new _TypeResolver();
+ ClassIntrospector classIntrospector = new _ClassIntrospector();
+ TypeDeclarationResolver typeDeclarationResolver =
+ new _TypeDeclarationResolver();
+ for (MapEntry<SourceLibraryBuilder,
+ LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
+ LibraryMacroApplicationData libraryMacroApplicationData =
+ libraryEntry.value;
+ for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
+ in libraryMacroApplicationData.memberApplications.entries) {
+ MemberBuilder memberBuilder = memberEntry.key;
+ Declaration? declaration = _getMemberDeclaration(memberBuilder);
+ if (declaration != null) {
+ List<MacroExecutionResult> results = await _applyDefinitionMacros(
+ declaration,
+ memberEntry.value,
+ typeResolver,
+ classIntrospector,
+ typeDeclarationResolver);
+ dataForTesting?.memberDefinitionsResults[memberBuilder] = results;
+ }
+ }
+ }
+ }
}
class MacroApplication {
@@ -78,14 +230,163 @@
// TODO(johnniwinther): Add support for arguments.
MacroApplication(this.classBuilder, this.constructorName);
+
+ late MacroInstanceIdentifier instanceIdentifier;
+}
+
+class MacroApplicationDataForTesting {
+ Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
+ Map<MemberBuilder, List<MacroExecutionResult>> memberDefinitionsResults = {};
}
class LibraryMacroApplicationData {
Map<SourceClassBuilder, ClassMacroApplicationData> classData = {};
- Map<MemberBuilder, MacroApplications> memberApplications = {};
+ Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
}
class ClassMacroApplicationData {
- MacroApplications? classApplications;
- Map<MemberBuilder, MacroApplications> memberApplications = {};
+ List<MacroApplication>? classApplications;
+ Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
+}
+
+FunctionDeclaration createTopLevelFunctionDeclaration(
+ SourceProcedureBuilder builder) {
+ List<ParameterDeclarationImpl>? positionalParameters;
+ List<ParameterDeclarationImpl>? namedParameters;
+
+ List<FormalParameterBuilder>? formals = builder.formals;
+ if (formals == null) {
+ positionalParameters = namedParameters = const [];
+ } else {
+ positionalParameters = [];
+ namedParameters = [];
+ for (FormalParameterBuilder formal in formals) {
+ TypeAnnotationImpl type = computeTypeAnnotation(formal.type);
+ // TODO(johnniwinther): Support default values.
+ if (formal.isNamed) {
+ namedParameters.add(new ParameterDeclarationImpl(
+ id: _removeInstanceId++,
+ name: formal.name,
+ isRequired: formal.isNamedRequired,
+ isNamed: true,
+ type: type,
+ defaultValue: null));
+ } else {
+ positionalParameters.add(new ParameterDeclarationImpl(
+ id: _removeInstanceId++,
+ name: formal.name,
+ isRequired: formal.isRequired,
+ isNamed: false,
+ type: type,
+ defaultValue: null));
+ }
+ }
+ }
+
+ return new FunctionDeclarationImpl(
+ id: _removeInstanceId++,
+ name: builder.name,
+ isAbstract: builder.isAbstract,
+ isExternal: builder.isExternal,
+ isGetter: builder.isGetter,
+ isSetter: builder.isSetter,
+ positionalParameters: positionalParameters,
+ namedParameters: namedParameters,
+ returnType: computeTypeAnnotation(builder.returnType),
+ // TODO(johnniwinther): Support typeParameters
+ typeParameters: const []);
+}
+
+// TODO(johnniwinther): Cache remote instances when needed.
+int _removeInstanceId = 0;
+
+List<TypeAnnotationImpl> computeTypeAnnotations(
+ List<TypeBuilder>? typeBuilders) {
+ if (typeBuilders == null) return const [];
+ return new List.generate(typeBuilders.length,
+ (int index) => computeTypeAnnotation(typeBuilders[index]));
+}
+
+TypeAnnotationImpl computeTypeAnnotation(TypeBuilder? typeBuilder) {
+ if (typeBuilder != null) {
+ if (typeBuilder is NamedTypeBuilder) {
+ Object name = typeBuilder.name;
+ List<TypeAnnotationImpl> typeArguments =
+ computeTypeAnnotations(typeBuilder.arguments);
+ bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
+ if (name is String) {
+ return new NamedTypeAnnotationImpl(
+ id: _removeInstanceId++,
+ name: name,
+ typeArguments: typeArguments,
+ isNullable: isNullable);
+ } else if (name is QualifiedName) {
+ assert(name.qualifier is String);
+ return new NamedTypeAnnotationImpl(
+ id: _removeInstanceId++,
+ name: '${name.qualifier}.${name.name}',
+ typeArguments: typeArguments,
+ isNullable: isNullable);
+ }
+ }
+ }
+ return new NamedTypeAnnotationImpl(
+ id: _removeInstanceId++,
+ name: 'dynamic',
+ isNullable: false,
+ typeArguments: const []);
+}
+
+class _TypeResolver implements TypeResolver {
+ @override
+ Future<StaticType> resolve(TypeAnnotation typeAnnotation) {
+ // TODO: implement resolve
+ throw new UnimplementedError('_TypeResolver.resolve');
+ }
+}
+
+class _ClassIntrospector implements ClassIntrospector {
+ @override
+ Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) {
+ // TODO: implement constructorsOf
+ throw new UnimplementedError('_ClassIntrospector.constructorsOf');
+ }
+
+ @override
+ Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) {
+ // TODO: implement fieldsOf
+ throw new UnimplementedError('_ClassIntrospector.fieldsOf');
+ }
+
+ @override
+ Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) {
+ // TODO: implement interfacesOf
+ throw new UnimplementedError('_ClassIntrospector.interfacesOf');
+ }
+
+ @override
+ Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) {
+ // TODO: implement methodsOf
+ throw new UnimplementedError('_ClassIntrospector.methodsOf');
+ }
+
+ @override
+ Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) {
+ // TODO: implement mixinsOf
+ throw new UnimplementedError('_ClassIntrospector.mixinsOf');
+ }
+
+ @override
+ Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) {
+ // TODO: implement superclassOf
+ throw new UnimplementedError('_ClassIntrospector.superclassOf');
+ }
+}
+
+class _TypeDeclarationResolver implements TypeDeclarationResolver {
+ @override
+ Future<TypeDeclaration> declarationOf(NamedStaticType annotation) {
+ // TODO: implement declarationOf
+ throw new UnimplementedError('_TypeDeclarationResolver.declarationOf');
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index a0fef49..55c1e0b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -158,14 +158,16 @@
NullabilityBuilder combineNullabilityBuildersForSubstitution(
NullabilityBuilder a, NullabilityBuilder b) {
assert(
- (identical(a, const NullabilityBuilder.nullable()) ||
- identical(a, const NullabilityBuilder.omitted())) &&
- (identical(b, const NullabilityBuilder.nullable()) ||
- identical(b, const NullabilityBuilder.omitted())),
+ // ignore: unnecessary_null_comparison
+ a != null && b != null,
"Both arguments to combineNullabilityBuildersForSubstitution "
"should be identical to either 'const NullabilityBuilder.nullable()' or "
"'const NullabilityBuilder.omitted()'.");
+ if (identical(a, const NullabilityBuilder.inherent()) &&
+ identical(b, const NullabilityBuilder.inherent())) {
+ return const NullabilityBuilder.inherent();
+ }
if (identical(a, const NullabilityBuilder.nullable()) ||
identical(b, const NullabilityBuilder.nullable())) {
return const NullabilityBuilder.nullable();
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 67f880b..0b7498f 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -1630,7 +1630,7 @@
TypeBuilder addVoidType(int charOffset) {
// 'void' is always nullable.
return addNamedType(
- "void", const NullabilityBuilder.nullable(), null, charOffset,
+ "void", const NullabilityBuilder.inherent(), null, charOffset,
instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
..bind(
new VoidTypeDeclarationBuilder(const VoidType(), this, charOffset));
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index a731d66..d764604 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -8,6 +8,8 @@
import 'dart:convert' show utf8;
import 'dart:typed_data' show Uint8List;
+import 'package:_fe_analyzer_shared/src/macros/executor.dart'
+ show MacroExecutor;
import 'package:_fe_analyzer_shared/src/parser/class_member_parser.dart'
show ClassMemberParser;
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
@@ -44,7 +46,6 @@
import '../builder/invalid_type_declaration_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
-import '../builder/metadata_builder.dart';
import '../builder/modifier_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/procedure_builder.dart';
@@ -1426,23 +1427,10 @@
}
}
- Future<void> computeMacroApplications() async {
- if (!enableMacros || _macroClassBuilder == null) return;
+ Future<MacroApplications?> computeMacroApplications() async {
+ if (!enableMacros || _macroClassBuilder == null) return null;
- MacroApplications? computeApplications(
- SourceLibraryBuilder enclosingLibrary,
- Scope scope,
- Uri fileUri,
- List<MetadataBuilder>? annotations) {
- List<MacroApplication>? result = prebuildAnnotations(
- enclosingLibrary: enclosingLibrary,
- metadataBuilders: annotations,
- fileUri: fileUri,
- scope: scope);
- return result != null ? new MacroApplications(result) : null;
- }
-
- MacroApplicationData macroApplicationData = new MacroApplicationData();
+ Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
for (SourceLibraryBuilder libraryBuilder in sourceLibraryBuilders) {
// TODO(johnniwinther): Handle patch libraries.
LibraryMacroApplicationData libraryMacroApplicationData =
@@ -1454,28 +1442,28 @@
SourceClassBuilder classBuilder = builder;
ClassMacroApplicationData classMacroApplicationData =
new ClassMacroApplicationData();
- classMacroApplicationData.classApplications = computeApplications(
- libraryBuilder,
- classBuilder.scope,
- classBuilder.fileUri,
- classBuilder.metadata);
+ classMacroApplicationData.classApplications = prebuildAnnotations(
+ enclosingLibrary: libraryBuilder,
+ scope: classBuilder.scope,
+ fileUri: classBuilder.fileUri,
+ metadataBuilders: classBuilder.metadata);
builder.forEach((String name, Builder memberBuilder) {
if (memberBuilder is SourceProcedureBuilder) {
- MacroApplications? macroApplications = computeApplications(
- libraryBuilder,
- classBuilder.scope,
- memberBuilder.fileUri,
- memberBuilder.metadata);
+ List<MacroApplication>? macroApplications = prebuildAnnotations(
+ enclosingLibrary: libraryBuilder,
+ scope: classBuilder.scope,
+ fileUri: memberBuilder.fileUri,
+ metadataBuilders: memberBuilder.metadata);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
macroApplications;
}
} else if (memberBuilder is SourceFieldBuilder) {
- MacroApplications? macroApplications = computeApplications(
- libraryBuilder,
- classBuilder.scope,
- memberBuilder.fileUri,
- memberBuilder.metadata);
+ List<MacroApplication>? macroApplications = prebuildAnnotations(
+ enclosingLibrary: libraryBuilder,
+ scope: classBuilder.scope,
+ fileUri: memberBuilder.fileUri,
+ metadataBuilders: memberBuilder.metadata);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
macroApplications;
@@ -1484,11 +1472,11 @@
});
classBuilder.forEachConstructor((String name, Builder memberBuilder) {
if (memberBuilder is DeclaredSourceConstructorBuilder) {
- MacroApplications? macroApplications = computeApplications(
- libraryBuilder,
- classBuilder.scope,
- memberBuilder.fileUri,
- memberBuilder.metadata);
+ List<MacroApplication>? macroApplications = prebuildAnnotations(
+ enclosingLibrary: libraryBuilder,
+ scope: classBuilder.scope,
+ fileUri: memberBuilder.fileUri,
+ metadataBuilders: memberBuilder.metadata);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
macroApplications;
@@ -1502,21 +1490,21 @@
classMacroApplicationData;
}
} else if (builder is SourceProcedureBuilder) {
- MacroApplications? macroApplications = computeApplications(
- libraryBuilder,
- libraryBuilder.scope,
- builder.fileUri,
- builder.metadata);
+ List<MacroApplication>? macroApplications = prebuildAnnotations(
+ enclosingLibrary: libraryBuilder,
+ scope: libraryBuilder.scope,
+ fileUri: builder.fileUri,
+ metadataBuilders: builder.metadata);
if (macroApplications != null) {
libraryMacroApplicationData.memberApplications[builder] =
macroApplications;
}
} else if (builder is SourceFieldBuilder) {
- MacroApplications? macroApplications = computeApplications(
- libraryBuilder,
- libraryBuilder.scope,
- builder.fileUri,
- builder.metadata);
+ List<MacroApplication>? macroApplications = prebuildAnnotations(
+ enclosingLibrary: libraryBuilder,
+ scope: libraryBuilder.scope,
+ fileUri: builder.fileUri,
+ metadataBuilders: builder.metadata);
if (macroApplications != null) {
libraryMacroApplicationData.memberApplications[builder] =
macroApplications;
@@ -1525,18 +1513,21 @@
}
if (libraryMacroApplicationData.classData.isNotEmpty ||
libraryMacroApplicationData.memberApplications.isNotEmpty) {
- macroApplicationData.libraryData[libraryBuilder] =
- libraryMacroApplicationData;
- if (retainDataForTesting) {
- dataForTesting!.macroApplicationData.libraryData[libraryBuilder] =
- libraryMacroApplicationData;
- }
+ libraryData[libraryBuilder] = libraryMacroApplicationData;
}
}
- if (macroApplicationData.libraryData.isNotEmpty) {
- await macroApplicationData
- .loadMacroIds(target.context.options.macroExecutorProvider);
+ if (libraryData.isNotEmpty) {
+ MacroExecutor macroExecutor =
+ await target.context.options.macroExecutorProvider();
+ Map<MacroClass, Uri> precompiledMacroUris =
+ target.context.options.precompiledMacroUris;
+ return await MacroApplications.loadMacroIds(
+ macroExecutor,
+ precompiledMacroUris,
+ libraryData,
+ dataForTesting?.macroApplicationData);
}
+ return null;
}
void finishDeferredLoadTearoffs() {
@@ -2012,11 +2003,15 @@
ClassHierarchyBuilder hierarchyBuilder = _hierarchyBuilder =
ClassHierarchyBuilder.build(
objectClass, sourceClasses, this, coreTypes);
+ typeInferenceEngine.hierarchyBuilder = hierarchyBuilder;
+ ticker.logMs("Built class hierarchy");
+ }
+
+ void buildClassHierarchyMembers(List<SourceClassBuilder> sourceClasses) {
ClassMembersBuilder membersBuilder = _membersBuilder =
ClassMembersBuilder.build(hierarchyBuilder, sourceClasses);
- typeInferenceEngine.hierarchyBuilder = hierarchyBuilder;
typeInferenceEngine.membersBuilder = membersBuilder;
- ticker.logMs("Built class hierarchy");
+ ticker.logMs("Built class hierarchy members");
}
void createTypeInferenceEngine() {
@@ -2558,7 +2553,8 @@
final MacroDeclarationData macroDeclarationData = new MacroDeclarationData();
- final MacroApplicationData macroApplicationData = new MacroApplicationData();
+ final MacroApplicationDataForTesting macroApplicationData =
+ new MacroApplicationDataForTesting();
}
class _SourceClassGraph implements Graph<SourceClassBuilder> {
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 4d54b4b..0deb368 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -23,7 +23,7 @@
import 'fasta/fasta_codes.dart' show LocatedMessage;
-import 'fasta/kernel/kernel_target.dart' show KernelTarget;
+import 'fasta/kernel/kernel_target.dart' show BuildResult, KernelTarget;
import 'fasta/kernel/utils.dart' show printComponentText, serializeComponent;
@@ -96,8 +96,9 @@
new KernelTarget(fs, false, dillTarget, uriTranslator);
sourceLoader = kernelTarget.loader;
kernelTarget.setEntryPoints(options.inputs);
- Component summaryComponent =
- (await kernelTarget.buildOutlines(nameRoot: nameRoot))!;
+ BuildResult buildResult =
+ await kernelTarget.buildOutlines(nameRoot: nameRoot);
+ Component summaryComponent = buildResult.component!;
List<int>? summary = null;
if (buildSummary) {
if (options.verify) {
@@ -159,13 +160,19 @@
Component? component;
if (buildComponent) {
- component = await kernelTarget.buildComponent(verify: options.verify);
+ buildResult = await kernelTarget.buildComponent(
+ macroApplications: buildResult.macroApplications,
+ verify: options.verify);
+ component = buildResult.component;
if (options.debugDump) {
printComponentText(component,
libraryFilter: kernelTarget.isSourceLibraryForDebugging);
}
options.ticker.logMs("Generated component");
}
+ // TODO(johnniwinther): Should we reuse the macro executor on subsequent
+ // compilations where possible?
+ buildResult.macroApplications?.macroExecutor.close();
return new InternalCompilerResult(
summary: summary,
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index 13b47b5..b9a1a86 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -4,11 +4,20 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:_fe_analyzer_shared/src/testing/id.dart'
- show ActualData, ClassId, Id, IdKind, IdValue, MemberId, NodeId;
+ show
+ ActualData,
+ ClassId,
+ DataRegistry,
+ Id,
+ IdKind,
+ IdValue,
+ MemberId,
+ NodeId;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/base/nnbd_mode.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/target/targets.dart';
+
import '../api_prototype/compiler_options.dart'
show CompilerOptions, DiagnosticMessage;
import '../api_prototype/experimental_flags.dart'
@@ -23,8 +32,8 @@
import 'id_testing_utils.dart';
export '../fasta/compiler_context.dart' show CompilerContext;
-export '../kernel_generator_impl.dart' show InternalCompilerResult;
export '../fasta/messages.dart' show FormattedMessage;
+export '../kernel_generator_impl.dart' show InternalCompilerResult;
/// Test configuration used for testing CFE in its default state.
const TestConfig defaultCfeConfig = const TestConfig(cfeMarker, 'cfe');
@@ -213,11 +222,8 @@
}
}
-abstract class CfeDataExtractor<T> extends DataExtractor<T> {
- final InternalCompilerResult compilerResult;
-
- CfeDataExtractor(this.compilerResult, Map<Id, ActualData<T>> actualMap)
- : super(actualMap);
+mixin CfeDataRegistryMixin<T> implements DataRegistry<T> {
+ InternalCompilerResult get compilerResult;
@override
void report(Uri uri, int offset, String message) {
@@ -231,6 +237,25 @@
}
}
+class CfeDataRegistry<T> with DataRegistry<T>, CfeDataRegistryMixin<T> {
+ @override
+ final InternalCompilerResult compilerResult;
+
+ @override
+ final Map<Id, ActualData<T>> actualMap;
+
+ CfeDataRegistry(this.compilerResult, this.actualMap);
+}
+
+abstract class CfeDataExtractor<T> extends DataExtractor<T>
+ with CfeDataRegistryMixin<T> {
+ @override
+ final InternalCompilerResult compilerResult;
+
+ CfeDataExtractor(this.compilerResult, Map<Id, ActualData<T>> actualMap)
+ : super(actualMap);
+}
+
/// Create the testing URI used for [fileName] in annotated tests.
Uri createUriForFileName(String fileName) => toTestUri(fileName);
diff --git a/pkg/front_end/test/explicit_creation_git_test.dart b/pkg/front_end/test/explicit_creation_git_test.dart
index 726ffae..0f00042 100644
--- a/pkg/front_end/test/explicit_creation_git_test.dart
+++ b/pkg/front_end/test/explicit_creation_git_test.dart
@@ -101,8 +101,10 @@
kernelTarget.setEntryPoints(c.options.inputs);
dillTarget.buildOutlines();
- await kernelTarget.buildOutlines();
- await kernelTarget.buildComponent();
+ BuildResult buildResult = await kernelTarget.buildOutlines();
+ buildResult = await kernelTarget.buildComponent(
+ macroApplications: buildResult.macroApplications);
+ buildResult.macroApplications?.macroExecutor.close();
});
print("Done in ${stopwatch.elapsedMilliseconds} ms. "
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 2c4da28..d4e1b8c 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -53,7 +53,7 @@
import 'package:front_end/src/fasta/kernel/hierarchy/hierarchy_node.dart'
show ClassHierarchyNode;
import 'package:front_end/src/fasta/kernel/kernel_target.dart'
- show KernelTarget;
+ show BuildResult, KernelTarget;
import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent;
import 'package:front_end/src/fasta/messages.dart' show LocatedMessage;
@@ -1846,13 +1846,17 @@
if (compilationSetup.testOptions.errors != null) {
compilationSetup.errors.addAll(compilationSetup.testOptions.errors!);
}
- Component p = (await sourceTarget.buildOutlines())!;
+ BuildResult buildResult = await sourceTarget.buildOutlines();
+ Component p = buildResult.component!;
if (compileMode == CompileMode.full) {
- p = (await sourceTarget.buildComponent(
+ buildResult = await sourceTarget.buildComponent(
+ macroApplications: buildResult.macroApplications,
verify: compilationSetup.folderOptions.noVerify
? false
- : context.verify))!;
+ : context.verify);
+ p = buildResult.component!;
}
+ buildResult.macroApplications?.macroExecutor.close();
// To avoid possible crash in mixin transformation in the transformation
// of the user of this linked dependency we have to transform this too.
@@ -1907,20 +1911,24 @@
new ValidatingInstrumentation();
await instrumentation.loadExpectations(description.uri);
sourceTarget.loader.instrumentation = instrumentation;
- Component p = (await sourceTarget.buildOutlines())!;
+ BuildResult buildResult = await sourceTarget.buildOutlines();
+ Component p = buildResult.component!;
Set<Uri> userLibraries = createUserLibrariesImportUriSet(
p, sourceTarget.uriTranslator,
excludedLibraries: excludedLibraries);
if (compileMode != CompileMode.outline) {
- p = (await sourceTarget.buildComponent(
+ buildResult = await sourceTarget.buildComponent(
+ macroApplications: buildResult.macroApplications,
verify: compilationSetup.folderOptions.noVerify
? false
- : context.verify))!;
+ : context.verify);
+ p = buildResult.component!;
instrumentation.finish();
if (instrumentation.hasProblems) {
if (updateComments) {
await instrumentation.fixSource(description.uri, false);
} else {
+ buildResult.macroApplications?.macroExecutor.close();
return new Result<ComponentResult>(
new ComponentResult(description, p, userLibraries,
compilationSetup, sourceTarget),
@@ -1931,6 +1939,7 @@
}
}
}
+ buildResult.macroApplications?.macroExecutor.close();
return pass(new ComponentResult(
description, p, userLibraries, compilationSetup, sourceTarget));
});
diff --git a/pkg/front_end/test/macro_application/data/package_config.json b/pkg/front_end/test/macro_application/data/package_config.json
new file mode 100644
index 0000000..fbfd870
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/package_config.json
@@ -0,0 +1,18 @@
+{
+ "configVersion": 2,
+ "packages": [
+ {
+ "name": "macro",
+ "rootUri": "pkgs/macro/lib/"
+ },
+ {
+ "name": "meta",
+ "rootUri": "../../../../meta/",
+ "packageUri": "lib/"
+ },
+ {
+ "name": "_fe_analyzer_shared",
+ "rootUri": "../../../../_fe_analyzer_shared/lib/"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
new file mode 100644
index 0000000..a5469f1
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2021, 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 FunctionDefinitionMacro1 implements FunctionDefinitionMacro {
+ const FunctionDefinitionMacro1();
+
+ FutureOr<void> buildDefinitionForFunction(
+ FunctionDeclaration function, FunctionDefinitionBuilder builder) {
+ builder.augment(new FunctionBodyCode.fromString('''{
+ return 42;
+}'''));
+ }
+}
diff --git a/pkg/front_end/test/macro_application/data/tests/marker.options b/pkg/front_end/test/macro_application/data/tests/marker.options
new file mode 100644
index 0000000..578e904
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/marker.options
@@ -0,0 +1 @@
+cfe=pkg/front_end/test/macro_application/macro_application_test.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/parameters.dart b/pkg/front_end/test/macro_application/data/tests/parameters.dart
new file mode 100644
index 0000000..41fcf36
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/parameters.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:macro/macro.dart';
+
+@FunctionDefinitionMacro1()
+/*member: topLevelFunction1:
+augment void topLevelFunction1(int a, ) {
+ return 42;
+}*/
+external void topLevelFunction1(int a);
+
+@FunctionDefinitionMacro1()
+/*member: topLevelFunction2:
+augment void topLevelFunction2(int a, int b, ) {
+ return 42;
+}*/
+external void topLevelFunction2(int a, int b);
+
+@FunctionDefinitionMacro1()
+/*member: topLevelFunction3:
+augment void topLevelFunction3(int a, [int? b, ]) {
+ return 42;
+}*/
+external void topLevelFunction3(int a, [int? b]);
+
+@FunctionDefinitionMacro1()
+/*member: topLevelFunction4:
+augment void topLevelFunction4(int a, {int? b, int? c, }) {
+ return 42;
+}*/
+external void topLevelFunction4(int a, {int? b, int? c});
diff --git a/pkg/front_end/test/macro_application/data/tests/type_annotations.dart b/pkg/front_end/test/macro_application/data/tests/type_annotations.dart
new file mode 100644
index 0000000..b6a4cd8
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/type_annotations.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math' as math;
+
+import 'package:macro/macro.dart';
+
+/*member: topLevelFunction1:
+augment void topLevelFunction1() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external void topLevelFunction1();
+
+/*member: topLevelFunction2:
+augment dynamic topLevelFunction2() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external dynamic topLevelFunction2();
+
+/*member: topLevelFunction3:
+augment int topLevelFunction3() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external int topLevelFunction3();
+
+/*member: topLevelFunction4:
+augment dynamic topLevelFunction4() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external topLevelFunction4();
+
+/*member: topLevelFunction5:
+augment math.Random topLevelFunction5() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external math.Random topLevelFunction5();
+
+/*member: topLevelFunction6:
+augment List<int> topLevelFunction6() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external List<int> topLevelFunction6();
+
+/*member: topLevelFunction7:
+augment Map<math.Random, List<int>> topLevelFunction7() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external Map<math.Random, List<int>> topLevelFunction7();
+
+/*member: topLevelFunction8:
+augment Map<int?, String>? topLevelFunction8() {
+ return 42;
+}*/
+@FunctionDefinitionMacro1()
+external Map<int?, String>? topLevelFunction8();
diff --git a/pkg/front_end/test/macro_application/macro_application_test.dart b/pkg/front_end/test/macro_application/macro_application_test.dart
new file mode 100644
index 0000000..db171e8
--- /dev/null
+++ b/pkg/front_end/test/macro_application/macro_application_test.dart
@@ -0,0 +1,135 @@
+// Copyright (c) 2021, 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:io' show Directory, Platform;
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/isolated_executor/isolated_executor.dart'
+ as isolatedExecutor;
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/api_prototype/kernel_generator.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/fasta/kernel/utils.dart';
+import 'package:front_end/src/testing/compiler_common.dart';
+import 'package:front_end/src/testing/id_extractor.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:kernel/ast.dart' hide Arguments;
+import 'package:kernel/kernel.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:vm/target/vm.dart';
+
+Future<Uri> compileMacros(Directory directory) async {
+ CompilerOptions options = new CompilerOptions();
+ options.target = new VmTarget(new TargetFlags());
+ options.explicitExperimentalFlags[ExperimentalFlag.macros] = true;
+ options.environmentDefines = {};
+ options.packagesFileUri = Platform.script.resolve('data/package_config.json');
+
+ CompilerResult? compilerResult = await compileScript({
+ 'main.dart': bootstrapMacroIsolate(
+ 'package:macro/macro.dart', 'FunctionDefinitionMacro1', [''])
+ }, options: options, requireMain: false);
+ Uri uri = directory.absolute.uri.resolve('macros.dill');
+ await writeComponentToFile(compilerResult!.component!, uri);
+ return uri;
+}
+
+Future<void> main(List<String> args) async {
+ enableMacros = true;
+
+ Directory tempDirectory =
+ await Directory.systemTemp.createTemp('macro_application');
+
+ Uri macrosUri = await compileMacros(tempDirectory);
+ Map<MacroClass, Uri> precompiledMacroUris = {
+ new MacroClass(
+ Uri.parse('package:macro/macro.dart'), 'FunctionDefinitionMacro1'):
+ macrosUri
+ };
+
+ Directory dataDir =
+ new Directory.fromUri(Platform.script.resolve('data/tests'));
+ await runTests<String>(dataDir,
+ args: args,
+ createUriForFileName: createUriForFileName,
+ onFailure: onFailure,
+ runTest: runTestFor(const MacroDataComputer(),
+ [new MacroTestConfig(precompiledMacroUris)]),
+ preserveWhitespaceInAnnotations: true);
+}
+
+class MacroTestConfig extends TestConfig {
+ final Map<MacroClass, Uri> precompiledMacroUris;
+
+ MacroTestConfig(this.precompiledMacroUris)
+ : super(cfeMarker, 'cfe',
+ explicitExperimentalFlags: {ExperimentalFlag.macros: true},
+ packageConfigUri:
+ Platform.script.resolve('data/package_config.json'));
+
+ @override
+ void customizeCompilerOptions(CompilerOptions options, TestData testData) {
+ options.macroExecutorProvider = () async {
+ return await isolatedExecutor.start();
+ };
+ options.precompiledMacroUris = precompiledMacroUris;
+ }
+}
+
+class MacroDataComputer extends DataComputer<String> {
+ const MacroDataComputer();
+
+ @override
+ DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+
+ @override
+ void computeMemberData(TestResultData testResultData, Member member,
+ Map<Id, ActualData<String>> actualMap,
+ {bool? verbose}) {
+ CfeDataRegistry<String> registry =
+ new CfeDataRegistry(testResultData.compilerResult, actualMap);
+ MacroApplicationDataForTesting macroApplicationData = testResultData
+ .compilerResult
+ .kernelTargetForTesting!
+ .loader
+ .dataForTesting!
+ .macroApplicationData;
+ for (MapEntry<MemberBuilder, List<MacroExecutionResult>> entry
+ in macroApplicationData.memberDefinitionsResults.entries) {
+ if (entry.key.member == member) {
+ StringBuffer sb = new StringBuffer();
+ for (MacroExecutionResult result in entry.value) {
+ sb.write('\n${codeToString(result.augmentations.first)}');
+ }
+ Id id = computeMemberId(member);
+ registry.registerValue(
+ member.fileUri, member.fileOffset, id, sb.toString(), member);
+ }
+ }
+ }
+}
+
+void _codeToString(StringBuffer sb, Code code) {
+ for (Object part in code.parts) {
+ if (part is Code) {
+ _codeToString(sb, part);
+ } else if (part is TypeAnnotation) {
+ _codeToString(sb, part.code);
+ } else {
+ sb.write(part);
+ }
+ }
+}
+
+String codeToString(Code code) {
+ StringBuffer sb = new StringBuffer();
+ _codeToString(sb, code);
+ return sb.toString();
+}
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 2ceca95..756e587 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
+
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/fasta/builder/class_builder.dart';
@@ -106,20 +107,22 @@
class MacroDataExtractor extends CfeDataExtractor<Features> {
final TestResultData testResultData;
- late final MacroDeclarationData macroDeclarationData;
- late final MacroApplicationData macroApplicationData;
MacroDataExtractor(
this.testResultData, Map<Id, ActualData<Features>> actualMap)
- : super(testResultData.compilerResult, actualMap) {
- macroDeclarationData = testResultData.compilerResult.kernelTargetForTesting!
- .loader.dataForTesting!.macroDeclarationData;
- macroApplicationData = testResultData.compilerResult.kernelTargetForTesting!
- .loader.dataForTesting!.macroApplicationData;
- }
+ : super(testResultData.compilerResult, actualMap);
TestMacroExecutor get macroExecutor => testResultData.customData;
+ MacroDeclarationData get macroDeclarationData => testResultData.compilerResult
+ .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;
+ MacroApplicationDataForTesting get macroApplicationData => testResultData
+ .compilerResult
+ .kernelTargetForTesting!
+ .loader
+ .dataForTesting!
+ .macroApplicationData;
+
LibraryMacroApplicationData? getLibraryMacroApplicationData(Library library) {
for (MapEntry<LibraryBuilder, LibraryMacroApplicationData> entry
in macroApplicationData.libraryData.entries) {
@@ -144,13 +147,13 @@
return null;
}
- MacroApplications? getClassMacroApplications(Class cls) {
+ List<MacroApplication>? getClassMacroApplications(Class cls) {
return getClassMacroApplicationData(cls)?.classApplications;
}
- MacroApplications? getMemberMacroApplications(Member member) {
+ List<MacroApplication>? getMemberMacroApplications(Member member) {
Class? enclosingClass = member.enclosingClass;
- Map<MemberBuilder, MacroApplications>? memberApplications;
+ Map<MemberBuilder, List<MacroApplication>>? memberApplications;
if (enclosingClass != null) {
memberApplications =
getClassMacroApplicationData(enclosingClass)?.memberApplications;
@@ -160,7 +163,7 @@
?.memberApplications;
}
if (memberApplications != null) {
- for (MapEntry<MemberBuilder, MacroApplications> entry
+ for (MapEntry<MemberBuilder, List<MacroApplication>> entry
in memberApplications.entries) {
if (entry.key.member == member) {
return entry.value;
@@ -171,9 +174,9 @@
}
void registerMacroApplications(
- Features features, MacroApplications? macroApplications) {
+ Features features, List<MacroApplication>? macroApplications) {
if (macroApplications != null) {
- for (MacroApplication application in macroApplications.macros) {
+ for (MacroApplication application in macroApplications) {
String className = application.classBuilder.name;
String constructorName = application.constructorName == ''
? 'new'
@@ -258,9 +261,8 @@
MacroInstanceIdentifier macro,
Declaration declaration,
TypeResolver typeResolver,
- ClassIntrospector classIntrospector) {
- // TODO: implement executeDeclarationsPhase
- throw UnimplementedError();
+ ClassIntrospector classIntrospector) async {
+ return new _MacroExecutionResult();
}
@override
@@ -269,16 +271,14 @@
Declaration declaration,
TypeResolver typeResolver,
ClassIntrospector classIntrospector,
- TypeDeclarationResolver typeDeclarationResolver) {
- // TODO: implement executeDefinitionsPhase
- throw UnimplementedError();
+ TypeDeclarationResolver typeDeclarationResolver) async {
+ return new _MacroExecutionResult();
}
@override
Future<MacroExecutionResult> executeTypesPhase(
- MacroInstanceIdentifier macro, Declaration declaration) {
- // TODO: implement executeTypesPhase
- throw UnimplementedError();
+ MacroInstanceIdentifier macro, Declaration declaration) async {
+ return new _MacroExecutionResult();
}
@override
@@ -343,3 +343,14 @@
@override
void serialize(Serializer serializer) => throw UnimplementedError();
}
+
+class _MacroExecutionResult implements MacroExecutionResult {
+ @override
+ Iterable<DeclarationCode> augmentations = const [];
+
+ @override
+ Iterable<DeclarationCode> imports = const [];
+
+ @override
+ void serialize(Serializer serializer) {}
+}
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 09b0c93..d69db07 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -1518,6 +1518,7 @@
information
informational
informs
+inherent
inherently
inherit
inheritable
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index d0f87bb..9b60daf 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -494,6 +494,7 @@
"test/extensions/data/",
"test/id_testing/data/",
"test/language_versioning/data/",
+ "test/macro_application/data/",
"test/macros/data/",
"test/patching/data",
"test/predicates/data",
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 70b5606..f99d05f 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -37,7 +37,7 @@
show IncrementalCompiler;
import 'package:front_end/src/fasta/kernel/kernel_target.dart'
- show KernelTarget;
+ show BuildResult, KernelTarget;
import 'package:front_end/src/fasta/kernel/utils.dart'
show printComponentText, writeComponentToFile;
@@ -304,10 +304,27 @@
{Uri? output,
bool omitPlatform: false,
bool supportAdditionalDills: true}) async {
+ KernelTarget kernelTarget = await _createKernelTarget();
+ BuildResult buildResult = await _buildOutline(kernelTarget,
+ output: output,
+ omitPlatform: omitPlatform,
+ supportAdditionalDills: supportAdditionalDills);
+ buildResult.macroApplications?.macroExecutor.close();
+ return kernelTarget;
+ }
+
+ Future<KernelTarget> _createKernelTarget() async {
UriTranslator uriTranslator = await c.options.getUriTranslator();
ticker.logMs("Read packages file");
DillTarget dillTarget = createDillTarget(uriTranslator);
- KernelTarget kernelTarget = createKernelTarget(dillTarget, uriTranslator);
+ return createKernelTarget(dillTarget, uriTranslator);
+ }
+
+ Future<BuildResult> _buildOutline(KernelTarget kernelTarget,
+ {Uri? output,
+ bool omitPlatform: false,
+ bool supportAdditionalDills: true}) async {
+ DillTarget dillTarget = kernelTarget.dillTarget;
if (supportAdditionalDills) {
Component? sdkSummary = await c.options.loadSdkSummary(null);
@@ -329,7 +346,8 @@
kernelTarget.setEntryPoints(c.options.inputs);
dillTarget.buildOutlines();
- var outline = await kernelTarget.buildOutlines();
+ BuildResult buildResult = await kernelTarget.buildOutlines();
+ Component? outline = buildResult.component;
if (c.options.debugDump && output != null) {
printComponentText(outline,
libraryFilter: kernelTarget.isSourceLibraryForDebugging);
@@ -353,17 +371,21 @@
await writeComponentToFile(outline!, output);
ticker.logMs("Wrote outline to ${output.toFilePath()}");
}
- return kernelTarget;
+ return buildResult;
}
Future<Uri> compile(
{bool omitPlatform: false, bool supportAdditionalDills: true}) async {
c.options.reportNullSafetyCompilationModeInfo();
- KernelTarget kernelTarget =
- await buildOutline(supportAdditionalDills: supportAdditionalDills);
+ KernelTarget kernelTarget = await _createKernelTarget();
+ BuildResult buildResult = await _buildOutline(kernelTarget,
+ supportAdditionalDills: supportAdditionalDills);
Uri uri = c.options.output!;
- Component component =
- (await kernelTarget.buildComponent(verify: c.options.verify))!;
+ buildResult = await kernelTarget.buildComponent(
+ macroApplications: buildResult.macroApplications,
+ verify: c.options.verify);
+ buildResult.macroApplications?.macroExecutor.close();
+ Component component = buildResult.component!;
if (c.options.debugDump) {
printComponentText(component,
libraryFilter: kernelTarget.isSourceLibraryForDebugging);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 360c4a4..097f562 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -5513,8 +5513,11 @@
return memcmp(a->untag()->data(), b->untag()->data(), Size(a)) == 0;
}
- uint32_t Hash() const {
- return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart()), Size());
+ uint32_t Hash() const { return Hash(ptr()); }
+
+ static uint32_t Hash(const InstructionsPtr instr) {
+ return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart(instr)),
+ Size(instr));
}
CodeStatistics* stats() const;
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 9d57230..b7f31f3 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -1178,7 +1178,9 @@
static Value ValueOf(Pair kv) { return kv; }
- static inline uword Hash(Key key) { return Utils::WordHash(key->Size()); }
+ static inline uword Hash(Key key) {
+ return Utils::WordHash(Instructions::Hash(key->instructions()));
+ }
static inline bool IsKeyEqual(Pair pair, Key key) {
// In AOT, disabled code objects should not be considered for deduplication.
diff --git a/sdk/lib/core/pattern.dart b/sdk/lib/core/pattern.dart
index dbf7a23..fbf70ea 100644
--- a/sdk/lib/core/pattern.dart
+++ b/sdk/lib/core/pattern.dart
@@ -95,7 +95,7 @@
///
/// The result may be `null` if the pattern didn't assign a value to it
/// as part of this match.
- /// ```dart import dart:convert
+ /// ```dart import:convert
///
/// final string = '[00:13.37] This is a chat message.';
/// final regExp = RegExp(r'^\[\s*(\d+):(\d+)\.(\d+)\]\s*(.*)$');
@@ -119,7 +119,7 @@
///
/// The list contains the strings returned by [group] for each index in
/// [groupIndices].
- /// ```dart import dart:convert
+ /// ```dart import:convert
///
/// final string = '[00:13.37] This is a chat message.';
/// final regExp = RegExp(r'^\[\s*(\d+):(\d+)\.(\d+)\]\s*(.*)$');
diff --git a/tools/VERSION b/tools/VERSION
index f958102..78a60d7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 24
+PRERELEASE 25
PRERELEASE_PATCH 0
\ No newline at end of file