| Index: editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java
|
| diff --git a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java
|
| index 9bface5b0b907613d78ad1bd48e592da0aca22fe..7b722bf696a1504a612a11055ed0cdbfead49729 100644
|
| --- a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java
|
| +++ b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java
|
| @@ -237,6 +237,24 @@ public class ElementResolver extends SimpleASTVisitor<Void> {
|
| }
|
|
|
| /**
|
| + * Checks if the given expression is the reference to the type, if it is then the
|
| + * {@link ClassElement} is returned, otherwise {@code null} is returned.
|
| + *
|
| + * @param expr the expression to evaluate
|
| + * @return the {@link ClassElement} if the given expression is the reference to the type, and
|
| + * {@code null} otherwise
|
| + */
|
| + public static ClassElementImpl getTypeReference(Expression expr) {
|
| + if (expr instanceof Identifier) {
|
| + Identifier identifier = (Identifier) expr;
|
| + if (identifier.getStaticElement() instanceof ClassElementImpl) {
|
| + return (ClassElementImpl) identifier.getStaticElement();
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| * @return {@code true} if the given identifier is the return type of a constructor declaration.
|
| */
|
| private static boolean isConstructorReturnType(SimpleIdentifier node) {
|
| @@ -937,8 +955,18 @@ public class ElementResolver extends SimpleASTVisitor<Void> {
|
| propagatedElement = null;
|
| } else {
|
| Type staticType = getStaticType(target);
|
| - staticElement = resolveInvokedElement(target, staticType, methodName);
|
| - propagatedElement = resolveInvokedElement(target, getPropagatedType(target), methodName);
|
| + //
|
| + // If this method invocation is of the form 'C.m' where 'C' is a class, then we don't call
|
| + // resolveInvokedElement(..) which walks up the class hierarchy, instead we just look for the
|
| + // member in the type only.
|
| + //
|
| + ClassElementImpl typeReference = getTypeReference(target);
|
| + if (typeReference != null) {
|
| + staticElement = propagatedElement = resolveElement(typeReference, methodName.getName());
|
| + } else {
|
| + staticElement = resolveInvokedElement(target, staticType, methodName);
|
| + propagatedElement = resolveInvokedElement(target, getPropagatedType(target), methodName);
|
| + }
|
| }
|
| staticElement = convertSetterToGetter(staticElement);
|
| propagatedElement = convertSetterToGetter(propagatedElement);
|
| @@ -2541,6 +2569,29 @@ public class ElementResolver extends SimpleASTVisitor<Void> {
|
| }
|
|
|
| /**
|
| + * Given an invocation of the form 'C.x()' where 'C' is a class, find and return the element 'x'
|
| + * in 'C'.
|
| + *
|
| + * @param classElement the class element
|
| + * @param memberName the member name
|
| + */
|
| + private Element resolveElement(ClassElementImpl classElement, String memberName) {
|
| + Element element = null;
|
| + String methodNameStr = memberName;
|
| + element = classElement.getMethod(methodNameStr);
|
| + if (element == null) {
|
| + element = classElement.getSetter(memberName);
|
| + if (element == null) {
|
| + element = classElement.getGetter(memberName);
|
| + }
|
| + }
|
| + if (element != null && element.isAccessibleIn(definingLibrary)) {
|
| + return element;
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the element being invoked.
|
| * If the returned element is a method, then the method will be invoked. If the returned element
|
| * is a getter, the getter will be invoked without arguments and the result of that invocation
|
| @@ -2645,7 +2696,23 @@ public class ElementResolver extends SimpleASTVisitor<Void> {
|
|
|
| private void resolvePropertyAccess(Expression target, SimpleIdentifier propertyName) {
|
| Type staticType = getStaticType(target);
|
| - ExecutableElement staticElement = resolveProperty(target, staticType, propertyName);
|
| + Type propagatedType = getPropagatedType(target);
|
| +
|
| + Element staticElement = null;
|
| + Element propagatedElement = null;
|
| +
|
| + //
|
| + // If this property access is of the form 'C.m' where 'C' is a class, then we don't call
|
| + // resolveProperty(..) which walks up the class hierarchy, instead we just look for the
|
| + // member in the type only.
|
| + //
|
| + ClassElementImpl typeReference = getTypeReference(target);
|
| + if (typeReference != null) {
|
| + staticElement = propagatedElement = resolveElement(typeReference, propertyName.getName());
|
| + } else {
|
| + staticElement = resolveProperty(target, staticType, propertyName);
|
| + propagatedElement = resolveProperty(target, propagatedType, propertyName);
|
| + }
|
|
|
| // May be part of annotation, record property element only if exists.
|
| // Error was already reported in validateAnnotationElement().
|
| @@ -2655,10 +2722,8 @@ public class ElementResolver extends SimpleASTVisitor<Void> {
|
| }
|
| return;
|
| }
|
| - propertyName.setStaticElement(staticElement);
|
|
|
| - Type propagatedType = getPropagatedType(target);
|
| - ExecutableElement propagatedElement = resolveProperty(target, propagatedType, propertyName);
|
| + propertyName.setStaticElement(staticElement);
|
| propertyName.setPropagatedElement(propagatedElement);
|
|
|
| boolean shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticElement)
|
| @@ -2849,7 +2914,7 @@ public class ElementResolver extends SimpleASTVisitor<Void> {
|
| * @param member the result of the look-up
|
| * @return {@code true} if we should report an error
|
| */
|
| - private boolean shouldReportMissingMember(Type type, ExecutableElement member) {
|
| + private boolean shouldReportMissingMember(Type type, Element member) {
|
| if (member != null || type == null || type.isDynamic() || type.isBottom()) {
|
| return false;
|
| }
|
|
|