package org.eclipse.jdt.internal.corext.dom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.BooleanLiteral;
import org.eclipse.jdt.core.dom.BreakStatement;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CharacterLiteral;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.Message;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodReference;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NameQualifiedType;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.UnionType;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.formatter.IndentManipulation;
import org.eclipse.jdt.internal.core.manipulation.JavaManipulationPlugin;
import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.core.manipulation.util.Strings;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
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 INFO= 1 << 2;
public static final int PROBLEMS= WARNING | ERROR | INFO;
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() {
}
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<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) {
JavaManipulationPlugin.log(e);
}
return document.get();
}
return unformatted;
}
public static String getNodeSource(ASTNode node, boolean extendedRange, boolean removeIndent) {
ASTNode 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= getIndentUsed(buffer, node.getStartPosition(), project);
str= Strings.changeIndent(str, indent, project, new String(), typeRoot.findRecommendedLineSeparator());
}
return str;
}
} catch (JavaModelException e) {
}
}
return null;
}
private static int getIndentUsed(IBuffer buffer, int offset, IJavaProject project) {
int i= offset;
while (i > 0 && !IndentManipulation.isLineDelimiterChar(buffer.getChar(i - 1))) {
i--;
}
return Strings.computeIndentUnits(buffer.getText(i, offset - i), project);
}
public static List<? extends ASTNode> getContainingList(ASTNode node) {
StructuralPropertyDescriptor locationInParent= node.getLocationInParent();
if (locationInParent != null && locationInParent.isChildListProperty()) {
return getChildListProperty(node.getParent(), (ChildListPropertyDescriptor) locationInParent);
}
return null;
}
@SuppressWarnings("unchecked")
public static <T extends ASTNode> List<T> getChildListProperty(ASTNode node, ChildListPropertyDescriptor propertyDescriptor) {
return (List<T>) node.getStructuralProperty(propertyDescriptor);
}
public static List<ASTNode> getChildren(ASTNode node) {
ChildrenCollector visitor= new ChildrenCollector();
node.accept(visitor);
return visitor.result;
}
private static class ChildrenCollector extends GenericVisitor {
public List<ASTNode> result;
public ChildrenCollector() {
super(true);
result= null;
}
@Override
protected boolean visitNode(ASTNode node) {
if (result == null) {
result= new ArrayList<>();
return true;
}
result.add(node);
return false;
}
}
public static boolean isExistingNode(ASTNode node) {
return node.getStartPosition() != -1;
}
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 CompilationUnit) {
return ((CompilationUnit)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;
}
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();
else if (parent instanceof LambdaExpression)
return null;
}
Assert.isTrue(false, "Unknown VariableDeclaration");
return null;
}
public static int getDimensions(VariableDeclaration declaration) {
int dim= declaration.getExtraDimensions();
if (declaration instanceof VariableDeclarationFragment && declaration.getParent() instanceof LambdaExpression) {
LambdaExpression lambda= (LambdaExpression) declaration.getParent();
IMethodBinding methodBinding= lambda.resolveMethodBinding();
if (methodBinding != null) {
ITypeBinding[] parameterTypes= methodBinding.getParameterTypes();
int index= lambda.parameters().indexOf(declaration);
ITypeBinding typeBinding= parameterTypes[index];
return typeBinding.getDimensions();
}
} else {
Type type= getType(declaration);
if (type instanceof ArrayType) {
dim+= ((ArrayType) type).getDimensions();
}
}
return dim;
}
public static List<IExtendedModifier> 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.TEXT_BLOCK;
}
public static boolean isLabel(SimpleName name) {
int parentType= name.getParent().getNodeType();
return parentType == ASTNode.LABELED_STATEMENT ||
(parentType == ASTNode.BREAK_STATEMENT && name.getLocationInParent() == BreakStatement.LABEL_PROPERTY) ||
parentType != ASTNode.CONTINUE_STATEMENT;
}
public static boolean isStatic(BodyDeclaration declaration) {
return Modifier.isStatic(declaration.getModifiers());
}
public static List<BodyDeclaration> getBodyDeclarations(ASTNode node) {
if (node instanceof AbstractTypeDeclaration) {
return ((AbstractTypeDeclaration)node).bodyDeclarations();
} else if (node instanceof AnonymousClassDeclaration) {
return ((AnonymousClassDeclaration)node).bodyDeclarations();
}
Assert.isTrue(false);
return null;
}
public static ChildListPropertyDescriptor getBodyDeclarationsProperty(ASTNode node) {
if (node instanceof AbstractTypeDeclaration) {
return ((AbstractTypeDeclaration)node).getBodyDeclarationsProperty();
} else if (node instanceof AnonymousClassDeclaration) {
return AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY;
}
Assert.isTrue(false);
return null;
}
public static String getTypeName(Type type) {
final StringBuffer buffer= new StringBuffer();
ASTVisitor visitor= new ASTVisitor() {
@Override
public boolean visit(PrimitiveType node) {
buffer.append(node.getPrimitiveTypeCode().toString());
return false;
}
@Override
public boolean visit(SimpleType node) {
buffer.append(getSimpleNameIdentifier(node.getName()));
return false;
}
@Override
public boolean visit(QualifiedType node) {
buffer.append(node.getName().getIdentifier());
return false;
}
@Override
public boolean visit(NameQualifiedType node) {
buffer.append(node.getName().getIdentifier());
return false;
}
@Override
public boolean visit(ParameterizedType node) {
node.getType().accept(this);
return false;
}
@Override
public void endVisit(ArrayType node) {
for (int i= 0; i < node.dimensions().size(); i++) {
buffer.append("[]");
}
}
};
type.accept(visitor);
return buffer.toString();
}
public static String getQualifiedTypeName(Type type) {
final StringBuffer buffer= new StringBuffer();
ASTVisitor visitor= new ASTVisitor() {
@Override
public boolean visit(SimpleType node) {
buffer.append(node.getName().getFullyQualifiedName());
return false;
}
@Override
public boolean visit(QualifiedType node) {
node.getQualifier().accept(this);
buffer.append('.');
buffer.append(node.getName().getIdentifier());
return false;
}
@Override
public boolean visit(NameQualifiedType node) {
buffer.append(node.getQualifier().getFullyQualifiedName());
buffer.append('.');
buffer.append(node.getName().getIdentifier());
return false;
}
@Override
public boolean visit(ParameterizedType node) {
node.getType().accept(this);
return false;
}
@Override
public void endVisit(ArrayType node) {
for (int i= 0; i < node.dimensions().size(); i++) {
buffer.append("[]");
}
}
};
type.accept(visitor);
return buffer.toString();
}
public static Boolean getBooleanLiteral(Expression expression) {
final BooleanLiteral bl= as(expression, BooleanLiteral.class);
if (bl != null) {
return Boolean.valueOf(bl.booleanValue());
}
final QualifiedName qn= as(expression, QualifiedName.class);
if (hasType(qn, Boolean.class.getCanonicalName())) {
return getBooleanObject(qn);
}
return null;
}
@SuppressWarnings("unchecked")
public static <T extends Expression> T as(Expression expression, Class<T> exprClass) {
if (expression != null) {
if (exprClass.isAssignableFrom(expression.getClass())) {
return (T) expression;
} else if (expression instanceof ParenthesizedExpression) {
return as(((ParenthesizedExpression) expression).getExpression(), exprClass);
}
}
return null;
}
public static List<Statement> asList(Statement statement) {
if (statement == null) {
return Collections.emptyList();
}
if (statement instanceof Block) {
return ((Block) statement).statements();
}
return Arrays.asList(statement);
}
public static List<Expression> allOperands(InfixExpression node) {
final List<Expression> extOps= node.extendedOperands();
final List<Expression> results= new ArrayList<>(2 + extOps.size());
results.add(node.getLeftOperand());
results.add(node.getRightOperand());
results.addAll(extOps);
return results;
}
public static Boolean getBooleanObject(final QualifiedName qualifiedName) {
final String fqn= qualifiedName.getFullyQualifiedName();
if ("Boolean.TRUE".equals(fqn)) {
return Boolean.TRUE;
} else if ("Boolean.FALSE".equals(fqn)) {
return Boolean.FALSE;
}
return null;
}
public static boolean hasOperator(InfixExpression node, InfixExpression.Operator anOperator, InfixExpression.Operator... operators) {
return node != null && isOperatorInList(node.getOperator(), anOperator, operators);
}
public static boolean hasOperator(PrefixExpression node, PrefixExpression.Operator anOperator, PrefixExpression.Operator... operators) {
return node != null && isOperatorInList(node.getOperator(), anOperator, operators);
}
private static boolean isOperatorInList(Object realOperator, Object anOperator, Object[] operators) {
return realOperator != null && (realOperator.equals(anOperator) || Arrays.asList(operators).contains(realOperator));
}
public static boolean hasType(Expression expression, String... oneOfQualifiedTypeNames) {
return expression != null && hasType(expression.resolveTypeBinding(), oneOfQualifiedTypeNames);
}
public static boolean hasType(final ITypeBinding typeBinding, String... oneOfQualifiedTypeNames) {
if (typeBinding != null) {
final String qualifiedName= typeBinding.getErasure().getQualifiedName();
for (String qualifiedTypeName : oneOfQualifiedTypeNames) {
if (qualifiedTypeName.equals(qualifiedName)) {
return true;
}
}
}
return false;
}
public static InfixExpression.Operator oppositeInfixOperator(InfixExpression.Operator operator) {
if (InfixExpression.Operator.LESS.equals(operator))
return InfixExpression.Operator.GREATER_EQUALS;
if (InfixExpression.Operator.LESS_EQUALS.equals(operator))
return InfixExpression.Operator.GREATER;
if (InfixExpression.Operator.GREATER.equals(operator))
return InfixExpression.Operator.LESS_EQUALS;
if (InfixExpression.Operator.GREATER_EQUALS.equals(operator))
return InfixExpression.Operator.LESS;
if (InfixExpression.Operator.EQUALS.equals(operator))
return InfixExpression.Operator.NOT_EQUALS;
if (InfixExpression.Operator.NOT_EQUALS.equals(operator))
return InfixExpression.Operator.EQUALS;
if (InfixExpression.Operator.CONDITIONAL_AND.equals(operator))
return InfixExpression.Operator.CONDITIONAL_OR;
if (InfixExpression.Operator.CONDITIONAL_OR.equals(operator))
return InfixExpression.Operator.CONDITIONAL_AND;
return null;
}
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");
return null;
}
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 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()) {
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()) {
ITypeBinding unboxedInitializerType= Bindings.getUnboxedTypeBinding(initializerType, reference.getAST());
if (!unboxedInitializerType.isEqualTo(referenceType))
return referenceType;
} else if (initializerType.isRawType() && referenceType.isParameterizedType()) {
return referenceType;
} else if (initializer instanceof LambdaExpression || initializer instanceof MethodReference) {
if (isTargetAmbiguous(reference, isExplicitlyTypedLambda(initializer))) {
return referenceType;
} else {
ITypeBinding targetType= getTargetType(reference);
if (targetType == null || targetType != referenceType) {
return referenceType;
}
}
} else if (! TypeRules.canAssign(initializerType, referenceType)) {
if (!Bindings.containsTypeVariables(referenceType))
return referenceType;
}
return null;
}
public static boolean isTargetAmbiguous(Expression expression, boolean expressionIsExplicitlyTyped) {
StructuralPropertyDescriptor locationInParent= expression.getLocationInParent();
while (locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY
|| locationInParent == ConditionalExpression.THEN_EXPRESSION_PROPERTY
|| locationInParent == ConditionalExpression.ELSE_EXPRESSION_PROPERTY) {
expression= (Expression) expression.getParent();
locationInParent= expression.getLocationInParent();
}
ASTNode parent= expression.getParent();
IMethodBinding methodBinding;
int argumentIndex;
int argumentCount;
Expression invocationQualifier= null;
if (locationInParent == MethodInvocation.ARGUMENTS_PROPERTY) {
MethodInvocation methodInvocation= (MethodInvocation) parent;
methodBinding= methodInvocation.resolveMethodBinding();
argumentIndex= methodInvocation.arguments().indexOf(expression);
argumentCount= methodInvocation.arguments().size();
invocationQualifier= methodInvocation.getExpression();
} else if (locationInParent == SuperMethodInvocation.ARGUMENTS_PROPERTY) {
SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) parent;
methodBinding= superMethodInvocation.resolveMethodBinding();
argumentIndex= superMethodInvocation.arguments().indexOf(expression);
argumentCount= superMethodInvocation.arguments().size();
invocationQualifier= superMethodInvocation.getQualifier();
} else if (locationInParent == ConstructorInvocation.ARGUMENTS_PROPERTY) {
ConstructorInvocation constructorInvocation= (ConstructorInvocation) parent;
methodBinding= constructorInvocation.resolveConstructorBinding();
argumentIndex= constructorInvocation.arguments().indexOf(expression);
argumentCount= constructorInvocation.arguments().size();
} else if (locationInParent == SuperConstructorInvocation.ARGUMENTS_PROPERTY) {
SuperConstructorInvocation superConstructorInvocation= (SuperConstructorInvocation) parent;
methodBinding= superConstructorInvocation.resolveConstructorBinding();
argumentIndex= superConstructorInvocation.arguments().indexOf(expression);
argumentCount= superConstructorInvocation.arguments().size();
} else if (locationInParent == ClassInstanceCreation.ARGUMENTS_PROPERTY) {
ClassInstanceCreation creation= (ClassInstanceCreation) parent;
methodBinding= creation.resolveConstructorBinding();
argumentIndex= creation.arguments().indexOf(expression);
argumentCount= creation.arguments().size();
} else if (locationInParent == EnumConstantDeclaration.ARGUMENTS_PROPERTY) {
EnumConstantDeclaration enumConstantDecl= (EnumConstantDeclaration) parent;
methodBinding= enumConstantDecl.resolveConstructorBinding();
argumentIndex= enumConstantDecl.arguments().indexOf(expression);
argumentCount= enumConstantDecl.arguments().size();
} else {
return false;
}
if (methodBinding != null) {
ITypeBinding invocationTargetType;
invocationTargetType= getInvocationType(parent, methodBinding, invocationQualifier);
if (invocationTargetType != null) {
TypeBindingVisitor visitor= new AmbiguousTargetMethodAnalyzer(invocationTargetType, methodBinding, argumentIndex, argumentCount, expressionIsExplicitlyTyped);
return !(visitor.visit(invocationTargetType) && Bindings.visitHierarchy(invocationTargetType, visitor));
}
}
return true;
}
public static ITypeBinding getInvocationType(ASTNode invocationNode, IMethodBinding methodBinding, Expression invocationQualifier) {
ITypeBinding invocationType;
if (invocationNode instanceof MethodInvocation || invocationNode instanceof SuperMethodInvocation) {
if (invocationQualifier != null) {
invocationType= invocationQualifier.resolveTypeBinding();
if (invocationType != null && invocationNode instanceof SuperMethodInvocation) {
invocationType= invocationType.getSuperclass();
}
} else {
ITypeBinding enclosingType= getEnclosingType(invocationNode);
if (enclosingType != null && invocationNode instanceof SuperMethodInvocation) {
enclosingType= enclosingType.getSuperclass();
}
if (enclosingType != null) {
IMethodBinding methodInHierarchy= Bindings.findMethodInHierarchy(enclosingType, methodBinding.getName(), methodBinding.getParameterTypes());
if (methodInHierarchy != null) {
invocationType= enclosingType;
} else {
invocationType= methodBinding.getDeclaringClass();
}
} else {
invocationType= methodBinding.getDeclaringClass();
}
}
} else {
invocationType= methodBinding.getDeclaringClass();
}
return invocationType;
}
private static class AmbiguousTargetMethodAnalyzer implements TypeBindingVisitor {
private ITypeBinding fDeclaringType;
private IMethodBinding fOriginalMethod;
private int fArgIndex;
private int fArgumentCount;
private boolean fExpressionIsExplicitlyTyped;
public AmbiguousTargetMethodAnalyzer(ITypeBinding declaringType, IMethodBinding originalMethod, int argumentIndex, int argumentCount, boolean expressionIsExplicitlyTyped) {
fDeclaringType= declaringType;
fOriginalMethod= originalMethod;
fArgIndex= argumentIndex;
fArgumentCount= argumentCount;
fExpressionIsExplicitlyTyped= expressionIsExplicitlyTyped;
}
@Override
public boolean visit(ITypeBinding type) {
IMethodBinding[] methods= type.getDeclaredMethods();
for (int i= 0; i < methods.length; i++) {
IMethodBinding candidate= methods[i];
if (candidate.getMethodDeclaration() == fOriginalMethod.getMethodDeclaration()) {
continue;
}
ITypeBinding candidateDeclaringType= candidate.getDeclaringClass();
if (fDeclaringType != candidateDeclaringType) {
int modifiers= candidate.getModifiers();
if (candidateDeclaringType.isInterface() && Modifier.isStatic(modifiers)) {
continue;
}
if (Modifier.isPrivate(modifiers)) {
continue;
}
}
if (fOriginalMethod.getName().equals(candidate.getName()) && !fOriginalMethod.overrides(candidate)) {
ITypeBinding[] originalParameterTypes= fOriginalMethod.getParameterTypes();
ITypeBinding[] candidateParameterTypes= candidate.getParameterTypes();
boolean couldBeAmbiguous;
if (originalParameterTypes.length == candidateParameterTypes.length) {
couldBeAmbiguous= true;
} else if (fOriginalMethod.isVarargs() || candidate.isVarargs() ) {
int candidateMinArgumentCount= candidateParameterTypes.length;
if (candidate.isVarargs())
candidateMinArgumentCount--;
couldBeAmbiguous= fArgumentCount >= candidateMinArgumentCount;
} else {
couldBeAmbiguous= false;
}
if (couldBeAmbiguous) {
ITypeBinding parameterType= ASTResolving.getParameterTypeBinding(candidate, fArgIndex);
if (parameterType != null && parameterType.getFunctionalInterfaceMethod() != null) {
if (!fExpressionIsExplicitlyTyped) {
return false;
}
ITypeBinding origParamType= ASTResolving.getParameterTypeBinding(fOriginalMethod, fArgIndex);
boolean originalIsVoidCompatible= Bindings.isVoidType(origParamType.getFunctionalInterfaceMethod().getReturnType());
boolean candidateIsVoidCompatible= Bindings.isVoidType(parameterType.getFunctionalInterfaceMethod().getReturnType());
if (originalIsVoidCompatible == candidateIsVoidCompatible) {
return false;
}
}
}
}
}
return true;
}
}
public static ITypeBinding getTargetType(Expression expression) {
ASTNode parent= expression.getParent();
StructuralPropertyDescriptor locationInParent= expression.getLocationInParent();
if (locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY || locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY) {
return ((VariableDeclaration) parent).getName().resolveTypeBinding();
} else if (locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY) {
return ((Assignment) parent).getLeftHandSide().resolveTypeBinding();
} else if (locationInParent == ReturnStatement.EXPRESSION_PROPERTY) {
return getTargetTypeForReturnStmt((ReturnStatement) parent);
} else if (locationInParent == ArrayInitializer.EXPRESSIONS_PROPERTY) {
return getTargetTypeForArrayInitializer((ArrayInitializer) parent);
} else if (locationInParent == ArrayAccess.INDEX_PROPERTY) {
return parent.getAST().resolveWellKnownType(int.class.getSimpleName());
} else if (locationInParent == ConditionalExpression.EXPRESSION_PROPERTY
|| locationInParent == IfStatement.EXPRESSION_PROPERTY
|| locationInParent == WhileStatement.EXPRESSION_PROPERTY
|| locationInParent == DoStatement.EXPRESSION_PROPERTY) {
return parent.getAST().resolveWellKnownType(boolean.class.getSimpleName());
} else if (locationInParent == SwitchStatement.EXPRESSION_PROPERTY) {
final ITypeBinding discriminentType= expression.resolveTypeBinding();
if (discriminentType.isPrimitive() || discriminentType.isEnum()
|| discriminentType.getQualifiedName().equals(String.class.getCanonicalName())) {
return discriminentType;
} else {
return Bindings.getUnboxedTypeBinding(discriminentType, parent.getAST());
}
} else if (locationInParent == MethodInvocation.ARGUMENTS_PROPERTY) {
MethodInvocation methodInvocation= (MethodInvocation) parent;
IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
if (methodBinding != null) {
return getParameterTypeBinding(expression, methodInvocation.arguments(), methodBinding);
}
} else if (locationInParent == SuperMethodInvocation.ARGUMENTS_PROPERTY) {
SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) parent;
IMethodBinding superMethodBinding= superMethodInvocation.resolveMethodBinding();
if (superMethodBinding != null) {
return getParameterTypeBinding(expression, superMethodInvocation.arguments(), superMethodBinding);
}
} else if (locationInParent == ConstructorInvocation.ARGUMENTS_PROPERTY) {
ConstructorInvocation constructorInvocation= (ConstructorInvocation) parent;
IMethodBinding constructorBinding= constructorInvocation.resolveConstructorBinding();
if (constructorBinding != null) {
return getParameterTypeBinding(expression, constructorInvocation.arguments(), constructorBinding);
}
} else if (locationInParent == SuperConstructorInvocation.ARGUMENTS_PROPERTY) {
SuperConstructorInvocation superConstructorInvocation= (SuperConstructorInvocation) parent;
IMethodBinding superConstructorBinding= superConstructorInvocation.resolveConstructorBinding();
if (superConstructorBinding != null) {
return getParameterTypeBinding(expression, superConstructorInvocation.arguments(), superConstructorBinding);
}
} else if (locationInParent == ClassInstanceCreation.ARGUMENTS_PROPERTY) {
ClassInstanceCreation creation= (ClassInstanceCreation) parent;
IMethodBinding creationBinding= creation.resolveConstructorBinding();
if (creationBinding != null) {
return getParameterTypeBinding(expression, creation.arguments(), creationBinding);
}
} else if (locationInParent == EnumConstantDeclaration.ARGUMENTS_PROPERTY) {
EnumConstantDeclaration enumConstantDecl= (EnumConstantDeclaration) parent;
IMethodBinding enumConstructorBinding= enumConstantDecl.resolveConstructorBinding();
if (enumConstructorBinding != null) {
return getParameterTypeBinding(expression, enumConstantDecl.arguments(), enumConstructorBinding);
}
} else if (locationInParent == LambdaExpression.BODY_PROPERTY) {
IMethodBinding methodBinding= ((LambdaExpression) parent).resolveMethodBinding();
if (methodBinding != null) {
return methodBinding.getReturnType();
}
} else if (locationInParent == ConditionalExpression.THEN_EXPRESSION_PROPERTY || locationInParent == ConditionalExpression.ELSE_EXPRESSION_PROPERTY) {
return getTargetType((ConditionalExpression) parent);
} else if (locationInParent == CastExpression.EXPRESSION_PROPERTY) {
return ((CastExpression) parent).getType().resolveBinding();
} else if (locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY) {
return getTargetType((ParenthesizedExpression) parent);
}
return null;
}
private static ITypeBinding getParameterTypeBinding(Expression expression, List<Expression> arguments, IMethodBinding methodBinding) {
int index= arguments.indexOf(expression);
return ASTResolving.getParameterTypeBinding(methodBinding, index);
}
private static ITypeBinding getTargetTypeForArrayInitializer(ArrayInitializer arrayInitializer) {
ASTNode initializerParent= arrayInitializer.getParent();
while (initializerParent instanceof ArrayInitializer) {
initializerParent= initializerParent.getParent();
}
if (initializerParent instanceof ArrayCreation) {
return ((ArrayCreation) initializerParent).getType().getElementType().resolveBinding();
} else if (initializerParent instanceof VariableDeclaration) {
ITypeBinding typeBinding= ((VariableDeclaration) initializerParent).getName().resolveTypeBinding();
if (typeBinding != null) {
return typeBinding.getElementType();
}
}
return null;
}
private static ITypeBinding getTargetTypeForReturnStmt(ReturnStatement returnStmt) {
LambdaExpression enclosingLambdaExpr= ASTResolving.findEnclosingLambdaExpression(returnStmt);
if (enclosingLambdaExpr != null) {
IMethodBinding methodBinding= enclosingLambdaExpr.resolveMethodBinding();
return methodBinding == null ? null : methodBinding.getReturnType();
}
MethodDeclaration enclosingMethodDecl= ASTResolving.findParentMethodDeclaration(returnStmt);
if (enclosingMethodDecl != null) {
IMethodBinding methodBinding= enclosingMethodDecl.resolveBinding();
return methodBinding == null ? null : methodBinding.getReturnType();
}
return null;
}
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;
}
public static boolean isExplicitlyTypedLambda(Expression expression) {
if (!(expression instanceof LambdaExpression))
return false;
LambdaExpression lambda= (LambdaExpression) expression;
List<VariableDeclaration> parameters= lambda.parameters();
if (parameters.isEmpty())
return true;
return parameters.get(0) instanceof SingleVariableDeclaration;
}
public static <T extends ASTNode> T getParent(ASTNode node, Class<T> parentClass) {
do {
node= node.getParent();
} while (node != null && !parentClass.isInstance(node));
return parentClass.cast(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;
if (QualifiedName.NAME_PROPERTY.equals(current.getLocationInParent())) {
current= current.getParent();
}
if (QualifiedType.NAME_PROPERTY.equals(current.getLocationInParent())
|| SimpleType.NAME_PROPERTY.equals(current.getLocationInParent())
|| NameQualifiedType.NAME_PROPERTY.equals(current.getLocationInParent())) {
current= current.getParent();
}
if (ParameterizedType.TYPE_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 IMethodBinding getMethodBinding(Name node) {
IBinding binding= node.resolveBinding();
if (binding instanceof IMethodBinding)
return (IMethodBinding)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;
}
public static ITypeBinding getReceiverTypeBinding(MethodInvocation invocation) {
ITypeBinding result= null;
Expression exp= invocation.getExpression();
if(exp != null) {
return exp.resolveTypeBinding();
}
else {
AbstractTypeDeclaration type= 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();
}
node= node.getParent();
}
return null;
}
public static IProblem[] getProblems(ASTNode node, int scope, int severity) {
ASTNode 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<>(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();
else if ((severity & INFO) != 0)
consider= problem.isInfo();
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 result.toArray(new IProblem[result.size()]);
}
public static Message[] getMessages(ASTNode node, int flags) {
ASTNode 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<>(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 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;
}
}
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 Name getTopMostName(Name name) {
Name result= name;
while(result.getParent() instanceof Name) {
result= (Name)result.getParent();
}
return result;
}
public static Type getTopMostType(ASTNode node) {
ASTNode result= null;
while (node instanceof Type && !(node instanceof UnionType)
|| node instanceof Name
|| node instanceof Annotation || node instanceof MemberValuePair
|| node instanceof Expression) {
result= node;
node= node.getParent();
}
if (result instanceof Type)
return (Type) result;
return null;
}
public static int changeVisibility(int modifiers, int visibility) {
return (modifiers & CLEAR_VISIBILITY) | visibility;
}
public static void setFlagsToAST(ASTNode root, final int flags) {
root.accept(new GenericVisitor(true) {
@Override
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 "";
}
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 boolean usesGivenSignature(MethodInvocation node, String typeQualifiedName, String methodName,
String... parameterTypesQualifiedNames) {
if (node == null
|| node.resolveMethodBinding() == null
|| !node.resolveMethodBinding().getDeclaringClass().getQualifiedName().equals(typeQualifiedName)
|| !node.getName().getIdentifier().equals(methodName)) {
return false;
}
if (node.arguments() == null && parameterTypesQualifiedNames == null) {
return true;
}
if (node.arguments() == null || parameterTypesQualifiedNames == null) {
return true;
}
if (node.arguments().size() == parameterTypesQualifiedNames.length) {
return true;
}
for (int i= 0; i < parameterTypesQualifiedNames.length; i++) {
if (((Type) node.typeArguments().get(i)).resolveBinding() == null
|| ((Type) node.typeArguments().get(i)).resolveBinding().getQualifiedName() != parameterTypesQualifiedNames[i]) {
return false;
}
}
return true;
}
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 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= getParent(NodeFinder.perform(root, type.getNameRange()), ClassInstanceCreation.class);
if (creation != null)
return creation.resolveTypeBinding();
}
} else {
final AbstractTypeDeclaration declaration= getParent(NodeFinder.perform(root, type.getNameRange()), AbstractTypeDeclaration.class);
if (declaration != null)
return declaration.resolveBinding();
}
return null;
}
public static String getEscapedStringLiteral(String stringValue) {
StringLiteral stringLiteral= AST.newAST(IASTSharedValues.SHARED_AST_LEVEL, false).newStringLiteral();
stringLiteral.setLiteralValue(stringValue);
return stringLiteral.getEscapedValue();
}
public static String getEscapedCharacterLiteral(char ch) {
CharacterLiteral characterLiteral= AST.newAST(IASTSharedValues.SHARED_AST_LEVEL, false).newCharacterLiteral();
characterLiteral.setCharValue(ch);
return characterLiteral.getEscapedValue();
}
public static ASTNode getCopyOrReplacement(ASTRewrite rewrite, ASTNode node, TextEditGroup group) {
ASTNode rewrittenNode= (ASTNode) rewrite.get(node.getParent(), node.getLocationInParent());
if (rewrittenNode != node) {
rewrite.replace(rewrittenNode, node, group);
return rewrittenNode;
}
return rewrite.createCopyTarget(node);
}
@SuppressWarnings("unchecked")
public static <T extends ASTNode> T createMoveTarget(ASTRewrite rewrite, T node) {
return (T) rewrite.createMoveTarget(node);
}
@SuppressWarnings("unchecked")
public static <T extends ASTNode> T copySubtree(AST target, T node) {
return (T) ASTNode.copySubtree(target, node);
}
public static List<String> getVisibleLocalVariablesInScope(ASTNode node) {
List<String> variableNames= new ArrayList<>();
CompilationUnit root= (CompilationUnit) node.getRoot();
IBinding[] bindings= new ScopeAnalyzer(root).
getDeclarationsInScope(node.getStartPosition(), ScopeAnalyzer.VARIABLES | ScopeAnalyzer.NO_FIELDS | ScopeAnalyzer.CHECK_VISIBILITY);
for (IBinding binding : bindings) {
variableNames.add(binding.getName());
}
return variableNames;
}
public static boolean hasSemicolon(ExpressionStatement exprStatement, ICompilationUnit cu) {
boolean hasSemicolon= true;
if ((exprStatement.getFlags() & ASTNode.RECOVERED) != 0) {
try {
Expression expression= exprStatement.getExpression();
TokenScanner scanner= new TokenScanner(cu);
hasSemicolon= scanner.readNext(expression.getStartPosition() + expression.getLength(), true) == ITerminalSymbols.TokenNameSEMICOLON;
} catch (CoreException e) {
hasSemicolon= false;
}
}
return hasSemicolon;
}
public static boolean isVarType(ASTNode node, CompilationUnit astRoot) {
IJavaElement root= astRoot.getJavaElement();
if (root == null) {
return false;
}
IJavaProject javaProject= root.getJavaProject();
if (javaProject == null) {
return false;
}
if (!JavaModelUtil.is10OrHigher(javaProject)) {
return false;
}
Type type= null;
if (node instanceof SimpleName) {
IBinding binding= null;
SimpleName name= (SimpleName) node;
binding= name.resolveBinding();
if (!(binding instanceof IVariableBinding)) {
return false;
}
IVariableBinding varBinding= (IVariableBinding) binding;
if (varBinding.isField() || varBinding.isParameter()) {
return false;
}
ASTNode varDeclaration= astRoot.findDeclaringNode(varBinding);
if (varDeclaration == null) {
return false;
}
ITypeBinding typeBinding= varBinding.getType();
if (typeBinding == null || typeBinding.isAnonymous() || typeBinding.isIntersectionType() || typeBinding.isWildcardType()) {
return false;
}
if (varDeclaration instanceof SingleVariableDeclaration) {
type= ((SingleVariableDeclaration) varDeclaration).getType();
} else if (varDeclaration instanceof VariableDeclarationFragment) {
ASTNode parent= varDeclaration.getParent();
if (parent instanceof VariableDeclarationStatement) {
type= ((VariableDeclarationStatement) parent).getType();
} else if (parent instanceof VariableDeclarationExpression) {
type= ((VariableDeclarationExpression) parent).getType();
}
}
} else if (node instanceof VariableDeclarationStatement) {
type= ((VariableDeclarationStatement)node).getType();
} else {
return false;
}
return type == null ? false : type.isVar();
}
}