aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorszarnekow2009-03-26 10:03:38 (EDT)
committersefftinge2009-03-26 10:03:38 (EDT)
commit79db19ed047eb23a0acdc1095d809f6f3b75fdb0 (patch)
tree9f3f96aff521ecefadb8b1aefcb6ec4c89ac6284
parent4001dad8f9be884228242c6edcda2c03526604a3 (diff)
downloadorg.eclipse.xtext-79db19ed047eb23a0acdc1095d809f6f3b75fdb0.zip
org.eclipse.xtext-79db19ed047eb23a0acdc1095d809f6f3b75fdb0.tar.gz
org.eclipse.xtext-79db19ed047eb23a0acdc1095d809f6f3b75fdb0.tar.bz2
improvements to DefaultLocationInFileProvider, introduce XtextLocationInFileProvider
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/DefaultLocationInFileProvider.java134
1 files changed, 104 insertions, 30 deletions
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/DefaultLocationInFileProvider.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/DefaultLocationInFileProvider.java
index 1fbf245..086a14f 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/DefaultLocationInFileProvider.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/DefaultLocationInFileProvider.java
@@ -9,18 +9,22 @@
package org.eclipse.xtext.ui.core;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.text.Region;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.parsetree.AbstractNode;
import org.eclipse.xtext.parsetree.CompositeNode;
+import org.eclipse.xtext.parsetree.LeafNode;
import org.eclipse.xtext.parsetree.NodeAdapter;
import org.eclipse.xtext.parsetree.NodeUtil;
-
+import org.eclipse.xtext.parsetree.util.ParsetreeSwitch;
/**
* @author Peter Friese - Implementation
@@ -29,50 +33,120 @@ import org.eclipse.xtext.parsetree.NodeUtil;
public class DefaultLocationInFileProvider implements ILocationInFileProvider {
public Region getLocation(EObject obj) {
- NodeAdapter adapter = NodeUtil.getNodeAdapter(obj);
- if (adapter == null)
- return new Region(0,0);
-
- CompositeNode startNode = adapter.getParserNode();
- EList<AbstractNode> leafNodes = startNode.getChildren();
+ final NodeAdapter adapter = NodeUtil.getNodeAdapter(obj);
+ if (adapter == null) {
+ if (obj.eContainer() == null)
+ return new Region(0, 0);
+ return getLocation(obj.eContainer());
+ }
+
+ List<AbstractNode> nodes = getLocationNodes(obj);
+ if (nodes == null || nodes.isEmpty())
+ nodes = Collections.<AbstractNode> singletonList(adapter.getParserNode());
+
+ return createRegion(nodes);
+ }
+
+ protected List<AbstractNode> getLocationNodes(EObject obj) {
+ final EStructuralFeature nameFeature = getIdentifierFeature(obj);
+ if (nameFeature != null)
+ return NodeUtil.findNodesForFeature(obj, nameFeature);
+
+ List<AbstractNode> resultNodes = new ArrayList<AbstractNode>();
+ final NodeAdapter adapter = NodeUtil.getNodeAdapter(obj);
+ final CompositeNode startNode = adapter.getParserNode();
AbstractNode keywordNode = null;
- List<AbstractNode> idNodes = null;
- for (AbstractNode leafNode : leafNodes) {
- EObject grammarElement = leafNode.getGrammarElement();
+ // use LeafNodes instead of children?
+ EList<AbstractNode> children = startNode.getChildren();
+ for (AbstractNode child : children) {
+ EObject grammarElement = child.getGrammarElement();
if (grammarElement instanceof RuleCall) {
RuleCall ruleCall = (RuleCall) grammarElement;
String ruleName = ruleCall.getRule().getName();
-
- // TODO usually we use the name feature if the instead of the id call
- // LeafNode.getFeature()
if (ruleName.equals("ID")) {
- if (idNodes == null) {
- idNodes = new ArrayList<AbstractNode>();
- }
- idNodes.add(leafNode);
+ resultNodes.add(child);
}
}
else if (grammarElement instanceof Keyword) {
- if (keywordNode == null) {
- keywordNode = leafNode;
+ // TODO use only keywords, that aren't symbols like '=' ?
+ if (keywordNode == null && useKeyword((Keyword) grammarElement, obj)) {
+ keywordNode = child;
}
}
}
+ if (resultNodes.isEmpty() && keywordNode != null)
+ resultNodes.add(keywordNode);
+ return resultNodes;
+ }
+
+ protected boolean useKeyword(Keyword keyword, EObject context) {
+ return true;
+ }
+
+ protected EStructuralFeature getIdentifierFeature(EObject obj) {
+ final EClass eClass = obj.eClass();
+ final EStructuralFeature result = eClass.getEStructuralFeature("name");
+ return result != null ? result : eClass.getEStructuralFeature("id");
+ }
- if (idNodes != null) {
- // if we've got more than one ID elements, we want to select
- // them all
- AbstractNode firstIdNode = idNodes.get(0);
- AbstractNode lastIdNode = idNodes.get(idNodes.size() - 1);
- int length = (lastIdNode.getOffset() - firstIdNode.getOffset()) + lastIdNode.getLength();
- return new Region(firstIdNode.getOffset(), length);
+ protected static class OffsetCalculator extends ParsetreeSwitch<LeafNode> {
+
+ private boolean forward = true;
+
+ @Override
+ public LeafNode caseCompositeNode(CompositeNode object) {
+ return handleImpl(object.getChildren());
}
- else if (keywordNode != null) {
- return new Region(keywordNode.getOffset(), keywordNode.getLength());
+
+ public AbstractNode handle(List<AbstractNode> nodes, boolean forward) {
+ this.forward = forward;
+ AbstractNode result = handleImpl(nodes);
+ if (result == null) {
+ if (forward)
+ result = nodes.get(0);
+ else
+ result = nodes.get(nodes.size()-1);
+ }
+ return result;
+ }
+
+ public LeafNode handleImpl(List<AbstractNode> nodes) {
+ if(forward) {
+ for (AbstractNode node: nodes) {
+ LeafNode result = doSwitch(node);
+ if (result != null)
+ return result;
+ }
+ } else {
+ for(int i = nodes.size() - 1; i >= 0; i--) {
+ AbstractNode node = nodes.get(i);
+ LeafNode result = doSwitch(node);
+ if (result != null)
+ return result;
+ }
+ }
+ return null;
}
- else {
- return new Region(startNode.getOffset(), startNode.getLength());
+
+ @Override
+ public LeafNode caseLeafNode(LeafNode object) {
+ if (!object.isHidden())
+ return object;
+ return null;
}
}
+ protected Region createRegion(final List<AbstractNode> nodes) {
+ // if we've got more than one ID elements, we want to select them all
+ OffsetCalculator calculator = createCalculator();
+ AbstractNode firstNode = calculator.handle(nodes, true);
+ AbstractNode lastNode = calculator.handle(nodes, false);
+ int length = (lastNode.getOffset() - firstNode.getOffset()) + lastNode.getLength();
+ return new Region(firstNode.getOffset(), length);
+ }
+
+ protected OffsetCalculator createCalculator() {
+ return new OffsetCalculator();
+ }
+
}