Store CallStructure in StaticUse

- in preparation for tracking unused optional arguments of static methods

Change-Id: I8a9b1d0d9acd57256d383f880b9c602d91804486
Reviewed-on: https://dart-review.googlesource.com/29801
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Johnni Winther 2017-12-19 10:21:08 +00:00
parent 72443f777d
commit 66398a511a
4 changed files with 62 additions and 37 deletions

View file

@ -9,6 +9,7 @@ import '../constants/expressions.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/resolution_types.dart';
import '../universe/call_structure.dart';
import '../universe/feature.dart';
import '../universe/selector.dart';
import '../universe/use.dart';
@ -84,6 +85,10 @@ class ImpactSerializer implements WorldImpactVisitor {
if (staticUse.type != null) {
object.setType(Key.TYPE, staticUse.type);
}
if (staticUse.callStructure != null) {
serializeCallStructure(
staticUse.callStructure, object.createObject(Key.CALL_STRUCTURE));
}
}
@override
@ -148,7 +153,14 @@ class ImpactDeserializer {
Element usedElement =
deserializeElementReference(element, Key.ELEMENT, Key.NAME, object);
ResolutionDartType type = object.getType(Key.TYPE, isOptional: true);
staticUses.add(new StaticUse.internal(usedElement, kind, type));
ObjectDecoder callStructureObject =
object.getObject(Key.CALL_STRUCTURE, isOptional: true);
CallStructure callStructure;
if (callStructureObject != null) {
callStructure = deserializeCallStructure(callStructureObject);
}
staticUses.add(new StaticUse.internal(usedElement, kind,
type: type, callStructure: callStructure));
}
ListDecoder dynamicUseDecoder = objectDecoder.getList(Key.DYNAMIC_USES);

View file

@ -37,24 +37,33 @@ Name deserializeName(ObjectDecoder decoder) {
return new Name(name, library, isSetter: isSetter);
}
/// Serialize [callStructure] into [encoder].
void serializeCallStructure(
CallStructure callStructure, ObjectEncoder encoder) {
encoder.setInt(Key.ARGUMENTS, callStructure.argumentCount);
encoder.setStrings(Key.NAMED_ARGUMENTS, callStructure.namedArguments);
}
/// Serialize [selector] into [encoder].
void serializeSelector(Selector selector, ObjectEncoder encoder) {
encoder.setEnum(Key.KIND, selector.kind);
encoder.setInt(Key.ARGUMENTS, selector.callStructure.argumentCount);
encoder.setStrings(
Key.NAMED_ARGUMENTS, selector.callStructure.namedArguments);
serializeCallStructure(selector.callStructure, encoder);
serializeName(selector.memberName, encoder);
}
/// Deserialize a [CallStructure] from [decoder].
CallStructure deserializeCallStructure(ObjectDecoder decoder) {
int argumentCount = decoder.getInt(Key.ARGUMENTS);
List<String> namedArguments =
decoder.getStrings(Key.NAMED_ARGUMENTS, isOptional: true);
return new CallStructure(argumentCount, namedArguments);
}
/// Deserialize a [Selector] from [decoder].
Selector deserializeSelector(ObjectDecoder decoder) {
SelectorKind kind = decoder.getEnum(Key.KIND, SelectorKind.values);
int argumentCount = decoder.getInt(Key.ARGUMENTS);
List<String> namedArguments =
decoder.getStrings(Key.NAMED_ARGUMENTS, isOptional: true);
return new Selector(kind, deserializeName(decoder),
new CallStructure(argumentCount, namedArguments));
CallStructure callStructure = deserializeCallStructure(decoder);
return new Selector(kind, deserializeName(decoder), callStructure);
}
/// Serialize [sendStructure] into [encoder].

View file

