blob: 979ec15d7e443c4ca0cdcc6264dc832591e39e27 [file] [log] [blame]
// Copyright (c) 2015, 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.
library dart2js.serialization.impact;
import '../dart_types.dart';
import '../common/resolution.dart';
import '../constants/expressions.dart';
import '../elements/elements.dart';
import '../universe/call_structure.dart';
import '../universe/selector.dart';
import '../universe/world_impact.dart';
import '../universe/use.dart';
import '../util/enumset.dart';
import 'keys.dart';
import 'serialization.dart';
/// Visitor that serializes a [ResolutionImpact] object using an
/// [ObjectEncoder].
class ImpactSerializer implements WorldImpactVisitor {
final ObjectEncoder objectEncoder;
final ListEncoder staticUses;
final ListEncoder dynamicUses;
final ListEncoder typeUses;
ImpactSerializer(ObjectEncoder objectEncoder)
: this.objectEncoder = objectEncoder,
staticUses = objectEncoder.createList(Key.STATIC_USES),
dynamicUses = objectEncoder.createList(Key.DYNAMIC_USES),
typeUses = objectEncoder.createList(Key.TYPE_USES);
void serialize(ResolutionImpact resolutionImpact) {
resolutionImpact.apply(this);
objectEncoder.setStrings(Key.SYMBOLS, resolutionImpact.constSymbolNames);
objectEncoder.setConstants(
Key.CONSTANTS, resolutionImpact.constantLiterals);
objectEncoder.setEnums(Key.FEATURES, resolutionImpact.features);
if (resolutionImpact.listLiterals.isNotEmpty) {
ListEncoder encoder = objectEncoder.createList(Key.LISTS);
for (ListLiteralUse use in resolutionImpact.listLiterals) {
ObjectEncoder useEncoder = encoder.createObject();
useEncoder.setType(Key.TYPE, use.type);
useEncoder.setBool(Key.IS_CONST, use.isConstant);
useEncoder.setBool(Key.IS_EMPTY, use.isEmpty);
}
}
if (resolutionImpact.mapLiterals.isNotEmpty) {
ListEncoder encoder = objectEncoder.createList(Key.MAPS);
for (MapLiteralUse use in resolutionImpact.mapLiterals) {
ObjectEncoder useEncoder = encoder.createObject();
useEncoder.setType(Key.TYPE, use.type);
useEncoder.setBool(Key.IS_CONST, use.isConstant);
useEncoder.setBool(Key.IS_EMPTY, use.isEmpty);
}
}
}
@override
void visitDynamicUse(DynamicUse dynamicUse) {
ObjectEncoder object = dynamicUses.createObject();
object.setEnum(Key.KIND, dynamicUse.selector.kind);
object.setInt(Key.ARGUMENTS,
dynamicUse.selector.callStructure.argumentCount);
object.setStrings(Key.NAMED_ARGUMENTS,
dynamicUse.selector.callStructure.namedArguments);
object.setString(Key.NAME,
dynamicUse.selector.memberName.text);
object.setBool(Key.IS_SETTER,
dynamicUse.selector.memberName.isSetter);
if (dynamicUse.selector.memberName.library != null) {
object.setElement(Key.LIBRARY,
dynamicUse.selector.memberName.library);
}
}
@override
void visitStaticUse(StaticUse staticUse) {
if (staticUse.element.isGenerativeConstructor &&
staticUse.element.enclosingClass.isUnnamedMixinApplication) {
// TODO(johnniwinther): Handle static use of forwarding constructors.
return;
}
ObjectEncoder object = staticUses.createObject();
object.setEnum(Key.KIND, staticUse.kind);
object.setElement(Key.ELEMENT, staticUse.element);
}
@override
void visitTypeUse(TypeUse typeUse) {
ObjectEncoder object = typeUses.createObject();
object.setEnum(Key.KIND, typeUse.kind);
object.setType(Key.TYPE, typeUse.type);
}
}
/// A deserialized [WorldImpact] object.
class DeserializedResolutionImpact extends WorldImpact
implements ResolutionImpact {
final Iterable<String> constSymbolNames;
final Iterable<ConstantExpression> constantLiterals;
final Iterable<DynamicUse> dynamicUses;
final EnumSet<Feature> _features;
final Iterable<ListLiteralUse> listLiterals;
final Iterable<MapLiteralUse> mapLiterals;
final Iterable<StaticUse> staticUses;
final Iterable<TypeUse> typeUses;
DeserializedResolutionImpact({
this.constSymbolNames,
this.constantLiterals,
this.dynamicUses,
EnumSet<Feature> features,
this.listLiterals,
this.mapLiterals,
this.staticUses,
this.typeUses})
: this._features = features;
Iterable<Feature> get features => _features.iterable(Feature.values);
}
class ImpactDeserializer {
/// Deserializes a [WorldImpact] from [objectDecoder].
static ResolutionImpact deserializeImpact(ObjectDecoder objectDecoder) {
ListDecoder staticUseDecoder = objectDecoder.getList(Key.STATIC_USES);
List<StaticUse> staticUses = <StaticUse>[];
for (int index = 0; index < staticUseDecoder.length; index++) {
ObjectDecoder object = staticUseDecoder.getObject(index);
StaticUseKind kind = object.getEnum(Key.KIND, StaticUseKind.values);
Element element = object.getElement(Key.ELEMENT);
staticUses.add(new StaticUse.internal(element, kind));
}
ListDecoder dynamicUseDecoder = objectDecoder.getList(Key.DYNAMIC_USES);
List<DynamicUse> dynamicUses = <DynamicUse>[];
for (int index = 0; index < dynamicUseDecoder.length; index++) {
ObjectDecoder object = dynamicUseDecoder.getObject(index);
SelectorKind kind = object.getEnum(Key.KIND, SelectorKind.values);
int argumentCount = object.getInt(Key.ARGUMENTS);
List<String> namedArguments =
object.getStrings(Key.NAMED_ARGUMENTS, isOptional: true);
String name = object.getString(Key.NAME);
bool isSetter = object.getBool(Key.IS_SETTER);
LibraryElement library = object.getElement(Key.LIBRARY, isOptional: true);
dynamicUses.add(
new DynamicUse(
new Selector(
kind,
new Name(name, library, isSetter: isSetter),
new CallStructure(argumentCount, namedArguments)),
null));
}
ListDecoder typeUseDecoder = objectDecoder.getList(Key.TYPE_USES);
List<TypeUse> typeUses = <TypeUse>[];
for (int index = 0; index < typeUseDecoder.length; index++) {
ObjectDecoder object = typeUseDecoder.getObject(index);
TypeUseKind kind = object.getEnum(Key.KIND, TypeUseKind.values);
DartType type = object.getType(Key.TYPE);
typeUses.add(new TypeUse.internal(type, kind));
}
List<String> constSymbolNames =
objectDecoder.getStrings(Key.SYMBOLS, isOptional: true);
List<ConstantExpression> constantLiterals =
objectDecoder.getConstants(Key.CONSTANTS, isOptional: true);
EnumSet<Feature> features =
objectDecoder.getEnums(Key.FEATURES, isOptional: true);
ListDecoder listLiteralDecoder =
objectDecoder.getList(Key.LISTS, isOptional: true);
List<ListLiteralUse> listLiterals = const <ListLiteralUse>[];
if (listLiteralDecoder != null) {
listLiterals = <ListLiteralUse>[];
for (int i = 0; i < listLiteralDecoder.length; i++) {
ObjectDecoder useDecoder = listLiteralDecoder.getObject(i);
DartType type = useDecoder.getType(Key.TYPE);
bool isConstant = useDecoder.getBool(Key.IS_CONST);
bool isEmpty = useDecoder.getBool(Key.IS_EMPTY);
listLiterals.add(new ListLiteralUse(
type, isConstant: isConstant, isEmpty: isEmpty));
}
}
ListDecoder mapLiteralDecoder =
objectDecoder.getList(Key.MAPS, isOptional: true);
List<MapLiteralUse> mapLiterals = const <MapLiteralUse>[];
if (mapLiteralDecoder != null) {
mapLiterals = <MapLiteralUse>[];
for (int i = 0; i < mapLiteralDecoder.length; i++) {
ObjectDecoder useDecoder = mapLiteralDecoder.getObject(i);
DartType type = useDecoder.getType(Key.TYPE);
bool isConstant = useDecoder.getBool(Key.IS_CONST);
bool isEmpty = useDecoder.getBool(Key.IS_EMPTY);
mapLiterals.add(new MapLiteralUse(
type, isConstant: isConstant, isEmpty: isEmpty));
}
}
return new DeserializedResolutionImpact(
constSymbolNames: constSymbolNames,
constantLiterals: constantLiterals,
dynamicUses: dynamicUses,
features: features,
listLiterals: listLiterals,
mapLiterals: mapLiterals,
staticUses: staticUses,
typeUses: typeUses);
}
}