blob: cf3ff21a596b9a436647e2c607dd3ce6a2ea22c8 [file] [log] [blame]
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
import 'remote_instance.dart';
import 'serialization.dart';
import '../api.dart';
extension DeserializerExtensions on Deserializer {
T expectRemoteInstance<T>() {
int id = expectInt();
// Server side we just return the cached remote instance by ID.
if (!serializationMode.isClient) {
return RemoteInstance.cached(id) as T;
}
moveNext();
RemoteInstanceKind kind = RemoteInstanceKind.values[expectInt()];
switch (kind) {
case RemoteInstanceKind.classIntrospector:
case RemoteInstanceKind.namedStaticType:
case RemoteInstanceKind.staticType:
case RemoteInstanceKind.typeDeclarationResolver:
case RemoteInstanceKind.typeResolver:
// These are simple wrappers, just pass in the kind
return new RemoteInstanceImpl(id: id, kind: kind) as T;
case RemoteInstanceKind.classDeclaration:
moveNext();
return _expectClassDeclaration(id) as T;
case RemoteInstanceKind.constructorDeclaration:
moveNext();
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.identifier:
moveNext();
return _expectIdentifier(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.variableDeclaration:
moveNext();
return _expectVariableDeclaration(id) as T;
}
}
/// Helper method to read a list of [RemoteInstance]s.
List<T> _expectRemoteInstanceList<T extends RemoteInstance>() {
expectList();
return [
for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
expectRemoteInstance(),
];
}
NamedTypeAnnotation _expectNamedTypeAnnotation(int id) =>
new NamedTypeAnnotationImpl(
id: id,
isNullable: expectBool(),
identifier: RemoteInstance.deserialize(this),
typeArguments: (this..moveNext())._expectRemoteInstanceList(),
);
FunctionTypeAnnotation _expectFunctionTypeAnnotation(int id) =>
new FunctionTypeAnnotationImpl(
id: id,
isNullable: expectBool(),
returnType: RemoteInstance.deserialize(this),
positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
namedParameters: (this..moveNext())._expectRemoteInstanceList(),
typeParameters: (this..moveNext())._expectRemoteInstanceList(),
);
Identifier _expectIdentifier(int id) => new IdentifierImpl(
id: id,
name: expectString(),
);
ParameterDeclaration _expectParameterDeclaration(int id) =>
new ParameterDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
isNamed: (this..moveNext()).expectBool(),
isRequired: (this..moveNext()).expectBool(),
type: RemoteInstance.deserialize(this),
);
TypeParameterDeclaration _expectTypeParameterDeclaration(int id) =>
new TypeParameterDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
bound: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
);
FunctionDeclaration _expectFunctionDeclaration(int id) =>
new FunctionDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
isAbstract: (this..moveNext()).expectBool(),
isExternal: (this..moveNext()).expectBool(),
isGetter: (this..moveNext()).expectBool(),
isOperator: (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,
identifier: expectRemoteInstance(),
isAbstract: (this..moveNext()).expectBool(),
isExternal: (this..moveNext()).expectBool(),
isGetter: (this..moveNext()).expectBool(),
isOperator: (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),
isStatic: (this..moveNext()).expectBool(),
);
ConstructorDeclaration _expectConstructorDeclaration(int id) =>
new ConstructorDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
isAbstract: (this..moveNext()).expectBool(),
isExternal: (this..moveNext()).expectBool(),
isGetter: (this..moveNext()).expectBool(),
isOperator: (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),
// There is an extra boolean here representing the `isStatic` field
// which we just skip past.
isFactory: (this
..moveNext()
..expectBool()
..moveNext())
.expectBool(),
);
VariableDeclaration _expectVariableDeclaration(int id) =>
new VariableDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
isExternal: (this..moveNext()).expectBool(),
isFinal: (this..moveNext()).expectBool(),
isLate: (this..moveNext()).expectBool(),
type: RemoteInstance.deserialize(this),
);
FieldDeclaration _expectFieldDeclaration(int id) => new FieldDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
isExternal: (this..moveNext()).expectBool(),
isFinal: (this..moveNext()).expectBool(),
isLate: (this..moveNext()).expectBool(),
type: RemoteInstance.deserialize(this),
definingClass: RemoteInstance.deserialize(this),
isStatic: (this..moveNext()).expectBool(),
);
ClassDeclaration _expectClassDeclaration(int id) => new ClassDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
typeParameters: (this..moveNext())._expectRemoteInstanceList(),
interfaces: (this..moveNext())._expectRemoteInstanceList(),
isAbstract: (this..moveNext()).expectBool(),
isExternal: (this..moveNext()).expectBool(),
mixins: (this..moveNext())._expectRemoteInstanceList(),
superclass:
(this..moveNext()).checkNull() ? null : expectRemoteInstance(),
);
TypeAliasDeclaration _expectTypeAliasDeclaration(int id) =>
new TypeAliasDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
typeParameters: (this..moveNext())._expectRemoteInstanceList(),
aliasedType: RemoteInstance.deserialize(this),
);
List<String> _readStringList() => [
for (bool hasNext = (this
..moveNext()
..expectList())
.moveNext();
hasNext;
hasNext = moveNext())
expectString(),
];
List<T> _readCodeList<T extends Code>() => [
for (bool hasNext = (this
..moveNext()
..expectList())
.moveNext();
hasNext;
hasNext = moveNext())
expectCode(),
];
List<Object> _readParts() {
moveNext();
expectList();
List<Object> parts = [];
while (moveNext()) {
_CodePartKind partKind = _CodePartKind.values[expectInt()];
moveNext();
switch (partKind) {
case _CodePartKind.code:
parts.add(expectCode());
break;
case _CodePartKind.string:
parts.add(expectString());
break;
case _CodePartKind.identifier:
parts.add(expectRemoteInstance());
break;
}
}
return parts;
}
T expectCode<T extends Code>() {
CodeKind kind = CodeKind.values[expectInt()];
switch (kind) {
case CodeKind.raw:
return new Code.fromParts(_readParts()) as T;
case CodeKind.declaration:
return new DeclarationCode.fromParts(_readParts()) as T;
case CodeKind.expression:
return new ExpressionCode.fromParts(_readParts()) as T;
case CodeKind.functionBody:
return new FunctionBodyCode.fromParts(_readParts()) as T;
case CodeKind.functionTypeAnnotation:
return new FunctionTypeAnnotationCode(
namedParameters: _readCodeList(),
positionalParameters: _readCodeList(),
returnType: (this..moveNext()).expectNullableCode(),
typeParameters: _readCodeList()) as T;
case CodeKind.namedTypeAnnotation:
return new NamedTypeAnnotationCode(
name: RemoteInstance.deserialize(this),
typeArguments: _readCodeList()) as T;
case CodeKind.nullableTypeAnnotation:
return new NullableTypeAnnotationCode((this..moveNext()).expectCode())
as T;
case CodeKind.parameter:
return new ParameterCode(
defaultValue: (this..moveNext()).expectNullableCode(),
keywords: _readStringList(),
name: (this..moveNext()).expectString(),
type: (this..moveNext()).expectNullableCode()) as T;
case CodeKind.typeParameter:
return new TypeParameterCode(
bound: (this..moveNext()).expectNullableCode(),
name: (this..moveNext()).expectString()) 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 {
void serialize(Serializer serializer) {
serializer.addInt(kind.index);
switch (kind) {
case CodeKind.namedTypeAnnotation:
NamedTypeAnnotationCode self = this as NamedTypeAnnotationCode;
(self.name as IdentifierImpl).serialize(serializer);
serializer.startList();
for (TypeAnnotationCode typeArg in self.typeArguments) {
typeArg.serialize(serializer);
}
serializer.endList();
return;
case CodeKind.functionTypeAnnotation:
FunctionTypeAnnotationCode self = this as FunctionTypeAnnotationCode;
serializer.startList();
for (ParameterCode named in self.namedParameters) {
named.serialize(serializer);
}
serializer
..endList()
..startList();
for (ParameterCode positional in self.positionalParameters) {
positional.serialize(serializer);
}
serializer..endList();
self.returnType.serializeNullable(serializer);
serializer.startList();
for (TypeParameterCode typeParam in self.typeParameters) {
typeParam.serialize(serializer);
}
serializer.endList();
return;
case CodeKind.nullableTypeAnnotation:
NullableTypeAnnotationCode self = this as NullableTypeAnnotationCode;
self.underlyingType.serialize(serializer);
return;
case CodeKind.parameter:
ParameterCode self = this as ParameterCode;
self.defaultValue.serializeNullable(serializer);
serializer.startList();
for (String keyword in self.keywords) {
serializer.addString(keyword);
}
serializer
..endList()
..addString(self.name);
self.type.serializeNullable(serializer);
return;
case CodeKind.typeParameter:
TypeParameterCode self = this as TypeParameterCode;
self.bound.serializeNullable(serializer);
serializer.addString(self.name);
return;
default:
serializer.startList();
for (Object part in parts) {
if (part is String) {
serializer
..addInt(_CodePartKind.string.index)
..addString(part);
} else if (part is Code) {
serializer.addInt(_CodePartKind.code.index);
part.serialize(serializer);
} else if (part is IdentifierImpl) {
serializer.addInt(_CodePartKind.identifier.index);
part.serialize(serializer);
} else {
throw new StateError('Unrecognized code part $part');
}
}
serializer.endList();
return;
}
}
}
enum _CodePartKind {
string,
code,
identifier,
}