]> git.uio.no Git - ifi-stolz-refaktor.git/commitdiff
Making the ExtractAndMoveMethodAnalysisResult lightweight enough for it
authorErlend Kristiansen <erlenkr@ifi.uio.no>
Tue, 14 Jan 2014 20:14:38 +0000 (21:14 +0100)
committerErlend Kristiansen <erlenkr@ifi.uio.no>
Tue, 14 Jan 2014 20:14:38 +0000 (21:14 +0100)
to be stored in a collection when analyzing a large codebase. This is
achieved by giving the ExtractAndMoveMethodAnalysisResult memento-like
behavior for handling the variable binding. (Storing its key and
restoring the binding again when needed.)

software/no.uio.ifi.refaktor.benchmark/src/no/uio/ifi/refaktor/benchmark/ProjectWideSearchBasedExtractAndMoveMethodAnalyzer.java
software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/analyze/ExtractAndMoveMethodAnalysisResult.java
software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/analyze/VariableBindingFinder.java [new file with mode: 0644]
software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/utils/CompilationUnitTextSelection.java

index d930cfd471c03bd315fa66ad658c924e8e499302..74703218d79d663fe084b9661c6e418d3321ee09 100644 (file)
@@ -1,5 +1,8 @@
 package no.uio.ifi.refaktor.benchmark;
 
+import java.util.LinkedList;
+import java.util.List;
+
 import no.uio.ifi.refaktor.analyze.ExtractAndMoveMethodAnalysisResult;
 import no.uio.ifi.refaktor.analyze.FavorNoUnfixesAnalysisResultComparator;
 import no.uio.ifi.refaktor.analyze.NoTargetFoundException;
@@ -19,11 +22,13 @@ import org.eclipse.jdt.core.JavaModelException;
 public class ProjectWideSearchBasedExtractAndMoveMethodAnalyzer {
 
        private final IProject project;
+       private final List<ExtractAndMoveMethodAnalysisResult> results;
        private int methodCount;
        private long analysisStart;
 
        public ProjectWideSearchBasedExtractAndMoveMethodAnalyzer(IProject project) {
                this.project = project;
+               results = new LinkedList<ExtractAndMoveMethodAnalysisResult>();
                methodCount = 0;
        }
 
@@ -45,11 +50,19 @@ public class ProjectWideSearchBasedExtractAndMoveMethodAnalyzer {
                } catch (JavaModelException e) {
                        throw new RuntimeException(e);
                } finally {
-                       RefaktorDebug.println("Time used on analysis: " + timeSinceAnalysisStart());
-                       RefaktorDebug.println("\n" + methodCount + " methods analyzed");
+                       debugPrintFinalStatistics();
                }
        }
 
+       private void debugPrintFinalStatistics() {
+               for (ExtractAndMoveMethodAnalysisResult result: results)
+                       RefaktorDebug.println(result);
+
+               RefaktorDebug.println("Number of results: " + results.size());
+               RefaktorDebug.println("Time used on analysis: " + timeSinceAnalysisStart());
+               RefaktorDebug.println(methodCount + " methods analyzed");
+       }
+
        private void analyzeMethodsInPackage(IPackageFragment packageFragment) throws JavaModelException {
                for (ICompilationUnit compilationUnit: packageFragment.getCompilationUnits())
                        analyzeMethodsInCompilationUnit(compilationUnit);
@@ -78,10 +91,9 @@ public class ProjectWideSearchBasedExtractAndMoveMethodAnalyzer {
                        }
                        analyzer = new SearchBasedExtractAndMoveMethodAnalyzer(method, new FavorNoUnfixesAnalysisResultComparator());
                        analyzer.analyze();
-                       ExtractAndMoveMethodAnalysisResult result = analyzer.getResult();
-                       RefaktorDebug.println(result);
+                       results.add(analyzer.getResult());
                } catch (NoTargetFoundException e) {
-                       RefaktorDebug.println("No target found for " + method + "\n(" + analyzer.getNumberOfStatementsAnalyzed() + " statements analyzed)");
+//                     RefaktorDebug.println("No target found for " + method + "\n(" + analyzer.getNumberOfStatementsAnalyzed() + " statements analyzed)");
                }
        }
 
