package no.uio.ifi.refaktor.analyze.analyzers; import java.util.Collections; import java.util.LinkedList; import java.util.Set; import no.uio.ifi.refaktor.analyze.ExtractAndMoveMethodCandidate; import no.uio.ifi.refaktor.analyze.comparators.ExtractAndMoveMethodCandidateComparator; import no.uio.ifi.refaktor.analyze.comparators.IgnorantCandidateComparator; import no.uio.ifi.refaktor.analyze.exceptions.GenericAnalyzerException; import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException; import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException; import no.uio.ifi.refaktor.utils.CompilationUnitTextSelection; import no.uio.ifi.refaktor.utils.RefaktorDebug; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.JavaModelException; /** * A class for searching through a method body to find the best * candidate for the Extract and Move Method refactoring. */ public class SearchBasedExtractAndMoveMethodAnalyzer implements Analyzer { private final IMethod method; private final ExtractAndMoveMethodCandidateComparator candidateComparator; private final LinkedList candidates; private final StatementListsCreator statementsCreator; private Set textSelections; private ExtractAndMoveMethodCandidate chosenCandidate; public SearchBasedExtractAndMoveMethodAnalyzer(IMethod method) { this(method, new IgnorantCandidateComparator()); } /** * @param method The handle of the method to analyze. * @param candidateComparator A candidate comparator to compare two analysis candidates when deciding * which of them that is the best candidate for the refactoring. */ public SearchBasedExtractAndMoveMethodAnalyzer(IMethod method, ExtractAndMoveMethodCandidateComparator candidateComparator) { this.method = method; this.candidateComparator = candidateComparator; candidates = new LinkedList(); statementsCreator = new StatementListsCreator(method); } public ExtractAndMoveMethodCandidate getCandidate() { return chosenCandidate; } @Override public void analyze() throws RefaktorAnalyzerException { // TODO: make the Extract and Move Method Refactoring work with static methods abortIfStaticMethod(); try { generateTextSelections(); findPotentialCandidates(); } catch (RefaktorAnalyzerException e) { throw new NoTargetFoundException(e); } if (candidates.isEmpty()) throw new NoTargetFoundException(); chooseCandidate(); } private void abortIfStaticMethod() { try { if (Flags.isStatic(method.getFlags())) throw new NoTargetFoundException(method.getElementName() + " is static!"); } catch (JavaModelException e) { RefaktorDebug.log(e); throw new GenericAnalyzerException(e); } } private void generateTextSelections() { textSelections = TextSelectionsGenerator.generateTextSelections(statementsCreator, method.getCompilationUnit()); } private void findPotentialCandidates() { for (CompilationUnitTextSelection textSelection: textSelections) { ExtractAndMoveMethodAnalyzer analyzer = new ExtractAndMoveMethodAnalyzer(textSelection); analyzer.analyze(); if (analyzer.hasUsefulResults()) candidates.add(new ExtractAndMoveMethodCandidate(method, analyzer, textSelection, statementsCreator.getNumberOfStatements(), textSelections.size())); } } private void chooseCandidate() { sortCandidates(); chosenCandidate = candidates.getLast(); } private void sortCandidates() { Collections.sort(candidates, candidateComparator); } }