| /* |
| * Copyright (c) 2012, the Dart project authors. |
| * |
| * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.dart.compiler.ast; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Lists; |
| import com.google.dart.compiler.common.SourceInfo; |
| import com.google.dart.compiler.parser.Token; |
| import com.google.dart.compiler.resolver.Element; |
| import com.google.dart.compiler.resolver.ElementKind; |
| import com.google.dart.compiler.resolver.FieldElement; |
| import com.google.dart.compiler.resolver.MethodElement; |
| import com.google.dart.compiler.resolver.NodeElement; |
| import com.google.dart.compiler.resolver.VariableElement; |
| import com.google.dart.compiler.type.InterfaceType; |
| import com.google.dart.compiler.type.Type; |
| import com.google.dart.compiler.type.TypeKind; |
| |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * Defines utility methods that operate on nodes in a Dart AST structure (instances of |
| * {@link DartNode} and its subclasses). |
| */ |
| public class ASTNodes { |
| |
| /** |
| * @return <code>true</code> if given {@link DartNode} is part of static method or top-level |
| * function. |
| */ |
| public static boolean isStaticContext(DartNode node ) { |
| while (node != null) { |
| DartNode parent = node.getParent(); |
| if (node instanceof DartMethodDefinition) { |
| DartMethodDefinition method = (DartMethodDefinition) node; |
| if (method.getModifiers().isStatic()) { |
| return true; |
| } |
| return parent instanceof DartUnit; |
| } |
| if (node instanceof DartField) { |
| DartField field = (DartField) node; |
| if (field.getModifiers().isStatic() || field.getModifiers().isConstant()) { |
| return true; |
| } |
| return parent != null && parent.getParent() instanceof DartUnit; |
| } |
| node = parent; |
| } |
| return false; |
| } |
| |
| /** |
| * @return <code>true</code> if given {@link DartNode} is part of factory method. |
| */ |
| public static boolean isFactoryContext(DartNode node) { |
| while (node != null) { |
| if (node instanceof DartMethodDefinition) { |
| DartMethodDefinition method = (DartMethodDefinition) node; |
| return method.getModifiers().isFactory(); |
| } |
| node = node.getParent(); |
| } |
| return false; |
| } |
| |
| /** |
| * @return <code>true</code> if given {@link DartNode} is part of static method or factory. |
| */ |
| public static boolean isStaticOrFactoryContext(DartNode node) { |
| return isFactoryContext(node) || isStaticContext(node); |
| } |
| |
| /** |
| * Returns complete field access node for given field name. |
| * |
| * <pre> |
| * node = 1; => node |
| * obj.node = 1; => obj.node |
| * </pre> |
| * |
| * Note, that we don't check if given {@link DartNode} is actually field name. |
| */ |
| public static DartNode getPropertyAccessNode(DartNode node) { |
| DartNode parent = node.getParent(); |
| if (parent instanceof DartPropertyAccess && ((DartPropertyAccess) parent).getName() == node) { |
| return parent; |
| } |
| return node; |
| } |
| |
| public static List<DartNode> findDeepestCommonPath(List<DartNode> nodes) { |
| List<List<DartNode>> parents = Lists.newArrayList(); |
| for (DartNode node : nodes) { |
| parents.add(getParents(node)); |
| } |
| return getLongestListPrefix(parents); |
| } |
| |
| /** |
| * @return the {@link DartNode} of given {@link Class} which is given {@link DartNode} itself, or |
| * one of its parents. |
| */ |
| @SuppressWarnings("unchecked") |
| public static <E extends DartNode> E getAncestor(DartNode node, Class<E> enclosingClass) { |
| while (node != null && !enclosingClass.isInstance(node)) { |
| node = node.getParent(); |
| }; |
| return (E) node; |
| } |
| |
| /** |
| * Get the element associated with the given AST node. |
| * |
| * @param node the target node |
| * @param includeDeclarations <code>true</code> if elements should be returned for declaration |
| * sites as well as for reference sites |
| * @return the associated element (or <code>null</code> if none can be found) |
| */ |
| public static Element getElement(DartNode node, boolean includeDeclarations) { |
| Element targetElement = node.getElement(); |
| DartNode parent = node.getParent(); |
| // name of named parameter in invocation |
| if (node instanceof DartIdentifier && node.getParent() instanceof DartNamedExpression) { |
| DartNamedExpression namedExpression = (DartNamedExpression) node.getParent(); |
| if (namedExpression.getName() == node) { |
| Object parameterId = ((DartIdentifier) node).getInvocationParameterId(); |
| if (parameterId instanceof VariableElement) { |
| targetElement = (VariableElement) parameterId; |
| } |
| } |
| } |
| // target of "new X()" or "new X.a()" is not just a type, it is a constructor |
| if (parent instanceof DartTypeNode || parent instanceof DartPropertyAccess) { |
| DartNode grandparent = parent.getParent(); |
| if (grandparent instanceof DartNewExpression) { |
| targetElement = ((DartNewExpression) grandparent).getElement(); |
| } |
| } else if (parent instanceof DartRedirectConstructorInvocation |
| || parent instanceof DartSuperConstructorInvocation) { |
| targetElement = parent.getElement(); |
| } |
| return targetElement; |
| } |
| |
| /** |
| * Return the class definition enclosing the given node, or <code>null</code> if the node is not a |
| * child of a class definition. |
| * |
| * @param node the node enclosed in the class definition to be returned |
| * @return the class definition enclosing the given node |
| */ |
| public static DartClass getEnclosingDartClass(DartNode node) { |
| return getEnclosingNodeOfType(DartClass.class, node); |
| } |
| |
| /** |
| * Return the first node of the given class that encloses the given node, or <code>null</code> if |
| * the node is not a child of a node of the given class. The node itself will <b>not</b> be |
| * returned, even if it is an instance of the given class. |
| * |
| * @param enclosingNodeClass the class of node to be returned |
| * @param node the child of the node to be returned |
| * @return the specified parent of the given node |
| */ |
| @SuppressWarnings("unchecked") |
| public static <E extends DartNode> E getEnclosingNodeOfType(Class<E> enclosingNodeClass, |
| DartNode node) { |
| DartNode parent = node.getParent(); |
| while (parent != null && !enclosingNodeClass.isInstance(parent)) { |
| parent = parent.getParent(); |
| } |
| return (E) parent; |
| } |
| |
| public static int getExclusiveEnd(DartNode node) { |
| SourceInfo sourceInfo = node.getSourceInfo(); |
| return sourceInfo.getOffset() + sourceInfo.getLength(); |
| } |
| |
| /** |
| * @return the {@link FieldElement} with {@link ElementKind#VARIABLE} if the given |
| * {@link DartIdentifier} is the field reference, or <code>null</code> in the other case. |
| */ |
| public static FieldElement getFieldElement(DartIdentifier node) { |
| NodeElement element = node.getElement(); |
| if (ElementKind.of(element) == ElementKind.FIELD) { |
| return (FieldElement) element; |
| } |
| return null; |
| } |
| |
| public static int getInclusiveEnd(DartNode node) { |
| SourceInfo sourceInfo = node.getSourceInfo(); |
| return sourceInfo.getOffset() + sourceInfo.getLength() - 1; |
| } |
| |
| /** |
| * @return the {@link DartExpression} qualified if given node is name part of |
| * {@link DartPropertyAccess}. May be <code>null</code>. |
| */ |
| public static DartNode getNodeQualifier(DartIdentifier node) { |
| if (node.getParent() instanceof DartPropertyAccess) { |
| DartPropertyAccess propertyAccess = (DartPropertyAccess) node.getParent(); |
| if (propertyAccess.getName() == node) { |
| return propertyAccess.getQualifier(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @return the {@link VariableElement} if the given {@link DartIdentifier} is the parameter |
| * reference, or <code>null</code> in the other case. |
| */ |
| public static VariableElement getParameterElement(DartIdentifier node) { |
| Element element = node.getElement(); |
| if (ElementKind.of(element) == ElementKind.PARAMETER) { |
| return (VariableElement) element; |
| } |
| return null; |
| } |
| |
| /** |
| * @return the index of given {@link VariableElement} in parameters, or <code>-1</code> if not |
| * parameter. |
| */ |
| public static int getParameterIndex(VariableElement variableElement) { |
| Element enclosingElement = variableElement.getEnclosingElement(); |
| if (enclosingElement instanceof MethodElement) { |
| MethodElement methodElement = (MethodElement) enclosingElement; |
| return methodElement.getParameters().indexOf(variableElement); |
| } |
| return -1; |
| } |
| |
| /** |
| * Returns the closest ancestor of <code>node</code> that is an instance of |
| * <code>parentClass</code>, or <code>null</code> if none. |
| * <p> |
| * <b>Warning:</b> This method does not stop at any boundaries like parentheses, statements, body |
| * declarations, etc. The resulting node may be in a totally different scope than the given node. |
| * Consider using one of the {@link ASTResolving}<code>.find(..)</code> methods instead. |
| * </p> |
| * |
| * @param node the node |
| * @param parentClass the class of the sought ancestor node |
| * @return the closest ancestor of <code>node</code> that is an instance of |
| * <code>parentClass</code>, or <code>null</code> if none |
| */ |
| @SuppressWarnings("unchecked") |
| public static <E extends DartNode> E getParent(DartNode node, Class<E> parentClass) { |
| do { |
| node = node.getParent(); |
| } while (node != null && !parentClass.isInstance(node)); |
| return (E) node; |
| } |
| |
| // private static class ChildrenCollector extends ASTVisitor<Void> { |
| // public List<DartNode> result; |
| // |
| // @Override |
| // public Void visitNode(DartNode node) { |
| // // first visitNode: on the node's parent: do nothing, return true |
| // if (result == null) { |
| // result = Lists.newArrayList(); |
| // return super.visitNode(node); |
| // } else { |
| // result.add(node); |
| // } |
| // } |
| // } |
| // |
| // public static final int NODE_ONLY = 0; |
| // public static final int INCLUDE_FIRST_PARENT = 1; |
| // |
| // public static final int INCLUDE_ALL_PARENTS = 2; |
| // public static final int WARNING = 1 << 0; |
| // public static final int ERROR = 1 << 1; |
| // |
| // public static final int PROBLEMS = WARNING | ERROR; |
| // private static final Message[] EMPTY_MESSAGES = new Message[0]; |
| // |
| // private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0]; |
| // |
| // private static final int CLEAR_VISIBILITY = |
| // ~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE); |
| // |
| // public static String asFormattedString(DartNode node, |
| // int indent, |
| // String lineDelim, |
| // Map<String, String> options) { |
| // String unformatted = asString(node); |
| // TextEdit edit = CodeFormatterUtil.format2(node, unformatted, indent, lineDelim, options); |
| // if (edit != null) { |
| // Document document = new Document(unformatted); |
| // try { |
| // edit.apply(document, TextEdit.NONE); |
| // } catch (BadLocationException e) { |
| // JavaPlugin.log(e); |
| // } |
| // return document.get(); |
| // } |
| // return unformatted; // unknown node |
| // } |
| // |
| // public static String asString(DartNode node) { |
| // ASTFlattener flattener = new ASTFlattener(); |
| // node.accept(flattener); |
| // return flattener.getResult(); |
| // } |
| // |
| // public static int changeVisibility(int modifiers, int visibility) { |
| // return modifiers & CLEAR_VISIBILITY | visibility; |
| // } |
| // |
| // public static InfixExpression.Operator convertToInfixOperator(Assignment.Operator operator) { |
| // if (operator.equals(Assignment.Operator.PLUS_ASSIGN)) { |
| // return InfixExpression.Operator.PLUS; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.MINUS_ASSIGN)) { |
| // return InfixExpression.Operator.MINUS; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.TIMES_ASSIGN)) { |
| // return InfixExpression.Operator.TIMES; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.DIVIDE_ASSIGN)) { |
| // return InfixExpression.Operator.DIVIDE; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.BIT_AND_ASSIGN)) { |
| // return InfixExpression.Operator.AND; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.BIT_OR_ASSIGN)) { |
| // return InfixExpression.Operator.OR; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.BIT_XOR_ASSIGN)) { |
| // return InfixExpression.Operator.XOR; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.REMAINDER_ASSIGN)) { |
| // return InfixExpression.Operator.REMAINDER; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.LEFT_SHIFT_ASSIGN)) { |
| // return InfixExpression.Operator.LEFT_SHIFT; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN)) { |
| // return InfixExpression.Operator.RIGHT_SHIFT_SIGNED; |
| // } |
| // |
| // if (operator.equals(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN)) { |
| // return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED; |
| // } |
| // |
| // Assert.isTrue(false, "Cannot convert assignment operator"); //$NON-NLS-1$ |
| // return null; |
| // } |
| // |
| // public static DartNode findDeclaration(IBinding binding, DartNode root) { |
| // root = root.getRoot(); |
| // if (root instanceof CompilationUnit) { |
| // return ((CompilationUnit) root).findDeclaringNode(binding); |
| // } |
| // return null; |
| // } |
| // |
| // public static Modifier findModifierNode(int flag, List<IExtendedModifier> modifiers) { |
| // for (int i = 0; i < modifiers.size(); i++) { |
| // Object curr = modifiers.get(i); |
| // if (curr instanceof Modifier && ((Modifier) curr).getKeyword().toFlagValue() == flag) { |
| // return (Modifier) curr; |
| // } |
| // } |
| // return null; |
| // } |
| // |
| // public static DartNode findParent(DartNode node, StructuralPropertyDescriptor[][] pathes) { |
| // for (int p = 0; p < pathes.length; p++) { |
| // StructuralPropertyDescriptor[] path = pathes[p]; |
| // DartNode current = node; |
| // int d = path.length - 1; |
| // for (; d >= 0 && current != null; d--) { |
| // StructuralPropertyDescriptor descriptor = path[d]; |
| // if (!descriptor.equals(current.getLocationInParent())) { |
| // break; |
| // } |
| // current = current.getParent(); |
| // } |
| // if (d < 0) { |
| // return current; |
| // } |
| // } |
| // return null; |
| // } |
| // |
| // public static VariableDeclaration findVariableDeclaration(IVariableBinding binding, DartNode root) { |
| // if (binding.isField()) { |
| // return null; |
| // } |
| // DartNode result = findDeclaration(binding, root); |
| // if (result instanceof VariableDeclaration) { |
| // return (VariableDeclaration) result; |
| // } |
| // |
| // return null; |
| // } |
| // |
| // public static List<BodyDeclaration> getBodyDeclarations(DartNode node) { |
| // if (node instanceof AbstractTypeDeclaration) { |
| // return ((AbstractTypeDeclaration) node).bodyDeclarations(); |
| // } else if (node instanceof AnonymousClassDeclaration) { |
| // return ((AnonymousClassDeclaration) node).bodyDeclarations(); |
| // } |
| // // should not happen. |
| // Assert.isTrue(false); |
| // return null; |
| // } |
| // |
| // /** |
| // * Returns the structural property descriptor for the "bodyDeclarations" property of this node |
| // * (element type: {@link BodyDeclaration}). |
| // * |
| // * @param node the node, either an {@link AbstractTypeDeclaration} or an |
| // * {@link AnonymousClassDeclaration} |
| // * @return the property descriptor |
| // */ |
| // public static ChildListPropertyDescriptor getBodyDeclarationsProperty(DartNode node) { |
| // if (node instanceof AbstractTypeDeclaration) { |
| // return ((AbstractTypeDeclaration) node).getBodyDeclarationsProperty(); |
| // } else if (node instanceof AnonymousClassDeclaration) { |
| // return AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY; |
| // } |
| // // should not happen. |
| // Assert.isTrue(false); |
| // return null; |
| // } |
| // |
| // /** |
| // * Returns a list of the direct children of a node. The siblings are ordered by start offset. |
| // * |
| // * @param node the node to get the children for |
| // * @return the children |
| // */ |
| // public static List<DartNode> getChildren(DartNode node) { |
| // ChildrenCollector visitor = new ChildrenCollector(); |
| // node.accept(visitor); |
| // return visitor.result; |
| // } |
| // |
| // /** |
| // * Returns the list that contains the given DartNode. If the node isn't part of any list, |
| // * <code>null</code> is returned. |
| // * |
| // * @param node the node in question |
| // * @return the list that contains the node or <code>null</code> |
| // */ |
| // public static List<? extends DartNode> getContainingList(DartNode node) { |
| // StructuralPropertyDescriptor locationInParent = node.getLocationInParent(); |
| // if (locationInParent != null && locationInParent.isChildListProperty()) { |
| // return (List<? extends DartNode>) node.getParent().getStructuralProperty(locationInParent); |
| // } |
| // return null; |
| // } |
| // |
| // public static int getDimensions(VariableDeclaration declaration) { |
| // int dim = declaration.getExtraDimensions(); |
| // Type type = getType(declaration); |
| // if (type instanceof ArrayType) { |
| // dim += ((ArrayType) type).getDimensions(); |
| // } |
| // return dim; |
| // } |
| // |
| // /** |
| // * Returns the element type. This is a convenience method that returns its argument if it is a |
| // * simple type and the element type if the parameter is an array type. |
| // * |
| // * @param type The type to get the element type from. |
| // * @return The element type of the type or the type itself. |
| // */ |
| // public static Type getElementType(Type type) { |
| // if (!type.isArrayType()) { |
| // return type; |
| // } |
| // return ((ArrayType) type).getElementType(); |
| // } |
| // |
| // public static ITypeBinding getEnclosingType(DartNode node) { |
| // while (node != null) { |
| // if (node instanceof AbstractTypeDeclaration) { |
| // return ((AbstractTypeDeclaration) node).resolveBinding(); |
| // } else if (node instanceof AnonymousClassDeclaration) { |
| // return ((AnonymousClassDeclaration) node).resolveBinding(); |
| // } |
| // node = node.getParent(); |
| // } |
| // return null; |
| // } |
| // |
| // public static int getExclusiveEnd(DartNode node) { |
| // return node.getStartPosition() + node.getLength(); |
| // } |
| // |
| // /** |
| // * Returns the type to which an inlined variable initializer should be cast, or <code>null</code> |
| // * if no cast is necessary. |
| // * |
| // * @param initializer the initializer expression of the variable to inline |
| // * @param reference the reference to the variable (which is to be inlined) |
| // * @return a type binding to which the initializer should be cast, or <code>null</code> iff no |
| // * cast is necessary |
| // */ |
| // public static ITypeBinding getExplicitCast(Expression initializer, Expression reference) { |
| // ITypeBinding initializerType = initializer.resolveTypeBinding(); |
| // ITypeBinding referenceType = reference.resolveTypeBinding(); |
| // if (initializerType == null || referenceType == null) { |
| // return null; |
| // } |
| // |
| // if (initializerType.isPrimitive() |
| // && referenceType.isPrimitive() |
| // && !referenceType.isEqualTo(initializerType)) { |
| // return referenceType; |
| // |
| // } else if (initializerType.isPrimitive() && !referenceType.isPrimitive()) { // initializer is autoboxed |
| // ITypeBinding unboxedReferenceType = |
| // Bindings.getUnboxedTypeBinding(referenceType, reference.getAST()); |
| // if (!unboxedReferenceType.isEqualTo(initializerType)) { |
| // return unboxedReferenceType; |
| // } else if (needsExplicitBoxing(reference)) { |
| // return referenceType; |
| // } |
| // |
| // } else if (!initializerType.isPrimitive() && referenceType.isPrimitive()) { // initializer is autounboxed |
| // ITypeBinding unboxedInitializerType = |
| // Bindings.getUnboxedTypeBinding(initializerType, reference.getAST()); |
| // if (!unboxedInitializerType.isEqualTo(referenceType)) { |
| // return referenceType; |
| // } |
| // |
| // } else if (initializerType.isRawType() && referenceType.isParameterizedType()) { |
| // return referenceType; // don't lose the unchecked conversion |
| // |
| // } else if (!TypeRules.canAssign(initializerType, referenceType)) { |
| // if (!Bindings.containsTypeVariables(referenceType)) { |
| // return referenceType; |
| // } |
| // } |
| // |
| // return null; |
| // } |
| // |
| // public static IVariableBinding getFieldBinding(Name node) { |
| // IVariableBinding result = getVariableBinding(node); |
| // if (result == null || !result.isField()) { |
| // return null; |
| // } |
| // |
| // return result; |
| // } |
| // |
| // public static int getInclusiveEnd(DartNode node) { |
| // return node.getStartPosition() + node.getLength() - 1; |
| // } |
| // |
| // /** |
| // * Computes the insertion index to be used to add the given member to the the list |
| // * <code>container</code>. |
| // * |
| // * @param member the member to add |
| // * @param container a list containing objects of type <code>BodyDeclaration</code> |
| // * @return the insertion index to be used |
| // */ |
| // public static int getInsertionIndex(BodyDeclaration member, |
| // List<? extends BodyDeclaration> container) { |
| // int containerSize = container.size(); |
| // |
| // MembersOrderPreferenceCache orderStore = |
| // JavaPlugin.getDefault().getMemberOrderPreferenceCache(); |
| // |
| // int orderIndex = getOrderPreference(member, orderStore); |
| // |
| // int insertPos = containerSize; |
| // int insertPosOrderIndex = -1; |
| // |
| // for (int i = containerSize - 1; i >= 0; i--) { |
| // int currOrderIndex = getOrderPreference(container.get(i), orderStore); |
| // if (orderIndex == currOrderIndex) { |
| // if (insertPosOrderIndex != orderIndex) { // no perfect match yet |
| // insertPos = i + 1; // after a same kind |
| // insertPosOrderIndex = orderIndex; // perfect match |
| // } |
| // } else if (insertPosOrderIndex != orderIndex) { // not yet a perfect match |
| // if (currOrderIndex < orderIndex) { // we are bigger |
| // if (insertPosOrderIndex == -1) { |
| // insertPos = i + 1; // after |
| // insertPosOrderIndex = currOrderIndex; |
| // } |
| // } else { |
| // insertPos = i; // before |
| // insertPosOrderIndex = currOrderIndex; |
| // } |
| // } |
| // } |
| // return insertPos; |
| // } |
| // |
| // public static SimpleName getLeftMostSimpleName(Name name) { |
| // if (name instanceof SimpleName) { |
| // return (SimpleName) name; |
| // } else { |
| // final SimpleName[] result = new SimpleName[1]; |
| // ASTVisitor visitor = new ASTVisitor() { |
| // @Override |
| // public boolean visit(QualifiedName qualifiedName) { |
| // Name left = qualifiedName.getQualifier(); |
| // if (left instanceof SimpleName) { |
| // result[0] = (SimpleName) left; |
| // } else { |
| // left.accept(this); |
| // } |
| // return false; |
| // } |
| // }; |
| // name.accept(visitor); |
| // return result[0]; |
| // } |
| // } |
| // |
| // public static SimpleType getLeftMostSimpleType(QualifiedType type) { |
| // final SimpleType[] result = new SimpleType[1]; |
| // ASTVisitor visitor = new ASTVisitor() { |
| // @Override |
| // public boolean visit(QualifiedType qualifiedType) { |
| // Type left = qualifiedType.getQualifier(); |
| // if (left instanceof SimpleType) { |
| // result[0] = (SimpleType) left; |
| // } else { |
| // left.accept(this); |
| // } |
| // return false; |
| // } |
| // }; |
| // type.accept(visitor); |
| // return result[0]; |
| // } |
| // |
| // public static IVariableBinding getLocalVariableBinding(Name node) { |
| // IVariableBinding result = getVariableBinding(node); |
| // if (result == null || result.isField()) { |
| // return null; |
| // } |
| // |
| // return result; |
| // } |
| // |
| // public static Message[] getMessages(DartNode node, int flags) { |
| // DartNode root = node.getRoot(); |
| // if (!(root instanceof CompilationUnit)) { |
| // return EMPTY_MESSAGES; |
| // } |
| // Message[] messages = ((CompilationUnit) root).getMessages(); |
| // if (root == node) { |
| // return messages; |
| // } |
| // final int iterations = computeIterations(flags); |
| // List<Message> result = new ArrayList<Message>(5); |
| // for (int i = 0; i < messages.length; i++) { |
| // Message message = messages[i]; |
| // DartNode temp = node; |
| // int count = iterations; |
| // do { |
| // int nodeOffset = temp.getStartPosition(); |
| // int messageOffset = message.getStartPosition(); |
| // if (nodeOffset <= messageOffset && messageOffset < nodeOffset + temp.getLength()) { |
| // result.add(message); |
| // count = 0; |
| // } else { |
| // count--; |
| // } |
| // } while ((temp = temp.getParent()) != null && count > 0); |
| // } |
| // return result.toArray(new Message[result.size()]); |
| // } |
| // |
| // public static IMethodBinding getMethodBinding(Name node) { |
| // IBinding binding = node.resolveBinding(); |
| // if (binding instanceof IMethodBinding) { |
| // return (IMethodBinding) binding; |
| // } |
| // return null; |
| // } |
| // |
| // public static List<IExtendedModifier> getModifiers(VariableDeclaration declaration) { |
| // Assert.isNotNull(declaration); |
| // if (declaration instanceof SingleVariableDeclaration) { |
| // return ((SingleVariableDeclaration) declaration).modifiers(); |
| // } else if (declaration instanceof VariableDeclarationFragment) { |
| // DartNode parent = declaration.getParent(); |
| // if (parent instanceof VariableDeclarationExpression) { |
| // return ((VariableDeclarationExpression) parent).modifiers(); |
| // } else if (parent instanceof VariableDeclarationStatement) { |
| // return ((VariableDeclarationStatement) parent).modifiers(); |
| // } |
| // } |
| // return new ArrayList<IExtendedModifier>(0); |
| // } |
| // |
| // /** |
| // * Returns the source of the given node from the location where it was parsed. |
| // * |
| // * @param node the node to get the source from |
| // * @param extendedRange if set, the extended ranges of the nodes should ne used |
| // * @param removeIndent if set, the indentation is removed. |
| // * @return return the source for the given node or null if accessing the source failed. |
| // */ |
| // public static String getNodeSource(DartNode node, boolean extendedRange, boolean removeIndent) { |
| // DartNode root = node.getRoot(); |
| // if (root instanceof CompilationUnit) { |
| // CompilationUnit astRoot = (CompilationUnit) root; |
| // ITypeRoot typeRoot = astRoot.getTypeRoot(); |
| // try { |
| // if (typeRoot != null && typeRoot.getBuffer() != null) { |
| // IBuffer buffer = typeRoot.getBuffer(); |
| // int offset = |
| // extendedRange ? astRoot.getExtendedStartPosition(node) : node.getStartPosition(); |
| // int length = extendedRange ? astRoot.getExtendedLength(node) : node.getLength(); |
| // String str = buffer.getText(offset, length); |
| // if (removeIndent) { |
| // IJavaProject project = typeRoot.getJavaProject(); |
| // int indent = StubUtility.getIndentUsed(buffer, node.getStartPosition(), project); |
| // str = |
| // Strings.changeIndent( |
| // str, |
| // indent, |
| // project, |
| // new String(), |
| // typeRoot.findRecommendedLineSeparator()); |
| // } |
| // return str; |
| // } |
| // } catch (JavaModelException e) { |
| // // ignore |
| // } |
| // } |
| // return null; |
| // } |
| // |
| // public static DartNode getNormalizedNode(DartNode node) { |
| // DartNode current = node; |
| // // normalize name |
| // if (QualifiedName.NAME_PROPERTY.equals(current.getLocationInParent())) { |
| // current = current.getParent(); |
| // } |
| // // normalize type |
| // if (QualifiedType.NAME_PROPERTY.equals(current.getLocationInParent()) |
| // || SimpleType.NAME_PROPERTY.equals(current.getLocationInParent())) { |
| // current = current.getParent(); |
| // } |
| // // normalize parameterized types |
| // if (ParameterizedType.TYPE_PROPERTY.equals(current.getLocationInParent())) { |
| // current = current.getParent(); |
| // } |
| // return current; |
| // } |
| |
| /** |
| * @return parent {@link DartNode}s from {@link DartUnit} (at index "0") to the given one. |
| */ |
| public static List<DartNode> getParents(DartNode node) { |
| List<DartNode> parents = Lists.newArrayList(); |
| DartNode current = node; |
| do { |
| parents.add(current.getParent()); |
| current = current.getParent(); |
| } while (current.getParent() != null); |
| Collections.reverse(parents); |
| return parents; |
| } |
| |
| /** |
| * @return given {@link DartStatement} if not {@link DartBlock}, first child {@link DartStatement} |
| * if {@link DartBlock}, or <code>null</code> if more than one child. |
| */ |
| public static DartStatement getSingleStatement(DartStatement statement) { |
| if (statement instanceof DartBlock) { |
| List<DartStatement> blockStatements = ((DartBlock) statement).getStatements(); |
| if (blockStatements.size() != 1) { |
| return null; |
| } |
| return blockStatements.get(0); |
| } |
| return statement; |
| } |
| |
| /** |
| * @return given {@link DartStatement} if not {@link DartBlock}, all children |
| * {@link DartStatement}s if {@link DartBlock}. |
| */ |
| public static List<DartStatement> getStatements(DartStatement statement) { |
| if (statement instanceof DartBlock) { |
| return ((DartBlock) statement).getStatements(); |
| } |
| return ImmutableList.of(statement); |
| } |
| |
| /** |
| * @return the {@link DartThisExpression} if given node is name of {@link DartPropertyAccess} with |
| * {@link DartThisExpression} qualifier. May be <code>null</code>. |
| */ |
| public static DartThisExpression getThisQualifier(DartIdentifier node) { |
| if (node.getParent() instanceof DartPropertyAccess) { |
| DartPropertyAccess propertyAccess = (DartPropertyAccess) node.getParent(); |
| if (propertyAccess.getName() == node |
| && propertyAccess.getQualifier() instanceof DartThisExpression) { |
| return (DartThisExpression) propertyAccess.getQualifier(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return the type associated with the given type node, or <code>null</code> if the type could not |
| * be determined. |
| * |
| * @param typeNode the type node whose type is to be returned |
| * @return the type associated with the given type node |
| */ |
| public static Type getType(DartTypeNode typeNode) { |
| Type type = typeNode.getType(); |
| if (type == null) { |
| DartNode parent = typeNode.getParent(); |
| if (parent instanceof DartTypeNode) { |
| Type parentType = getType((DartTypeNode) parent); |
| if (parentType != null && parentType.getKind() == TypeKind.INTERFACE) { |
| int index = ((DartTypeNode) parent).getTypeArguments().indexOf(typeNode); |
| return ((InterfaceType) parentType).getArguments().get(index); |
| } |
| } |
| } |
| return type; |
| } |
| |
| /** |
| * @return the {@link VariableElement} with {@link ElementKind#VARIABLE} if the given |
| * {@link DartIdentifier} is the local variable reference, or <code>null</code> in the |
| * other case. |
| */ |
| public static VariableElement getVariableElement(DartIdentifier node) { |
| NodeElement element = node.getElement(); |
| if (ElementKind.of(element) == ElementKind.VARIABLE) { |
| return (VariableElement) element; |
| } |
| return null; |
| } |
| |
| /** |
| * @return the {@link VariableElement} with {@link ElementKind#VARIABLE} or |
| * {@link ElementKind#PARAMETER} if the given {@link DartIdentifier} is the reference to |
| * local variable or parameter, or <code>null</code> in the other case. |
| */ |
| public static VariableElement getVariableOrParameterElement(DartIdentifier node) { |
| NodeElement element = node.getElement(); |
| if (element instanceof VariableElement) { |
| return (VariableElement) element; |
| } |
| return null; |
| } |
| |
| /** |
| * Return <code>true</code> if the given method is a constructor. |
| * |
| * @param method the method being tested |
| * @return <code>true</code> if the given method is a constructor |
| */ |
| public static boolean isConstructor(DartMethodDefinition method) { |
| MethodElement methodElement = method.getElement(); |
| if (methodElement != null) { |
| return methodElement.isConstructor(); |
| } |
| return isConstructor(((DartClass) method.getParent()).getClassName(), method); |
| } |
| |
| /** |
| * Return <code>true</code> if the given method is a constructor. |
| * |
| * @param className the name of the type containing the method definition |
| * @param method the method being tested |
| * @return <code>true</code> if the given method is a constructor |
| */ |
| public static boolean isConstructor(String className, DartMethodDefinition method) { |
| if (method.getModifiers().isFactory()) { |
| return true; |
| } |
| DartExpression name = method.getName(); |
| if (name instanceof DartIdentifier) { |
| return ((DartIdentifier) name).getName().equals(className); |
| } else if (name instanceof DartPropertyAccess) { |
| DartPropertyAccess property = (DartPropertyAccess) name; |
| DartNode qualifier = property.getQualifier(); |
| if (qualifier instanceof DartIdentifier) { |
| return ((DartIdentifier) qualifier).getName().equals(className); |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * @return <code>true</code> if given {@link DartNode} is the name of some {@link DartDeclaration} |
| * . |
| */ |
| public static boolean isNameOfDeclaration(DartNode node) { |
| return node.getParent() instanceof DartDeclaration<?> |
| && ((DartDeclaration<?>) node.getParent()).getName() == node; |
| } |
| |
| /** |
| * @return <code>true</code> if given {@link List}s are equals at given position. |
| */ |
| private static <T> boolean allListsEqual(List<List<T>> lists, int position) { |
| T element = lists.get(0).get(position); |
| for (List<T> list : lists) { |
| if (list.get(position) != element) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private static <T> List<T> getLongestListPrefix(List<List<T>> lists) { |
| if (lists.isEmpty()) { |
| return ImmutableList.of(); |
| } |
| // prepare minimal length of all arrays |
| int minLength = lists.get(0).size(); |
| for (List<T> list : lists) { |
| minLength = Math.min(minLength, list.size()); |
| } |
| // find length of the common prefix |
| int length = -1; |
| for (int i = 0; i < minLength; i++) { |
| if (!allListsEqual(lists, i)) { |
| break; |
| } |
| length++; |
| } |
| // done |
| return lists.get(0).subList(0, length + 1); |
| } |
| |
| // /** |
| // * Returns the closest ancestor of <code>node</code> whose type is <code>nodeType</code>, or |
| // * <code>null</code> if none. |
| // * <p> |
| // * <b>Warning:</b> This method does not stop at any boundaries like parentheses, statements, body |
| // * declarations, etc. The resulting node may be in a totally different scope than the given node. |
| // * Consider using one of the {@link ASTResolving}<code>.find(..)</code> methods instead. |
| // * </p> |
| // * |
| // * @param node the node |
| // * @param nodeType the node type constant from {@link DartNode} |
| // * @return the closest ancestor of <code>node</code> whose type is <code>nodeType</code>, or |
| // * <code>null</code> if none |
| // */ |
| // public static DartNode getParent(DartNode node, int nodeType) { |
| // do { |
| // node = node.getParent(); |
| // } while (node != null && node.getNodeType() != nodeType); |
| // return node; |
| // } |
| // |
| // public static IProblem[] getProblems(DartNode node, int scope, int severity) { |
| // DartNode root = node.getRoot(); |
| // if (!(root instanceof CompilationUnit)) { |
| // return EMPTY_PROBLEMS; |
| // } |
| // IProblem[] problems = ((CompilationUnit) root).getProblems(); |
| // if (root == node) { |
| // return problems; |
| // } |
| // final int iterations = computeIterations(scope); |
| // List<IProblem> result = new ArrayList<IProblem>(5); |
| // for (int i = 0; i < problems.length; i++) { |
| // IProblem problem = problems[i]; |
| // boolean consider = false; |
| // if ((severity & PROBLEMS) == PROBLEMS) { |
| // consider = true; |
| // } else if ((severity & WARNING) != 0) { |
| // consider = problem.isWarning(); |
| // } else if ((severity & ERROR) != 0) { |
| // consider = problem.isError(); |
| // } |
| // if (consider) { |
| // DartNode temp = node; |
| // int count = iterations; |
| // do { |
| // int nodeOffset = temp.getStartPosition(); |
| // int problemOffset = problem.getSourceStart(); |
| // if (nodeOffset <= problemOffset && problemOffset < nodeOffset + temp.getLength()) { |
| // result.add(problem); |
| // count = 0; |
| // } else { |
| // count--; |
| // } |
| // } while ((temp = temp.getParent()) != null && count > 0); |
| // } |
| // } |
| // return result.toArray(new IProblem[result.size()]); |
| // } |
| // |
| // public static String getQualifier(Name name) { |
| // if (name.isQualifiedName()) { |
| // return ((QualifiedName) name).getQualifier().getFullyQualifiedName(); |
| // } |
| // return ""; //$NON-NLS-1$ |
| // } |
| // |
| // /** |
| // * Returns the receiver's type binding of the given method invocation. |
| // * |
| // * @param invocation method invocation to resolve type of |
| // * @return the type binding of the receiver |
| // */ |
| // public static ITypeBinding getReceiverTypeBinding(MethodInvocation invocation) { |
| // ITypeBinding result = null; |
| // Expression exp = invocation.getExpression(); |
| // if (exp != null) { |
| // return exp.resolveTypeBinding(); |
| // } else { |
| // AbstractTypeDeclaration type = |
| // (AbstractTypeDeclaration) getParent(invocation, AbstractTypeDeclaration.class); |
| // if (type != null) { |
| // return type.resolveBinding(); |
| // } |
| // } |
| // return result; |
| // } |
| // |
| // public static String getSimpleNameIdentifier(Name name) { |
| // if (name.isQualifiedName()) { |
| // return ((QualifiedName) name).getName().getIdentifier(); |
| // } else { |
| // return ((SimpleName) name).getIdentifier(); |
| // } |
| // } |
| // |
| // public static Name getTopMostName(Name name) { |
| // Name result = name; |
| // while (result.getParent() instanceof Name) { |
| // result = (Name) result.getParent(); |
| // } |
| // return result; |
| // } |
| // |
| // public static Type getTopMostType(Type type) { |
| // Type result = type; |
| // while (result.getParent() instanceof Type) { |
| // result = (Type) result.getParent(); |
| // } |
| // return result; |
| // } |
| // |
| // /** |
| // * Returns the type node for the given declaration. |
| // * |
| // * @param declaration the declaration |
| // * @return the type node |
| // */ |
| // public static Type getType(VariableDeclaration declaration) { |
| // if (declaration instanceof SingleVariableDeclaration) { |
| // return ((SingleVariableDeclaration) declaration).getType(); |
| // } else if (declaration instanceof VariableDeclarationFragment) { |
| // DartNode parent = ((VariableDeclarationFragment) declaration).getParent(); |
| // if (parent instanceof VariableDeclarationExpression) { |
| // return ((VariableDeclarationExpression) parent).getType(); |
| // } else if (parent instanceof VariableDeclarationStatement) { |
| // return ((VariableDeclarationStatement) parent).getType(); |
| // } else if (parent instanceof FieldDeclaration) { |
| // return ((FieldDeclaration) parent).getType(); |
| // } |
| // } |
| // Assert.isTrue(false, "Unknown VariableDeclaration"); //$NON-NLS-1$ |
| // return null; |
| // } |
| // |
| // public static ITypeBinding getTypeBinding(CompilationUnit root, IType type) |
| // throws JavaModelException { |
| // if (type.isAnonymous()) { |
| // final IJavaElement parent = type.getParent(); |
| // if (parent instanceof IField && Flags.isEnum(((IMember) parent).getFlags())) { |
| // final EnumConstantDeclaration constant = |
| // (EnumConstantDeclaration) NodeFinder.perform( |
| // root, |
| // ((ISourceReference) parent).getSourceRange()); |
| // if (constant != null) { |
| // final AnonymousClassDeclaration declaration = constant.getAnonymousClassDeclaration(); |
| // if (declaration != null) { |
| // return declaration.resolveBinding(); |
| // } |
| // } |
| // } else { |
| // final ClassInstanceCreation creation = |
| // (ClassInstanceCreation) getParent( |
| // NodeFinder.perform(root, type.getNameRange()), |
| // ClassInstanceCreation.class); |
| // if (creation != null) { |
| // return creation.resolveTypeBinding(); |
| // } |
| // } |
| // } else { |
| // final AbstractTypeDeclaration declaration = |
| // (AbstractTypeDeclaration) getParent( |
| // NodeFinder.perform(root, type.getNameRange()), |
| // AbstractTypeDeclaration.class); |
| // if (declaration != null) { |
| // return declaration.resolveBinding(); |
| // } |
| // } |
| // return null; |
| // } |
| // |
| // public static ITypeBinding getTypeBinding(Name node) { |
| // IBinding binding = node.resolveBinding(); |
| // if (binding instanceof ITypeBinding) { |
| // return (ITypeBinding) binding; |
| // } |
| // return null; |
| // } |
| // |
| // public static String getTypeName(Type type) { |
| // final StringBuffer buffer = new StringBuffer(); |
| // ASTVisitor visitor = new ASTVisitor() { |
| // @Override |
| // public void endVisit(ArrayType node) { |
| // buffer.append("[]"); //$NON-NLS-1$ |
| // } |
| // |
| // @Override |
| // public boolean visit(PrimitiveType node) { |
| // buffer.append(node.getPrimitiveTypeCode().toString()); |
| // return false; |
| // } |
| // |
| // @Override |
| // public boolean visit(QualifiedName node) { |
| // buffer.append(node.getName().getIdentifier()); |
| // return false; |
| // } |
| // |
| // @Override |
| // public boolean visit(SimpleName node) { |
| // buffer.append(node.getIdentifier()); |
| // return false; |
| // } |
| // }; |
| // type.accept(visitor); |
| // return buffer.toString(); |
| // } |
| // |
| // public static IVariableBinding getVariableBinding(Name node) { |
| // IBinding binding = node.resolveBinding(); |
| // if (binding instanceof IVariableBinding) { |
| // return (IVariableBinding) binding; |
| // } |
| // return null; |
| // } |
| // |
| // /** |
| // * Returns true if a node at a given location is a body of a control statement. Such body nodes |
| // * are interesting as when replacing them, it has to be evaluates if a Block is needed instead. |
| // * E.g. <code> if (x) do(); -> if (x) { do1(); do2() } </code> |
| // * |
| // * @param locationInParent Location of the body node |
| // * @return Returns true if the location is a body node location of a control statement. |
| // */ |
| // public static boolean isControlStatementBody(StructuralPropertyDescriptor locationInParent) { |
| // return locationInParent == IfStatement.THEN_STATEMENT_PROPERTY |
| // || locationInParent == IfStatement.ELSE_STATEMENT_PROPERTY |
| // || locationInParent == ForStatement.BODY_PROPERTY |
| // || locationInParent == EnhancedForStatement.BODY_PROPERTY |
| // || locationInParent == WhileStatement.BODY_PROPERTY |
| // || locationInParent == DoStatement.BODY_PROPERTY; |
| // } |
| // |
| // public static boolean isDeclaration(Name name) { |
| // if (name.isQualifiedName()) { |
| // return ((QualifiedName) name).getName().isDeclaration(); |
| // } else { |
| // return ((SimpleName) name).isDeclaration(); |
| // } |
| // } |
| // |
| // /** |
| // * Returns true if this is an existing node, i.e. it was created as part of a parsing process of a |
| // * source code file. Returns false if this is a newly created node which has not yet been given a |
| // * source position. |
| // * |
| // * @param node the node to be tested. |
| // * @return true if this is an existing node, false if not. |
| // */ |
| // public static boolean isExistingNode(DartNode node) { |
| // return node.getStartPosition() != -1; |
| // } |
| // |
| // public static boolean isLabel(SimpleName name) { |
| // int parentType = name.getParent().getNodeType(); |
| // return parentType == DartNode.LABELED_STATEMENT |
| // || parentType == DartNode.BREAK_STATEMENT |
| // || parentType != DartNode.CONTINUE_STATEMENT; |
| // } |
| // |
| // public static boolean isLiteral(Expression expression) { |
| // int type = expression.getNodeType(); |
| // return type == DartNode.BOOLEAN_LITERAL |
| // || type == DartNode.CHARACTER_LITERAL |
| // || type == DartNode.NULL_LITERAL |
| // || type == DartNode.NUMBER_LITERAL |
| // || type == DartNode.STRING_LITERAL |
| // || type == DartNode.TYPE_LITERAL; |
| // } |
| // |
| // /** |
| // * Returns <code>true</code> iff <code>parent</code> is a true ancestor of <code>node</code> (i.e. |
| // * returns <code>false</code> if <code>parent == node</code>). |
| // * |
| // * @param node node to test |
| // * @param parent assumed parent |
| // * @return <code>true</code> iff <code>parent</code> is a true ancestor of <code>node</code> |
| // */ |
| // public static boolean isParent(DartNode node, DartNode parent) { |
| // Assert.isNotNull(parent); |
| // do { |
| // node = node.getParent(); |
| // if (node == parent) { |
| // return true; |
| // } |
| // } while (node != null); |
| // return false; |
| // } |
| // |
| // public static boolean isSingleDeclaration(VariableDeclaration declaration) { |
| // Assert.isNotNull(declaration); |
| // if (declaration instanceof SingleVariableDeclaration) { |
| // return true; |
| // } else if (declaration instanceof VariableDeclarationFragment) { |
| // DartNode parent = declaration.getParent(); |
| // if (parent instanceof VariableDeclarationExpression) { |
| // return ((VariableDeclarationExpression) parent).fragments().size() == 1; |
| // } else if (parent instanceof VariableDeclarationStatement) { |
| // return ((VariableDeclarationStatement) parent).fragments().size() == 1; |
| // } |
| // } |
| // return false; |
| // } |
| // |
| // public static boolean isStatic(BodyDeclaration declaration) { |
| // return Modifier.isStatic(declaration.getModifiers()); |
| // } |
| // |
| // /** |
| // * Adds flags to the given node and all its descendants. |
| // * |
| // * @param root The root node |
| // * @param flags The flags to set |
| // */ |
| // public static void setFlagsToAST(DartNode root, final int flags) { |
| // root.accept(new GenericVisitor(true) { |
| // @Override |
| // protected boolean visitNode(DartNode node) { |
| // node.setFlags(node.getFlags() | flags); |
| // return true; |
| // } |
| // }); |
| // } |
| // |
| // private static int computeIterations(int flags) { |
| // switch (flags) { |
| // case NODE_ONLY: |
| // return 1; |
| // case INCLUDE_ALL_PARENTS: |
| // return Integer.MAX_VALUE; |
| // case INCLUDE_FIRST_PARENT: |
| // return 2; |
| // default: |
| // return 1; |
| // } |
| // } |
| // |
| // private static int getOrderPreference(BodyDeclaration member, MembersOrderPreferenceCache store) { |
| // int memberType = member.getNodeType(); |
| // int modifiers = member.getModifiers(); |
| // |
| // switch (memberType) { |
| // case DartNode.TYPE_DECLARATION: |
| // case DartNode.ENUM_DECLARATION: |
| // case DartNode.ANNOTATION_TYPE_DECLARATION: |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.TYPE_INDEX) * 2; |
| // case DartNode.FIELD_DECLARATION: |
| // if (Modifier.isStatic(modifiers)) { |
| // int index = store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_FIELDS_INDEX) * 2; |
| // if (Modifier.isFinal(modifiers)) { |
| // return index; // first final static, then static |
| // } |
| // return index + 1; |
| // } |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.FIELDS_INDEX) * 2; |
| // case DartNode.INITIALIZER: |
| // if (Modifier.isStatic(modifiers)) { |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_INIT_INDEX) * 2; |
| // } |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.INIT_INDEX) * 2; |
| // case DartNode.ANNOTATION_TYPE_MEMBER_DECLARATION: |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.METHOD_INDEX) * 2; |
| // case DartNode.METHOD_DECLARATION: |
| // if (Modifier.isStatic(modifiers)) { |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_METHODS_INDEX) * 2; |
| // } |
| // if (((MethodDeclaration) member).isConstructor()) { |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX) * 2; |
| // } |
| // return store.getCategoryIndex(MembersOrderPreferenceCache.METHOD_INDEX) * 2; |
| // default: |
| // return 100; |
| // } |
| // } |
| // |
| // /** |
| // * Returns whether an expression at the given location needs explicit boxing. |
| // * |
| // * @param expression the expression |
| // * @return <code>true</code> iff an expression at the given location needs explicit boxing |
| // */ |
| // private static boolean needsExplicitBoxing(Expression expression) { |
| // StructuralPropertyDescriptor locationInParent = expression.getLocationInParent(); |
| // if (locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY) { |
| // return needsExplicitBoxing((ParenthesizedExpression) expression.getParent()); |
| // } |
| // |
| // if (locationInParent == ClassInstanceCreation.EXPRESSION_PROPERTY |
| // || locationInParent == FieldAccess.EXPRESSION_PROPERTY |
| // || locationInParent == MethodInvocation.EXPRESSION_PROPERTY) { |
| // return true; |
| // } |
| // |
| // return false; |
| // } |
| |
| private ASTNodes() { |
| // no instance; |
| } |
| |
| /** |
| * Looks to see if the property access requires a getter. |
| * <p> |
| * A property access requires a getter if it is on the right hand side of an assignment, or if it |
| * is on the left hand side of an assignment and uses one of the assignment operators other than |
| * plain '='. |
| * <p> |
| * Note, that we don't check if given {@link DartNode} is actually field name. |
| */ |
| public static boolean inGetterContext(DartNode node) { |
| if (node.getParent() instanceof DartBinaryExpression) { |
| DartBinaryExpression expr = (DartBinaryExpression) node.getParent(); |
| if (expr.getArg1() == node && expr.getOperator() == Token.ASSIGN) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Looks to see if the property access requires a setter. |
| * <p> |
| * Basically, this boils down to any property access on the left hand side of an assignment. |
| * <p> |
| * Keep in mind that an assignment of the form node = <expr> is the only kind of write-only |
| * expression. Other types of assignments also read the value and require a getter access. |
| * <p> |
| * Note, that we don't check if given {@link DartNode} is actually field name. |
| */ |
| public static boolean inSetterContext(DartNode node) { |
| if (node.getParent() instanceof DartUnaryExpression) { |
| DartUnaryExpression expr = (DartUnaryExpression) node.getParent(); |
| return expr.getArg() == node && expr.getOperator().isCountOperator(); |
| } |
| if (node.getParent() instanceof DartBinaryExpression) { |
| DartBinaryExpression expr = (DartBinaryExpression) node.getParent(); |
| return expr.getArg1() == node && expr.getOperator().isAssignmentOperator(); |
| } |
| return false; |
| } |
| |
| /** |
| * @return the {@link DartIdentifier} corresponding to the name of constructor. |
| */ |
| public static DartIdentifier getConstructorNameNode(DartNewExpression node) { |
| DartNode constructor = node.getConstructor(); |
| return getConstructorNameNode(constructor); |
| } |
| |
| /** |
| * @return the {@link DartIdentifier} corresponding to the name of constructor. |
| */ |
| private static DartIdentifier getConstructorNameNode(DartNode constructor) { |
| if (constructor instanceof DartPropertyAccess) { |
| return ((DartPropertyAccess) constructor).getName(); |
| } else if (constructor instanceof DartTypeNode) { |
| return getConstructorNameNode(((DartTypeNode) constructor).getIdentifier()); |
| } else { |
| return (DartIdentifier) constructor; |
| } |
| } |
| |
| } |