Skip to content

Commit

Permalink
Version 3.5.0-198.0.dev
Browse files Browse the repository at this point in the history
Merge 004d6a3 into dev
  • Loading branch information
Dart CI committed May 28, 2024
2 parents 19aa7bd + 004d6a3 commit 9ce1489
Show file tree
Hide file tree
Showing 21 changed files with 550 additions and 92 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

#### Pub

- Support for [workspaces](https://dart.dev/go/pub-workspaces). Multiple
related packages can be resolved together when developing.
- New flag `dart pub downgrade --tighten` to restrict lower bounds of
dependencies' constraints to the minimum that can be resolved.

Expand Down
5 changes: 5 additions & 0 deletions pkg/_macros/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.1.8

- Add identifiers to `NamedStaticType`.
- Add `StaticType.asInstanceOf`.

## 0.1.7

- Fix for generating code after extendsType
Expand Down
27 changes: 26 additions & 1 deletion pkg/_macros/lib/src/api/introspection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,36 @@ abstract interface class StaticType {

/// Returns true if this is an identical type to [other].
Future<bool> isExactly(covariant StaticType other);

/// Returns a [NamedStaticType] having a [NamedStaticType.declaration] equal
/// to the [declaration] passed here, while also being a supertype of `this`
/// type.
///
/// This is useful to obtain the type parameters required for a known
/// superclass. Consider a class defined as `class MyMap implements
/// Map<Foo, Bar>` and a macro interested in dealing with maps. Once that
/// macro has resolved `MyMap` to a static type, it would call [asInstanceOf]
/// with the type declaration of the `Map` type from `dart:core` to obtain the
/// [NamedStaticType.typeArguments] required on `Map` to be a supertype of
/// `MyMap` (`Foo` and `Bar`, in this case).
///
/// To query whether this type is a subtype of a given type declaration, it
/// is easier to resolve that type and then call [isSubtypeOf].
///
/// Returns null if there is no instantiation of [declaration] that is a
/// supertype of `this`.
Future<NamedStaticType?> asInstanceOf(TypeDeclaration declaration);
}

/// A subtype of [StaticType] representing types that can be resolved by name
/// to a concrete declaration.
abstract interface class NamedStaticType implements StaticType {}
abstract interface class NamedStaticType implements StaticType {
/// The [ParameterizedTypeDeclaration] declaring this type.
ParameterizedTypeDeclaration get declaration;

/// The type arguments passed to [declaration] to obtain this type.
List<StaticType> get typeArguments;
}

/// The interface for all declarations.
abstract interface class Declaration implements Annotatable, MacroTarget {
Expand Down
24 changes: 8 additions & 16 deletions pkg/_macros/lib/src/executor/executor_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ abstract class ExternalMacroExecutorBase extends MacroExecutor {
}

// These are initialized in the switch below.
final Serializable result;
final Serializable? result;
final MessageType resultType;
int? requestId;

Expand All @@ -84,18 +84,10 @@ abstract class ExternalMacroExecutorBase extends MacroExecutor {
ResolveTypeRequest request =
ResolveTypeRequest.deserialize(deserializer, zoneId);
requestId = request.id;
StaticType instance = await (request.introspector.instance
result = await (request.introspector.instance
as DeclarationPhaseIntrospector)
.resolve(request.typeAnnotationCode);
result = RemoteInstanceImpl(
id: RemoteInstance.uniqueId,
instance: instance,
kind: instance is NamedStaticType
? RemoteInstanceKind.namedStaticType
: RemoteInstanceKind.staticType);
resultType = instance is NamedStaticType
? MessageType.namedStaticType
: MessageType.staticType;
.resolve(request.typeAnnotationCode) as StaticTypeImpl;
resultType = MessageType.remoteInstance;
case MessageType.inferTypeRequest:
InferTypeRequest request =
InferTypeRequest.deserialize(deserializer, zoneId);
Expand All @@ -108,16 +100,16 @@ abstract class ExternalMacroExecutorBase extends MacroExecutor {
IsExactlyTypeRequest request =
IsExactlyTypeRequest.deserialize(deserializer, zoneId);
requestId = request.id;
StaticType leftType = request.leftType.instance as StaticType;
StaticType rightType = request.rightType.instance as StaticType;
StaticType leftType = request.leftType as StaticType;
StaticType rightType = request.rightType as StaticType;
result = BooleanValue(await leftType.isExactly(rightType));
resultType = MessageType.boolean;
case MessageType.isSubtypeOfRequest:
IsSubtypeOfRequest request =
IsSubtypeOfRequest.deserialize(deserializer, zoneId);
requestId = request.id;
StaticType leftType = request.leftType.instance as StaticType;
StaticType rightType = request.rightType.instance as StaticType;
StaticType leftType = request.leftType as StaticType;
StaticType rightType = request.rightType as StaticType;
result = BooleanValue(await leftType.isSubtypeOf(rightType));
resultType = MessageType.boolean;
case MessageType.declarationOfRequest:
Expand Down
55 changes: 55 additions & 0 deletions pkg/_macros/lib/src/executor/introspection_impls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,61 @@ class NamedTypeAnnotationImpl extends TypeAnnotationImpl
}
}

class StaticTypeImpl<T extends StaticType> extends RemoteInstance
implements StaticType {
StaticTypeImpl(super.id);

@override
RemoteInstanceKind get kind => RemoteInstanceKind.staticType;

// When used by the client, requests need to made through the
// ClientStaticTypeImpl wrapper which will issue RPC requests to implement
// these methods.
@override
Future<NamedStaticType?> asInstanceOf(TypeDeclaration declaration) {
throw UnsupportedError('use ClientStaticTypeImpl');
}

@override
Future<bool> isExactly(covariant StaticType other) {
throw UnsupportedError('use ClientStaticTypeImpl');
}

@override
Future<bool> isSubtypeOf(covariant StaticType other) {
throw UnsupportedError('use ClientStaticTypeImpl');
}
}

class NamedStaticTypeImpl extends StaticTypeImpl<NamedStaticType>
implements NamedStaticType {
@override
final ParameterizedTypeDeclarationImpl declaration;

@override
final List<StaticTypeImpl> typeArguments;

@override
RemoteInstanceKind get kind => RemoteInstanceKind.namedStaticType;

NamedStaticTypeImpl(
super.id, {
required this.declaration,
required this.typeArguments,
});

@override
void serializeUncached(Serializer serializer) {
super.serializeUncached(serializer);
declaration.serialize(serializer);
serializer.startList();
for (StaticTypeImpl typeArg in typeArguments) {
typeArg.serialize(serializer);
}
serializer.endList();
}
}

class RecordTypeAnnotationImpl extends TypeAnnotationImpl
implements RecordTypeAnnotation {
@override
Expand Down
107 changes: 87 additions & 20 deletions pkg/_macros/lib/src/executor/protocol.dart
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@ class ResolveTypeRequest extends IntrospectionRequest {

/// A request to check if a type is exactly another type.
class IsExactlyTypeRequest extends Request {
final RemoteInstanceImpl leftType;
final RemoteInstanceImpl rightType;
final RemoteInstance leftType;
final RemoteInstance rightType;

IsExactlyTypeRequest(this.leftType, this.rightType,
{required super.serializationZoneId});
Expand All @@ -435,8 +435,8 @@ class IsExactlyTypeRequest extends Request {

/// A request to check if a type is exactly another type.
class IsSubtypeOfRequest extends Request {
final RemoteInstanceImpl leftType;
final RemoteInstanceImpl rightType;
final RemoteInstance leftType;
final RemoteInstance rightType;

IsSubtypeOfRequest(this.leftType, this.rightType,
{required super.serializationZoneId});
Expand All @@ -457,6 +457,29 @@ class IsSubtypeOfRequest extends Request {
}
}

/// A request to check if a type is a subtype of the type defined by an
/// identifier, and, if so, also obtain the matching instantiation.
class AsInstanceOfRequest extends Request {
final RemoteInstance left;
final TypeDeclarationImpl right;
AsInstanceOfRequest(this.left, this.right,
{required super.serializationZoneId});

/// When deserializing we have already consumed the message type, so we don't
/// consume it again.
AsInstanceOfRequest.deserialize(super.deserializer, super.serializationZoneId)
: left = RemoteInstance.deserialize(deserializer),
right = RemoteInstance.deserialize(deserializer),
super.deserialize();
@override
void serialize(Serializer serializer) {
serializer.addInt(MessageType.asInstanceOfRequest.index);
left.serialize(serializer);
right.serialize(serializer);
super.serialize(serializer);
}
}

/// A general request class for all requests coming from methods on the
/// [DeclarationPhaseIntrospector] interface that are related to a single type.
class TypeIntrospectorRequest extends IntrospectionRequest {
Expand Down Expand Up @@ -557,6 +580,10 @@ class DeclarationsOfRequest extends IntrospectionRequest {
}
}

/// Signature of a function able to send requests and return a response using
/// an arbitrary communication channel.
typedef SendRequest = Future<Response> Function(Request request);

/// The base class for the client side introspectors from any phase, as well as
/// client side [StaticType]s.
///
Expand All @@ -570,7 +597,7 @@ base class ClientIntrospector {

/// A function that can send a request and return a response using an
/// arbitrary communication channel.
final Future<Response> Function(Request request) _sendRequest;
final SendRequest _sendRequest;

ClientIntrospector(this._sendRequest,
{required this.remoteInstance, required this.serializationZoneId});
Expand Down Expand Up @@ -611,19 +638,12 @@ final class ClientDeclarationPhaseIntrospector
ResolveTypeRequest request = ResolveTypeRequest(
typeAnnotation, remoteInstance,
serializationZoneId: serializationZoneId);
RemoteInstanceImpl remoteType =
_handleResponse(await _sendRequest(request));
return switch (remoteType.kind) {
RemoteInstanceKind.namedStaticType => ClientNamedStaticTypeImpl(
_sendRequest,
remoteInstance: remoteType,
serializationZoneId: serializationZoneId),
RemoteInstanceKind.staticType => ClientStaticTypeImpl(_sendRequest,
remoteInstance: remoteType, serializationZoneId: serializationZoneId),
_ => throw StateError(
'Expected either a StaticType or NamedStaticType but got '
'${remoteType.kind}'),
};
StaticTypeImpl remoteType = _handleResponse(await _sendRequest(request));
return ClientStaticTypeImpl.ofRemote(
instance: remoteType,
serializationZoneId: serializationZoneId,
sendRequest: _sendRequest,
);
}

@override
Expand Down Expand Up @@ -706,6 +726,28 @@ base class ClientStaticTypeImpl extends ClientIntrospector
ClientStaticTypeImpl(super._sendRequest,
{required super.remoteInstance, required super.serializationZoneId});

factory ClientStaticTypeImpl.ofRemote({
required StaticTypeImpl instance,
required SendRequest sendRequest,
required int serializationZoneId,
}) {
RemoteInstanceImpl remoteInstance =
RemoteInstanceImpl(id: instance.id, kind: instance.kind);
return switch (instance.kind) {
RemoteInstanceKind.namedStaticType => ClientNamedStaticTypeImpl(
sendRequest,
staticType: instance as NamedStaticTypeImpl,
remoteInstance: remoteInstance,
serializationZoneId: serializationZoneId),
RemoteInstanceKind.staticType => ClientStaticTypeImpl(sendRequest,
remoteInstance: remoteInstance,
serializationZoneId: serializationZoneId),
_ => throw StateError(
'Expected either a StaticType or NamedStaticType but got '
'${instance.kind}'),
};
}

@override
Future<bool> isExactly(ClientStaticTypeImpl other) async {
IsExactlyTypeRequest request = IsExactlyTypeRequest(
Expand All @@ -721,13 +763,37 @@ base class ClientStaticTypeImpl extends ClientIntrospector
serializationZoneId: serializationZoneId);
return _handleResponse<BooleanValue>(await _sendRequest(request)).value;
}

@override
Future<NamedStaticType?> asInstanceOf(TypeDeclaration declaration) async {
AsInstanceOfRequest request = AsInstanceOfRequest(
remoteInstance, declaration as TypeDeclarationImpl,
serializationZoneId: serializationZoneId);
return _handleResponse<NamedStaticType?>(await _sendRequest(request));
}
}

/// Named variant of the [ClientStaticTypeImpl].
final class ClientNamedStaticTypeImpl extends ClientStaticTypeImpl
implements NamedStaticType {
ClientNamedStaticTypeImpl(super.sendRequest,
{required super.remoteInstance, required super.serializationZoneId});
@override
final ParameterizedTypeDeclaration declaration;

@override
final List<StaticType> typeArguments;

ClientNamedStaticTypeImpl(
super.sendRequest, {
required NamedStaticTypeImpl staticType,
required super.serializationZoneId,
required super.remoteInstance,
}) : declaration = staticType.declaration,
typeArguments = staticType.typeArguments
.map((raw) => ClientStaticTypeImpl.ofRemote(
instance: raw,
sendRequest: sendRequest,
serializationZoneId: serializationZoneId))
.toList();
}

/// Client side implementation of a [DeclarationBuilder].
Expand Down Expand Up @@ -793,6 +859,7 @@ enum MessageType {
inferTypeRequest,
isExactlyTypeRequest,
isSubtypeOfRequest,
asInstanceOfRequest,
loadMacroRequest,
remoteInstance,
macroInstanceIdentifier,
Expand Down
2 changes: 1 addition & 1 deletion pkg/_macros/lib/src/executor/remote_instance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ abstract class RemoteInstance implements Serializable {
/// a generic object.
///
/// The wrapped object is not serialized.
class RemoteInstanceImpl extends RemoteInstance {
final class RemoteInstanceImpl extends RemoteInstance {
/// Always null on the client side, has an actual instance on the server side.
final Object? instance;

Expand Down
15 changes: 12 additions & 3 deletions pkg/_macros/lib/src/executor/serialization_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ extension DeserializerExtensions on Deserializer {
final RemoteInstance instance = switch (kind) {
RemoteInstanceKind.declarationPhaseIntrospector ||
RemoteInstanceKind.definitionPhaseIntrospector ||
RemoteInstanceKind.typePhaseIntrospector ||
RemoteInstanceKind.namedStaticType ||
RemoteInstanceKind.staticType =>
RemoteInstanceKind.typePhaseIntrospector =>
// These are simple wrappers, just pass in the kind
RemoteInstanceImpl(id: id, kind: kind),
RemoteInstanceKind.classDeclaration =>
Expand Down Expand Up @@ -58,6 +56,8 @@ extension DeserializerExtensions on Deserializer {
RemoteInstanceKind.library => (this..moveNext())._expectLibrary(id),
RemoteInstanceKind.methodDeclaration =>
(this..moveNext())._expectMethodDeclaration(id),
RemoteInstanceKind.namedStaticType =>
(this..moveNext())._expectNamedStaticType(id),
RemoteInstanceKind.namedTypeAnnotation =>
(this..moveNext())._expectNamedTypeAnnotation(id),
RemoteInstanceKind.omittedTypeAnnotation =>
Expand All @@ -68,6 +68,7 @@ extension DeserializerExtensions on Deserializer {
(this..moveNext())._expectRecordField(id),
RemoteInstanceKind.recordTypeAnnotation =>
(this..moveNext())._expectRecordTypeAnnotation(id),
RemoteInstanceKind.staticType => StaticTypeImpl(id),
RemoteInstanceKind.typeAliasDeclaration =>
(this..moveNext())._expectTypeAliasDeclaration(id),
RemoteInstanceKind.typeParameter =>
Expand Down Expand Up @@ -116,6 +117,14 @@ extension DeserializerExtensions on Deserializer {
};
}

NamedStaticTypeImpl _expectNamedStaticType(int id) {
return NamedStaticTypeImpl(
id,
declaration: expectRemoteInstance(),
typeArguments: (this..moveNext())._expectRemoteInstanceList(),
);
}

NamedTypeAnnotationImpl _expectNamedTypeAnnotation(int id) =>
NamedTypeAnnotationImpl(
id: id,
Expand Down
Loading

0 comments on commit 9ce1489

Please sign in to comment.