package no.uio.ifi.refaktor.analyze.collectors; import no.uio.ifi.refaktor.analyze.exceptions.TypeBindingNullException; import no.uio.ifi.refaktor.prefix.Prefix; import no.uio.ifi.refaktor.prefix.PrefixSet; import no.uio.ifi.refaktor.textselection.CompilationUnitTextSelection; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ArrayAccess; import org.eclipse.jdt.core.dom.Assignment; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.FieldAccess; 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.InfixExpression.Operator; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; public class UnfixesCollector extends PropertyCollector { private final PrefixSet unfixes; public UnfixesCollector(CompilationUnitTextSelection selection) { super(selection); this.unfixes = new PrefixSet(); } public PrefixSet getUnfixes() { return unfixes; } @Override public boolean visit(SingleVariableDeclaration node) { if (!nodeInSelection(node)) return false; addSimpleNameToUnfixes(node.getName()); return true; } @Override public boolean visit(VariableDeclarationFragment node) { if (!nodeInSelection(node)) return false; addSimpleNameToUnfixes(node.getName()); return true; } @Override public boolean visit(Assignment node) { if (!nodeInSelection(node)) return false; addLeftHandSideToUnfixesIfSimpleName(node); return true; } private void addLeftHandSideToUnfixesIfSimpleName(Assignment node) { Expression lhs = node.getLeftHandSide(); if (lhs instanceof ArrayAccess) return; if (lhs instanceof FieldAccess) { addSimpleNameToUnfixes(((FieldAccess) lhs).getName()); } else { assert lhs instanceof Name; Name name = (Name) lhs; if (name.isSimpleName()) addSimpleNameToUnfixes((SimpleName) name); } } private void addSimpleNameToUnfixes(SimpleName simpleName) { unfixes.add(new Prefix(simpleName)); } @Override public boolean visit(SimpleName node) { if (!nodeInSelection(node)) return false; if (nodeIsUsageOfVariableWithUnacceptableType(node) || parentNodeIsNullTest(node)) addSimpleNameToUnfixes(node); return false; } private boolean nodeIsUsageOfVariableWithUnacceptableType(SimpleName node) { return nodeIsUsageOfVariable(node) && !nodeHasAcceptableTypeBinding(node); } private boolean nodeIsUsageOfVariable(SimpleName node) { return !node.isDeclaration() && node.resolveBinding() instanceof IVariableBinding; } private boolean nodeHasAcceptableTypeBinding(SimpleName node) { ITypeBinding typeBinding = node.resolveTypeBinding(); if (typeBinding == null) throw new TypeBindingNullException(this.getClass()); return typeBinding.isFromSource() && typeBinding.isClass() && !typeBinding.isInterface() && !typeBinding.isLocal(); } private boolean parentNodeIsNullTest(SimpleName node) { ASTNode parent = node.getParent(); if (parent instanceof InfixExpression) { InfixExpression infixExpression = (InfixExpression) parent; Operator operator = infixExpression.getOperator(); return operator.equals(Operator.EQUALS) || operator.equals(Operator.NOT_EQUALS); } else { return false; } } @Override public void clearData() { unfixes.clear(); } }