@ -95,12 +95,12 @@ class StaticUse {
final StaticUseKind kind;
final int hashCode;
final DartType type;
final CallStructure callStructure;
StaticUse.internal(Entity element, StaticUseKind kind, [DartType type = null])
StaticUse.internal(Entity element, this.kind, {this.type, this.callStructure})
: this.element = element,
this.kind = kind,
this.type = type,
this.hashCode = Hashing.objectsHash(element, kind, type) {
this.hashCode =
Hashing.objectsHash(element, kind, type, callStructure) {
assert(
!(element is Element && !element.isDeclaration),
failedAt(element,
@ -111,14 +111,14 @@ class StaticUse {
/// [callStructure].
factory StaticUse.staticInvoke(
FunctionEntity element, CallStructure callStructure) {
// TODO(johnniwinther): Use the [callStructure].
assert(
element.isStatic || element.isTopLevel,
failedAt(
element,
"Static invoke element $element must be a top-level "
"or static method."));
return new StaticUse.internal(element, StaticUseKind.GENERAL);
return new StaticUse.internal(element, StaticUseKind.GENERAL,
callStructure: callStructure);
}
/// Closurization of a static or top-level function [element].
@ -179,12 +179,12 @@ class StaticUse {
/// Invocation of a super method [element] with the given [callStructure].
factory StaticUse.superInvoke(
FunctionEntity element, CallStructure callStructure) {
// TODO(johnniwinther): Use the [callStructure].
assert(
element.isInstanceMember,
failedAt(element,
"Super invoke element $element must be an instance method."));
return new StaticUse.internal(element, StaticUseKind.GENERAL);
return new StaticUse.internal(element, StaticUseKind.GENERAL,
callStructure: callStructure);
}
/// Read access of a super field or getter [element].
@ -235,35 +235,35 @@ class StaticUse {
/// constructor call with the given [callStructure].
factory StaticUse.superConstructorInvoke(
ConstructorEntity element, CallStructure callStructure) {
// TODO(johnniwinther): Use the [callStructure].
assert(
element.isGenerativeConstructor,
failedAt(
element,
"Constructor invoke element $element must be a "
"generative constructor."));
return new StaticUse.internal(element, StaticUseKind.GENERAL);
return new StaticUse.internal(element, StaticUseKind.GENERAL,
callStructure: callStructure);
}
/// Invocation of a constructor (body) [element] through a this or super
/// constructor call with the given [callStructure].
factory StaticUse.constructorBodyInvoke(
ConstructorBodyEntity element, CallStructure callStructure) {
// TODO(johnniwinther): Use the [callStructure].
return new StaticUse.internal(element, StaticUseKind.GENERAL);
return new StaticUse.internal(element, StaticUseKind.GENERAL,
callStructure: callStructure);
}
/// Direct invocation of a method [element] with the given [callStructure].
factory StaticUse.directInvoke(
FunctionEntity element, CallStructure callStructure) {
// TODO(johnniwinther): Use the [callStructure].
assert(
element.isInstanceMember,
failedAt(element,
"Direct invoke element $element must be an instance member."));
assert(element.isFunction,
failedAt(element, "Direct invoke element $element must be a method."));
return new StaticUse.internal(element, StaticUseKind.DIRECT_INVOKE);
return new StaticUse.internal(element, StaticUseKind.DIRECT_INVOKE,
callStructure: callStructure);
}
/// Direct read access of a field or getter [element].
@ -297,8 +297,8 @@ class StaticUse {
element.isConstructor,
failedAt(element,
"Constructor invocation element $element must be a constructor."));
// TODO(johnniwinther): Use the [callStructure].
return new StaticUse.internal(element, StaticUseKind.GENERAL);
return new StaticUse.internal(element, StaticUseKind.GENERAL,
callStructure: callStructure);
}
/// Constructor invocation of [element] with the given [callStructure] on
@ -313,9 +313,8 @@ class StaticUse {
element,
"Typed constructor invocation element $element "
"must be a constructor."));
// TODO(johnniwinther): Use the [callStructure].
return new StaticUse.internal(
element, StaticUseKind.CONSTRUCTOR_INVOKE, type);
return new StaticUse.internal(element, StaticUseKind.CONSTRUCTOR_INVOKE,
type: type, callStructure: callStructure);
}
/// Constant constructor invocation of [element] with the given
@ -330,9 +329,9 @@ class StaticUse {
element,
"Const constructor invocation element $element "
"must be a constructor."));
// TODO(johnniwinther): Use the [callStructure].
return new StaticUse.internal(
element, StaticUseKind.CONST_CONSTRUCTOR_INVOKE, type);
element, StaticUseKind.CONST_CONSTRUCTOR_INVOKE,
type: type, callStructure: callStructure);
}
/// Constructor redirection to [element] on [type].
@ -344,7 +343,8 @@ class StaticUse {
element.isConstructor,
failedAt(element,
"Constructor redirection element $element must be a constructor."));
return new StaticUse.internal(element, StaticUseKind.REDIRECTION, type);
return new StaticUse.internal(element, StaticUseKind.REDIRECTION,
type: type);
}
/// Initialization of an instance field [element].
@ -407,17 +407,20 @@ class StaticUse {
/// Inlining of [element].
factory StaticUse.inlining(
FunctionEntity element, InterfaceType instanceType) {
return new StaticUse.internal(
element, StaticUseKind.INLINING, instanceType);
return new StaticUse.internal(element, StaticUseKind.INLINING,
type: instanceType);
}
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! StaticUse) return false;
return element == other.element && kind == other.kind && type == other.type;
return element == other.element &&
kind == other.kind &&
type == other.type &&
callStructure == other.callStructure;
}
String toString() => 'StaticUse($element,$kind,$type)';
String toString() => 'StaticUse($element,$kind,$type,$callStructure)';
}
enum TypeUseKind {

View file

@ -43,8 +43,9 @@ class Hashing {
}
/// Mix the bits of `.hashCode` all non-null objects.
static int objectsHash(Object obj1, [Object obj2, Object obj3]) {
static int objectsHash(Object obj1, [Object obj2, Object obj3, Object obj4]) {
int hash = 0;
if (obj4 != null) hash = objectHash(obj4, hash);
if (obj3 != null) hash = objectHash(obj3, hash);
if (obj2 != null) hash = objectHash(obj2, hash);
return objectHash(obj1, hash);