Skip to content

Commit

Permalink
Allow customizing the NodeModelUtils and the way to obtain an INode
Browse files Browse the repository at this point in the history
Node lookup can be customized by implementing INodeReference on the
EMF model. Node storage by means of specializing the NodeModelBuilder.
Common operations on nodes by provding custom implementations of INode
and overriding INode.utils().

Signed-off-by: Sebastian Zarnekow <sebastian.zarnekow@gmail.com>
  • Loading branch information
szarnekow committed Jan 29, 2024
1 parent b125aa2 commit 6d47133
Show file tree
Hide file tree
Showing 5 changed files with 419 additions and 268 deletions.
12 changes: 12 additions & 0 deletions org.eclipse.xtext/src/org/eclipse/xtext/nodemodel/INode.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package org.eclipse.xtext.nodemodel;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.util.ITextRegion;
import org.eclipse.xtext.util.ITextRegionWithLineInformation;

Expand Down Expand Up @@ -291,5 +292,16 @@ public interface INode {
* @since 2.5
*/
ITextRegionWithLineInformation getTotalTextRegionWithLineInformation();

/**
* Offers access to the {@link org.eclipse.xtext.nodemodel.util.NodeModelUtils.Implementation} and is thereby an
* opportunity for low-level customizing.
*
* @see INodeReference
* @since 2.34
*/
default NodeModelUtils.Implementation utils() {
return NodeModelUtils.Implementation.Default.INSTANCE;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2024 Sebastian Zarnekow and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.xtext.nodemodel;

import org.eclipse.xtext.nodemodel.impl.NodeModelBuilder;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;

/**
* An EMF object might store the node model information differently from the default adapter
* based approach. If it implements {@link INodeReference}, it will be queried by
* {@link NodeModelUtils#getNode(org.eclipse.emf.ecore.EObject)}.
*
* @since 2.34
*
* @see NodeModelBuilder#associateWithSemanticElement(ICompositeNode, org.eclipse.emf.ecore.EObject)
*/
public interface INodeReference {

/**
* Return the referenced node, if any.
*/
/* @Nullable */ ICompositeNode getNode();


}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
* so it makes sense to remove the duplicate arrays. This {@link GrammarElementsInterner} tries to reuse an interned version of such an array
* wherever possible
*/

public class GrammarElementsInterner {

private static class InternKey {
Expand Down Expand Up @@ -81,8 +80,10 @@ public boolean equals(Object o) {
* list has already been produced in the past, return an interned version. Note that
* this code will only function efficiently if repeated invocation uses the same grammar element
* objects and arrays or else a new concatenated array will be created every time.
*
* @since 2.34
*/
EObject[] prependAndIntern(EObject grammarElement, Object grammarElements) {
protected EObject[] prependAndIntern(EObject grammarElement, Object grammarElements) {
GrammarElementsInterner.InternKey internKey = new InternKey(grammarElement, grammarElements);
return interningMap.computeIfAbsent(internKey, key -> key.prependedGrammarElements());
}
Expand All @@ -92,8 +93,10 @@ EObject[] prependAndIntern(EObject grammarElement, Object grammarElements) {
* list has already been produced in the past, return an interned version. Note that
* this code will only function efficiently if repeated invocation uses the same grammar element
* objects and arrays or else a new concatenated array will be created every time.
*
* @since 2.34
*/
EObject[] appendAndIntern(Object grammarElements, EObject grammarElement) {
protected EObject[] appendAndIntern(Object grammarElements, EObject grammarElement) {
GrammarElementsInterner.InternKey internKey = new InternKey(grammarElement, grammarElements);
return interningMap.computeIfAbsent(internKey, key -> key.appendedGrammarElements());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2017 itemis AG (http://www.itemis.eu) and others.
* Copyright (c) 2010, 2024 itemis AG (http://www.itemis.eu) and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
Expand All @@ -15,22 +15,39 @@
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.INodeReference;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;

/**
* A stateful (!) builder that provides call back methods for clients who
* want to create a node model and maintain its invariants.
* @author Sebastian Zarnekow - Initial contribution and API
* @noextend This class is not intended to be subclassed by clients.
*
* @see INodeReference
*/
public class NodeModelBuilder {

private EObject forcedGrammarElement;

private GrammarElementsInterner cachedFoldedGrammarElements = new GrammarElementsInterner();
private final GrammarElementsInterner cachedFoldedGrammarElements;

private boolean compressRoot = true;

/**
* @since 2.34
*/
protected NodeModelBuilder(GrammarElementsInterner cachedFoldedGrammarElements) {
this.cachedFoldedGrammarElements = cachedFoldedGrammarElements;
}

/**
* @since 2.34
*/
public NodeModelBuilder() {
this(new GrammarElementsInterner());
}

public void addChild(ICompositeNode node, AbstractNode child) {
checkValidNewChild(child);
CompositeNode composite = (CompositeNode) node;
Expand Down Expand Up @@ -330,5 +347,25 @@ public void setForcedFirstGrammarElement(RuleCall ruleCall) {
protected void setLookAhead(CompositeNode node, int lookAhead) {
node.basicSetLookAhead(lookAhead);
}

/**
* @since 2.34
*/
protected GrammarElementsInterner getCachedFoldedGrammarElements() {
return cachedFoldedGrammarElements;
}

/**
* @since 2.34
*/
protected boolean isCompressRoot() {
return compressRoot;
}

/**
* @since 2.34
*/
protected EObject getForcedGrammarElement() {
return forcedGrammarElement;
}
}
Loading

0 comments on commit 6d47133

Please sign in to comment.