package no.uio.ifi.refaktor.analyze.checkers; import java.util.HashSet; import java.util.Set; import no.uio.ifi.refaktor.analyze.CollectorManager; import no.uio.ifi.refaktor.analyze.collectors.PropertyCollector; import no.uio.ifi.refaktor.analyze.exceptions.IllegalExpressionFoundException; import no.uio.ifi.refaktor.analyze.exceptions.IllegalStatementFoundException; import no.uio.ifi.refaktor.textselection.CompilationUnitTextSelection; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Assignment; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.ReturnStatement; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; public class AmbiguousReturnValueChecker extends PropertyCollector implements Checker { private class AssigneesUsedOutsideSelectionChecker extends PropertyCollector { private final Set referrals; public AssigneesUsedOutsideSelectionChecker(CompilationUnitTextSelection selection) { super(selection); referrals = new HashSet(); } @Override public void clearData() { referrals.clear(); } @Override public boolean visit(SimpleName node) { if (nodeInSelectionOrBefore(node)) return false; IBinding binding = node.resolveBinding(); if (binding instanceof IVariableBinding && assigneesBindingKeys.contains(binding.getKey())) { referrals.add(binding.getKey()); if (selectionContainsReturn || referrals.size() > 1) throw new IllegalStatementFoundException(SimpleName.class); } return true; } private boolean nodeInSelectionOrBefore(ASTNode node) { return nodeInSelection(node) || nodeBeforeSelection(node); } private boolean nodeBeforeSelection(ASTNode node) { int nodeEndPosition = node.getStartPosition() + node.getLength(); return node.getStartPosition() < selection.getOffset() && nodeEndPosition < selection.getOffset(); } } private final Set assigneesBindingKeys; private boolean selectionContainsReturn; public AmbiguousReturnValueChecker(CompilationUnitTextSelection selection) { super(selection); assigneesBindingKeys = new HashSet(); selectionContainsReturn = false; } @Override public void check() throws IllegalStatementFoundException, IllegalExpressionFoundException { CollectorManager.collectProperties(selection, this); CollectorManager.collectPropertiesFromEnclosingMethod(selection, new AssigneesUsedOutsideSelectionChecker(selection)); } @Override public void clearData() { assigneesBindingKeys.clear(); selectionContainsReturn = false; } @Override public boolean visit(Assignment node) { if (!nodeInSelection(node)) return false; if (node.getLeftHandSide() instanceof SimpleName) { SimpleName name = (SimpleName) node.getLeftHandSide(); IBinding binding = name.resolveBinding(); assert binding instanceof IVariableBinding; if (!((IVariableBinding) binding).isField()) assigneesBindingKeys.add(binding.getKey()); } return true; } @Override public boolean visit(VariableDeclarationFragment node) { if (!nodeInSelection(node)) return false; IBinding binding = node.getName().resolveBinding(); assert binding instanceof IVariableBinding; assigneesBindingKeys.add(binding.getKey()); return true; } @Override public boolean visit(ReturnStatement node) { if (!nodeInSelection(node)) return false; selectionContainsReturn = true; return true; } }