At the same time removing PropertyExtractorExecutor.
LongestCommonPrefixExtractor now works on ExpressionStatements only, and
when the expression is a MethodInvocation.
--- /dev/null
+package no.uio.ifi.refaktor.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import no.uio.ifi.refaktor.extractors.LongestCommonPrefixExtractor;
+import no.uio.ifi.refaktor.utils.SmartTextSelection;
+
+import org.eclipse.jface.text.Document;
+import org.junit.Before;
+import org.junit.Test;
+
+public class LongestCommonPrefixExtractorTest {
+
+ private String classStart;
+ private String methodText;
+ private String endStartFoo;
+ private String startFoo;
+ private String testCode;
+ private String singleStatement;
+ private String testExpression;
+ private String blockText;
+
+ @Before
+ public void setUp() throws Exception {
+ classStart = "class TestClass {";
+ endStartFoo = "b.c.d();a.b.c.f();";
+ startFoo = "a." + endStartFoo;
+ singleStatement = "a.b.c.g(a.c);";
+ testExpression = "a.b.d.f()";
+ blockText = "{" + startFoo + "if(" + testExpression + "){" + singleStatement + "return a.b.d();}}";
+ methodText = "public void foo() " + blockText;
+ testCode = classStart + methodText + "}";
+ }
+
+ @Test
+ public void testSelectionIsValidStartFoo() {
+ makeStartFooExtractor();
+ }
+
+ @Test
+ public void testExtractPropertyStartFoo() {
+ LongestCommonPrefixExtractor extractor = makeStartFooExtractor();
+ extractor.extractProperty();
+ assertEquals("a.b.c", extractor.stringProperty());
+ }
+
+ private LongestCommonPrefixExtractor makeStartFooExtractor() {
+ SmartTextSelection selection = new SmartTextSelection(new Document(testCode), testCode.indexOf(startFoo), startFoo.length());
+ LongestCommonPrefixExtractor extractor = new LongestCommonPrefixExtractor(selection);
+ assertTrue(extractor.selectionIsValid());
+ return extractor;
+ }
+
+ @Test
+ public void testSelectionIsValidEndStartFoo() {
+ SmartTextSelection selection = new SmartTextSelection(new Document(testCode), testCode.indexOf(endStartFoo), endStartFoo.length());
+ LongestCommonPrefixExtractor extractor = new LongestCommonPrefixExtractor(selection);
+ assertFalse("Partial selection of statements shall not be allowed", extractor.selectionIsValid());
+ }
+
+ @Test
+ public void testSelectionIsValidSingleStatement() {
+ makeSingleStatementExtractor();
+ }
+
+ @Test
+ public void testExtractPropertySingleStatement() {
+ LongestCommonPrefixExtractor extractor = makeSingleStatementExtractor();
+ extractor.extractProperty();
+ assertEquals("a.b.c", extractor.stringProperty());
+ }
+
+ private LongestCommonPrefixExtractor makeSingleStatementExtractor() {
+ SmartTextSelection selection = new SmartTextSelection(new Document(testCode), testCode.indexOf(singleStatement), singleStatement.length());
+ LongestCommonPrefixExtractor extractor = new LongestCommonPrefixExtractor(selection);
+ assertTrue("Single statements shall be allowed", extractor.selectionIsValid());
+ return extractor;
+ }
+
+ @Test
+ public void testSelectionIsValidTestExpression() {
+ SmartTextSelection selection = new SmartTextSelection(new Document(testCode), testCode.indexOf(testExpression), testExpression.length());
+ LongestCommonPrefixExtractor extractor = new LongestCommonPrefixExtractor(selection);
+ assertFalse("Expressions shall not be allowed", extractor.selectionIsValid());
+ }
+
+ @Test
+ public void testSelectionIsValidMethodText() {
+ makeMethodTextExtractor();
+ }
+
+ @Test
+ public void testExtractPropertyMethodText() {
+ LongestCommonPrefixExtractor extractor = makeMethodTextExtractor();
+ extractor.extractProperty();
+ assertEquals("a.b.c", extractor.stringProperty());
+ }
+
+ private LongestCommonPrefixExtractor makeMethodTextExtractor() {
+ SmartTextSelection selection = new SmartTextSelection(new Document(testCode), testCode.indexOf(methodText), methodText.length());
+ LongestCommonPrefixExtractor extractor = new LongestCommonPrefixExtractor(selection);
+ assertTrue("Selecting whole methods should be allowed", extractor.selectionIsValid());
+ return extractor;
+ }
+
+ @Test
+ public void testSelectionIsValidBlockText() {
+ makeBlockTextExtractor();
+ }
+
+ @Test
+ public void textExtractPropertyBlockText() {
+ LongestCommonPrefixExtractor extractor = makeBlockTextExtractor();
+ extractor.extractProperty();
+ assertEquals("a.b.c", extractor.stringProperty());
+ }
+
+ private LongestCommonPrefixExtractor makeBlockTextExtractor() {
+ SmartTextSelection selection = new SmartTextSelection(new Document(testCode), testCode.indexOf(blockText), blockText.length());
+ LongestCommonPrefixExtractor extractor = new LongestCommonPrefixExtractor(selection);
+ assertTrue("Selecting blocks should be allowed", extractor.selectionIsValid());
+ return extractor;
+ }
+
+}
+++ /dev/null
-package no.uio.ifi.refaktor.tests;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import no.uio.ifi.refaktor.extractors.PropertyExtractor;
-import no.uio.ifi.refaktor.extractors.PropertyExtractorExecutor;
-import no.uio.ifi.refaktor.utils.ParseUtils;
-import no.uio.ifi.refaktor.utils.SmartTextSelection;
-
-import org.eclipse.jdt.core.dom.MethodDeclaration;
-import org.eclipse.jface.text.Document;
-import org.junit.Before;
-import org.junit.Test;
-
-public class PropertyExtractorExecutorTest {
-
- private String methodText;
- private SmartTextSelection selection;
- private SimplePropertyExtractor extractor;
- private PropertyExtractorExecutor executor;
-
- class SimplePropertyExtractor extends PropertyExtractor {
-
- private String property;
-
- public SimplePropertyExtractor(SmartTextSelection selection) {
- super(selection);
- }
-
- @Override
- public boolean selectionIsValid() {
- return getSelection() != null && getSelection().getText().equals(methodText);
- }
-
- public String property() {
- return property;
- }
-
- public boolean visit(MethodDeclaration node) {
- property = ParseUtils.getNodeText(node, getDocument());
- return false;
- }
- }
-
- @Before
- public void setUp() throws Exception {
- methodText = "public void foo() { System.out.println(\"bar\"); }";
- String classStart = "class TestCode { ";
- String testCode = classStart + methodText + "}";
- selection = new SmartTextSelection(new Document(testCode), classStart.length(), methodText.length());
- extractor = new SimplePropertyExtractor(selection);
- executor = new PropertyExtractorExecutor(extractor);
- }
-
- @Test
- public void testExtractProperty() {
- assertEquals("The selection range may have been poorly defined.", methodText, selection.getText());
- executor.extractProperty();
- assertEquals(selection.getText(), extractor.property());
- }
-
- @Test
- public void testSelectionIsValid() {
- assertTrue(executor.selectionIsValid());
- }
-
-}
package no.uio.ifi.refaktor.extractors;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+
import no.uio.ifi.refaktor.utils.ParseUtils;
import no.uio.ifi.refaktor.utils.SmartTextSelection;
-import org.eclipse.jdt.core.dom.QualifiedName;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.ExpressionStatement;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.NodeFinder;
+import org.eclipse.jdt.core.dom.Statement;
public class LongestCommonPrefixExtractor extends PropertyExtractor {
-
+
+ protected class SelectionAttributesCollector extends ASTVisitor {
+
+ private SmartTextSelection selection;
+ private LinkedList<ASTNode> selectedStatements;
+ private NodeFinder nodeFinder;
+
+ public SelectionAttributesCollector(SmartTextSelection selection) {
+ this.selection = selection;
+ this.selectedStatements = new LinkedList<ASTNode>();
+ nodeFinder = ParseUtils.getNodeFinder(selection);
+ findSelectedStatements(getCoveringNode());
+ }
+
+ private ASTNode getCoveringNode() {
+ return nodeFinder.getCoveringNode();
+ }
+
+ private ASTNode getCoveredNode() {
+ return nodeFinder.getCoveredNode();
+ }
+
+ public boolean isSingleNodeSelection() {
+ return getCoveringNode() == getCoveredNode();
+ }
+
+ public ASTNode getSelectedNode() {
+ if (!isSingleNodeSelection())
+ return null;
+ return getCoveredNode();
+ }
+
+ public void findSelectedStatements(ASTNode node) {
+ node.accept(this);
+ Collections.sort(selectedStatements, new Comparator<ASTNode>(){
+ @Override
+ public int compare(ASTNode node1, ASTNode node2) {
+ if (node1.equals(node2))
+ return 0;
+ else if (node1.getStartPosition() < node2.getStartPosition())
+ return -1;
+ else if (node1.getStartPosition() > node2.getStartPosition())
+ return 1;
+ else
+ return 0;
+ }});
+ }
+
+ @Override
+ public boolean preVisit2(ASTNode node) {
+ if (node instanceof Statement && nodeInSelection(node, selection)) {
+ selectedStatements.add(node);
+ // Only visit top-level statements
+ return false;
+ }
+
+ if (node instanceof MethodDeclaration || node instanceof Block )
+ return true;
+
+ return false;
+ }
+
+ public boolean selectedNodeHasBlockStructure() {
+ return isSingleNodeSelection() &&
+ (getSelectedNode() instanceof MethodDeclaration || getSelectedNode() instanceof Block);
+ }
+
+ public boolean noStatementsSelected() {
+ return selectedStatements.isEmpty();
+ }
+
+ private boolean selectionMatchesStatementsStartAndEnd() {
+ return selectedStatements.getFirst().getStartPosition() == selection.getOffset()
+ && nodeEnd(selectedStatements.getLast()) == selection.getEnd();
+ }
+
+ private int nodeEnd(ASTNode astNode) {
+ return astNode.getStartPosition() + astNode.getLength();
+ }
+ }
+
protected String property;
+ private SelectionAttributesCollector selectionAttributesCollector;
public LongestCommonPrefixExtractor(SmartTextSelection selection) {
super(selection);
+ selectionAttributesCollector = new SelectionAttributesCollector(selection);
}
-
- //TODO: what about simple names?
@Override
- public boolean visit(QualifiedName node) {
+ public boolean visit(ExpressionStatement node) {
if (!nodeInSelection(node))
return false;
-
- String nodeText = ParseUtils.getNodeText(node, getSelection().getDocument()).trim();
-
+
+ String prefix = getPrefix(node);
+
if (property == null) {
- property = nodeText;
+ property = prefix;
} else {
- property = longestCommonPrefix(property, nodeText);
+ property = longestCommonPrefix(property, prefix);
}
return false;
}
+ public String getPrefix(ExpressionStatement node) {
+ Expression expression = node.getExpression();
+ if (expression instanceof MethodInvocation)
+ return ParseUtils.getNodeText(((MethodInvocation) expression).getExpression(), getDocument()).trim();
+ return ParseUtils.getNodeText(node, getDocument()).trim();
+ }
+
private String longestCommonPrefix(String attribute, String nodeText) {
String commonPrefix = attribute.substring(0, numberOfCommonCharacters(attribute, nodeText));
if (commonPrefix.endsWith(".")) {
private boolean belowStringLengths(int index, String attribute, String nodeText) {
return index < attribute.length() && index < nodeText.length();
}
-
+
private boolean charsMatchingAt(String attribute, String nodeText, int index) {
return attribute.charAt(index) == nodeText.charAt(index);
}
public String stringProperty() {
return property;
}
+
+ @Override
+ public boolean selectionIsValid() {
+ if (!super.selectionIsValid())
+ return false;
+
+ if (selectionAttributesCollector.noStatementsSelected())
+ return false;
+
+ if (selectionAttributesCollector.selectedNodeHasBlockStructure())
+ return true;
+
+ return selectionAttributesCollector.selectionMatchesStatementsStartAndEnd();
+ }
+
+ @Override
+ protected ASTNode getStartNode() {
+ return selectionAttributesCollector.getCoveringNode();
+ }
}
\ No newline at end of file
package no.uio.ifi.refaktor.extractors;
+import no.uio.ifi.refaktor.utils.ParseUtils;
import no.uio.ifi.refaktor.utils.SmartTextSelection;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
public abstract class PropertyExtractor extends ASTVisitor {
public IDocument getDocument() {
return selection.getDocument();
}
-
protected boolean nodeInSelection(ASTNode node) {
+ return nodeInSelection(node, getSelection());
+ }
+
+ protected boolean nodeInSelection(ASTNode node, ITextSelection selection) {
return selection.getOffset() <= node.getStartPosition() &&
(node.getStartPosition() + node.getLength()) <= (selection.getOffset() + selection.getLength());
}
return selection != null;
}
- public void extractProperty(ASTNode startNode) {
+ public void extractProperty() {
if (!selectionIsValid())
throw new RuntimeException(this.getClass().getCanonicalName() + ": Trying to extract property from invalid selection!");
- startNode.accept(this);
+ getStartNode().accept(this);
+ }
+
+ protected ASTNode getStartNode() {
+ return ParseUtils.getNodeFinder(selection).getCoveringNode();
}
}
+++ /dev/null
-package no.uio.ifi.refaktor.extractors;
-
-import no.uio.ifi.refaktor.utils.ParseUtils;
-
-import org.eclipse.jdt.core.dom.ASTNode;
-
-public class PropertyExtractorExecutor {
-
- private PropertyExtractor extractor;
-
- public PropertyExtractorExecutor(PropertyExtractor extractor) {
- this.extractor = extractor;
- }
-
- public void extractProperty() {
- extractor.extractProperty(getCoveringNode());
- }
-
- private ASTNode getCoveringNode() {
- return ParseUtils.getNodeFinder(extractor.getDocument(), extractor.getSelection()).getCoveringNode();
- }
-
- public boolean selectionIsValid() {
- return extractor.selectionIsValid();
- }
-
-}
-
public String stringProperty() {
return property;
}
-
}
package no.uio.ifi.refaktor.handlers;
import no.uio.ifi.refaktor.extractors.LongestCommonPrefixExtractor;
-import no.uio.ifi.refaktor.extractors.PropertyExtractorExecutor;
import no.uio.ifi.refaktor.utils.ParseUtils;
import no.uio.ifi.refaktor.utils.SmartTextSelection;
editor.getSite().getSelectionProvider().setSelection(smartTextSelection);
LongestCommonPrefixExtractor extractor = new LongestCommonPrefixExtractor(smartTextSelection);
- PropertyExtractorExecutor executor = new PropertyExtractorExecutor(extractor);
String dialogText;
- if (executor.selectionIsValid()) {
- executor.extractProperty();
+ if (extractor.selectionIsValid()) {
+ extractor.extractProperty();
dialogText = extractor.stringProperty();
} else {
dialogText = "Selection is invalid";
return new NodeFinder(cu.getRoot(), selection.getOffset(), selection.getLength());
}
+ public static NodeFinder getNodeFinder(SmartTextSelection selection) {
+ return getNodeFinder(selection.getDocument(), selection);
+ }
+
}
return document;
}
+ public int getEnd() {
+ return getOffset() + getLength();
+ }
+
}