]>
Commit | Line | Data |
---|---|---|
b0b82148 EK |
1 | package no.uio.ifi.refaktor.analyze; |
2 | ||
34328ca2 | 3 | import java.util.Collections; |
b0b82148 EK |
4 | import java.util.HashSet; |
5 | import java.util.LinkedList; | |
b0b82148 EK |
6 | import java.util.Set; |
7 | ||
d6c79186 EK |
8 | import no.uio.ifi.refaktor.analyze.comparators.ExtractAndMoveMethodAnalysisResultComparator; |
9 | import no.uio.ifi.refaktor.analyze.comparators.IgnorantAnalysisResultComparator; | |
b0b82148 | 10 | import no.uio.ifi.refaktor.utils.CompilationUnitTextSelection; |
e70f7fb2 | 11 | import no.uio.ifi.refaktor.utils.RefaktorDebug; |
b0b82148 | 12 | |
7dc416b3 | 13 | import org.eclipse.jdt.core.Flags; |
b0b82148 | 14 | import org.eclipse.jdt.core.IMethod; |
e70f7fb2 | 15 | import org.eclipse.jdt.core.JavaModelException; |
b0b82148 EK |
16 | import org.eclipse.jdt.core.dom.Statement; |
17 | ||
cce93a88 EK |
18 | /** |
19 | * A class for searching through a method body to find the best | |
20 | * candidate for the Extract and Move Method refactoring. | |
21 | */ | |
b0b82148 EK |
22 | public class SearchBasedExtractAndMoveMethodAnalyzer implements Analyzer { |
23 | ||
24 | private final IMethod method; | |
14dc9ff0 | 25 | private final ExtractAndMoveMethodAnalysisResultComparator analysisResultComparator; |
e70f7fb2 | 26 | private final AnalysisStatistics statistics; |
b0b82148 | 27 | private Set<CompilationUnitTextSelection> textSelections; |
14dc9ff0 EK |
28 | private LinkedList<ExtractAndMoveMethodAnalysisResult> possibleResults; |
29 | private ExtractAndMoveMethodAnalysisResult chosenResult; | |
4f577e24 | 30 | private StatementsCreator statementsCreator; |
b0b82148 EK |
31 | |
32 | public SearchBasedExtractAndMoveMethodAnalyzer(IMethod method) { | |
14dc9ff0 EK |
33 | this(method, new IgnorantAnalysisResultComparator()); |
34 | } | |
35 | ||
e70f7fb2 EK |
36 | public SearchBasedExtractAndMoveMethodAnalyzer(IMethod method, |
37 | ExtractAndMoveMethodAnalysisResultComparator analysisResultComparator) { | |
38 | this(method, analysisResultComparator, new AnalysisStatistics()); | |
39 | } | |
40 | ||
cce93a88 EK |
41 | /** |
42 | * @param method The handler for the method to analyze. | |
43 | * @param analysisResultComparator A result comparator to compare two analysis results when deciding | |
44 | * which of them that is the best candidate for the refactoring. | |
e70f7fb2 | 45 | * @param statistics |
cce93a88 | 46 | */ |
e70f7fb2 EK |
47 | public SearchBasedExtractAndMoveMethodAnalyzer(IMethod method, |
48 | ExtractAndMoveMethodAnalysisResultComparator analysisResultComparator, AnalysisStatistics statistics) { | |
b0b82148 | 49 | this.method = method; |
14dc9ff0 | 50 | this.analysisResultComparator = analysisResultComparator; |
e70f7fb2 | 51 | this.statistics = statistics; |
b0b82148 | 52 | textSelections = new HashSet<CompilationUnitTextSelection>(); |
14dc9ff0 | 53 | possibleResults = new LinkedList<ExtractAndMoveMethodAnalysisResult>(); |
4f577e24 | 54 | statementsCreator = new StatementsCreator(method); |
b0b82148 EK |
55 | } |
56 | ||
cce93a88 EK |
57 | public ExtractAndMoveMethodAnalysisResult getResult() { |
58 | return chosenResult; | |
59 | } | |
60 | ||
b0b82148 EK |
61 | @Override |
62 | public void analyze() { | |
affb97cf EK |
63 | statistics.incrementMethodCount(); |
64 | ||
e70f7fb2 EK |
65 | printDebugInfo(); |
66 | ||
7dc416b3 EK |
67 | // TODO: make the Extract and Move Method Refactoring work with static methods |
68 | abortIfStaticMethod(); | |
69 | ||
b0b82148 | 70 | generateTextSelections(); |
34328ca2 EK |
71 | generatePossibleResults(); |
72 | ||
73 | if (possibleResults.isEmpty()) | |
74 | throw new NoTargetFoundException(); | |
20f03b7c | 75 | |
34328ca2 EK |
76 | chooseResult(); |
77 | } | |
78 | ||
e70f7fb2 EK |
79 | private void printDebugInfo() { |
80 | try { | |
affb97cf | 81 | RefaktorDebug.println("#" + statistics.getMethodCount() + " (" + statistics.timeSinceStart() + "): " + method.getDeclaringType().getElementName() + "." + method.getElementName() + " (" + "offset: " |
e70f7fb2 EK |
82 | + method.getSourceRange().getOffset() + ", length: " + method.getSourceRange().getLength() + ")"); |
83 | } catch (JavaModelException e) { | |
84 | RefaktorDebug.println("No info about " + method.getElementName()); | |
85 | } | |
86 | } | |
87 | ||
7dc416b3 EK |
88 | private void abortIfStaticMethod() { |
89 | try { | |
90 | if (Flags.isStatic(method.getFlags())) | |
91 | throw new NoTargetFoundException(method.getElementName() + " is static!"); | |
92 | } catch (JavaModelException e) { | |
93 | RefaktorDebug.log(e); | |
94 | throw new GenericAnalyzerException(e); | |
95 | } | |
96 | } | |
97 | ||
b0b82148 | 98 | private void generateTextSelections() { |
4f577e24 | 99 | for (Statement statement: statementsCreator.getStatements()) |
b0b82148 EK |
100 | generateSelectionsFrom(statement); |
101 | } | |
102 | ||
103 | private void generateSelectionsFrom(Statement statement) { | |
104 | Set<CompilationUnitTextSelection> newSelections = new HashSet<CompilationUnitTextSelection>(); | |
105 | CompilationUnitTextSelection textSelectionFromStatement = createTextSelectionFromStatement(statement); | |
106 | newSelections.add(textSelectionFromStatement); | |
107 | ||
108 | for (CompilationUnitTextSelection textSelection: textSelections) | |
109 | newSelections.add(addTextSelections(textSelection, textSelectionFromStatement)); | |
34328ca2 | 110 | |
b0b82148 EK |
111 | textSelections.addAll(newSelections); |
112 | } | |
113 | ||
34328ca2 EK |
114 | private CompilationUnitTextSelection createTextSelectionFromStatement(Statement statement) { |
115 | return new CompilationUnitTextSelection(method.getCompilationUnit(), statement.getStartPosition(), statement.getLength()); | |
116 | } | |
117 | ||
b0b82148 EK |
118 | private CompilationUnitTextSelection addTextSelections( |
119 | CompilationUnitTextSelection textSelectionOne, CompilationUnitTextSelection textSelectionTwo) { | |
120 | int offset = Math.min(textSelectionOne.getOffset(), textSelectionTwo.getOffset()); | |
121 | int length = Math.max(textSelectionOne.getEnd(), textSelectionTwo.getEnd()) - offset; | |
122 | return new CompilationUnitTextSelection(textSelectionOne.getCompilationUnit(), offset, length); | |
123 | } | |
124 | ||
4f577e24 EK |
125 | private void generatePossibleResults() { |
126 | for (CompilationUnitTextSelection textSelection: textSelections) { | |
127 | ExtractAndMoveMethodAnalyzer analyzer = new ExtractAndMoveMethodAnalyzer(textSelection); | |
128 | analyzer.analyze(); | |
09f273fa | 129 | |
4f577e24 | 130 | if (analyzer.hasUsefulResults()) |
cce93a88 | 131 | possibleResults.add(new ExtractAndMoveMethodAnalysisResult(method, analyzer, textSelection, statementsCreator.getNumberOfStatements(), textSelections.size())); |
b0b82148 | 132 | } |
09f273fa EK |
133 | } |
134 | ||
4f577e24 EK |
135 | private void chooseResult() { |
136 | sortPossibleResults(); | |
137 | chosenResult = possibleResults.getLast(); | |
b0b82148 EK |
138 | } |
139 | ||
4f577e24 EK |
140 | private void sortPossibleResults() { |
141 | Collections.sort(possibleResults, analysisResultComparator); | |
b0b82148 | 142 | } |
b0b82148 | 143 | } |