Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(413)

Unified Diff: dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java

Issue 59073003: Version 0.8.10.4 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java
===================================================================
--- dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java (revision 29808)
+++ dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java (working copy)
@@ -237,6 +237,24 @@
}
/**
+ * 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 @@
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);
@@ -1169,7 +1197,7 @@
// Validate annotation element.
if (node.getParent() instanceof Annotation) {
Annotation annotation = (Annotation) node.getParent();
- resolveAnnotationElement(annotation, element, null);
+ resolveAnnotationElement(annotation);
return null;
}
return null;
@@ -1178,7 +1206,7 @@
// May be annotation, resolve invocation of "const" constructor.
if (node.getParent() instanceof Annotation) {
Annotation annotation = (Annotation) node.getParent();
- resolveAnnotationElement(annotation, prefixElement, identifier);
+ resolveAnnotationElement(annotation);
}
//
@@ -1338,7 +1366,7 @@
//
if (node.getParent() instanceof Annotation) {
Annotation annotation = (Annotation) node.getParent();
- resolveAnnotationElement(annotation, element, null);
+ resolveAnnotationElement(annotation);
}
return null;
}
@@ -2295,64 +2323,121 @@
}
/**
- * Validates that the given {@link Element} is the constant variable; or resolves it as a
- * constructor invocation.
+ * Continues resolution of the given {@link Annotation}.
*
* @param annotation the {@link Annotation} to resolve
- * @param element the current known {@link Element} of the annotation, or {@link ClassElement}
- * @param nameNode the name of the invoked constructor, may be {@code null} if unnamed constructor
- * or not a constructor invocation
*/
- private void resolveAnnotationElement(Annotation annotation, Element element,
- SimpleIdentifier nameNode) {
- // constant variable
- if (element instanceof PropertyAccessorElement) {
- PropertyAccessorElement accessorElement = (PropertyAccessorElement) element;
- // accessor should be synthetic
- if (!accessorElement.isSynthetic()) {
- resolver.reportError(CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+ private void resolveAnnotationElement(Annotation annotation) {
+ SimpleIdentifier nameNode1;
+ SimpleIdentifier nameNode2;
+ {
+ Identifier annName = annotation.getName();
+ if (annName instanceof PrefixedIdentifier) {
+ PrefixedIdentifier prefixed = (PrefixedIdentifier) annName;
+ nameNode1 = prefixed.getPrefix();
+ nameNode2 = prefixed.getIdentifier();
+ } else {
+ nameNode1 = (SimpleIdentifier) annName;
+ nameNode2 = null;
+ }
+ }
+ SimpleIdentifier nameNode3 = annotation.getConstructorName();
+ ConstructorElement constructor = null;
+ //
+ // CONST or Class(args)
+ //
+ if (nameNode1 != null && nameNode2 == null && nameNode3 == null) {
+ Element element1 = nameNode1.getStaticElement();
+ // CONST
+ if (element1 instanceof PropertyAccessorElement) {
+ resolveAnnotationElementGetter(annotation, (PropertyAccessorElement) element1);
return;
}
- // variable should be constant
- VariableElement variableElement = accessorElement.getVariable();
- if (!variableElement.isConst()) {
- resolver.reportError(CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+ // Class(args)
+ if (element1 instanceof ClassElement) {
+ ClassElement classElement = (ClassElement) element1;
+ constructor = new InterfaceTypeImpl(classElement).lookUpConstructor(null, definingLibrary);
}
- // OK
- return;
}
- // const constructor invocation
- if (element instanceof ClassElement) {
- // prepare constructor name
- if (nameNode == null) {
- nameNode = annotation.getConstructorName();
+ //
+ // prefix.CONST or prefix.Class() or Class.CONST or Class.constructor(args)
+ //
+ if (nameNode1 != null && nameNode2 != null && nameNode3 == null) {
+ Element element1 = nameNode1.getStaticElement();
+ Element element2 = nameNode2.getStaticElement();
+ // Class.CONST - not resolved yet
+ if (element1 instanceof ClassElement) {
+ ClassElement classElement = (ClassElement) element1;
+ element2 = classElement.lookUpGetter(nameNode2.getName(), definingLibrary);
}
- String name = nameNode != null ? nameNode.getName() : null;
- // look up ConstructorElement
- ConstructorElement constructor;
- {
- InterfaceType interfaceType = new InterfaceTypeImpl((ClassElement) element);
- constructor = interfaceType.lookUpConstructor(name, definingLibrary);
- }
- // not a constructor
- if (constructor == null) {
- resolver.reportError(CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+ // prefix.CONST or Class.CONST
+ if (element2 instanceof PropertyAccessorElement) {
+ nameNode2.setStaticElement(element2);
+ annotation.setElement(element2);
+ resolveAnnotationElementGetter(annotation, (PropertyAccessorElement) element2);
return;
}
- // record element
- annotation.setElement(constructor);
- if (nameNode != null) {
- nameNode.setStaticElement(constructor);
+ // prefix.Class()
+ if (element2 instanceof ClassElement) {
+ ClassElement classElement = (ClassElement) element2;
+ constructor = classElement.getUnnamedConstructor();
}
- // resolve arguments
- resolveAnnotationConstructorInvocationArguments(annotation, constructor);
- // OK
+ // Class.constructor(args)
+ if (element1 instanceof ClassElement) {
+ ClassElement classElement = (ClassElement) element1;
+ constructor = new InterfaceTypeImpl(classElement).lookUpConstructor(
+ nameNode2.getName(),
+ definingLibrary);
+ nameNode2.setStaticElement(constructor);
+ }
+ }
+ //
+ // prefix.Class.CONST or prefix.Class.constructor(args)
+ //
+ if (nameNode1 != null && nameNode2 != null && nameNode3 != null) {
+ Element element2 = nameNode2.getStaticElement();
+ // element2 should be ClassElement
+ if (element2 instanceof ClassElement) {
+ ClassElement classElement = (ClassElement) element2;
+ String name3 = nameNode3.getName();
+ // prefix.Class.CONST
+ PropertyAccessorElement getter = classElement.lookUpGetter(name3, definingLibrary);
+ if (getter != null) {
+ nameNode3.setStaticElement(getter);
+ annotation.setElement(element2);
+ resolveAnnotationElementGetter(annotation, getter);
+ return;
+ }
+ // prefix.Class.constructor(args)
+ constructor = new InterfaceTypeImpl(classElement).lookUpConstructor(name3, definingLibrary);
+ nameNode3.setStaticElement(constructor);
+ }
+ }
+ // we need constructor
+ if (constructor == null) {
+ resolver.reportError(CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
return;
}
- // something unknown
- if (element != null) {
+ // record element
+ annotation.setElement(constructor);
+ // resolve arguments
+ resolveAnnotationConstructorInvocationArguments(annotation, constructor);
+ }
+
+ private void resolveAnnotationElementGetter(Annotation annotation,
+ PropertyAccessorElement accessorElement) {
+ // accessor should be synthetic
+ if (!accessorElement.isSynthetic()) {
resolver.reportError(CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+ return;
}
+ // variable should be constant
+ VariableElement variableElement = accessorElement.getVariable();
+ if (!variableElement.isConst()) {
+ resolver.reportError(CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+ }
+ // OK
+ return;
}
/**
@@ -2484,6 +2569,29 @@
}
/**
+ * 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
@@ -2588,8 +2696,24 @@
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().
if (target.getParent().getParent() instanceof Annotation) {
@@ -2598,10 +2722,8 @@
}
return;
}
+
propertyName.setStaticElement(staticElement);
-
- Type propagatedType = getPropagatedType(target);
- ExecutableElement propagatedElement = resolveProperty(target, propagatedType, propertyName);
propertyName.setPropagatedElement(propagatedElement);
boolean shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticElement)
@@ -2792,7 +2914,7 @@
* @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;
}

Powered by Google App Engine
This is Rietveld 408576698