mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 16:58:56 +00:00
[xtext][locationInFileProvider] Improved the computation of significant and full regions
This commit is contained in:
parent
cc25489506
commit
41df70b922
2 changed files with 55 additions and 4 deletions
|
@ -28,6 +28,8 @@ import org.eclipse.xtext.nodemodel.ILeafNode;
|
|||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.nodemodel.impl.AbstractNode;
|
||||
import org.eclipse.xtext.resource.EObjectAtOffsetHelper;
|
||||
import org.eclipse.xtext.resource.ILocationInFileProvider;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
|
@ -35,6 +37,11 @@ import com.google.common.collect.Lists;
|
|||
* The NodeModelUtils are a collection of useful methods when dealing with the node model directly. They encapsulate the
|
||||
* default construction semantics of the node model as it is created by the parser.
|
||||
*
|
||||
* This API is quite low level and internal functionality of the framework relies on the implemened contracts.
|
||||
* Clients should rather use the language specific APIs that provide almost the same functionality, e.g.
|
||||
* {@link ILocationInFileProvider} and {@link EObjectAtOffsetHelper} if they want to to access the region
|
||||
* of a {@link EObject semantic object}.
|
||||
*
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
*/
|
||||
public class NodeModelUtils {
|
||||
|
@ -104,6 +111,7 @@ public class NodeModelUtils {
|
|||
/**
|
||||
* Returns the node that is directly associated with the given object by means of an EMF-Adapter.
|
||||
*
|
||||
* @param object the semantic object whose direct node should be provided.
|
||||
* @return the node that is directly associated with the given object.
|
||||
* @see NodeModelUtils#findActualNodeFor(EObject)
|
||||
*/
|
||||
|
@ -178,9 +186,23 @@ public class NodeModelUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the node that covers all assigned values of the given object. It handles the semantics of {@link Action
|
||||
* actions} and {@link RuleCall unassigned rule calls}.
|
||||
* <p>Returns the node that covers all assigned values of the given object. It handles the semantics of {@link Action
|
||||
* actions} and {@link RuleCall unassigned rule calls}. The returned node will include unassigned surrounding leafs,
|
||||
* e.g. if you use something like {@code Parenthesized expressions} redundant parentheses will be part of the returned node.</p>
|
||||
* <p>Consider the following simple expression (a number literal):
|
||||
* <pre>
|
||||
* ((1))
|
||||
* </pre>
|
||||
* Assuming it was parsed from a grammar like this:
|
||||
* <pre>
|
||||
* Expression: Number | Parentheses;
|
||||
* Parentheses: '(' Expression ')';
|
||||
* Number: value=INT
|
||||
* </pre>
|
||||
* The actual node for the only semantic object that was produced from the input {@code ((1))} is the root node
|
||||
* even though the minimal node would be the one with the text {@code 1}.
|
||||
*
|
||||
* @param semanticObject the semantic object whose node should be provided.
|
||||
* @return the node that covers all assigned values of the given object.
|
||||
*/
|
||||
public static ICompositeNode findActualNodeFor(EObject semanticObject) {
|
||||
|
|
|
@ -20,6 +20,8 @@ import org.eclipse.jdt.annotation.NonNull;
|
|||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.Action;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.Keyword;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
|
@ -72,7 +74,7 @@ public class DefaultLocationInFileProvider implements ILocationInFileProvider, I
|
|||
* @since 2.3
|
||||
*/
|
||||
protected ITextRegion doGetTextRegion(EObject obj, @NonNull RegionDescription query) {
|
||||
ICompositeNode node = NodeModelUtils.findActualNodeFor(obj);
|
||||
ICompositeNode node = findNodeFor(obj);
|
||||
if (node == null) {
|
||||
if (obj.eContainer() == null)
|
||||
return ITextRegion.EMPTY_REGION;
|
||||
|
@ -210,7 +212,7 @@ public class DefaultLocationInFileProvider implements ILocationInFileProvider, I
|
|||
}
|
||||
|
||||
List<INode> resultNodes = Lists.newArrayList();
|
||||
final ICompositeNode startNode = NodeModelUtils.getNode(obj);
|
||||
final ICompositeNode startNode = findNodeFor(obj);
|
||||
INode keywordNode = null;
|
||||
// use LeafNodes instead of children?
|
||||
for (INode child : startNode.getChildren()) {
|
||||
|
@ -299,4 +301,31 @@ public class DefaultLocationInFileProvider implements ILocationInFileProvider, I
|
|||
protected boolean isHidden(INode node) {
|
||||
return node instanceof ILeafNode && ((ILeafNode) node).isHidden();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the smallest node that covers all assigned values of the given object. It handles the semantics of {@link Action
|
||||
* actions} and {@link RuleCall unassigned rule calls}.
|
||||
*
|
||||
* @return the minimal node that covers all assigned values of the given object.
|
||||
* @since 2.3
|
||||
*/
|
||||
protected ICompositeNode findNodeFor(EObject semanticObject) {
|
||||
ICompositeNode result = NodeModelUtils.getNode(semanticObject);
|
||||
if (result != null) {
|
||||
ICompositeNode node = result;
|
||||
while (GrammarUtil.containingAssignment(node.getGrammarElement()) == null && node.getParent() != null && !node.getParent().hasDirectSemanticElement()) {
|
||||
ICompositeNode parent = node.getParent();
|
||||
if (node.hasSiblings()) {
|
||||
for(INode sibling: parent.getChildren()) {
|
||||
if (GrammarUtil.containingAssignment(sibling.getGrammarElement()) != null) {
|
||||
result = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue