| Index: pkg/compiler/lib/src/resolution/send_resolver.dart
|
| diff --git a/pkg/compiler/lib/src/resolution/send_resolver.dart b/pkg/compiler/lib/src/resolution/send_resolver.dart
|
| index 22cf9bc04bea2cf172d8ac20c1e78ba1bf97325c..77e35827ceb1f87252eb1e1ca789da3b51221940 100644
|
| --- a/pkg/compiler/lib/src/resolution/send_resolver.dart
|
| +++ b/pkg/compiler/lib/src/resolution/send_resolver.dart
|
| @@ -28,10 +28,82 @@ abstract class SendResolverMixin {
|
|
|
| internalError(Spannable spannable, String message);
|
|
|
| - AccessSemantics handleStaticallyResolvedAccess(Send node,
|
| - Element element,
|
| - Element getter) {
|
| + AccessSemantics handleCompoundErroneousSetterAccess(
|
| + Send node,
|
| + Element setter,
|
| + Element getter) {
|
| + assert(invariant(node, Elements.isUnresolved(setter),
|
| + message: "Unexpected erreneous compound setter: $setter."));
|
| + if (getter.isStatic) {
|
| + if (getter.isGetter) {
|
| + return new CompoundAccessSemantics(
|
| + CompoundAccessKind.UNRESOLVED_STATIC_SETTER, getter, setter);
|
| + } else if (getter.isField) {
|
| + // TODO(johnniwinther): Handle const field separately.
|
| + assert(invariant(node, getter.isFinal || getter.isConst,
|
| + message: "Field expected to be final or const."));
|
| + return new StaticAccess.finalStaticField(getter);
|
| + } else if (getter.isFunction) {
|
| + return new StaticAccess.staticMethod(getter);
|
| + } else {
|
| + return internalError(node,
|
| + "Unexpected erroneous static compound: getter=$getter");
|
| + }
|
| + } else if (getter.isTopLevel) {
|
| + if (getter.isGetter) {
|
| + return new CompoundAccessSemantics(
|
| + CompoundAccessKind.UNRESOLVED_TOPLEVEL_SETTER, getter, setter);
|
| + } else if (getter.isField) {
|
| + // TODO(johnniwinther): Handle const field separately.
|
| + assert(invariant(node, getter.isFinal || getter.isConst,
|
| + message: "Field expected to be final or const."));
|
| + return new StaticAccess.finalTopLevelField(getter);
|
| + } else if (getter.isFunction) {
|
| + return new StaticAccess.topLevelMethod(getter);
|
| + } else {
|
| + return internalError(node,
|
| + "Unexpected erroneous top level compound: getter=$getter");
|
| + }
|
| + } else if (getter.isParameter) {
|
| + assert(invariant(node, getter.isFinal,
|
| + message: "Parameter expected to be final."));
|
| + return new StaticAccess.finalParameter(getter);
|
| + } else if (getter.isLocal) {
|
| + if (getter.isVariable) {
|
| + // TODO(johnniwinther): Handle const variable separately.
|
| + assert(invariant(node, getter.isFinal || getter.isConst,
|
| + message: "Variable expected to be final or const."));
|
| + return new StaticAccess.finalLocalVariable(getter);
|
| + } else if (getter.isFunction) {
|
| + return new StaticAccess.localFunction(getter);
|
| + } else {
|
| + return internalError(node,
|
| + "Unexpected erroneous local compound: getter=$getter");
|
| + }
|
| + } else if (getter.isErroneous) {
|
| + return new StaticAccess.unresolved(getter);
|
| + } else {
|
| + return internalError(node,
|
| + "Unexpected erroneous compound: getter=$getter");
|
| + }
|
| + }
|
| +
|
| + AccessSemantics handleStaticallyResolvedAccess(
|
| + Send node,
|
| + Element element,
|
| + Element getter,
|
| + {bool isCompound}) {
|
| + if (element == null) {
|
| + assert(invariant(node, isCompound, message:
|
| + "Non-compound static access without element."));
|
| + assert(invariant(node, getter != null, message:
|
| + "Compound static access without element."));
|
| + return handleCompoundErroneousSetterAccess(node, element, getter);
|
| + }
|
| if (element.isErroneous) {
|
| + if (isCompound) {
|
| + return handleCompoundErroneousSetterAccess(node, element, getter);
|
| + }
|
| return new StaticAccess.unresolved(element);
|
| } else if (element.isParameter) {
|
| return new StaticAccess.parameter(element);
|
| @@ -43,13 +115,32 @@ abstract class SendResolverMixin {
|
| }
|
| } else if (element.isStatic) {
|
| if (element.isField) {
|
| + if (element.isFinal || element.isConst) {
|
| + // TODO(johnniwinther): Handle const field separately.
|
| + return new StaticAccess.finalStaticField(element);
|
| + }
|
| return new StaticAccess.staticField(element);
|
| } else if (element.isGetter) {
|
| + if (isCompound) {
|
| + return new CompoundAccessSemantics(
|
| + CompoundAccessKind.UNRESOLVED_STATIC_SETTER, element, null);
|
| + }
|
| return new StaticAccess.staticGetter(element);
|
| } else if (element.isSetter) {
|
| if (getter != null) {
|
| CompoundAccessKind accessKind;
|
| - if (getter.isGetter) {
|
| + if (getter.isErroneous) {
|
| + accessKind = CompoundAccessKind.UNRESOLVED_STATIC_GETTER;
|
| + } else if (getter.isAbstractField) {
|
| + AbstractFieldElement abstractField = getter;
|
| + if (abstractField.getter == null) {
|
| + accessKind = CompoundAccessKind.UNRESOLVED_STATIC_GETTER;
|
| + } else {
|
| + // TODO(johnniwinther): This might be dead code.
|
| + getter = abstractField.getter;
|
| + accessKind = CompoundAccessKind.STATIC_GETTER_SETTER;
|
| + }
|
| + } else if (getter.isGetter) {
|
| accessKind = CompoundAccessKind.STATIC_GETTER_SETTER;
|
| } else {
|
| accessKind = CompoundAccessKind.STATIC_METHOD_SETTER;
|
| @@ -64,13 +155,28 @@ abstract class SendResolverMixin {
|
| }
|
| } else if (element.isTopLevel) {
|
| if (element.isField) {
|
| + if (element.isFinal || element.isConst) {
|
| + // TODO(johnniwinther): Handle const field separately.
|
| + return new StaticAccess.finalTopLevelField(element);
|
| + }
|
| return new StaticAccess.topLevelField(element);
|
| } else if (element.isGetter) {
|
| return new StaticAccess.topLevelGetter(element);
|
| } else if (element.isSetter) {
|
| if (getter != null) {
|
| CompoundAccessKind accessKind;
|
| - if (getter.isGetter) {
|
| + if (getter.isErroneous) {
|
| + accessKind = CompoundAccessKind.UNRESOLVED_TOPLEVEL_GETTER;
|
| + } else if (getter.isAbstractField) {
|
| + AbstractFieldElement abstractField = getter;
|
| + if (abstractField.getter == null) {
|
| + accessKind = CompoundAccessKind.UNRESOLVED_TOPLEVEL_GETTER;
|
| + } else {
|
| + // TODO(johnniwinther): This might be dead code.
|
| + getter = abstractField.getter;
|
| + accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER;
|
| + }
|
| + } else if (getter.isGetter) {
|
| accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER;
|
| } else {
|
| accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER;
|
| @@ -215,8 +321,7 @@ abstract class SendResolverMixin {
|
| }
|
| AccessSemantics semantics = computeAccessSemantics(
|
| node,
|
| - isGetOrSet: kind == SendStructureKind.GET ||
|
| - kind == SendStructureKind.SET,
|
| + isSet: kind == SendStructureKind.SET,
|
| isInvoke: kind == SendStructureKind.INVOKE,
|
| isCompound: kind == SendStructureKind.COMPOUND ||
|
| kind == SendStructureKind.COMPOUND_INDEX_SET ||
|
| @@ -314,7 +419,7 @@ abstract class SendResolverMixin {
|
| }
|
|
|
| AccessSemantics computeAccessSemantics(Send node,
|
| - {bool isGetOrSet: false,
|
| + {bool isSet: false,
|
| bool isInvoke: false,
|
| bool isCompound: false}) {
|
| Element element = elements[node];
|
| @@ -325,7 +430,7 @@ abstract class SendResolverMixin {
|
| // but not compile-time constants and should have their own
|
| // [DeferredConstantExpression] class.
|
| ConstantExpression constant = elements.getConstant(
|
| - isInvoke ? node.selector : node);
|
| + isInvoke || isSet || isCompound ? node.selector : node);
|
| switch (dartType.kind) {
|
| case TypeKind.INTERFACE:
|
| return new ConstantAccess.classTypeLiteral(constant);
|
| @@ -344,8 +449,18 @@ abstract class SendResolverMixin {
|
| if (Elements.isUnresolved(getter)) {
|
| // TODO(johnniwinther): Ensure that [getter] is not null. This
|
| // happens in the case of missing super getter.
|
| - return new CompoundAccessSemantics(
|
| - CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element);
|
| + return new StaticAccess.unresolvedSuper(element);
|
| + } else if (getter.isField) {
|
| + assert(invariant(node, getter.isFinal,
|
| + message: "Super field expected to be final."));
|
| + return new StaticAccess.superFinalField(getter);
|
| + } else if (getter.isFunction) {
|
| + if (node.isIndex) {
|
| + return new CompoundAccessSemantics(
|
| + CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element);
|
| + } else {
|
| + return new StaticAccess.superMethod(getter);
|
| + }
|
| } else {
|
| return new CompoundAccessSemantics(
|
| CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element);
|
| @@ -370,6 +485,8 @@ abstract class SendResolverMixin {
|
| "Unsupported super call: $node : $element/$getter.");
|
| }
|
| return new CompoundAccessSemantics(accessKind, getter, element);
|
| + } else if (element.isFinal) {
|
| + return new StaticAccess.superFinalField(element);
|
| }
|
| return new StaticAccess.superField(element);
|
| } else if (element.isGetter) {
|
| @@ -405,25 +522,26 @@ abstract class SendResolverMixin {
|
| } else if (Elements.isErroneous(element)) {
|
| return new StaticAccess.unresolved(element);
|
| } else {
|
| - return handleStaticallyResolvedAccess(node, element, getter);
|
| + return handleStaticallyResolvedAccess(
|
| + node, element, getter, isCompound: isCompound);
|
| }
|
| } else {
|
| - if (Elements.isErroneous(element)) {
|
| - return new StaticAccess.unresolved(element);
|
| - } else if (isCompound && Elements.isErroneous(getter)) {
|
| - return new StaticAccess.unresolved(getter);
|
| - } else if (element == null || element.isInstanceMember) {
|
| + bool isDynamicAccess(Element e) => e == null || e.isInstanceMember;
|
| +
|
| + if (isDynamicAccess(element) &&
|
| + (!isCompound || isDynamicAccess(getter))) {
|
| if (node.receiver == null || node.receiver.isThis()) {
|
| return new AccessSemantics.thisProperty();
|
| } else {
|
| return new DynamicAccess.dynamicProperty(node.receiver);
|
| }
|
| - } else if (element.impliesType) {
|
| + } else if (element != null && element.impliesType) {
|
| // TODO(johnniwinther): Provide an [ErroneousElement].
|
| // This happens for code like `C.this`.
|
| return new StaticAccess.unresolved(null);
|
| } else {
|
| - return handleStaticallyResolvedAccess(node, element, getter);
|
| + return handleStaticallyResolvedAccess(
|
| + node, element, getter, isCompound: isCompound);
|
| }
|
| }
|
| }
|
|
|