import static org.junit.Assert.assertTrue;
import no.uio.ifi.refaktor.analyze.analyzers.Analyzer;
import no.uio.ifi.refaktor.analyze.analyzers.SearchBasedExtractAndMoveMethodAnalyzer;
-import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesExtractAndMoveCandidateComparator;
import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException;
import no.uio.ifi.refaktor.examples.manager.ExampleCodeManager;
import no.uio.ifi.refaktor.prefix.Prefix;
public void testSearchableMethodFavorNoUnfixes() throws Exception {
IMethod method = getTestDataMethod("searchableMethod");
- SearchBasedExtractAndMoveMethodAnalyzer analyzer = new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesCandidateComparator());
+ SearchBasedExtractAndMoveMethodAnalyzer analyzer = new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesExtractAndMoveCandidateComparator());
analyzer.analyze();
int methodOffset = method.getSourceRange().getOffset();
package no.uio.ifi.refaktor.analyze;
+import no.uio.ifi.refaktor.analyze.analyzers.ExtractAndMoveMethodAnalyzer;
+import no.uio.ifi.refaktor.analyze.analyzers.ExtractLocalVariableAnalyzer;
+import no.uio.ifi.refaktor.change.changers.ExtractAndMoveMethodChanger;
+import no.uio.ifi.refaktor.change.exceptions.RefactoringNotExecutedException;
+import no.uio.ifi.refaktor.prefix.Prefix;
+import no.uio.ifi.refaktor.prefix.PrefixSet;
+import no.uio.ifi.refaktor.textselection.CompilationUnitTextSelection;
+import no.uio.ifi.refaktor.textselection.MethodRelativeCompilationUnitTextSelection;
+
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+
+/**
+ * Currently does exactly the same thing as ExtractAndMoveMethodCandidate
+ *
+ * TODO make common abstract class
+ * TODO work on analyzer
+ *
+ * @author Anna Eilertsen
+ *
+ */
public class ExtractLocalVariableCandidate {
-}
+ private class CandidateDataCalculator {
+ private final ExtractLocalVariableAnalyzer analyzer;
+ private Prefix mostFrequentPrefix;
+
+ public CandidateDataCalculator(ExtractLocalVariableAnalyzer analyzer) {
+ this.analyzer = analyzer;
+ mostFrequentPrefix = analyzer.calculateMostFrequentPrefix();
+ }
+
+ public boolean hasMoreThanOnePossibleTarget() {
+ PrefixSet safePrefixes = analyzer.calculateSafePrefixes();
+ IBinding binding = safePrefixes.toList().getFirst().getVariableBindingOfFirstExpression();
+ for (Prefix prefix: safePrefixes) {
+ if (!prefix.getVariableBindingOfFirstExpression().isEqualTo(binding))
+ return true;
+ }
+ return false;
+ }
+
+ public int getTargetFrequency() {
+ if (hasMoreThanOnePossibleTarget())
+ ; // TODO: throw exception?
+ return mostFrequentPrefix.getCount();
+ }
+
+ public boolean hasNoUnfixes() {
+ return analyzer.getUnfixes().isEmpty();
+ }
+
+ public String calculateOriginalTargetKey() {
+ return analyzer.calculateOriginalTarget().getKey();
+ }
+
+ public int getPrefixTargetSegmentCount() {
+ return mostFrequentPrefix.getNumberOfSegments();
+ }
+
+ }
+
+ public final CompilationUnitTextSelection textSelection;
+ public final int numberOfStatementsAnalyzed;
+ public final int numberOfTextSelectionsAnalyzed;
+ public final IMethod method;
+
+ private final boolean hasMoreThanOnePossibleTarget;
+ private final int targetFrequency;
+ private final boolean hasNoUnfixes;
+ private final String originalTargetKey;
+ private int targetPrefixSegmentCount;
+
+ public ExtractLocalVariableCandidate(IMethod method, ExtractLocalVariableAnalyzer analyzer, CompilationUnitTextSelection textSelection, int numberOfStatementsAnalyzed, int numberOfTextSelectionsAnalyzed) {
+ this.method = method;
+ this.textSelection = new MethodRelativeCompilationUnitTextSelection(method, textSelection);
+ this.numberOfStatementsAnalyzed = numberOfStatementsAnalyzed;
+ this.numberOfTextSelectionsAnalyzed = numberOfTextSelectionsAnalyzed;
+
+ CandidateDataCalculator calculator = new CandidateDataCalculator(analyzer);
+ hasMoreThanOnePossibleTarget = calculator.hasMoreThanOnePossibleTarget();
+ targetFrequency = calculator.getTargetFrequency();
+ hasNoUnfixes = calculator.hasNoUnfixes();
+ originalTargetKey = calculator.calculateOriginalTargetKey();
+ targetPrefixSegmentCount = calculator.getPrefixTargetSegmentCount();
+ }
+
+ public boolean hasMoreThanOnePossibleTarget() {
+ return hasMoreThanOnePossibleTarget;
+ }
+
+ public boolean hasOnlyOnePossibleTarget() {
+ return !hasMoreThanOnePossibleTarget();
+ }
+
+ public int getTargetFrequency() {
+ return targetFrequency;
+ }
+
+ public boolean hasNoUnfixes() {
+ return hasNoUnfixes;
+ }
+
+ public boolean hasUnfixes() {
+ return !hasNoUnfixes();
+ }
+
+ public IVariableBinding calculateOriginalTarget() {
+ return restoreOriginalTarget();
+ }
+
+ private IVariableBinding restoreOriginalTarget() {
+ try {
+ VariableBindingFinder variableBindingFinder = new VariableBindingFinder(originalTargetKey);
+ textSelection.getCoveringNode().accept(variableBindingFinder);
+ String assertMessage = "Text selection: " + textSelection + ", Original target key: " + originalTargetKey;
+ assert variableBindingFinder.getVariableBinding() != null: assertMessage;
+ return variableBindingFinder.getVariableBinding();
+ } catch (NullPointerException e) {
+ // TODO: revisit
+ throw new RefactoringNotExecutedException(this.getClass().getCanonicalName(), e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Result for '" + method.getDeclaringType().getFullyQualifiedName() + "." + method.getElementName() + "' (" + numberOfStatementsAnalyzed + " statements analyzed): < " + textSelection + " >";
+ }
+
+ public String getNewMethodName() {
+ // TODO: do better
+ return ExtractAndMoveMethodChanger.generateName();
+ }
+
+ public String getOriginatingMethodName() {
+ return method.getDeclaringType().getFullyQualifiedName() + "." + method.getElementName();
+ }
+
+ public IMethod getMethod() {
+ return method;
+ }
+
+ public CompilationUnitTextSelection getTextSelection() {
+ return textSelection;
+ }
+
+ public int getTargetPrefixSegmentCount() {
+ return targetPrefixSegmentCount;
+ }
+
+ }
\ No newline at end of file
package no.uio.ifi.refaktor.analyze;
+import java.util.Collections;
import java.util.LinkedList;
+import java.util.Set;
import org.eclipse.jdt.core.IMethod;
import no.uio.ifi.refaktor.analyze.analyzers.Analyzer;
+import no.uio.ifi.refaktor.analyze.analyzers.ExtractAndMoveMethodAnalyzer;
+import no.uio.ifi.refaktor.analyze.analyzers.ExtractLocalVariableAnalyzer;
import no.uio.ifi.refaktor.analyze.analyzers.StatementListsCreator;
-import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesCandidateComparator;
+import no.uio.ifi.refaktor.analyze.analyzers.TextSelectionsGenerator;
+import no.uio.ifi.refaktor.analyze.comparators.ExtractAndMoveMethodCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.ExtractLocalVariableCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesExtractLocalVariableCandidateComparator;
import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException;
import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException;
+import no.uio.ifi.refaktor.textselection.CompilationUnitTextSelection;
public class SearchBasedExtractLocalVariableAnalyzer implements Analyzer{
private IMethod method;
- private Object candidateComparator;
+ private ExtractLocalVariableCandidateComparator candidateComparator;
private LinkedList<ExtractLocalVariableCandidate> candidates;
+ private StatementListsCreator statementsCreator;
+
+ private Set<CompilationUnitTextSelection> textSelections;
+ private ExtractLocalVariableCandidate chosenCandidate;
public SearchBasedExtractLocalVariableAnalyzer(IMethod method,
- FavorNoUnfixesCandidateComparator favorNoUnfixesCandidateComparator) {
+ FavorNoUnfixesExtractLocalVariableCandidateComparator favorNoUnfixesCandidateComparator) {
this.method = method;
- this.candidateComparator = candidateComparator;
+ this.candidateComparator = favorNoUnfixesCandidateComparator;
candidates = new LinkedList<ExtractLocalVariableCandidate>();
- StatementListsCreator statementsCreator = new StatementListsCreator(method);
+ statementsCreator = new StatementListsCreator(method);
}
public void analyze() {
if (candidates.isEmpty())
throw new NoTargetFoundException();
- getCandidate();
+ chooseCandidate();
- }
+ }
private void findPotentialCandidates() {
- // TODO Auto-generated method stub
-
+ for (CompilationUnitTextSelection textSelection: textSelections) {
+ ExtractLocalVariableAnalyzer analyzer = new ExtractLocalVariableAnalyzer(textSelection);
+ analyzer.analyze();
+
+ if (analyzer.hasUsefulResults())
+ candidates.add(new ExtractLocalVariableCandidate(method, analyzer, textSelection, statementsCreator.getNumberOfStatements(), textSelections.size()));
+ }
}
private void generateTextSelections() {
- // TODO Auto-generated method stub
+ textSelections = TextSelectionsGenerator.generateTextSelections(statementsCreator, method.getCompilationUnit());
}
- public Object getCandidate() {
- // TODO Auto-generated method stub
- return null;
+ private void chooseCandidate() {
+ sortCandidates();
+ chosenCandidate = candidates.getLast();
+ }
+
+ private void sortCandidates() {
+ Collections.sort(candidates, candidateComparator);
}
+ public ExtractLocalVariableCandidate getCandidate() {
+ return chosenCandidate;
+ }
}
--- /dev/null
+/**
+ *
+ */
+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.checkers.LegalStatementsChecker;
+import no.uio.ifi.refaktor.analyze.collectors.PrefixesCollector;
+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.textselection.CompilationUnitTextSelection;
+
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.Modifier;
+
+/**
+ * @author Anna Eilertsen
+ *
+ */
+public class ExtractLocalVariableAnalyzer implements Analyzer {
+
+ private final CompilationUnitTextSelection selection;
+ private final PrefixesCollector prefixesCollector;
+ private final UnfixesCollector unfixesCollector;
+ /**
+ * If ONLY_SAFE is set, non-final fields are not considered as candidates.
+ */
+ public boolean ONLY_SAFE = false;
+
+ public ExtractLocalVariableAnalyzer(CompilationUnitTextSelection selection) {
+ this.selection = selection;
+ prefixesCollector = new PrefixesCollector(selection);
+ unfixesCollector = new UnfixesCollector(selection);
+ }
+
+ /**
+ * Affected by {@link #ONLY_SAFE}.
+ */
+ public PrefixSet calculateSafePrefixes() {
+ PrefixSet safePrefixes = prefixesCollector.getPrefixes().minusEnclosedPrefixesFrom(unfixesCollector.getUnfixes());
+ removeUnusablePrefixes(safePrefixes);
+ return safePrefixes;
+ }
+
+ private void removeUnusablePrefixes(PrefixSet safePrefixes) {
+ for (Iterator<Prefix> iter = safePrefixes.iterator(); iter.hasNext();) {
+ final Prefix i = iter.next();
+ final IVariableBinding ie = i.getVariableBindingOfFirstExpression();
+ if (prefixHasSimpleExpressionAndOnlyOneOccurrence(i)
+ /* Filter out non-final fields as well? */
+ || (ONLY_SAFE && ie.isField() && !Modifier.isFinal(ie.getModifiers())))
+ 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<Prefix> listOfSafePrefixes = calculateListOfSafePrefixes();
+ sortAscendingByCountAndLength(listOfSafePrefixes);
+ return listOfSafePrefixes.getLast();
+ }
+
+ private LinkedList<Prefix> calculateListOfSafePrefixes() {
+ return calculateSafePrefixes().toList();
+ }
+
+ private void sortAscendingByCountAndLength(LinkedList<Prefix> values) {
+ Collections.sort(values, new Comparator<Prefix>() {
+ @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.getNumberOfSegments() > p2.getNumberOfSegments()) {
+ return 1;
+ } else if (p1.getNumberOfSegments() < p2.getNumberOfSegments()) {
+ return -1;
+ }
+ return 0;
+ }
+ });
+ }
+}
import java.util.List;
import no.uio.ifi.refaktor.analyze.ExtractAndMoveMethodCandidate;
-import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesExtractAndMoveCandidateComparator;
import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException;
import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException;
import no.uio.ifi.refaktor.debugging.RefaktorDebug;
private void analyzeMethod(IMethod method) {
try {
SearchBasedExtractAndMoveMethodAnalyzer analyzer =
- new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesCandidateComparator());
+ new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesExtractAndMoveCandidateComparator());
analyzer.analyze();
candidates.add(analyzer.getCandidate());
} catch (NoTargetFoundException e) {
--- /dev/null
+package no.uio.ifi.refaktor.analyze.comparators;
+
+import java.util.Comparator;
+
+import no.uio.ifi.refaktor.analyze.ExtractLocalVariableCandidate;
+
+public interface ExtractLocalVariableCandidateComparator extends Comparator<ExtractLocalVariableCandidate>{
+
+}
import no.uio.ifi.refaktor.analyze.ExtractAndMoveMethodCandidate;
-public final class FavorNoUnfixesCandidateComparator implements ExtractAndMoveMethodCandidateComparator {
+public final class FavorNoUnfixesExtractAndMoveCandidateComparator implements ExtractAndMoveMethodCandidateComparator {
@Override
public int compare(ExtractAndMoveMethodCandidate resultOne, ExtractAndMoveMethodCandidate resultTwo) {
if (resultOne.hasNoUnfixes() && resultTwo.hasUnfixes())
--- /dev/null
+/**
+ *
+ */
+package no.uio.ifi.refaktor.analyze.comparators;
+
+import no.uio.ifi.refaktor.analyze.ExtractLocalVariableCandidate;
+
+/**
+ * @author Anna Eilertsen
+ *
+ */
+public class FavorNoUnfixesExtractLocalVariableCandidateComparator implements ExtractLocalVariableCandidateComparator {
+ @Override
+ public int compare(ExtractLocalVariableCandidate resultOne, ExtractLocalVariableCandidate resultTwo) {
+ if (resultOne.hasNoUnfixes() && resultTwo.hasUnfixes())
+ return 1;
+ else if (resultOne.hasUnfixes() && resultTwo.hasNoUnfixes())
+ return -1;
+ else if (resultOne.hasOnlyOnePossibleTarget() && resultTwo.hasMoreThanOnePossibleTarget())
+ return 1;
+ else if (resultOne.hasMoreThanOnePossibleTarget() && resultTwo.hasOnlyOnePossibleTarget())
+ return -1;
+ else if (resultOne.hasMoreThanOnePossibleTarget() && resultTwo.hasMoreThanOnePossibleTarget())
+ return 0;
+ else if (resultOne.getTargetFrequency() > resultTwo.getTargetFrequency())
+ return 1;
+ else if (resultOne.getTargetFrequency() < resultTwo.getTargetFrequency())
+ return -1;
+ else if (resultOne.getTargetPrefixSegmentCount() > resultTwo.getTargetPrefixSegmentCount())
+ return 1;
+ else if (resultOne.getTargetPrefixSegmentCount() < resultTwo.getTargetPrefixSegmentCount())
+ return -1;
+ else
+ return 0;
+ }
+ }
\ No newline at end of file
import no.uio.ifi.refaktor.analyze.SearchBasedExtractLocalVariableAnalyzer;
import no.uio.ifi.refaktor.analyze.analyzers.SearchBasedExtractAndMoveMethodAnalyzer;
-import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesExtractAndMoveCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesExtractLocalVariableCandidateComparator;
import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException;
import no.uio.ifi.refaktor.change.changers.RefaktorChanger;
import no.uio.ifi.refaktor.change.executors.ExtractAndMoveMethodExecutor;
private SearchBasedExtractLocalVariableAnalyzer analyzer;
public SearchBasedExtractLocalVariableWithAssertsChanger(IMethod method) {
- this.analyzer = new SearchBasedExtractLocalVariableAnalyzer(method, new FavorNoUnfixesCandidateComparator());
+ this.analyzer = new SearchBasedExtractLocalVariableAnalyzer(method, new FavorNoUnfixesExtractLocalVariableCandidateComparator());
}
@Override
package no.uio.ifi.refaktor.change.changers;
import no.uio.ifi.refaktor.analyze.analyzers.SearchBasedExtractAndMoveMethodAnalyzer;
-import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesExtractAndMoveCandidateComparator;
import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException;
import no.uio.ifi.refaktor.change.executors.ExtractAndMoveMethodExecutor;
private SearchBasedExtractAndMoveMethodAnalyzer analyzer;
public SearchBasedExtractAndMoveMethodChanger(IMethod method) {
- this.analyzer = new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesCandidateComparator());
+ this.analyzer = new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesExtractAndMoveCandidateComparator());
}
@Override
import no.uio.ifi.refaktor.analyze.ExtractAndMoveMethodCandidate;
import no.uio.ifi.refaktor.analyze.analyzers.SearchBasedExtractAndMoveMethodAnalyzer;
-import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesCandidateComparator;
+import no.uio.ifi.refaktor.analyze.comparators.FavorNoUnfixesExtractAndMoveCandidateComparator;
import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException;
import no.uio.ifi.refaktor.debugging.RefaktorDebug;
import no.uio.ifi.refaktor.statistics.StatisticsAspect;
String message = "";
try {
StatisticsAspect.init();
- SearchBasedExtractAndMoveMethodAnalyzer analyzer = new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesCandidateComparator());
+ SearchBasedExtractAndMoveMethodAnalyzer analyzer = new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesExtractAndMoveCandidateComparator());
analyzer.analyze();
ExtractAndMoveMethodCandidate result = analyzer.getCandidate();
message = "Result:\n\nText selection:\n" + result.textSelection
IMethod method = (IMethod) o;
RefaktorChanger changer = new SearchBasedExtractLocalVariableWithAssertsChanger(method);
-
+ try {
+ changer.checkPreconditions();
+ changer.execute(new NullProgressMonitor());
+ MessageDialog.openInformation(window.getShell(), "no.uio.ifi.refaktor", changer.getClass() + " has been excuted");
+ return null;
+ } catch (RefaktorChangerException e) {
+ RefaktorDebug.log(e);
+ } catch (CoreException e) {
+ RefaktorDebug.log(e);
+ }
+
+ MessageDialog.openInformation(window.getShell(), "no.uio.ifi.refaktor", changer.getClass() + " did not execute correctly");
return null;
}
statementsListRewrite = null;
ast = null;
qualifier = null;
- super.endVisit(node); //Doesn't do anything, but kept for future
+ super.endVisit(node); //Doesn't do anything for now
}
@Override