index 3755a273550a267ec06f5726bc8b69468b7c0786..4d11258ccc387d3239c8e69d82b36f545fc9efd3 100644 (file)
@@ -1,36 +1,79 @@
 package no.uio.ifi.refaktor.analyze;
 
+import static no.uio.ifi.refaktor.RefaktorAssert.assertThat;
+import static org.hamcrest.CoreMatchers.notNullValue;
 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.IMethod;
 import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
 
 public class ExtractAndMoveMethodAnalysisResult {
+       private class ResultDataCalculator {
+               private final ExtractAndMoveMethodAnalyzer analyzer;
+
+               public ResultDataCalculator(ExtractAndMoveMethodAnalyzer analyzer) {
+                       this.analyzer = analyzer;
+               }
+
+               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 analyzer.calculateMostFrequentPrefix().getCount();
+               }
+
+               public boolean hasNoUnfixes() {
+                       return analyzer.getUnfixes().isEmpty();
+               }
+
+               public String calculateOriginalTargetKey() {
+                       return analyzer.calculateOriginalTarget().getKey();
+               }
+       }
+
        public final CompilationUnitTextSelection textSelection;
        public final int numberOfStatementsAnalyzed;
        public final int numberOfTextSelectionsAnalyzed;
        public final IMethod method;
 
-       private final ExtractAndMoveMethodAnalyzer analyzer;
+       private final boolean hasMoreThanOnePossibleTarget;
+       private final int targetFrequency;
+       private final boolean hasNoUnfixes;
+       private final String originalTargetKey;
 
        public ExtractAndMoveMethodAnalysisResult(IMethod method, ExtractAndMoveMethodAnalyzer analyzer, CompilationUnitTextSelection textSelection, int numberOfStatementsAnalyzed, int numberOfTextSelectionsAnalyzed) {
                this.method = method;
-               this.analyzer = analyzer;
                this.textSelection = textSelection;
                this.numberOfStatementsAnalyzed = numberOfStatementsAnalyzed;
                this.numberOfTextSelectionsAnalyzed = numberOfTextSelectionsAnalyzed;
+               
+               ResultDataCalculator calculator = new ResultDataCalculator(analyzer);
+               hasMoreThanOnePossibleTarget = calculator.hasMoreThanOnePossibleTarget();
+               targetFrequency = calculator.getTargetFrequency();
+               hasNoUnfixes = calculator.hasNoUnfixes();
+               originalTargetKey = calculator.calculateOriginalTargetKey();
+
+               dropExpensiveCachedData();
+       }
+
+       private void dropExpensiveCachedData() {
+               textSelection.dropCachedData();
        }
 
        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;
