/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for * bug "inline method - doesn't handle implicit cast" (see * https://bugs.eclipse.org/bugs/show_bug.cgi?id=24941). * Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for * bug Encapsulate field can fail when two variables in one variable declaration (see * https://bugs.eclipse.org/bugs/show_bug.cgi?id=51540). *******************************************************************************/ package org.eclipse.wst.jsdt.internal.corext.dom; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.eclipse.text.edits.TextEdit; import org.eclipse.wst.jsdt.core.IType; import org.eclipse.wst.jsdt.core.JavaScriptModelException; import org.eclipse.wst.jsdt.core.compiler.IProblem; import org.eclipse.wst.jsdt.core.dom.ASTNode; import org.eclipse.wst.jsdt.core.dom.ASTVisitor; import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration; import org.eclipse.wst.jsdt.core.dom.AnonymousClassDeclaration; import org.eclipse.wst.jsdt.core.dom.ArrayType; import org.eclipse.wst.jsdt.core.dom.Assignment; import org.eclipse.wst.jsdt.core.dom.BodyDeclaration; import org.eclipse.wst.jsdt.core.dom.ChildListPropertyDescriptor; import org.eclipse.wst.jsdt.core.dom.ClassInstanceCreation; import org.eclipse.wst.jsdt.core.dom.DoStatement; import org.eclipse.wst.jsdt.core.dom.EnhancedForStatement; import org.eclipse.wst.jsdt.core.dom.Expression; import org.eclipse.wst.jsdt.core.dom.FieldDeclaration; import org.eclipse.wst.jsdt.core.dom.ForInStatement; import org.eclipse.wst.jsdt.core.dom.ForStatement; import org.eclipse.wst.jsdt.core.dom.FunctionDeclaration; import org.eclipse.wst.jsdt.core.dom.FunctionInvocation; import org.eclipse.wst.jsdt.core.dom.IBinding; import org.eclipse.wst.jsdt.core.dom.IFunctionBinding; import org.eclipse.wst.jsdt.core.dom.ITypeBinding; import org.eclipse.wst.jsdt.core.dom.IVariableBinding; import org.eclipse.wst.jsdt.core.dom.IfStatement; import org.eclipse.wst.jsdt.core.dom.InfixExpression; import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit; import org.eclipse.wst.jsdt.core.dom.Message; import org.eclipse.wst.jsdt.core.dom.Modifier; import org.eclipse.wst.jsdt.core.dom.Name; import org.eclipse.wst.jsdt.core.dom.PrimitiveType; import org.eclipse.wst.jsdt.core.dom.QualifiedName; import org.eclipse.wst.jsdt.core.dom.QualifiedType; import org.eclipse.wst.jsdt.core.dom.ReturnStatement; import org.eclipse.wst.jsdt.core.dom.SimpleName; import org.eclipse.wst.jsdt.core.dom.SimpleType; import org.eclipse.wst.jsdt.core.dom.SingleVariableDeclaration; import org.eclipse.wst.jsdt.core.dom.StructuralPropertyDescriptor; import org.eclipse.wst.jsdt.core.dom.Type; import org.eclipse.wst.jsdt.core.dom.VariableDeclaration; import org.eclipse.wst.jsdt.core.dom.VariableDeclarationExpression; import org.eclipse.wst.jsdt.core.dom.VariableDeclarationFragment; import org.eclipse.wst.jsdt.core.dom.VariableDeclarationStatement; import org.eclipse.wst.jsdt.core.dom.WhileStatement; import org.eclipse.wst.jsdt.internal.corext.util.CodeFormatterUtil; import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin; import org.eclipse.wst.jsdt.internal.ui.preferences.MembersOrderPreferenceCache; /** * * Provisional API: This class/interface is part of an interim API that is still under development and expected to * change significantly before reaching stability. It is being made available at this early stage to solicit feedback * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken * (repeatedly) as the API evolves. */ public class ASTNodes { 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); private ASTNodes() { // no instance; } public static String asString(ASTNode node) { ASTFlattener flattener= new ASTFlattener(); node.accept(flattener); return flattener.getResult(); } public static String asFormattedString(ASTNode node, int indent, String lineDelim, Map options) { String unformatted= asString(node); TextEdit edit= CodeFormatterUtil.format2(node, unformatted, indent, lineDelim, options); if (edit != null) { return CodeFormatterUtil.evaluateFormatterEdit(unformatted, edit, null); } return unformatted; // unknown node } /** * Returns the list that contains the given ASTNode. 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 getContainingList(ASTNode node) { StructuralPropertyDescriptor locationInParent= node.getLocationInParent(); if (locationInParent != null && locationInParent.isChildListProperty()) { return (List) node.getParent().getStructuralProperty(locationInParent); } 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 getChildren(ASTNode node) { ChildrenCollector visitor= new ChildrenCollector(); node.accept(visitor); return visitor.result; } private static class ChildrenCollector extends GenericVisitor { public List result; public ChildrenCollector() { super(true); result= null; } protected boolean visitNode(ASTNode node) { if (result == null) { // first visitNode: on the node's parent: do nothing, return true result= new ArrayList(); return true; } result.add(node); return false; } } /** * 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(ASTNode node) { return node.getStartPosition() != -1; } /** * 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 ASTNode findDeclaration(IBinding binding, ASTNode root) { root= root.getRoot(); if (root instanceof JavaScriptUnit) { return ((JavaScriptUnit)root).findDeclaringNode(binding); } return null; } public static VariableDeclaration findVariableDeclaration(IVariableBinding binding, ASTNode root) { if (binding.isField()) return null; ASTNode result= findDeclaration(binding, root); if (result instanceof VariableDeclaration) return (VariableDeclaration)result; return null; } /** * 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) { ASTNode 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 int getDimensions(VariableDeclaration declaration) { int dim= declaration.getExtraDimensions(); Type type= getType(declaration); if (type instanceof ArrayType) { dim += ((ArrayType) type).getDimensions(); } return dim; } public static List getModifiers(VariableDeclaration declaration) { Assert.isNotNull(declaration); if (declaration instanceof SingleVariableDeclaration) { return ((SingleVariableDeclaration)declaration).modifiers(); } else if (declaration instanceof VariableDeclarationFragment) { ASTNode parent= declaration.getParent(); if (parent instanceof VariableDeclarationExpression) return ((VariableDeclarationExpression)parent).modifiers(); else if (parent instanceof VariableDeclarationStatement) return ((VariableDeclarationStatement)parent).modifiers(); } return new ArrayList(0); } public static boolean isSingleDeclaration(VariableDeclaration declaration) { Assert.isNotNull(declaration); if (declaration instanceof SingleVariableDeclaration) { return true; } else if (declaration instanceof VariableDeclarationFragment) { ASTNode 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 isLiteral(Expression expression) { int type= expression.getNodeType(); return type == ASTNode.BOOLEAN_LITERAL || type == ASTNode.CHARACTER_LITERAL || type == ASTNode.NULL_LITERAL || type == ASTNode.NUMBER_LITERAL || type == ASTNode.STRING_LITERAL || type == ASTNode.TYPE_LITERAL|| type == ASTNode.UNDEFINED_LITERAL || type == ASTNode.OBJECT_LITERAL || type == ASTNode.REGULAR_EXPRESSION_LITERAL; } public static boolean isLabel(SimpleName name) { int parentType= name.getParent().getNodeType(); return parentType == ASTNode.LABELED_STATEMENT || parentType == ASTNode.BREAK_STATEMENT || parentType != ASTNode.CONTINUE_STATEMENT; } public static boolean isStatic(BodyDeclaration declaration) { return Modifier.isStatic(declaration.getModifiers()); } public static List getBodyDeclarations(ASTNode 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; } public static ChildListPropertyDescriptor getBodyDeclarationsProperty(ASTNode node) { if (node instanceof JavaScriptUnit) { return JavaScriptUnit.STATEMENTS_PROPERTY; } else 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; } public static String getTypeName(Type type) { final StringBuffer buffer= new StringBuffer(); ASTVisitor visitor= new ASTVisitor() { public boolean visit(PrimitiveType node) { buffer.append(node.getPrimitiveTypeCode().toString()); return false; } public boolean visit(SimpleName node) { buffer.append(node.getIdentifier()); return false; } public boolean visit(QualifiedName node) { buffer.append(node.getName().getIdentifier()); return false; } public void endVisit(ArrayType node) { buffer.append("[]"); //$NON-NLS-1$ } }; type.accept(visitor); return buffer.toString(); } 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; } /** * 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 == ForInStatement.BODY_PROPERTY || locationInParent == EnhancedForStatement.BODY_PROPERTY || locationInParent == WhileStatement.BODY_PROPERTY || locationInParent == DoStatement.BODY_PROPERTY; } public static boolean needsParentheses(Expression expression) { int type= expression.getNodeType(); return type == ASTNode.INFIX_EXPRESSION || type == ASTNode.CONDITIONAL_EXPRESSION || type == ASTNode.PREFIX_EXPRESSION || type == ASTNode.POSTFIX_EXPRESSION || type == ASTNode.INSTANCEOF_EXPRESSION; } public static boolean substituteMustBeParenthesized(Expression substitute, Expression location) { if (!needsParentheses(substitute)) return false; ASTNode parent= location.getParent(); if (parent instanceof VariableDeclarationFragment){ VariableDeclarationFragment vdf= (VariableDeclarationFragment)parent; if (vdf.getInitializer().equals(location)) return false; } else if (parent instanceof FunctionInvocation){ FunctionInvocation mi= (FunctionInvocation)parent; if (mi.arguments().contains(location)) return false; } else if (parent instanceof ReturnStatement) return false; return true; } public static ASTNode getParent(ASTNode node, Class parentClass) { do { node= node.getParent(); } while (node != null && !parentClass.isInstance(node)); return node; } public static ASTNode getParent(ASTNode node, int nodeType) { do { node= node.getParent(); } while (node != null && node.getNodeType() != nodeType); return node; } public static ASTNode findParent(ASTNode node, StructuralPropertyDescriptor[][] pathes) { for (int p= 0; p < pathes.length; p++) { StructuralPropertyDescriptor[] path= pathes[p]; ASTNode 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 ASTNode getNormalizedNode(ASTNode node) { ASTNode 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(); } return current; } public static boolean isParent(ASTNode node, ASTNode parent) { Assert.isNotNull(parent); do { node= node.getParent(); if (node == parent) return true; } while (node != null); return false; } public static int getExclusiveEnd(ASTNode node){ return node.getStartPosition() + node.getLength(); } public static int getInclusiveEnd(ASTNode node){ return node.getStartPosition() + node.getLength() - 1; } public static IFunctionBinding getMethodBinding(Name node) { IBinding binding= node.resolveBinding(); if (binding instanceof IFunctionBinding) return (IFunctionBinding)binding; return null; } public static IVariableBinding getVariableBinding(Name node) { IBinding binding= node.resolveBinding(); if (binding instanceof IVariableBinding) return (IVariableBinding)binding; return null; } public static IVariableBinding getLocalVariableBinding(Name node) { IVariableBinding result= getVariableBinding(node); if (result == null || result.isField()) return null; return result; } public static IVariableBinding getFieldBinding(Name node) { IVariableBinding result= getVariableBinding(node); if (result == null || !result.isField()) return null; return result; } public static ITypeBinding getTypeBinding(Name node) { IBinding binding= node.resolveBinding(); if (binding instanceof ITypeBinding) return (ITypeBinding)binding; return null; } /** * 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(FunctionInvocation 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 ITypeBinding getEnclosingType(ASTNode node) { while(node != null) { if (node instanceof AbstractTypeDeclaration) { return ((AbstractTypeDeclaration)node).resolveBinding(); } else if (node instanceof AnonymousClassDeclaration) { return ((AnonymousClassDeclaration)node).resolveBinding(); } else if (node instanceof JavaScriptUnit) { return ((JavaScriptUnit)node).resolveBinding(); } node= node.getParent(); } return null; } public static IProblem[] getProblems(ASTNode node, int scope, int severity) { ASTNode root= node.getRoot(); if (!(root instanceof JavaScriptUnit)) return EMPTY_PROBLEMS; IProblem[] problems= ((JavaScriptUnit)root).getProblems(); if (root == node) return problems; final int iterations= computeIterations(scope); List result= new ArrayList(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) { ASTNode 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 (IProblem[]) result.toArray(new IProblem[result.size()]); } public static Message[] getMessages(ASTNode node, int flags) { ASTNode root= node.getRoot(); if (!(root instanceof JavaScriptUnit)) return EMPTY_MESSAGES; Message[] messages= ((JavaScriptUnit)root).getMessages(); if (root == node) return messages; final int iterations= computeIterations(flags); List result= new ArrayList(5); for (int i= 0; i < messages.length; i++) { Message message= messages[i]; ASTNode 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 (Message[]) result.toArray(new Message[result.size()]); } 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 ASTNode.TYPE_DECLARATION: return store.getCategoryIndex(MembersOrderPreferenceCache.TYPE_INDEX) * 2; case ASTNode.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 ASTNode.INITIALIZER: if (Modifier.isStatic(modifiers)) { return store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_INIT_INDEX) * 2; } return store.getCategoryIndex(MembersOrderPreferenceCache.INIT_INDEX) * 2; case ASTNode.FUNCTION_DECLARATION: if (Modifier.isStatic(modifiers)) { return store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_METHODS_INDEX) * 2; } if (((FunctionDeclaration) member).isConstructor()) { return store.getCategoryIndex(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX) * 2; } return store.getCategoryIndex(MembersOrderPreferenceCache.METHOD_INDEX) * 2; default: return 100; } } /** * 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 container) { int containerSize= container.size(); MembersOrderPreferenceCache orderStore= JavaScriptPlugin.getDefault().getMemberOrderPreferenceCache(); int orderIndex= getOrderPreference(member, orderStore); int insertPos= containerSize; int insertPosOrderIndex= -1; for (int i= containerSize - 1; i >= 0; i--) { int currOrderIndex= getOrderPreference((BodyDeclaration) 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() { 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() { 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 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; } public static int changeVisibility(int modifiers, int visibility) { return (modifiers & CLEAR_VISIBILITY) | visibility; } /** * 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(ASTNode root, final int flags) { root.accept(new GenericVisitor(true) { protected boolean visitNode(ASTNode node) { node.setFlags(node.getFlags() | flags); return true; } }); } public static String getQualifier(Name name) { if (name.isQualifiedName()) { return ((QualifiedName) name).getQualifier().getFullyQualifiedName(); } return ""; //$NON-NLS-1$ } public static String getSimpleNameIdentifier(Name name) { if (name.isQualifiedName()) { return ((QualifiedName) name).getName().getIdentifier(); } else { return ((SimpleName) name).getIdentifier(); } } public static boolean isDeclaration(Name name) { if (name.isQualifiedName()) { return ((QualifiedName) name).getName().isDeclaration(); } else { return ((SimpleName) name).isDeclaration(); } } public static Modifier findModifierNode(int flag, List 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 ITypeBinding getTypeBinding(JavaScriptUnit root, IType type) throws JavaScriptModelException { if (type.isAnonymous()) { 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; } }