blob: b9d2dd27d3447d4d1ece2fbe100b6cfe6e6e6974 [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.
import '../api.dart';
import '../executor.dart';
import 'exception_impls.dart';
import 'introspection_impls.dart';
import 'serialization.dart';
import 'serialization_extensions.dart';
/// Implementation of [MacroInstanceIdentifier].
class MacroInstanceIdentifierImpl implements MacroInstanceIdentifier {
/// Unique identifier for this instance, passed in from the server.
final int id;
/// A single int where each bit indicates whether a specific macro interface
/// is implemented by this macro.
final int _interfaces;
MacroInstanceIdentifierImpl._(this.id, this._interfaces);
factory MacroInstanceIdentifierImpl(Macro macro, int instanceId) {
// Build up the interfaces value, there is a bit for each declaration/phase
// combination (as there is an interface for each).
int interfaces = 0;
for (DeclarationKind declarationKind in DeclarationKind.values) {
for (Phase phase in Phase.values) {
int interfaceMask = _interfaceMask(declarationKind, phase);
switch (declarationKind) {
case DeclarationKind.classType:
switch (phase) {
case Phase.types:
if (macro is ClassTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is ClassDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is ClassDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.constructor:
switch (phase) {
case Phase.types:
if (macro is ConstructorTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is ConstructorDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is ConstructorDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.extension:
switch (phase) {
case Phase.types:
if (macro is ExtensionTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is ExtensionDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is ExtensionDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.extensionType:
switch (phase) {
case Phase.types:
if (macro is ExtensionTypeTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is ExtensionTypeDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is ExtensionTypeDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.field:
switch (phase) {
case Phase.types:
if (macro is FieldTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is FieldDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is FieldDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.function:
switch (phase) {
case Phase.types:
if (macro is FunctionTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is FunctionDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is FunctionDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.library:
switch (phase) {
case Phase.types:
if (macro is LibraryTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is LibraryDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is LibraryDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.method:
switch (phase) {
case Phase.types:
if (macro is MethodTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is MethodDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is MethodDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.enumType:
switch (phase) {
case Phase.types:
if (macro is EnumTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is EnumDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is EnumDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.enumValue:
switch (phase) {
case Phase.types:
if (macro is EnumValueTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is EnumValueDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is EnumValueDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.mixinType:
switch (phase) {
case Phase.types:
if (macro is MixinTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is MixinDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is MixinDefinitionMacro) {
interfaces |= interfaceMask;
}
}
case DeclarationKind.typeAlias:
switch (phase) {
case Phase.types:
if (macro is TypeAliasTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is TypeAliasDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
// Does not have definitions.
break;
}
case DeclarationKind.variable:
switch (phase) {
case Phase.types:
if (macro is VariableTypesMacro) {
interfaces |= interfaceMask;
}
case Phase.declarations:
if (macro is VariableDeclarationsMacro) {
interfaces |= interfaceMask;
}
case Phase.definitions:
if (macro is VariableDefinitionMacro) {
interfaces |= interfaceMask;
}
}
}
}
}
return MacroInstanceIdentifierImpl._(instanceId, interfaces);
}
MacroInstanceIdentifierImpl.deserialize(Deserializer deserializer)
: id = (deserializer..moveNext()).expectInt(),
_interfaces = (deserializer..moveNext()).expectInt();
@override
void serialize(Serializer serializer) => serializer
..addInt(id)
..addInt(_interfaces);
@override
operator ==(other) => other is MacroInstanceIdentifierImpl && id == other.id;
@override
int get hashCode => id;
@override
bool shouldExecute(DeclarationKind declarationKind, Phase phase) {
int mask = _interfaceMask(declarationKind, phase);
if (declarationKind == DeclarationKind.method) {
// Apply function macros to methods.
mask |= _interfaceMask(DeclarationKind.function, phase);
} else if (declarationKind == DeclarationKind.field) {
// Apply variable macros to fields.
mask |= _interfaceMask(DeclarationKind.variable, phase);
}
return _interfaces & mask != 0x0;
}
@override
bool supportsDeclarationKind(DeclarationKind declarationKind) {
for (Phase phase in Phase.values) {
if (shouldExecute(declarationKind, phase)) {
return true;
}
}
return false;
}
/// The mask for a particular interface, which is a combination of a kind of
/// declaration and a phase.
static int _interfaceMask(DeclarationKind declarationKind, Phase phase) =>
0x1 << (declarationKind.index * Phase.values.length) << phase.index;
}
/// Implementation of [MacroExecutionResult].
class MacroExecutionResultImpl implements MacroExecutionResult {
@override
final List<Diagnostic> diagnostics;
@override
final MacroExceptionImpl? exception;
@override
final Map<IdentifierImpl, List<DeclarationCode>> enumValueAugmentations;
@override
final Map<IdentifierImpl, NamedTypeAnnotationCode> extendsTypeAugmentations;
@override
final Map<IdentifierImpl, List<TypeAnnotationCode>> interfaceAugmentations;
@override
final List<DeclarationCode> libraryAugmentations;
@override
final Map<IdentifierImpl, List<TypeAnnotationCode>> mixinAugmentations;
@override
final List<String> newTypeNames;
@override
final Map<IdentifierImpl, List<DeclarationCode>> typeAugmentations;
MacroExecutionResultImpl({
required this.diagnostics,
this.exception,
required this.enumValueAugmentations,
required this.extendsTypeAugmentations,
required this.interfaceAugmentations,
required this.libraryAugmentations,
required this.mixinAugmentations,
required this.newTypeNames,
required this.typeAugmentations,
});
factory MacroExecutionResultImpl.deserialize(Deserializer deserializer) {
deserializer
..moveNext()
..expectList();
List<Diagnostic> diagnostics = [
for (; deserializer.moveNext();) deserializer.expectDiagnostic(),
];
MacroExceptionImpl? exception = (deserializer..moveNext()).checkNull()
? null
: deserializer.expectRemoteInstance();
deserializer
..moveNext()
..expectList();
Map<IdentifierImpl, List<DeclarationCode>> enumValueAugmentations = {
for (; deserializer.moveNext();)
deserializer.expectRemoteInstance(): [
for (bool hasNextCode = (deserializer
..moveNext()
..expectList())
.moveNext();
hasNextCode;
hasNextCode = deserializer.moveNext())
deserializer.expectCode(),
]
};
deserializer
..moveNext()
..expectList();
Map<IdentifierImpl, NamedTypeAnnotationCode> extendsTypeAugmentations = {
for (; deserializer.moveNext();)
deserializer.expectRemoteInstance():
(deserializer..moveNext()).expectCode(),
};
deserializer
..moveNext()
..expectList();
Map<IdentifierImpl, List<TypeAnnotationCode>> interfaceAugmentations = {
for (; deserializer.moveNext();)
deserializer.expectRemoteInstance(): [
for (bool hasNextCode = (deserializer
..moveNext()
..expectList())
.moveNext();
hasNextCode;
hasNextCode = deserializer.moveNext())
deserializer.expectCode(),
]
};
deserializer
..moveNext()
..expectList();
List<DeclarationCode> libraryAugmentations = [
for (; deserializer.moveNext();) deserializer.expectCode()
];
deserializer
..moveNext()
..expectList();
Map<IdentifierImpl, List<TypeAnnotationCode>> mixinAugmentations = {
for (; deserializer.moveNext();)
deserializer.expectRemoteInstance(): [
for (bool hasNextCode = (deserializer
..moveNext()
..expectList())
.moveNext();
hasNextCode;
hasNextCode = deserializer.moveNext())
deserializer.expectCode(),
]
};
deserializer
..moveNext()
..expectList();
List<String> newTypeNames = [
for (; deserializer.moveNext();) deserializer.expectString()
];
deserializer
..moveNext()
..expectList();
Map<IdentifierImpl, List<DeclarationCode>> typeAugmentations = {
for (; deserializer.moveNext();)
deserializer.expectRemoteInstance(): [
for (bool hasNextCode = (deserializer
..moveNext()
..expectList())
.moveNext();
hasNextCode;
hasNextCode = deserializer.moveNext())
deserializer.expectCode(),
]
};
return MacroExecutionResultImpl(
diagnostics: diagnostics,
exception: exception,
enumValueAugmentations: enumValueAugmentations,
extendsTypeAugmentations: extendsTypeAugmentations,
interfaceAugmentations: interfaceAugmentations,
libraryAugmentations: libraryAugmentations,
mixinAugmentations: mixinAugmentations,
newTypeNames: newTypeNames,
typeAugmentations: typeAugmentations,
);
}
@override
void serialize(Serializer serializer) {
serializer.startList();
for (Diagnostic diagnostic in diagnostics) {
diagnostic.serialize(serializer);
}
serializer.endList();
if (exception == null) {
serializer.addNull();
} else {
exception!.serialize(serializer);
}
serializer.startList();
for (IdentifierImpl enuum in enumValueAugmentations.keys) {
enuum.serialize(serializer);
serializer.startList();
for (DeclarationCode augmentation in enumValueAugmentations[enuum]!) {
augmentation.serialize(serializer);
}
serializer.endList();
}
serializer.endList();
serializer.startList();
for (IdentifierImpl type in extendsTypeAugmentations.keys) {
type.serialize(serializer);
extendsTypeAugmentations[type]!.serialize(serializer);
}
serializer.endList();
serializer.startList();
for (IdentifierImpl type in interfaceAugmentations.keys) {
type.serialize(serializer);
serializer.startList();
for (TypeAnnotationCode interface in interfaceAugmentations[type]!) {
interface.serialize(serializer);
}
serializer.endList();
}
serializer.endList();
serializer.startList();
for (DeclarationCode augmentation in libraryAugmentations) {
augmentation.serialize(serializer);
}
serializer.endList();
serializer.startList();
for (IdentifierImpl type in mixinAugmentations.keys) {
type.serialize(serializer);
serializer.startList();
for (TypeAnnotationCode mixin in mixinAugmentations[type]!) {
mixin.serialize(serializer);
}
serializer.endList();
}
serializer.endList();
serializer.startList();
for (String name in newTypeNames) {
serializer.addString(name);
}
serializer.endList();
serializer.startList();
for (IdentifierImpl type in typeAugmentations.keys) {
type.serialize(serializer);
serializer.startList();
for (DeclarationCode augmentation in typeAugmentations[type]!) {
augmentation.serialize(serializer);
}
serializer.endList();
}
serializer.endList();
}
}