]>
Commit | Line | Data |
---|---|---|
67073f0a EK |
1 | package no.uio.ifi.refaktor.extractors; |
2 | ||
47501704 EK |
3 | import java.util.Collections; |
4 | import java.util.Comparator; | |
5 | import java.util.LinkedList; | |
67073f0a | 6 | |
67073f0a EK |
7 | import no.uio.ifi.refaktor.utils.SmartTextSelection; |
8 | ||
0311e2cb | 9 | import org.eclipse.jdt.core.ICompilationUnit; |
67073f0a EK |
10 | import org.eclipse.jdt.core.dom.ASTNode; |
11 | import org.eclipse.jdt.core.dom.ASTVisitor; | |
12 | import org.eclipse.jdt.core.dom.Block; | |
13 | import org.eclipse.jdt.core.dom.Expression; | |
14 | import org.eclipse.jdt.core.dom.ExpressionStatement; | |
15 | import org.eclipse.jdt.core.dom.MethodDeclaration; | |
16 | import org.eclipse.jdt.core.dom.MethodInvocation; | |
17 | import org.eclipse.jdt.core.dom.NodeFinder; | |
18 | import org.eclipse.jdt.core.dom.Statement; | |
19 | ||
20 | public abstract class CommonPrefixExtractor extends PropertyExtractor { | |
21 | ||
22 | private class SelectionAttributesCollector extends ASTVisitor { | |
23 | ||
24 | private SmartTextSelection selection; | |
25 | private LinkedList<ASTNode> selectedStatements; | |
26 | private NodeFinder nodeFinder; | |
27 | ||
0311e2cb | 28 | public SelectionAttributesCollector(SmartTextSelection selection, ICompilationUnit icu) { |
67073f0a EK |
29 | this.selection = selection; |
30 | this.selectedStatements = new LinkedList<ASTNode>(); | |
0311e2cb | 31 | if (icu == null) |
2c782b57 | 32 | nodeFinder = selection.getNodeFinder(); |
0311e2cb | 33 | else |
2c782b57 | 34 | nodeFinder = selection.getNodeFinder(icu); |
67073f0a EK |
35 | findSelectedStatements(getCoveringNode()); |
36 | } | |
37 | ||
38 | ASTNode getCoveringNode() { | |
39 | return nodeFinder.getCoveringNode(); | |
40 | } | |
41 | ||
42 | private ASTNode getCoveredNode() { | |
43 | return nodeFinder.getCoveredNode(); | |
44 | } | |
45 | ||
46 | public boolean isSingleNodeSelection() { | |
47 | return getCoveringNode() == getCoveredNode(); | |
48 | } | |
49 | ||
50 | public ASTNode getSelectedNode() { | |
51 | if (!isSingleNodeSelection()) | |
52 | return null; | |
53 | return getCoveredNode(); | |
54 | } | |
55 | ||
56 | public void findSelectedStatements(ASTNode node) { | |
57 | node.accept(this); | |
58 | Collections.sort(selectedStatements, new Comparator<ASTNode>(){ | |
59 | @Override | |
60 | public int compare(ASTNode node1, ASTNode node2) { | |
61 | if (node1.equals(node2)) | |
62 | return 0; | |
63 | else if (node1.getStartPosition() < node2.getStartPosition()) | |
64 | return -1; | |
65 | else if (node1.getStartPosition() > node2.getStartPosition()) | |
66 | return 1; | |
67 | else | |
68 | return 0; | |
69 | }}); | |
70 | } | |
71 | ||
72 | @Override | |
73 | public boolean preVisit2(ASTNode node) { | |
74 | if (node instanceof Statement && nodeInSelection(node, selection)) { | |
75 | selectedStatements.add(node); | |
76 | // Only visit top-level statements | |
77 | return false; | |
78 | } | |
79 | ||
80 | if (node instanceof MethodDeclaration || node instanceof Block ) | |
81 | return true; | |
82 | ||
83 | return false; | |
84 | } | |
85 | ||
86 | public boolean selectedNodeHasBlockStructure() { | |
87 | return isSingleNodeSelection() && | |
88 | (getSelectedNode() instanceof MethodDeclaration || getSelectedNode() instanceof Block); | |
89 | } | |
90 | ||
91 | public boolean noStatementsSelected() { | |
92 | return selectedStatements.isEmpty(); | |
93 | } | |
94 | ||
95 | boolean selectionMatchesStatementsStartAndEnd() { | |
96 | return selectedStatements.getFirst().getStartPosition() == selection.getOffset() | |
97 | && nodeEnd(selectedStatements.getLast()) == selection.getEnd(); | |
98 | } | |
99 | ||
100 | private int nodeEnd(ASTNode astNode) { | |
101 | return astNode.getStartPosition() + astNode.getLength(); | |
102 | } | |
103 | } | |
104 | ||
105 | private SelectionAttributesCollector selectionAttributesCollector; | |
106 | ||
107 | public CommonPrefixExtractor(SmartTextSelection selection) { | |
0311e2cb | 108 | this(selection, null); |
67073f0a EK |
109 | } |
110 | ||
0311e2cb EK |
111 | public CommonPrefixExtractor(SmartTextSelection selection, ICompilationUnit icu) { |
112 | super(selection, icu); | |
113 | selectionAttributesCollector = new SelectionAttributesCollector(selection, icu); | |
114 | } | |
115 | ||
5a59d8de VS |
116 | /** |
117 | * @return null, if no prefix is generated from statement. | |
118 | * @Nullable | |
119 | */ | |
120 | private Prefix getPrefix(ExpressionStatement statement) { | |
0311e2cb | 121 | Expression expression = statement.getExpression(); |
6d7256a3 | 122 | // TODO: support more expression types |
67073f0a | 123 | if (expression instanceof MethodInvocation) |
7a978020 | 124 | return new Prefix(((MethodInvocation) expression).getExpression(), getDocument()); |
5a59d8de VS |
125 | else |
126 | return null; | |
67073f0a EK |
127 | } |
128 | ||
129 | @Override | |
130 | public boolean selectionIsValid() { | |
131 | if (!super.selectionIsValid()) | |
132 | return false; | |
133 | ||
134 | if (selectionAttributesCollector.noStatementsSelected()) | |
135 | return false; | |
136 | ||
137 | if (selectionAttributesCollector.selectedNodeHasBlockStructure()) | |
138 | return true; | |
139 | ||
140 | return selectionAttributesCollector.selectionMatchesStatementsStartAndEnd(); | |
141 | } | |
142 | ||
143 | @Override | |
144 | protected ASTNode getStartNode() { | |
145 | return selectionAttributesCollector.getCoveringNode(); | |
146 | } | |
147 | ||
148 | @Override | |
149 | public boolean visit(ExpressionStatement node) { | |
150 | if (!nodeInSelection(node)) | |
151 | return false; | |
152 | ||
5a59d8de VS |
153 | final Prefix p = getPrefix(node); |
154 | // No prefix generated? | |
155 | if (p != null) | |
156 | registerPrefix(p); | |
67073f0a | 157 | |
64970e7f | 158 | return true; |
67073f0a EK |
159 | } |
160 | ||
3db313c8 | 161 | protected abstract void registerPrefix(Prefix prefix); |
67073f0a | 162 | } |