package edu.ohio_state.khatchad.refactoring.core;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchStatement;
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.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.core.SourceRange;
import edu.ohio_state.khatchad.refactoring.Messages;
import edu.ohio_state.khatchad.refactoring.exceptions.DefinitelyNotEnumerizableException;
import edu.ohio_state.khatchad.refactoring.exceptions.DefinitelyNotEnumerizableOperationException;
import edu.ohio_state.khatchad.refactoring.exceptions.NonEnumerizableASTException;
import edu.ohio_state.khatchad.refactoring.exceptions.NonEnumerizableCastExpression;
import edu.ohio_state.khatchad.refactoring.exceptions.NonEnumerizableOperationException;
import edu.ohio_state.khatchad.refactoring.visitor.ParameterProcessingVisitor;
public class ASTNodeProcessor {
private static boolean containedIn(ASTNode node, Name name) {
ASTNode curr = name;
while (curr != null)
if (node.equals(curr))
return true;
else
curr = curr.getParent();
return false;
}
private static boolean containedIn(List arguments, Name name) {
ASTNode curr = name;
while (curr != null)
if (arguments.contains(curr))
return true;
else
curr = curr.getParent();
return false;
}
/**
* Returns to formal parameter number of svd starting from zero.
*
* @param svd
* The formal parameter.
* @return The formal parameter number starting at zero.
*/
private static int getFormalParameterNumber(SingleVariableDeclaration svd) {
final MethodDeclaration decl = (MethodDeclaration) svd.getParent();
return decl.parameters().indexOf(svd);
}
private static int getParamNumber(List arguments, Name name) {
ASTNode curr = name;
while (curr != null) {
final int inx = arguments.indexOf(curr);
if (inx != -1)
return inx;
else
curr = curr.getParent();
}
return -1;
}
private final Collection constFields;
private final Collection found = new LinkedHashSet();
private final Collection legalEncounteredInfixExpressionSourceLocations = new LinkedHashSet();
private final IProgressMonitor monitor;
private final Name name;
private final IJavaSearchScope scope;
public ASTNodeProcessor(ASTNode node, Collection constFields,
IJavaSearchScope scope, IProgressMonitor monitor) {
this.name = (Name) node;
this.constFields = constFields;
this.scope = scope;
this.monitor = monitor;
}
public Collection getFound() {
return this.found;
}
public Collection getLegalEncounteredInfixExpressionSourceLocations() {
return this.legalEncounteredInfixExpressionSourceLocations;
}
public void process() throws CoreException {
// boxing.
if (this.name != null && this.name.resolveBoxing())
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_EncounteredBoxedExpression, this.name);
if (this.name != null)
this.process(this.name);
}
private void findFormalsForVariable(ClassInstanceCreation ctorCall)
throws JavaModelException, CoreException {
final int paramNumber = getParamNumber(ctorCall.arguments(), this.name);
IMethod meth = (IMethod) ctorCall.resolveConstructorBinding()
.getJavaElement();
if (meth == null && ctorCall.getAnonymousClassDeclaration() != null) {
// most likely an anonymous class.
final AnonymousClassDeclaration acd = ctorCall
.getAnonymousClassDeclaration();
final ITypeBinding binding = acd.resolveBinding();
final ITypeBinding superBinding = binding.getSuperclass();
for (final Iterator it = Arrays.asList(
superBinding.getDeclaredMethods()).iterator(); it.hasNext();) {
final IMethodBinding imb = (IMethodBinding) it.next();
if (imb.isConstructor()) {
final ITypeBinding[] itb = imb.getParameterTypes();
if (itb.length > paramNumber) {
final ITypeBinding ithParamType = itb[paramNumber];
if (ithParamType.isEqualTo(((Expression) ctorCall
.arguments().get(paramNumber))
.resolveTypeBinding())) {
meth = (IMethod) imb.getJavaElement();
break;
}
}
}
}
}
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(Messages.ASTNodeProcessor_SourceNotPresent,
ctorCall);
else
this.findFormalsForVariable(top, paramNumber);
}
private void findFormalsForVariable(ConstructorInvocation ctorCall)
throws JavaModelException, CoreException {
final IMethod meth = (IMethod) ctorCall.resolveConstructorBinding()
.getJavaElement();
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(Messages.ASTNodeProcessor_SourceNotPresent,
ctorCall);
else
this.findFormalsForVariable(top, getParamNumber(ctorCall
.arguments(), this.name));
}
private void findFormalsForVariable(IMethod correspondingMethod,
final int paramNumber) throws CoreException {
final SearchPattern pattern = SearchPattern.createPattern(
correspondingMethod, IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_EXACT_MATCH);
this.findParameters(paramNumber, pattern);
}
private void findFormalsForVariable(MethodInvocation mi)
throws JavaModelException, CoreException {
final IMethod meth = (IMethod) mi.resolveMethodBinding()
.getJavaElement();
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(Messages.ASTNodeProcessor_SourceNotPresent,
mi);
else
this.findFormalsForVariable(top, getParamNumber(mi.arguments(),
this.name));
}
private void findFormalsForVariable(SuperConstructorInvocation ctorCall)
throws JavaModelException, CoreException {
final IMethod meth = (IMethod) ctorCall.resolveConstructorBinding()
.getJavaElement();
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(Messages.ASTNodeProcessor_SourceNotPresent,
ctorCall);
else
this.findFormalsForVariable(top, getParamNumber(ctorCall
.arguments(), this.name));
}
private void findFormalsForVariable(SuperMethodInvocation smi)
throws JavaModelException, CoreException {
final IMethod meth = (IMethod) smi.resolveMethodBinding()
.getJavaElement();
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(Messages.ASTNodeProcessor_SourceNotPresent,
smi);
else
this.findFormalsForVariable(top, getParamNumber(smi.arguments(),
this.name));
}
private void findParameters(final int paramNumber, SearchPattern pattern)
throws CoreException {
final SearchRequestor requestor = new SearchRequestor() {
public void acceptSearchMatch(SearchMatch match)
throws CoreException {
if (match.getAccuracy() == SearchMatch.A_ACCURATE
&& !match.isInsideDocComment()) {
IJavaElement elem = (IJavaElement) match.getElement();
ASTNode node = Util.getASTNode(elem,
ASTNodeProcessor.this.monitor);
ParameterProcessingVisitor visitor = new ParameterProcessingVisitor(
paramNumber, match.getOffset());
node.accept(visitor);
ASTNodeProcessor.this.found.addAll(visitor.getElements());
for (Iterator it = visitor.getExpressions().iterator(); it
.hasNext();) {
Expression exp = (Expression) it.next();
ASTNodeProcessor.this.processExpression(exp);
}
}
}
};
final SearchEngine searchEngine = new SearchEngine();
searchEngine.search(pattern, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, this.scope, requestor, null);
}
private void findVariablesForFormal(SingleVariableDeclaration svd)
throws CoreException {
// Find invocations of the corresponding method.
final IMethod meth = (IMethod) svd.resolveBinding()
.getDeclaringMethod().getJavaElement();
final SearchPattern pattern = SearchPattern.createPattern(meth,
IJavaSearchConstants.REFERENCES, SearchPattern.R_EXACT_MATCH);
this.findParameters(getFormalParameterNumber(svd), pattern);
}
private void process(ASTNode node) throws CoreException {
switch (node.getNodeType()) {
case ASTNode.QUALIFIED_NAME:
case ASTNode.SIMPLE_NAME:
case ASTNode.FIELD_ACCESS:
case ASTNode.SUPER_FIELD_ACCESS:
case ASTNode.ARRAY_INITIALIZER: {
this.process(node.getParent());
break;
}
case ASTNode.ARRAY_CREATION: {
final ArrayCreation creation = (ArrayCreation) node;
boolean legal = true;
for (final Iterator it = creation.dimensions().iterator(); it
.hasNext();) {
final Expression dimension = (Expression) it.next();
// if coming up from the index.
if (containedIn(dimension, this.name)) {
legal = false;
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_IllegalNodeContext, node);
}
}
if (legal)
this.process(node.getParent());
break;
}
case ASTNode.ARRAY_ACCESS: {
final ArrayAccess access = (ArrayAccess) node;
// if coming up from the index.
if (containedIn(access.getIndex(), this.name))
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_IllegalNodeContext, node);
else
this.process(node.getParent());
break;
}
case ASTNode.ASSIGNMENT: {
final Assignment assignment = (Assignment) node;
if (assignment.getOperator() == Assignment.Operator.ASSIGN) {
this.processExpression(assignment.getLeftHandSide());
this.processExpression(assignment.getRightHandSide());
}
else if (!Util.isSuspiciousAssignmentOperator(assignment
.getOperator()))
throw new DefinitelyNotEnumerizableOperationException(
Messages.ASTNodeProcessor_IllegalAssignmentExpression, assignment
.getOperator(), node);
else
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_IllegalAssignmentExpression, node);
break;
}
case ASTNode.VARIABLE_DECLARATION_STATEMENT: {
final VariableDeclarationStatement vds = (VariableDeclarationStatement) node;
for (final Iterator it = vds.fragments().iterator(); it.hasNext();) {
final VariableDeclarationFragment vdf = (VariableDeclarationFragment) it
.next();
final IJavaElement elem = vdf.resolveBinding().getJavaElement();
if (elem.isReadOnly() || vdf.getName().resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, vdf);
if (vdf.resolveBinding().getType().isEqualTo(
node.getAST().resolveWellKnownType("java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_IllegalArrayUpcast, vdf);
this.found.add(elem);
this.processExpression(vdf.getInitializer());
}
break;
}
case ASTNode.VARIABLE_DECLARATION_FRAGMENT: {
final VariableDeclarationFragment vdf = (VariableDeclarationFragment) node;
final IJavaElement elem = vdf.resolveBinding().getJavaElement();
if (!this.constFields.contains(elem)) {
if (elem == null || vdf == null || vdf.getName() == null)
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
if (elem.isReadOnly() || vdf.getName().resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
if (vdf.resolveBinding().getType().isEqualTo(
node.getAST().resolveWellKnownType("java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_IllegalArrayUpcast, vdf);
this.found.add(elem);
this.processExpression(vdf.getInitializer());
}
break;
}
case ASTNode.FIELD_DECLARATION: {
final FieldDeclaration fd = (FieldDeclaration) node;
for (final Iterator it = fd.fragments().iterator(); it.hasNext();) {
final VariableDeclarationFragment vdf = (VariableDeclarationFragment) it
.next();
final IJavaElement elem = vdf.resolveBinding().getJavaElement();
if (!this.constFields.contains(elem)) {
if (elem.isReadOnly() || vdf.getName().resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, vdf);
if (vdf.resolveBinding().getType().isEqualTo(
node.getAST().resolveWellKnownType(
"java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_IllegalArrayUpcast, vdf);
this.found.add(elem);
this.processExpression(vdf.getInitializer());
}
}
break;
}
case ASTNode.INFIX_EXPRESSION: {
final InfixExpression iexp = (InfixExpression) node;
final InfixExpression.Operator op = iexp.getOperator();
if (Util.isLegalInfixOperator(op)) {
if (Util.inNeedOfTransformation(op)) {
final ISourceRange range = new SourceRange(iexp
.getStartPosition(), iexp.getLength());
this.legalEncounteredInfixExpressionSourceLocations
.add(range);
}
this.processExpression(iexp.getLeftOperand());
this.processExpression(iexp.getRightOperand());
}
else if (!Util.isSuspiciousInfixOperator(op))
throw new DefinitelyNotEnumerizableOperationException(
Messages.ASTNodeProcessor_IllegalInfixExpression, op, node);
else
throw new NonEnumerizableOperationException(
Messages.ASTNodeProcessor_IllegalInfixExpression, op, node);
break;
}
case ASTNode.SWITCH_STATEMENT: {
final SwitchStatement sw = (SwitchStatement) node;
this.processExpression(sw.getExpression());
for (final Iterator it = sw.statements().iterator(); it.hasNext();) {
final Object obj = it.next();
if (obj instanceof SwitchCase) {
final SwitchCase sc = (SwitchCase) obj;
this.processExpression(sc.getExpression());
}
}
break;
}
case ASTNode.SWITCH_CASE: {
final SwitchCase sc = (SwitchCase) node;
this.processExpression(sc.getExpression());
this.process(sc.getParent());
break;
}
case ASTNode.RETURN_STATEMENT: {
final ReturnStatement rs = (ReturnStatement) node;
// process what is being returned.
this.processExpression(rs.getExpression());
// Get the corresponding method declaration.
final MethodDeclaration methDecl = Util.getMethodDeclaration(rs);
// Get the corresponding method.
final IMethod meth = (IMethod) methDecl.resolveBinding()
.getJavaElement();
// Get the top most method
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else {
// Find the topmost method.
if (top.isReadOnly())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
this.found.add(top);
}
break;
}
case ASTNode.CONDITIONAL_EXPRESSION: {
final ConditionalExpression ce = (ConditionalExpression) node;
this.processExpression(ce);
break;
}
case ASTNode.METHOD_DECLARATION: {
final ASTVisitor visitor = new ASTVisitor() {
public boolean visit(ReturnStatement node) {
try {
ASTNodeProcessor.this.processExpression(node
.getExpression());
} catch (JavaModelException E) {
throw new RuntimeException(E);
}
return true;
}
};
node.accept(visitor);
break;
}
case ASTNode.CLASS_INSTANCE_CREATION: {
final ClassInstanceCreation ctorCall = (ClassInstanceCreation) node;
// if coming up from a argument.
if (containedIn(ctorCall.arguments(), this.name))
// if we don't have the source, no can do.
if (!ctorCall.getType().resolveBinding().isFromSource())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else
// go find the formals.
this.findFormalsForVariable(ctorCall);
break;
}
case ASTNode.CONSTRUCTOR_INVOCATION: {
final ConstructorInvocation ctorCall = (ConstructorInvocation) node;
// if coming up from a argument.
if (containedIn(ctorCall.arguments(), this.name))
// if we don't have the source, no can do.
if (!ctorCall.resolveConstructorBinding().getDeclaringClass()
.isFromSource())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else
// go find the formals.
this.findFormalsForVariable(ctorCall);
break;
}
case ASTNode.SUPER_CONSTRUCTOR_INVOCATION: {
final SuperConstructorInvocation ctorCall = (SuperConstructorInvocation) node;
// if coming up from a argument.
if (containedIn(ctorCall.arguments(), this.name))
// if we don't have the source, no can do.
if (!ctorCall.resolveConstructorBinding().getDeclaringClass()
.isFromSource())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else
// go find the formals.
this.findFormalsForVariable(ctorCall);
break;
}
case ASTNode.SUPER_METHOD_INVOCATION: {
final SuperMethodInvocation smi = (SuperMethodInvocation) node;
// if coming up from a argument.
if (containedIn(smi.arguments(), this.name))
// if we don't have the source, no can do.
if (!smi.resolveMethodBinding().getDeclaringClass()
.isFromSource())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else
// go find the formals.
this.findFormalsForVariable(smi);
break;
}
case ASTNode.METHOD_INVOCATION: {
final MethodInvocation mi = (MethodInvocation) node;
// if coming up from a argument.
if (containedIn(mi.arguments(), this.name)) {
// if we don't have the source, no can do.
if (!mi.resolveMethodBinding().getDeclaringClass()
.isFromSource())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else
// go find the formals.
this.findFormalsForVariable(mi);
} else
this.process(node.getParent());
break;
}
case ASTNode.PARENTHESIZED_EXPRESSION: {
this.process(node.getParent());
break;
}
case ASTNode.SINGLE_VARIABLE_DECLARATION: {
// its a formal parameter.
final SingleVariableDeclaration svd = (SingleVariableDeclaration) node;
// take care of local usage.
final IJavaElement elem = svd.resolveBinding().getJavaElement();
if (elem.isReadOnly() || svd.getName().resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
if (svd.resolveBinding().getType().isEqualTo(
node.getAST().resolveWellKnownType("java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(Messages.ASTNodeProcessor_IllegalArrayUpcast,
svd);
this.found.add(elem);
// take care of remote usage.
// go find variables on the corresponding calls.
this.findVariablesForFormal(svd);
break;
}
case ASTNode.EXPRESSION_STATEMENT: {
// dead expression, it's valid just goes no where.
break;
}
case ASTNode.CAST_EXPRESSION: {
final CastExpression cast = (CastExpression) node;
throw new NonEnumerizableCastExpression(Messages.ASTNodeProcessor_IllegalNodeContext,
node, cast.getExpression().resolveTypeBinding(), cast
.getType().resolveBinding());
}
case ASTNode.ENUM_CONSTANT_DECLARATION:
case ASTNode.IF_STATEMENT:
case ASTNode.BOOLEAN_LITERAL:
case ASTNode.NUMBER_LITERAL:
case ASTNode.CHARACTER_LITERAL:
case ASTNode.POSTFIX_EXPRESSION:
case ASTNode.PREFIX_EXPRESSION: {
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_IllegalNodeContext, node);
}
default: {
throw new NonEnumerizableASTException(Messages.ASTNodeProcessor_IllegalNodeContext, node);
}
}
}
protected void processExpression(Expression node) throws JavaModelException {
if (node == null)
return;
switch (node.getNodeType()) {
case ASTNode.SIMPLE_NAME:
case ASTNode.QUALIFIED_NAME: {
final Name name = (Name) node;
if (name.resolveBinding().getJavaElement() == null)
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_NonEnumerizableTypeEncountered, node);
else {
final IJavaElement elem = name.resolveBinding()
.getJavaElement();
if (elem.isReadOnly() || name.resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
if (name.resolveTypeBinding().isEqualTo(
node.getAST().resolveWellKnownType("java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_IllegalArrayUpcast, name);
this.found.add(elem);
}
break;
}
case ASTNode.ARRAY_ACCESS: {
final ArrayAccess access = (ArrayAccess) node;
this.processExpression(access.getArray());
break;
}
case ASTNode.ARRAY_CREATION: {
final ArrayCreation creation = (ArrayCreation) node;
this.processExpression(creation.getInitializer());
break;
}
case ASTNode.ARRAY_INITIALIZER: {
final ArrayInitializer init = (ArrayInitializer) node;
for (final Iterator it = init.expressions().iterator(); it
.hasNext();) {
final Expression exp = (Expression) it.next();
this.processExpression(exp);
}
break;
}
case ASTNode.ASSIGNMENT: {
final Assignment assignment = (Assignment) node;
if (assignment.getOperator() == Assignment.Operator.ASSIGN) {
this.processExpression(assignment.getLeftHandSide());
this.processExpression(assignment.getRightHandSide());
}
else if (!Util.isSuspiciousAssignmentOperator(assignment
.getOperator()))
throw new DefinitelyNotEnumerizableOperationException(
Messages.ASTNodeProcessor_IllegalAssignmentExpression, assignment
.getOperator(), node);
else
throw new NonEnumerizableOperationException(
Messages.ASTNodeProcessor_IllegalAssignmentExpression, assignment
.getOperator(), node);
break;
}
case ASTNode.CONDITIONAL_EXPRESSION: {
final ConditionalExpression ce = (ConditionalExpression) node;
this.processExpression(ce.getThenExpression());
this.processExpression(ce.getElseExpression());
break;
}
case ASTNode.FIELD_ACCESS: {
final FieldAccess fieldAccess = (FieldAccess) node;
if (fieldAccess.resolveFieldBinding().getJavaElement() == null)
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_NonEnumerizableTypeEncountered, node);
else {
final IJavaElement elem = fieldAccess.resolveFieldBinding()
.getJavaElement();
if (elem.isReadOnly() || fieldAccess.resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
if (fieldAccess.resolveTypeBinding().isEqualTo(
node.getAST().resolveWellKnownType("java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_IllegalArrayUpcast, fieldAccess);
this.found.add(elem);
}
break;
}
case ASTNode.INFIX_EXPRESSION: {
final InfixExpression ie = (InfixExpression) node;
final InfixExpression.Operator op = ie.getOperator();
if (Util.isLegalInfixOperator(op)) {
if (Util.inNeedOfTransformation(op)) {
final ISourceRange range = new SourceRange(ie
.getStartPosition(), ie.getLength());
this.legalEncounteredInfixExpressionSourceLocations
.add(range);
}
this.processExpression(ie.getLeftOperand());
this.processExpression(ie.getRightOperand());
}
else if (!Util.isSuspiciousInfixOperator(op))
throw new DefinitelyNotEnumerizableOperationException(
Messages.ASTNodeProcessor_IllegalInfixExpression, op, node);
else
throw new NonEnumerizableOperationException(
Messages.ASTNodeProcessor_IllegalInfixExpression, op, node);
break;
}
case ASTNode.METHOD_INVOCATION: {
final MethodInvocation m = (MethodInvocation) node;
final IMethod meth = (IMethod) m.resolveMethodBinding()
.getJavaElement();
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else {
if (top.isReadOnly())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
this.found.add(top);
}
break;
}
case ASTNode.PARENTHESIZED_EXPRESSION: {
final ParenthesizedExpression pe = (ParenthesizedExpression) node;
this.processExpression(pe.getExpression());
break;
}
case ASTNode.SUPER_FIELD_ACCESS: {
final SuperFieldAccess superFieldAccess = (SuperFieldAccess) node;
final IJavaElement elem = superFieldAccess.resolveFieldBinding()
.getJavaElement();
if (elem.isReadOnly() || superFieldAccess.resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
if (superFieldAccess.resolveTypeBinding().isEqualTo(
node.getAST().resolveWellKnownType("java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(Messages.ASTNodeProcessor_IllegalArrayUpcast,
superFieldAccess);
this.found.add(elem);
break;
}
case ASTNode.SUPER_METHOD_INVOCATION: {
final SuperMethodInvocation sm = (SuperMethodInvocation) node;
final IMethod meth = (IMethod) sm.resolveMethodBinding()
.getJavaElement();
final IMethod top = Util.getTopMostSourceMethod(meth, this.monitor);
if (top == null)
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
else {
if (top.isReadOnly())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, node);
this.found.add(top);
}
break;
}
case ASTNode.VARIABLE_DECLARATION_EXPRESSION: {
final VariableDeclarationExpression varDec = (VariableDeclarationExpression) node;
for (final Iterator it = varDec.fragments().iterator(); it
.hasNext();) {
final VariableDeclarationFragment vdf = (VariableDeclarationFragment) it
.next();
final IJavaElement elem = vdf.resolveBinding().getJavaElement();
if (elem.isReadOnly() || vdf.getName().resolveBoxing())
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_SourceNotPresent, vdf);
if (vdf.resolveBinding().getType().isEqualTo(
node.getAST().resolveWellKnownType("java.lang.Object"))) //$NON-NLS-1$
throw new NonEnumerizableASTException(
Messages.ASTNodeProcessor_IllegalArrayUpcast, vdf);
this.found.add(elem);
}
break;
}
case ASTNode.CAST_EXPRESSION: {
final CastExpression cast = (CastExpression) node;
throw new NonEnumerizableCastExpression(Messages.ASTNodeProcessor_IllegalNodeContext,
node, cast.getExpression().resolveTypeBinding(), cast
.getType().resolveBinding());
}
case ASTNode.ENUM_CONSTANT_DECLARATION:
case ASTNode.IF_STATEMENT:
case ASTNode.BOOLEAN_LITERAL:
case ASTNode.NUMBER_LITERAL:
case ASTNode.CHARACTER_LITERAL:
case ASTNode.POSTFIX_EXPRESSION:
case ASTNode.PREFIX_EXPRESSION: {
throw new DefinitelyNotEnumerizableException(
Messages.ASTNodeProcessor_IllegalNodeContext, node);
}
default: {
throw new NonEnumerizableASTException(Messages.ASTNodeProcessor_IllegalExpression, node);
}
}
}
}