1 package no.uio.ifi.refaktor.extractors;
3 import java.util.Collections;
4 import java.util.Comparator;
5 import java.util.LinkedList;
7 import no.uio.ifi.refaktor.utils.SmartTextSelection;
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;
20 public abstract class CommonPrefixExtractor extends PropertyExtractor {
22 private class SelectionAttributesCollector extends ASTVisitor {
24 private SmartTextSelection selection;
25 private LinkedList<ASTNode> selectedStatements;
26 private NodeFinder nodeFinder;
28 public SelectionAttributesCollector(SmartTextSelection selection, ICompilationUnit icu) {
29 this.selection = selection;
30 this.selectedStatements = new LinkedList<ASTNode>();
32 nodeFinder = selection.getNodeFinder();
34 nodeFinder = selection.getNodeFinder(icu);
35 findSelectedStatements(getCoveringNode());
38 ASTNode getCoveringNode() {
39 return nodeFinder.getCoveringNode();
42 private ASTNode getCoveredNode() {
43 return nodeFinder.getCoveredNode();
46 public boolean isSingleNodeSelection() {
47 return getCoveringNode() == getCoveredNode();
50 public ASTNode getSelectedNode() {
51 if (!isSingleNodeSelection())
53 return getCoveredNode();
56 public void findSelectedStatements(ASTNode node) {
58 Collections.sort(selectedStatements, new Comparator<ASTNode>(){
60 public int compare(ASTNode node1, ASTNode node2) {
61 if (node1.equals(node2))
63 else if (node1.getStartPosition() < node2.getStartPosition())
65 else if (node1.getStartPosition() > node2.getStartPosition())
73 public boolean preVisit2(ASTNode node) {
74 if (node instanceof Statement && nodeInSelection(node, selection)) {
75 selectedStatements.add(node);
76 // Only visit top-level statements
80 if (node instanceof MethodDeclaration || node instanceof Block )
86 public boolean selectedNodeHasBlockStructure() {
87 return isSingleNodeSelection() &&
88 (getSelectedNode() instanceof MethodDeclaration || getSelectedNode() instanceof Block);
91 public boolean noStatementsSelected() {
92 return selectedStatements.isEmpty();
95 boolean selectionMatchesStatementsStartAndEnd() {
96 return selectedStatements.getFirst().getStartPosition() == selection.getOffset()
97 && nodeEnd(selectedStatements.getLast()) == selection.getEnd();
100 private int nodeEnd(ASTNode astNode) {
101 return astNode.getStartPosition() + astNode.getLength();
105 private SelectionAttributesCollector selectionAttributesCollector;
107 public CommonPrefixExtractor(SmartTextSelection selection) {
108 this(selection, null);
111 public CommonPrefixExtractor(SmartTextSelection selection, ICompilationUnit icu) {
112 super(selection, icu);
113 selectionAttributesCollector = new SelectionAttributesCollector(selection, icu);
117 * @return null, if no prefix is generated from statement.
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());
130 public boolean selectionIsValid() {
131 if (!super.selectionIsValid())
134 if (selectionAttributesCollector.noStatementsSelected())
137 if (selectionAttributesCollector.selectedNodeHasBlockStructure())
140 return selectionAttributesCollector.selectionMatchesStatementsStartAndEnd();
144 protected ASTNode getStartNode() {
145 return selectionAttributesCollector.getCoveringNode();
149 public boolean visit(ExpressionStatement node) {
150 if (!nodeInSelection(node))
153 final Prefix p = getPrefix(node);
154 // No prefix generated?
161 protected abstract void registerPrefix(Prefix prefix);