blob: e7e2bdefd8d06af640d9724b33c6aff40034518a [file] [log] [blame]
package experiments;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.core.refactoring.AbstractRefactoringASTAnalyzer;
import org.eclipse.jdt.internal.core.refactoring.Assert;
import org.eclipse.jdt.internal.core.refactoring.SearchResult;
class ReorderParameterASTAnalyzer extends AbstractRefactoringASTAnalyzer {
private List fSearchResults;
ReorderParameterASTAnalyzer(List searchResults){
fSearchResults= searchResults;
}
private boolean isStartPositionOnList(int start){
for (Iterator iter=fSearchResults.iterator(); iter.hasNext();){
SearchResult sr= (SearchResult)iter.next();
if (sr.getStart() == start)
return true;
};
return false;
}
private boolean isOurMethod(MessageSend messageSend){
return isStartPositionOnList((int) (messageSend.nameSourcePosition >> 32));
}
private static boolean canAnyHaveSideEffects(Expression[] ex){
if (ex == null)
return false;
for (int i= 0; i < ex.length; i++){
if (ex[i] != null && canHaveSideEffects(ex[i]))
return true;
}
return false;
}
/**
* returns true if the expression has for sure safe no side effects
*/
private static boolean canHaveSideEffects(Expression ex){
if (ex == null)
return false;
if (ex instanceof AllocationExpression)
return true;
if (ex instanceof ArrayAllocationExpression)
return canAnyHaveSideEffects(((ArrayAllocationExpression)ex).dimensions);
if (ex instanceof ArrayInitializer)
return canAnyHaveSideEffects(((ArrayInitializer)ex).expressions);
if (ex instanceof Assignment)
return canHaveSideEffects(((Assignment)ex).expression);
if (ex instanceof CastExpression)
return canHaveSideEffects(((CastExpression)ex).expression);
if (ex instanceof ClassLiteralAccess)
return false;
if (ex instanceof Literal)
return false;
if (ex instanceof MessageSend)
return true;
if (ex instanceof BinaryExpression){
return canHaveSideEffects(((BinaryExpression)ex).left)
|| canHaveSideEffects(((BinaryExpression)ex).right);
}
if (ex instanceof ConditionalExpression){
return canHaveSideEffects(((ConditionalExpression)ex).condition)
|| canHaveSideEffects(((ConditionalExpression)ex).valueIfTrue)
|| canHaveSideEffects(((ConditionalExpression)ex).valueIfFalse);
}
if (ex instanceof InstanceOfExpression)
return canHaveSideEffects(((InstanceOfExpression)ex).expression);
if (ex instanceof UnaryExpression)
return canHaveSideEffects(((UnaryExpression)ex).expression);
if (ex instanceof ArrayReference){
return canHaveSideEffects(((ArrayReference)ex).receiver)
|| canHaveSideEffects(((ArrayReference)ex).position);
}
if (ex instanceof FieldReference)
return canHaveSideEffects(((FieldReference)ex).receiver);
if (ex instanceof NameReference)
return false;
if (ex instanceof ThisReference)
return false;
if (ex instanceof TypeReference)
return false;
return true;
}
private void analyzeArgument(Expression ex){
if (canHaveSideEffects(ex))
addError("Expression used in method invocation in line:" + getLineNumber(ex) + " may have side effects. If it does, reordering the parameters will modify your program's behavior");
}
//------- visit methods
public boolean visit(MessageSend messageSend, BlockScope scope) {
if (! isOurMethod(messageSend))
return true;
Assert.isTrue(messageSend.arguments != null, "analyzed method must have arguments");
for (int i= 0; i < messageSend.arguments.length; i++)
analyzeArgument(messageSend.arguments[i]);
return true;
}
}