blob: 68d0f940287165a3cfcd2d46e8eeea9338d491a3 [file] [log] [blame]
// 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.
/// Defines the objects used for communication between the macro executor and
/// the isolate or process doing the work of macro loading and execution.
library _fe_analyzer_shared.src.macros.executor_shared.protocol;
import '../executor.dart';
import '../api.dart';
import '../executor_shared/response_impls.dart';
import 'introspection_impls.dart';
import 'remote_instance.dart';
import 'serialization.dart';
/// Base class all requests extend, provides a unique id for each request.
abstract class Request implements Serializable {
final int id;
final int serializationZoneId;
Request({int? id, required this.serializationZoneId})
: this.id = id ?? _next++;
Request.deserialize(Deserializer deserializer)
: serializationZoneId = (deserializer..moveNext()).expectNum(),
id = (deserializer..moveNext()).expectNum();
void serialize(Serializer serializer) => serializer
..addNum(serializationZoneId)
..addNum(id);
static int _next = 0;
}
/// A generic response object that contains either a response or an error, and
/// a unique ID.
class Response {
final Object? response;
final Object? error;
final int requestId;
Response({this.response, this.error, required this.requestId})
: assert(response != null || error != null),
assert(response == null || error == null);
}
/// A serializable [Response], contains the message type as an enum.
class SerializableResponse implements Response, Serializable {
final Serializable? response;
final MessageType responseType;
final String? error;
final int requestId;
final int serializationZoneId;
SerializableResponse({
this.error,
required this.requestId,
this.response,
required this.responseType,
required this.serializationZoneId,
}) : assert(response != null || error != null),
assert(response == null || error == null);
/// You must first parse the [serializationZoneId] yourself, and then
/// call this function in that zone, and pass the ID.
factory SerializableResponse.deserialize(
Deserializer deserializer, int serializationZoneId) {
deserializer.moveNext();
MessageType responseType = MessageType.values[deserializer.expectNum()];
Serializable? response;
String? error;
switch (responseType) {
case MessageType.error:
deserializer.moveNext();
error = deserializer.expectString();
break;
case MessageType.macroClassIdentifier:
response = new MacroClassIdentifierImpl.deserialize(deserializer);
break;
case MessageType.macroInstanceIdentifier:
response = new MacroInstanceIdentifierImpl.deserialize(deserializer);
break;
case MessageType.macroExecutionResult:
response = new MacroExecutionResultImpl.deserialize(deserializer);
break;
default:
throw new StateError('Unexpected response type $responseType');
}
return new SerializableResponse(
responseType: responseType,
response: response,
error: error,
requestId: (deserializer..moveNext()).expectNum(),
serializationZoneId: serializationZoneId);
}
void serialize(Serializer serializer) {
serializer
..addNum(serializationZoneId)
..addNum(responseType.index);
if (response != null) {
response!.serialize(serializer);
} else if (error != null) {
serializer.addString(error!.toString());
}
serializer.addNum(requestId);
}
}
/// A request to load a macro in this isolate.
class LoadMacroRequest extends Request {
final Uri library;
final String name;
LoadMacroRequest(this.library, this.name, {required int serializationZoneId})
: super(serializationZoneId: serializationZoneId);
LoadMacroRequest.deserialize(Deserializer deserializer)
: library = Uri.parse((deserializer..moveNext()).expectString()),
name = (deserializer..moveNext()).expectString(),
super.deserialize(deserializer);
@override
void serialize(Serializer serializer) {
serializer
..addNum(MessageType.loadMacroRequest.index)
..addString(library.toString())
..addString(name);
super.serialize(serializer);
}
}
/// A request to instantiate a macro instance.
class InstantiateMacroRequest extends Request {
final MacroClassIdentifier macroClass;
final String constructorName;
final Arguments arguments;
InstantiateMacroRequest(this.macroClass, this.constructorName, this.arguments,
{required int serializationZoneId})
: super(serializationZoneId: serializationZoneId);
InstantiateMacroRequest.deserialize(Deserializer deserializer)
: macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
constructorName = (deserializer..moveNext()).expectString(),
arguments = new Arguments.deserialize(deserializer),
super.deserialize(deserializer);
@override
void serialize(Serializer serializer) {
serializer.addNum(MessageType.instantiateMacroRequest.index);
macroClass.serialize(serializer);
serializer.addString(constructorName);
arguments.serialize(serializer);
super.serialize(serializer);
}
}
/// A request to execute a macro on a particular declaration in the definition
/// phase.
class ExecuteDefinitionsPhaseRequest extends Request {
final MacroInstanceIdentifier macro;
final DeclarationImpl declaration;
/// Client/Server specific implementation, not serialized.
final TypeResolver typeResolver;
/// Client/Server specific implementation, not serialized.
final ClassIntrospector classIntrospector;
/// Client/Server specific implementation, not serialized.
final TypeDeclarationResolver typeDeclarationResolver;
ExecuteDefinitionsPhaseRequest(this.macro, this.declaration,
this.typeResolver, this.classIntrospector, this.typeDeclarationResolver,
{required int serializationZoneId})
: super(serializationZoneId: serializationZoneId);
/// When deserializing we have already consumed the message type, so we don't
/// consume it again.
ExecuteDefinitionsPhaseRequest.deserialize(Deserializer deserializer,
this.typeResolver, this.classIntrospector, this.typeDeclarationResolver)
: macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
declaration = RemoteInstance.deserialize(deserializer),
super.deserialize(deserializer);
void serialize(Serializer serializer) {
serializer.addNum(MessageType.executeDefinitionsPhaseRequest.index);
macro.serialize(serializer);
declaration.serialize(serializer);
super.serialize(serializer);
}
}
/// A request to reflect on a type annotation
class ReflectTypeRequest extends Request {
final TypeAnnotationImpl typeAnnotation;
ReflectTypeRequest(this.typeAnnotation, {required int serializationZoneId})
: super(serializationZoneId: serializationZoneId);
/// When deserializing we have already consumed the message type, so we don't
/// consume it again.
ReflectTypeRequest.deserialize(Deserializer deserializer)
: typeAnnotation = RemoteInstance.deserialize(deserializer),
super.deserialize(deserializer);
void serialize(Serializer serializer) {
serializer.addNum(MessageType.reflectTypeRequest.index);
typeAnnotation.serialize(serializer);
super.serialize(serializer);
}
}
/// TODO: Implement this
class ClientTypeResolver implements TypeResolver {
@override
Future<StaticType> resolve(TypeAnnotation typeAnnotation) {
// TODO: implement resolve
throw new UnimplementedError();
}
}
/// TODO: Implement this
class ClientClassIntrospector implements ClassIntrospector {
@override
Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) {
// TODO: implement constructorsOf
throw new UnimplementedError();
}
@override
Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) {
// TODO: implement fieldsOf
throw new UnimplementedError();
}
@override
Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) {
// TODO: implement interfacesOf
throw new UnimplementedError();
}
@override
Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) {
// TODO: implement methodsOf
throw new UnimplementedError();
}
@override
Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) {
// TODO: implement mixinsOf
throw new UnimplementedError();
}
@override
Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) {
// TODO: implement superclassOf
throw new UnimplementedError();
}
}
/// TODO: Implement this
class ClientTypeDeclarationsResolver implements TypeDeclarationResolver {
@override
Future<TypeDeclaration> declarationOf(NamedStaticType annotation) {
// TODO: implement declarationOf
throw new UnimplementedError();
}
}
enum MessageType {
error,
executeDefinitionsPhaseRequest,
instantiateMacroRequest,
loadMacroRequest,
reflectTypeRequest,
macroClassIdentifier,
macroInstanceIdentifier,
macroExecutionResult,
}