Index: compiler/java/com/google/dart/compiler/resolver/Elements.java |
diff --git a/compiler/java/com/google/dart/compiler/resolver/Elements.java b/compiler/java/com/google/dart/compiler/resolver/Elements.java |
index e47c7ee9994710bf180fe5863f7c30d5cf82ea3e..71f87d3dfaaac873603696a54d4d1aceef95179b 100644 |
--- a/compiler/java/com/google/dart/compiler/resolver/Elements.java |
+++ b/compiler/java/com/google/dart/compiler/resolver/Elements.java |
@@ -6,27 +6,37 @@ package com.google.dart.compiler.resolver; |
import com.google.common.annotations.VisibleForTesting; |
import com.google.common.collect.Lists; |
+import com.google.dart.compiler.Source; |
import com.google.dart.compiler.ast.DartClass; |
+import com.google.dart.compiler.ast.DartClassMember; |
+import com.google.dart.compiler.ast.DartDeclaration; |
import com.google.dart.compiler.ast.DartExpression; |
import com.google.dart.compiler.ast.DartField; |
+import com.google.dart.compiler.ast.DartFunction; |
import com.google.dart.compiler.ast.DartFunctionExpression; |
import com.google.dart.compiler.ast.DartFunctionTypeAlias; |
import com.google.dart.compiler.ast.DartIdentifier; |
import com.google.dart.compiler.ast.DartLabel; |
import com.google.dart.compiler.ast.DartMethodDefinition; |
+import com.google.dart.compiler.ast.DartNativeBlock; |
import com.google.dart.compiler.ast.DartNode; |
import com.google.dart.compiler.ast.DartParameter; |
import com.google.dart.compiler.ast.DartParameterizedNode; |
import com.google.dart.compiler.ast.DartPropertyAccess; |
import com.google.dart.compiler.ast.DartSuperExpression; |
import com.google.dart.compiler.ast.DartTypeParameter; |
+import com.google.dart.compiler.ast.DartUnit; |
import com.google.dart.compiler.ast.DartVariable; |
import com.google.dart.compiler.ast.LibraryUnit; |
import com.google.dart.compiler.ast.Modifiers; |
+import com.google.dart.compiler.common.SourceInfo; |
import com.google.dart.compiler.type.InterfaceType; |
import com.google.dart.compiler.type.Type; |
import com.google.dart.compiler.type.TypeVariable; |
+import com.google.dart.compiler.util.Paths; |
+import java.io.File; |
+import java.text.MessageFormat; |
import java.util.Arrays; |
import java.util.List; |
@@ -208,6 +218,87 @@ public class Elements { |
return FunctionAliasElementImplementation.fromNode(node, library); |
} |
+ /** |
+ * @return <code>true</code> if given {@link Element} represents {@link VariableElement} for |
+ * parameter in {@link DartMethodDefinition}. |
+ */ |
+ public static boolean isConstructorParameter(Element element) { |
+ if (element instanceof VariableElement) { |
+ DartNode parentNode = element.getNode().getParent(); |
+ if (parentNode instanceof DartFunction |
+ && parentNode.getParent() instanceof DartMethodDefinition) { |
+ DartMethodDefinition parentMethod = (DartMethodDefinition) parentNode.getParent(); |
+ if (parentMethod.getSymbol().isConstructor()) { |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ /** |
+ * @return <code>true</code> if given {@link Element} represents {@link VariableElement} for |
+ * parameter in identically named setter {@link DartMethodDefinition}. |
+ */ |
+ public static boolean isParameterOfSameNameSetter(Element element) { |
+ if (element instanceof VariableElement) { |
+ DartNode parentNode = element.getNode().getParent(); |
+ if (parentNode instanceof DartFunction |
+ && parentNode.getParent() instanceof DartMethodDefinition) { |
+ DartMethodDefinition parentMethod = (DartMethodDefinition) parentNode.getParent(); |
+ if (parentMethod.getSymbol().getName().equals(element.getName())) { |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ /** |
+ * @return <code>true</code> if given {@link Element} represents {@link VariableElement} for |
+ * parameter in {@link DartMethodDefinition} without body, or with {@link DartNativeBlock} |
+ * as body. |
+ */ |
+ public static boolean isParameterOfMethodWithoutBody(Element element) { |
+ if (element instanceof VariableElementImplementation) { |
+ DartNode parentNode = element.getNode().getParent(); |
+ if (parentNode instanceof DartFunction) { |
+ DartFunction parentFunction = (DartFunction) parentNode; |
+ if (parentFunction.getBody() == null || parentFunction.getBody() instanceof DartNativeBlock) { |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ /** |
+ * @return <code>true</code> if {@link DartNode} of given {@link Element} if part of static |
+ * {@link DartClassMember} or part of top level declaration. |
+ */ |
+ public static boolean isStaticContext(Element element) { |
+ DartNode node = element.getNode(); |
+ while (node != null) { |
+ // Found DartUnit, so top level element was given. |
+ if (node instanceof DartUnit) { |
+ return true; |
+ } |
+ // Found DartClass, so not top level element, can not be static. |
+ if (node instanceof DartClass) { |
+ break; |
+ } |
+ // May be static method or field. |
+ if (node instanceof DartClassMember) { |
+ if (((DartClassMember<?>) node).getModifiers().isStatic()) { |
+ return true; |
+ } |
+ } |
+ // Go to parent. |
+ node = node.getParent(); |
+ } |
+ return false; |
+ } |
+ |
public static boolean isNonFactoryConstructor(Element method) { |
return !method.getModifiers().isFactory() |
&& ElementKind.of(method).equals(ElementKind.CONSTRUCTOR); |
@@ -324,4 +415,84 @@ public class Elements { |
} |
return names; |
} |
+ |
+ /** |
+ * @return the {@link DartNode} which is name of underlying {@link Element}, or just its |
+ * {@link DartNode} if name can not be found. |
+ */ |
+ @SuppressWarnings("unchecked") |
+ public static DartNode getNameNode(Element element) { |
+ DartNode node = element.getNode(); |
+ if (node instanceof DartDeclaration) { |
+ node = ((DartDeclaration<DartExpression>) node).getName(); |
+ } |
+ if (node instanceof DartFunctionExpression) { |
+ node = ((DartFunctionExpression) node).getName(); |
+ } |
+ return node; |
+ } |
+ |
+ /** |
+ * @return the {@link String} which contains user-readable description of "target" {@link Element} |
+ * location relative to "source". |
+ */ |
+ public static String getRelativeElementLocation(Element source, Element target) { |
+ // Prepare "target" SourceInfo. |
+ SourceInfo targetInfo; |
+ { |
+ DartNode targetNode = getNameNode(target); |
+ if (targetNode == null) { |
+ return "unknown"; |
+ } |
+ targetInfo = targetNode.getSourceInfo(); |
+ } |
+ // Prepare relative (short) path to the target unit from source unit. |
+ String relativePath; |
+ { |
+ SourceInfo sourceInfo = source.getNode().getSourceInfo(); |
+ String sourceName = getSourceName(sourceInfo); |
+ String targetName = getSourceName(targetInfo); |
+ relativePath = Paths.relativePathFor(new File(sourceName), new File(targetName)); |
+ } |
+ // Prepare (may be empty) target class name. |
+ String targetClassName; |
+ { |
+ ClassElement targetClass = getEnclosingClassElement(target); |
+ targetClassName = targetClass != null ? targetClass.getName() : ""; |
+ } |
+ // Format location string. |
+ return MessageFormat.format( |
+ "{0}:{1}:{2}:{3}", |
+ relativePath, |
+ targetClassName, |
+ targetInfo.getSourceLine(), |
+ targetInfo.getSourceColumn()); |
+ } |
+ |
+ /** |
+ * @return the result of {@link Source#getName()} safely, even if {@link Source} is |
+ * <code>null</code>. |
+ */ |
+ private static String getSourceName(SourceInfo sourceInfo) { |
+ Source source = sourceInfo.getSource(); |
+ if (source != null) { |
+ return source.getName(); |
+ } |
+ return ""; |
+ } |
+ |
+ /** |
+ * @return the enclosing {@link ClassElement} (may be same if already given {@link ClassElement}), |
+ * may be <code>null</code> if top level element. |
+ */ |
+ public static ClassElement getEnclosingClassElement(Element element) { |
+ DartNode node = element.getNode(); |
+ while (node != null) { |
+ if (node instanceof DartClass) { |
+ return ((DartClass) node).getSymbol(); |
+ } |
+ node = node.getParent(); |
+ } |
+ return null; |
+ } |
} |