+               return hasMoreThanOnePossibleTarget;
        }
 
        public boolean hasOnlyOnePossibleTarget() {
@@ -38,21 +81,26 @@ public class ExtractAndMoveMethodAnalysisResult {
        }
 
        public int getTargetFrequency() {
-               if (hasMoreThanOnePossibleTarget())
-                       ; // TODO: throw exception?
-               return analyzer.calculateMostFrequentPrefix().getCount();
+               return targetFrequency;
        }
 
        public boolean hasNoUnfixes() {
-               return analyzer.getUnfixes().isEmpty();
+               return hasNoUnfixes;
        }
 
        public boolean hasUnfixes() {
                return !hasNoUnfixes();
        }
 
-       public IBinding calculateOriginalTarget() {
-               return analyzer.calculateOriginalTarget();
+       public IVariableBinding calculateOriginalTarget() {
+               return restoreOriginalTarget();
+       }
+       
+       private IVariableBinding restoreOriginalTarget() {
+               VariableBindingFinder variableBindingFinder = new VariableBindingFinder(originalTargetKey);
+               textSelection.getCoveringNode().accept(variableBindingFinder);
+               assertThat(variableBindingFinder.getVariableBinding(), notNullValue());
+               return variableBindingFinder.getVariableBinding();
        }
 
        @Override
diff --git a/software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/analyze/VariableBindingFinder.java b/software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/analyze/VariableBindingFinder.java
new file mode 100644 (file)
index 0000000..935713b
--- /dev/null
@@ -0,0 +1,39 @@
+package no.uio.ifi.refaktor.analyze;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.SimpleName;
+
+public class VariableBindingFinder extends ASTVisitor {
+       private String bindingKey;
+       private boolean bindingFound;
+       private IVariableBinding variableBinding;
+
+       public VariableBindingFinder(String bindingKey) {
+               this.bindingKey = bindingKey;
+               bindingFound = false;
+       }
+
+       @Override
+       public boolean visit(SimpleName node) {
+               IBinding binding = node.resolveBinding();
+
+               if (binding instanceof IVariableBinding && binding.getKey().equals(bindingKey)) {
+                       variableBinding = (IVariableBinding) binding;
+                       bindingFound = true;
+               }
+
+               return false;
+       }
+       
+       @Override
+       public boolean preVisit2(ASTNode node) {
+               return !bindingFound;
+       }
+       
+       public IVariableBinding getVariableBinding() {
+               return variableBinding;
+       }
+}
index 8bbb440707969957a343206af7d8ec88e2b5623b..168657c64322b5c3ec47c8aa35a9e21dd5fa531a 100644 (file)
@@ -19,14 +19,29 @@ import org.eclipse.jface.text.TextSelection;
  */
 public class CompilationUnitTextSelection extends TextSelection implements ITextSelection {
 
+       private class NodeFinderCache {
+               private NodeFinder nodeFinder;
+
+               private NodeFinder getNodeFinder() {
+                       if (nodeFinder == null)
+                               nodeFinder = ParseUtils.createNodeFinder(ParseUtils.parse(compilationUnit), CompilationUnitTextSelection.this);
+                       return nodeFinder;
+               }
+
+               public void dropCachedData() {
+                       nodeFinder = null;
+               }
+       }
+
        private ICompilationUnit compilationUnit;
-       private NodeFinder nodeFinder;
+       private final NodeFinderCache nodeFinderCache;
 
        public CompilationUnitTextSelection(ICompilationUnit compilationUnit, int offset, int length) {
                super(offset, length);
                if (compilationUnit == null)
                        throw new NullPointerException(this.getClass().getCanonicalName() + ": given compilation unit cannot be null");
                this.compilationUnit = compilationUnit;
+               nodeFinderCache = new NodeFinderCache();
        }
 
        public CompilationUnitTextSelection(ICompilationUnit compilationUnit, ITextSelection selection) {
@@ -59,9 +74,7 @@ public class CompilationUnitTextSelection extends TextSelection implements IText
        }
 
        private NodeFinder getNodeFinder() {
-               if (nodeFinder == null)
-                       nodeFinder = ParseUtils.createNodeFinder(ParseUtils.parse(compilationUnit), this);
-               return nodeFinder;
+               return nodeFinderCache.getNodeFinder();
        }
 
        public boolean surroundsNode(ASTNode node) {
@@ -102,33 +115,37 @@ public class CompilationUnitTextSelection extends TextSelection implements IText
                        return super.equals(obj) && compilationUnit.equals(((CompilationUnitTextSelection)obj).compilationUnit);
                return false;
        }
-       
+
        @Override
        public int hashCode() {
                return (getOffset() << 24) | (getLength() << 16) | compilationUnit.hashCode();
        }
-       
+
        @Override
        public String toString() {
                return "Offset: " + getOffset() + "; Length: " + getLength() + "; End: " + getEnd() + "; CU handle identifier: " + compilationUnit.getHandleIdentifier();
        }
-       
+
        @Override
        public int getStartLine() {
                return createTextSelectionWithDocument().getStartLine();
        }
-       
+
        @Override
        public int getEndLine() {
                return createTextSelectionWithDocument().getEndLine();
        }
-       
+
        @Override
        public String getText() {
                return createTextSelectionWithDocument().getText();
        }
-       
+
        private TextSelection createTextSelectionWithDocument() {
                return new TextSelection(getDocument(), getOffset(), getLength());
        }
+
+       public void dropCachedData() {
+               nodeFinderCache.dropCachedData();
+       }
 }