]>
Commit | Line | Data |
---|---|---|
33b364ef | 1 | package no.uio.ifi.refaktor.analyze.analyzers; |
64970e7f | 2 | |
e411ecf3 EK |
3 | import java.util.Collections; |
4 | import java.util.Comparator; | |
e09f9054 | 5 | import java.util.Iterator; |
e411ecf3 | 6 | import java.util.LinkedList; |
2f82d251 | 7 | |
33b364ef | 8 | import no.uio.ifi.refaktor.analyze.CollectorManager; |
5748b416 | 9 | import no.uio.ifi.refaktor.analyze.collectors.BranchingStatementsChecker; |
fc35e1b0 EK |
10 | import no.uio.ifi.refaktor.analyze.collectors.PrefixesCollector; |
11 | import no.uio.ifi.refaktor.analyze.collectors.SelectionValidator; | |
12 | import no.uio.ifi.refaktor.analyze.collectors.UnfixesCollector; | |
ee0f23c0 | 13 | import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException; |
a554b0ce | 14 | import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException; |
2b4a9262 | 15 | import no.uio.ifi.refaktor.change.changers.ExtractAndMoveMethodChanger; |
e411ecf3 | 16 | import no.uio.ifi.refaktor.prefix.Prefix; |
e0fe6563 | 17 | import no.uio.ifi.refaktor.prefix.PrefixSet; |
1d39ea7d | 18 | import no.uio.ifi.refaktor.utils.CompilationUnitTextSelection; |
64970e7f | 19 | |
0b904053 EK |
20 | import org.eclipse.jdt.core.dom.IVariableBinding; |
21 | ||
fc35e1b0 | 22 | //TODO: rewrite docs |
7a978020 | 23 | /** |
520985c2 EK |
24 | * A property extractor that collects all the expression prefixes within a selection |
25 | * (see {@link PrefixesCollector}) that forms the base for calculating the | |
26 | * candidates for the move refactoring, and also the unfixes | |
27 | * that are non-candidates for the move refactoring. | |
28 | * | |
29 | * The set of prefixes that are not enclosing any unfixes is put in the set of safe prefixes. | |
30 | * This set is used by an Extract and Move Method refactoring to find a suitable target | |
31 | * for the Move Method. | |
32 | * | |
33 | * The class is typically used by the {@link ExtractAndMoveMethodChanger}. | |
7a978020 | 34 | */ |
fc35e1b0 | 35 | public class ExtractAndMoveMethodAnalyzer implements Analyzer { |
64970e7f | 36 | |
ee6a0b5b | 37 | private final CompilationUnitTextSelection selection; |
05d2dee5 EK |
38 | private final PrefixesCollector prefixesCollector; |
39 | private final UnfixesCollector unfixesCollector; | |
64970e7f | 40 | |
fc35e1b0 | 41 | public ExtractAndMoveMethodAnalyzer(CompilationUnitTextSelection selection) { |
ee6a0b5b | 42 | this.selection = selection; |
2f82d251 EK |
43 | prefixesCollector = new PrefixesCollector(selection); |
44 | unfixesCollector = new UnfixesCollector(selection); | |
64970e7f | 45 | } |
74581229 | 46 | |
95330826 | 47 | public PrefixSet calculateSafePrefixes() { |
e09f9054 EK |
48 | PrefixSet safePrefixes = prefixesCollector.getPrefixes().minusEnclosedPrefixesFrom(unfixesCollector.getUnfixes()); |
49 | removeUnusablePrefixes(safePrefixes); | |
50 | return safePrefixes; | |
51 | } | |
52 | ||
53 | private void removeUnusablePrefixes(PrefixSet safePrefixes) { | |
54 | for (Iterator<Prefix> iter = safePrefixes.iterator(); iter.hasNext();) { | |
55 | if (prefixHasSimpleExpressionAndOnlyOneOccurrence(iter.next())) | |
56 | iter.remove(); | |
57 | } | |
58 | } | |
59 | ||
60 | private boolean prefixHasSimpleExpressionAndOnlyOneOccurrence(Prefix prefix) { | |
61 | return prefix.getNumberOfSegments() == 1 && prefix.getCount() == 1; | |
087a79bf | 62 | } |
c4d4c07b EK |
63 | |
64 | protected PrefixSet getPrefixes() { | |
65 | return prefixesCollector.getPrefixes(); | |
66 | } | |
67 | ||
34328ca2 | 68 | public PrefixSet getUnfixes() { |
c4d4c07b EK |
69 | return unfixesCollector.getUnfixes(); |
70 | } | |
e411ecf3 | 71 | |
5748b416 | 72 | public void checkPreconditions() throws RefaktorAnalyzerException { |
e15b42b4 EK |
73 | SelectionValidator.checkIfSelectionIsValid(selection); |
74 | analyze(); | |
75 | checkIfUsefulTargetFound(); | |
76 | } | |
77 | ||
78 | private void checkIfUsefulTargetFound() { | |
79 | if (!hasUsefulResults()) | |
80 | throw new NoTargetFoundException(); | |
81 | } | |
82 | ||
b0b82148 | 83 | public boolean hasUsefulResults() { |
e15b42b4 EK |
84 | return !calculateSafePrefixes().isEmpty(); |
85 | } | |
86 | ||
87 | @Override | |
a554b0ce | 88 | public void analyze() throws RefaktorAnalyzerException { |
5748b416 EK |
89 | BranchingStatementsChecker branchingStatementsChecker = new BranchingStatementsChecker(selection); |
90 | if (branchingStatementsChecker.allStatementsOK()) | |
91 | CollectorManager.collectProperties(selection, prefixesCollector, unfixesCollector); | |
e15b42b4 EK |
92 | } |
93 | ||
94 | public IVariableBinding calculateOriginalTarget() { | |
95 | return calculateMostFrequentPrefix().getVariableBindingOfFirstExpression(); | |
96 | } | |
97 | ||
34328ca2 | 98 | public Prefix calculateMostFrequentPrefix() { |
e15b42b4 | 99 | LinkedList<Prefix> listOfSafePrefixes = calculateListOfSafePrefixes(); |
e411ecf3 EK |
100 | sortAscendingByCountAndLength(listOfSafePrefixes); |
101 | return listOfSafePrefixes.getLast(); | |
102 | } | |
103 | ||
e15b42b4 | 104 | private LinkedList<Prefix> calculateListOfSafePrefixes() { |
95330826 | 105 | return calculateSafePrefixes().toList(); |
e411ecf3 EK |
106 | } |
107 | ||
108 | private void sortAscendingByCountAndLength(LinkedList<Prefix> values) { | |
109 | Collections.sort(values, new Comparator<Prefix>() { | |
110 | @Override | |
111 | public int compare(Prefix p1, Prefix p2) { | |
112 | if (p1.getCount() > p2.getCount()) { | |
113 | return 1; | |
114 | } else if (p1.getCount() < p2.getCount()) { | |
115 | return -1; | |
116 | } else if (p1.length() > p2.length()) { | |
117 | return 1; | |
118 | } else if (p1.length() < p2.length()) { | |
119 | return -1; | |
120 | } | |
121 | return 0; | |
122 | } | |
123 | }); | |
124 | } | |
64970e7f | 125 | } |