]> git.uio.no Git - ifi-stolz-refaktor.git/blob - software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/extractors/CommonPrefixExtractor.java
6e7a54ebdc1b1f17760c53c30504625f719b6642
[ifi-stolz-refaktor.git] / software / no.uio.ifi.refaktor / src / no / uio / ifi / refaktor / extractors / CommonPrefixExtractor.java
1 package no.uio.ifi.refaktor.extractors;
2
3 import java.util.Collections;
4 import java.util.Comparator;
5 import java.util.LinkedList;
6
7 import no.uio.ifi.refaktor.utils.SmartTextSelection;
8
9 import org.eclipse.jdt.core.ICompilationUnit;
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         
28                 public SelectionAttributesCollector(SmartTextSelection selection, ICompilationUnit icu) {
29                         this.selection = selection;
30                         this.selectedStatements = new LinkedList<ASTNode>();
31                         if (icu == null)
32                                 nodeFinder = selection.getNodeFinder();
33                         else
34                                 nodeFinder = selection.getNodeFinder(icu);
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) {
108                 this(selection, null);
109         }
110
111         public CommonPrefixExtractor(SmartTextSelection selection, ICompilationUnit icu) {
112                 super(selection, icu);
113                 selectionAttributesCollector = new SelectionAttributesCollector(selection, icu);
114         }
115
116         /**
117          * @return null, if no prefix is generated from statement.
118          * @Nullable
119          */
120         private Prefix getPrefix(ExpressionStatement statement) {
121                 Expression expression = statement.getExpression();
122                 // TODO: support more expression types
123                 if (expression instanceof MethodInvocation)
124                         return new Prefix(((MethodInvocation) expression).getExpression(), statement, getDocument());
125                 else
126                         return null;
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         
153                 final Prefix p = getPrefix(node);
154                 // No prefix generated?
155                 if (p != null)
156                         registerPrefix(p);
157                 
158                 return true;
159         }
160
161         protected abstract void registerPrefix(Prefix prefix);
162 }