package no.uio.ifi.refaktor.analyze.analyzers; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import no.uio.ifi.refaktor.analyze.CollectorManager; import no.uio.ifi.refaktor.analyze.collectors.PrefixesCollector; import no.uio.ifi.refaktor.analyze.collectors.SelectionValidator; import no.uio.ifi.refaktor.analyze.collectors.UnfixesCollector; import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException; import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException; import no.uio.ifi.refaktor.change.changers.ExtractAndMoveMethodChanger; import no.uio.ifi.refaktor.prefix.Prefix; import no.uio.ifi.refaktor.prefix.PrefixSet; import no.uio.ifi.refaktor.utils.CompilationUnitTextSelection; import org.eclipse.jdt.core.dom.IVariableBinding; //TODO: rewrite docs /** * A property extractor that collects all the expression prefixes within a selection * (see {@link PrefixesCollector}) that forms the base for calculating the * candidates for the move refactoring, and also the unfixes * that are non-candidates for the move refactoring. * * The set of prefixes that are not enclosing any unfixes is put in the set of safe prefixes. * This set is used by an Extract and Move Method refactoring to find a suitable target * for the Move Method. * * The class is typically used by the {@link ExtractAndMoveMethodChanger}. */ public class ExtractAndMoveMethodAnalyzer implements Analyzer { private final CompilationUnitTextSelection selection; private final PrefixesCollector prefixesCollector; private final UnfixesCollector unfixesCollector; public ExtractAndMoveMethodAnalyzer(CompilationUnitTextSelection selection) { this.selection = selection; prefixesCollector = new PrefixesCollector(selection); unfixesCollector = new UnfixesCollector(selection); } public PrefixSet calculateSafePrefixes() { PrefixSet safePrefixes = prefixesCollector.getPrefixes().minusEnclosedPrefixesFrom(unfixesCollector.getUnfixes()); removeUnusablePrefixes(safePrefixes); return safePrefixes; } private void removeUnusablePrefixes(PrefixSet safePrefixes) { for (Iterator iter = safePrefixes.iterator(); iter.hasNext();) { if (prefixHasSimpleExpressionAndOnlyOneOccurrence(iter.next())) iter.remove(); } } private boolean prefixHasSimpleExpressionAndOnlyOneOccurrence(Prefix prefix) { return prefix.getNumberOfSegments() == 1 && prefix.getCount() == 1; } protected PrefixSet getPrefixes() { return prefixesCollector.getPrefixes(); } public PrefixSet getUnfixes() { return unfixesCollector.getUnfixes(); } public void checkPreconditions() throws RefaktorAnalyzerException { SelectionValidator.checkIfSelectionIsValid(selection); analyze(); checkIfUsefulTargetFound(); } private void checkIfUsefulTargetFound() { if (!hasUsefulResults()) throw new NoTargetFoundException(); } public boolean hasUsefulResults() { return !calculateSafePrefixes().isEmpty(); } @Override public void analyze() throws RefaktorAnalyzerException { LegalStatementsChecker legalStatementsChecker = new LegalStatementsChecker(selection); if (legalStatementsChecker.allStatementsAreLegal()) CollectorManager.collectProperties(selection, prefixesCollector, unfixesCollector); } public IVariableBinding calculateOriginalTarget() { return calculateMostFrequentPrefix().getVariableBindingOfFirstExpression(); } public Prefix calculateMostFrequentPrefix() { LinkedList listOfSafePrefixes = calculateListOfSafePrefixes(); sortAscendingByCountAndLength(listOfSafePrefixes); return listOfSafePrefixes.getLast(); } private LinkedList calculateListOfSafePrefixes() { return calculateSafePrefixes().toList(); } private void sortAscendingByCountAndLength(LinkedList values) { Collections.sort(values, new Comparator() { @Override public int compare(Prefix p1, Prefix p2) { if (p1.getCount() > p2.getCount()) { return 1; } else if (p1.getCount() < p2.getCount()) { return -1; } else if (p1.length() > p2.length()) { return 1; } else if (p1.length() < p2.length()) { return -1; } return 0; } }); } }