mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 08:48:55 +00:00
[formatter] fix ITextRegionAccess#getInvokingGrammarElement(EObject)
Make sure this method returns the same grammar element, no matter whether the text region access has been constructid via serializer or node model. Signed-off-by: Moritz Eysholdt <moritz.eysholdt@itemis.de>
This commit is contained in:
parent
794ac2268e
commit
0025d38d88
13 changed files with 271 additions and 197 deletions
|
@ -155,7 +155,9 @@ public class FormatterTester {
|
|||
if (req.isUseNodeModel() && useSerializer) {
|
||||
ITextRegionAccess nmRegions = createRegionAccessViaNodeModel(resource);
|
||||
ITextRegionAccess serRegions = createRegionAccessViaSerializer(resource);
|
||||
Assert.assertEquals(toString(nmRegions), toString(serRegions));
|
||||
String nmString = toString(nmRegions);
|
||||
String serString = toString(serRegions);
|
||||
Assert.assertEquals(nmString, serString);
|
||||
return nmRegions;
|
||||
} else if (req.isUseNodeModel()) {
|
||||
ITextRegionAccess nmRegions = createRegionAccessViaNodeModel(resource);
|
||||
|
|
|
@ -9,14 +9,17 @@ package org.eclipse.xtext.formatting2.debug;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.AbstractElement;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.formatting2.regionaccess.IAstRegion;
|
||||
import org.eclipse.xtext.formatting2.regionaccess.IComment;
|
||||
import org.eclipse.xtext.formatting2.regionaccess.IEObjectRegion;
|
||||
import org.eclipse.xtext.formatting2.regionaccess.IHiddenRegion;
|
||||
import org.eclipse.xtext.formatting2.regionaccess.IHiddenRegionPart;
|
||||
import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegion;
|
||||
|
@ -30,22 +33,48 @@ import org.eclipse.xtext.util.EmfFormatter;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.LinkedListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* @author Moritz Eysholdt - Initial contribution and API
|
||||
*/
|
||||
public class TextRegionAccessToString {
|
||||
|
||||
protected static enum AstRegionComparator implements Comparator<IAstRegion> {
|
||||
CHILDREN_FIRST {
|
||||
@Override
|
||||
public int compare(IAstRegion o1, IAstRegion o2) {
|
||||
EObject e1 = o1.getSemanticElement();
|
||||
EObject e2 = o2.getSemanticElement();
|
||||
if (e1 == e2)
|
||||
return 0;
|
||||
if (EcoreUtil.isAncestor(e1, e2))
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
},
|
||||
CONTAINER_FIRST {
|
||||
@Override
|
||||
public int compare(IAstRegion o1, IAstRegion o2) {
|
||||
EObject e1 = o1.getSemanticElement();
|
||||
EObject e2 = o2.getSemanticElement();
|
||||
if (e1 == e2)
|
||||
return 0;
|
||||
if (EcoreUtil.isAncestor(e1, e2))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static final int TITLE_WIDTH = 9;
|
||||
private static final String SEMANTIC_PADDED = Strings.padEnd("Semantic", TITLE_WIDTH, ' ');
|
||||
private static final String EOBJECT_END_PADDED = Strings.padEnd("End", TITLE_WIDTH, ' ');
|
||||
private static final String EOBJECT_START_PADDED = Strings.padEnd("Start", TITLE_WIDTH, ' ');
|
||||
private static final String HIDDEN = "Hidden";
|
||||
private static final String HIDDEN_PADDED = Strings.padEnd(HIDDEN, TITLE_WIDTH, ' ');
|
||||
private static final String EOBJECT_START_PADDED = Strings.padEnd("Start", TITLE_WIDTH, ' ');
|
||||
private static final String EOBJECT_END_PADDED = Strings.padEnd("End", TITLE_WIDTH, ' ');
|
||||
private static final String SEMANTIC_PADDED = Strings.padEnd("Semantic", TITLE_WIDTH, ' ');
|
||||
|
||||
private Function<AbstractElement, String> grammarToString = new GrammarElementTitleSwitch().showRule()
|
||||
.showAssignments().showQualified();
|
||||
|
@ -56,42 +85,6 @@ public class TextRegionAccessToString {
|
|||
|
||||
private ITextSegment origin;
|
||||
|
||||
protected void collectHiddenRegionsBySemanticObject(List<ITextSegment> regions,
|
||||
Multimap<IHiddenRegion, EObject> leadingHiddens, Multimap<IHiddenRegion, EObject> trailingHiddens,
|
||||
List<String> errors) {
|
||||
Set<EObject> sem = Sets.newHashSet();
|
||||
for (ITextSegment s : regions)
|
||||
if (s instanceof ISemanticRegion)
|
||||
sem.add(((ISemanticRegion) s).getSemanticElement());
|
||||
ISemanticRegion previous = ((ISequentialRegion) regions.get(0)).getPreviousSemanticRegion();
|
||||
if (previous != null)
|
||||
sem.add(previous.getSemanticElement());
|
||||
ISemanticRegion next = ((ISequentialRegion) regions.get(regions.size() - 1)).getNextSemanticRegion();
|
||||
if (next != null)
|
||||
sem.add(next.getSemanticElement());
|
||||
sem.remove(null);
|
||||
Set<EObject> containers = Sets.newHashSet();
|
||||
for (EObject s : sem) {
|
||||
EObject container = s.eContainer();
|
||||
while (container != null && containers.add(container))
|
||||
container = container.eContainer();
|
||||
}
|
||||
sem.addAll(containers);
|
||||
ITextRegionAccess access = regions.get(0).getTextRegionAccess();
|
||||
for (EObject s : sem) {
|
||||
IHiddenRegion leading = access.leadingHiddenRegion(s);
|
||||
if (leading == null)
|
||||
errors.add("ERROR: " + EmfFormatter.objPath(s) + " has no leading HiddenRegion.");
|
||||
else
|
||||
leadingHiddens.put(leading, s);
|
||||
IHiddenRegion trailing = access.trailingHiddenRegion(s);
|
||||
if (trailing == null)
|
||||
errors.add("ERROR: " + EmfFormatter.objPath(s) + " has no trailing HiddenRegion.");
|
||||
else
|
||||
trailingHiddens.put(trailing, s);
|
||||
}
|
||||
}
|
||||
|
||||
public TextRegionAccessToString hideColumnExplanation() {
|
||||
this.hideColumnExplanation = true;
|
||||
return this;
|
||||
|
@ -122,10 +115,27 @@ public class TextRegionAccessToString {
|
|||
@Override
|
||||
public String toString() {
|
||||
List<ITextSegment> list = toTokenAndGapList();
|
||||
Multimap<IHiddenRegion, EObject> leadingHiddens = LinkedHashMultimap.create();
|
||||
Multimap<IHiddenRegion, EObject> trailingHiddens = LinkedHashMultimap.create();
|
||||
if (list.isEmpty())
|
||||
return "(empty)";
|
||||
Multimap<IHiddenRegion, IEObjectRegion> hiddens = LinkedListMultimap.create();
|
||||
List<String> errors = Lists.newArrayList();
|
||||
collectHiddenRegionsBySemanticObject(list, leadingHiddens, trailingHiddens, errors);
|
||||
ITextRegionAccess access = list.get(0).getTextRegionAccess();
|
||||
List<IEObjectRegion> objects = access.regionsForAllEObjects();
|
||||
for (IEObjectRegion obj : objects) {
|
||||
IHiddenRegion previous = obj.getPreviousHiddenRegion();
|
||||
IHiddenRegion next = obj.getNextHiddenRegion();
|
||||
EObject element = obj.getSemanticElement();
|
||||
if (previous == null)
|
||||
errors.add("ERROR: " + EmfFormatter.objPath(element) + " has no leading HiddenRegion.");
|
||||
else
|
||||
hiddens.put(previous, obj);
|
||||
if (previous != next) {
|
||||
if (next == null)
|
||||
errors.add("ERROR: " + EmfFormatter.objPath(element) + " has no trailing HiddenRegion.");
|
||||
else
|
||||
hiddens.put(next, obj);
|
||||
}
|
||||
}
|
||||
TextRegionListToString result = new TextRegionListToString();
|
||||
if (!hideColumnExplanation) {
|
||||
String explanation = "Columns: 1:offset; 2:length; 3:hidden/semantic; 4: text; 5..n:grammar elements or whispace/comments";
|
||||
|
@ -134,17 +144,30 @@ public class TextRegionAccessToString {
|
|||
for (String error : errors)
|
||||
result.add(error, false);
|
||||
for (ITextSegment region : list) {
|
||||
List<IEObjectRegion> previous = Lists.newArrayList();
|
||||
List<IEObjectRegion> next = Lists.newArrayList();
|
||||
List<String> middle = Lists.newArrayList(toString(region));
|
||||
if (region instanceof IHiddenRegion) {
|
||||
Collection<EObject> collection = trailingHiddens.get((IHiddenRegion) region);
|
||||
if (!collection.isEmpty())
|
||||
result.add(EOBJECT_END_PADDED + toString(collection));
|
||||
}
|
||||
result.add(region, toString(region));
|
||||
if (region instanceof IHiddenRegion) {
|
||||
Collection<EObject> collection = leadingHiddens.get((IHiddenRegion) region);
|
||||
if (!collection.isEmpty())
|
||||
result.add(EOBJECT_START_PADDED + toString(collection));
|
||||
Collection<IEObjectRegion> found = hiddens.get((IHiddenRegion) region);
|
||||
for (IEObjectRegion obj : found) {
|
||||
boolean p = obj.getNextHiddenRegion().equals(region);
|
||||
boolean n = obj.getPreviousHiddenRegion().equals(region);
|
||||
if (p && n)
|
||||
middle.add("Semantic " + toString(obj));
|
||||
else if (p)
|
||||
previous.add(obj);
|
||||
else if (n)
|
||||
next.add(obj);
|
||||
}
|
||||
Collections.sort(previous, AstRegionComparator.CHILDREN_FIRST);
|
||||
Collections.sort(next, AstRegionComparator.CONTAINER_FIRST);
|
||||
}
|
||||
for (IEObjectRegion obj : previous)
|
||||
result.add(EOBJECT_END_PADDED + toString(obj));
|
||||
|
||||
result.add(region, Joiner.on(", ").join(middle));
|
||||
for (IEObjectRegion obj : next)
|
||||
result.add(EOBJECT_START_PADDED + toString(obj));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
@ -153,32 +176,6 @@ public class TextRegionAccessToString {
|
|||
return rule == null ? "null" : rule.getName();
|
||||
}
|
||||
|
||||
protected String toString(Collection<EObject> objs) {
|
||||
List<String> result = Lists.newArrayList();
|
||||
for (EObject obj : objs) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
EStructuralFeature containingFeature = obj.eContainingFeature();
|
||||
if (containingFeature != null) {
|
||||
builder.append(containingFeature.getName());
|
||||
if (containingFeature.isMany()) {
|
||||
int index = ((List<?>) obj.eContainer().eGet(containingFeature)).indexOf(obj);
|
||||
builder.append("[" + index + "]");
|
||||
}
|
||||
builder.append("=");
|
||||
}
|
||||
builder.append(obj.eClass().getName());
|
||||
EStructuralFeature nameFeature = obj.eClass().getEStructuralFeature("name");
|
||||
if (nameFeature != null) {
|
||||
Object name = obj.eGet(nameFeature);
|
||||
if (name != null)
|
||||
builder.append("'" + name + "'");
|
||||
}
|
||||
result.add(builder.toString());
|
||||
}
|
||||
Collections.sort(result);
|
||||
return Joiner.on(", ").join(result);
|
||||
}
|
||||
|
||||
protected String toString(EObject ele) {
|
||||
if (ele instanceof AbstractElement)
|
||||
return grammarToString.apply((AbstractElement) ele);
|
||||
|
@ -193,6 +190,35 @@ public class TextRegionAccessToString {
|
|||
return String.format("%s Comment:%s", text, gammar);
|
||||
}
|
||||
|
||||
protected String toString(IEObjectRegion region) {
|
||||
EObject obj = region.getSemanticElement();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
EStructuralFeature containingFeature = obj.eContainingFeature();
|
||||
if (containingFeature != null) {
|
||||
builder.append(containingFeature.getName());
|
||||
if (containingFeature.isMany()) {
|
||||
int index = ((List<?>) obj.eContainer().eGet(containingFeature)).indexOf(obj);
|
||||
builder.append("[" + index + "]");
|
||||
}
|
||||
builder.append("=");
|
||||
}
|
||||
builder.append(obj.eClass().getName());
|
||||
EStructuralFeature nameFeature = obj.eClass().getEStructuralFeature("name");
|
||||
if (nameFeature != null) {
|
||||
Object name = obj.eGet(nameFeature);
|
||||
if (name != null)
|
||||
builder.append("'" + name + "'");
|
||||
}
|
||||
EObject element = region.getGrammarElement();
|
||||
if (element instanceof AbstractElement)
|
||||
builder.append(" via " + grammarToString.apply((AbstractElement) element));
|
||||
else if (element instanceof AbstractRule)
|
||||
builder.append(" via " + ((AbstractRule) element).getName());
|
||||
else
|
||||
builder.append(": ERROR: EObject has no grammar element.");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
protected String toString(IHiddenRegion gap) {
|
||||
List<IHiddenRegionPart> whitespaceAndComments = gap.getParts();
|
||||
List<String> children = Lists.newArrayListWithExpectedSize(whitespaceAndComments.size());
|
||||
|
@ -210,7 +236,9 @@ public class TextRegionAccessToString {
|
|||
|
||||
protected String toString(ITextSegment region) {
|
||||
String result;
|
||||
if (region instanceof ISemanticRegion)
|
||||
if (region instanceof IEObjectRegion)
|
||||
result = toString((IEObjectRegion) region);
|
||||
else if (region instanceof ISemanticRegion)
|
||||
result = toString((ISemanticRegion) region);
|
||||
else if (region instanceof IHiddenRegion)
|
||||
result = toString((IHiddenRegion) region);
|
||||
|
@ -268,15 +296,15 @@ public class TextRegionAccessToString {
|
|||
return result;
|
||||
}
|
||||
|
||||
public TextRegionAccessToString withOrigin(ITextSegment origin) {
|
||||
this.origin = origin;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextRegionAccessToString withRegionAccess(ITextRegionAccess access) {
|
||||
this.origin = access.regionForRootEObject();
|
||||
this.hightlightOrigin = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextRegionAccessToString withOrigin(ITextSegment origin) {
|
||||
this.origin = origin;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -192,4 +192,6 @@ public interface ITextRegionAccess {
|
|||
String textForOffset(int offset, int length);
|
||||
|
||||
List<ILineRegion> expandToLines(ITextSegment segment, int leadingLinesToAdd, int trailingLinesToAdd);
|
||||
|
||||
List<IEObjectRegion> regionsForAllEObjects();
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ public class TextRegionAccessBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ISequenceAcceptor forSequence(EObject root) {
|
||||
return this.fromSequencer = createTextRegionAccessBuildingSequencer().withRoot(root);
|
||||
public ISequenceAcceptor forSequence(EObject ctx, EObject root) {
|
||||
return this.fromSequencer = createTextRegionAccessBuildingSequencer().withRoot(ctx, root);
|
||||
}
|
||||
|
||||
private TextRegionAccessBuildingSequencer createTextRegionAccessBuildingSequencer() {
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.google.common.collect.Lists;
|
|||
*/
|
||||
public abstract class AbstractEObjectRegion extends AbstractTextSegment implements IEObjectRegion {
|
||||
private final ITextRegionAccess access;
|
||||
private EObject grammarElement;
|
||||
private IHiddenRegion nextHidden;
|
||||
private IHiddenRegion previousHidden;
|
||||
private EObject semantcElement;
|
||||
|
@ -32,6 +33,11 @@ public abstract class AbstractEObjectRegion extends AbstractTextSegment implemen
|
|||
this.access = access;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EObject getGrammarElement() {
|
||||
return grammarElement;
|
||||
}
|
||||
|
||||
public IHiddenRegion getLeadingHiddenRegion() {
|
||||
return previousHidden;
|
||||
}
|
||||
|
@ -85,6 +91,10 @@ public abstract class AbstractEObjectRegion extends AbstractTextSegment implemen
|
|||
return nextHidden;
|
||||
}
|
||||
|
||||
protected void setGrammarElement(EObject grammarElement) {
|
||||
this.grammarElement = grammarElement;
|
||||
}
|
||||
|
||||
protected void setLeadingHiddenRegion(IHiddenRegion leading) {
|
||||
this.previousHidden = leading;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.formatting2.regionaccess.internal;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.AbstractElement;
|
||||
import org.eclipse.xtext.Action;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
|
||||
/**
|
||||
|
@ -25,25 +20,7 @@ public class NodeEObjectRegion extends AbstractEObjectRegion {
|
|||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractElement getGrammarElement() {
|
||||
INode current = node;
|
||||
while (current != null) {
|
||||
EObject grammarElement = current.getGrammarElement();
|
||||
if (GrammarUtil.isAssignedEObjectRuleCall(grammarElement))
|
||||
return (AbstractElement) grammarElement;
|
||||
if (grammarElement instanceof Action) {
|
||||
Action action = (Action) grammarElement;
|
||||
if (action.getFeature() != null)
|
||||
return (AbstractElement) grammarElement;
|
||||
else {
|
||||
EObject grammarElement2 = ((ICompositeNode) current).getFirstChild().getGrammarElement();
|
||||
if (GrammarUtil.isAssignedEObjectRuleCall(grammarElement2))
|
||||
return (AbstractElement) grammarElement2;
|
||||
}
|
||||
}
|
||||
current = current.getParent();
|
||||
}
|
||||
return null;
|
||||
public INode getNode() {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.formatting2.regionaccess.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
|
@ -17,6 +18,7 @@ import org.eclipse.xtext.nodemodel.INode;
|
|||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
|
@ -77,4 +79,9 @@ public class NodeModelBasedRegionAccess extends AbstractRegionAccess {
|
|||
return new TextSegment(this, 0, resource.getParseResult().getRootNode().getTotalEndOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IEObjectRegion> regionsForAllEObjects() {
|
||||
return ImmutableList.<IEObjectRegion> copyOf(eObjectToTokens.values());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Map;
|
|||
import org.eclipse.emf.ecore.EDataType;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.Action;
|
||||
import org.eclipse.xtext.Assignment;
|
||||
import org.eclipse.xtext.CrossReference;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
|
@ -146,6 +147,38 @@ public class NodeModelBasedRegionAccessBuilder {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected EObject findGrammarElement(INode node, EObject obj) {
|
||||
INode current = node;
|
||||
String feature = obj.eContainingFeature().getName();
|
||||
while (current != null) {
|
||||
EObject grammarElement = current.getGrammarElement();
|
||||
Assignment assignment = GrammarUtil.containingAssignment(grammarElement);
|
||||
if (assignment != null && feature.equals(assignment.getFeature()))
|
||||
return grammarElement;
|
||||
if (grammarElement instanceof Action) {
|
||||
Action action = (Action) grammarElement;
|
||||
if (feature.equals(action.getFeature()))
|
||||
return grammarElement;
|
||||
else if (current == node && current instanceof ICompositeNode) {
|
||||
INode child = ((ICompositeNode) current).getFirstChild();
|
||||
while (child instanceof ICompositeNode) {
|
||||
EObject grammarElement2 = child.getGrammarElement();
|
||||
Assignment assignment2 = GrammarUtil.containingAssignment(grammarElement2);
|
||||
if (assignment2 != null && feature.equals(assignment2.getFeature()))
|
||||
return grammarElement2;
|
||||
// if (child.hasDirectSemanticElement() && child.getSemanticElement() != obj)
|
||||
// break;
|
||||
child = ((ICompositeNode) child).getFirstChild();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (current.hasDirectSemanticElement() && current.getSemanticElement() != obj)
|
||||
return null;
|
||||
current = current.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void process(INode node, NodeModelBasedRegionAccess access) {
|
||||
NodeEObjectRegion tokens = stack.peek();
|
||||
boolean creator = isEObjectRoot(node);
|
||||
|
@ -155,10 +188,13 @@ public class NodeModelBasedRegionAccessBuilder {
|
|||
stack.push(tokens);
|
||||
}
|
||||
if (tokens.getSemanticElement() == null) {
|
||||
if (node.getParent() == null)
|
||||
if (node.getParent() == null) {
|
||||
tokens.setSemantcElement(resource.getContents().get(0));
|
||||
else if (node.hasDirectSemanticElement())
|
||||
tokens.setGrammarElement(node.getGrammarElement());
|
||||
} else if (node.hasDirectSemanticElement()) {
|
||||
tokens.setSemantcElement(node.getSemanticElement());
|
||||
tokens.setGrammarElement(findGrammarElement(node, tokens.getSemanticElement()));
|
||||
}
|
||||
}
|
||||
if (include(node)) {
|
||||
if (node instanceof ICompositeNode) {
|
||||
|
@ -179,6 +215,12 @@ public class NodeModelBasedRegionAccessBuilder {
|
|||
EObject semanticElement = popped.getSemanticElement();
|
||||
if (semanticElement == null)
|
||||
throw new IllegalStateException();
|
||||
if (!stack.isEmpty() && semanticElement.eContainer() != stack.peek().getSemanticElement())
|
||||
throw new IllegalStateException();
|
||||
EObject grammarElement = popped.getGrammarElement();
|
||||
if (grammarElement == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
NodeEObjectRegion old = eObjToTokens.put(semanticElement, popped);
|
||||
if (old != null)
|
||||
throw new IllegalStateException();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.formatting2.regionaccess.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
|
@ -14,6 +15,7 @@ import org.eclipse.xtext.formatting2.regionaccess.IEObjectRegion;
|
|||
import org.eclipse.xtext.formatting2.regionaccess.ITextSegment;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
|
@ -84,4 +86,9 @@ public class StringBasedRegionAccess extends AbstractRegionAccess {
|
|||
return string.substring(offset, offset + length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IEObjectRegion> regionsForAllEObjects() {
|
||||
return ImmutableList.<IEObjectRegion> copyOf(eObjectToTokens.values());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,23 +8,16 @@
|
|||
package org.eclipse.xtext.formatting2.regionaccess.internal;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.AbstractElement;
|
||||
|
||||
/**
|
||||
* @author Moritz Eysholdt - Initial contribution and API
|
||||
*/
|
||||
public class StringEObjectRegion extends AbstractEObjectRegion {
|
||||
private final AbstractElement grammarElement;
|
||||
|
||||
public StringEObjectRegion(StringBasedRegionAccess access, AbstractElement grammarElement,
|
||||
EObject semanticElement) {
|
||||
public StringEObjectRegion(StringBasedRegionAccess access, EObject grammarElement, EObject semanticElement) {
|
||||
super(access);
|
||||
this.grammarElement = grammarElement;
|
||||
this.setGrammarElement(grammarElement);
|
||||
this.setSemantcElement(semanticElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractElement getGrammarElement() {
|
||||
return grammarElement;
|
||||
}
|
||||
}
|
|
@ -157,7 +157,7 @@ public class TextRegionAccessBuildingSequencer implements ISequenceAcceptor {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected StringEObjectRegion enterEObject(AbstractElement ele, EObject semanticChild) {
|
||||
protected StringEObjectRegion enterEObject(EObject ele, EObject semanticChild) {
|
||||
StringEObjectRegion tokens = new StringEObjectRegion(regionAccess, ele, semanticChild);
|
||||
regionAccess.add(tokens);
|
||||
tokens.setLeadingHiddenRegion(last);
|
||||
|
@ -201,10 +201,10 @@ public class TextRegionAccessBuildingSequencer implements ISequenceAcceptor {
|
|||
// not relevant
|
||||
}
|
||||
|
||||
public TextRegionAccessBuildingSequencer withRoot(EObject root) {
|
||||
public TextRegionAccessBuildingSequencer withRoot(EObject ctx, EObject root) {
|
||||
this.regionAccess = new StringBasedRegionAccess((XtextResource) root.eResource());
|
||||
this.last = createHiddenRegion();
|
||||
this.regionAccess.setRootEObject(enterEObject(null, root));
|
||||
this.regionAccess.setRootEObject(enterEObject(ctx, root));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ public class Serializer implements ISerializer {
|
|||
EObject context = getContext(obj);
|
||||
TextRegionAccessBuilder builder = textRegionBuilderProvider.get();
|
||||
ISerializationDiagnostic.Acceptor errors = ISerializationDiagnostic.EXCEPTION_THROWING_ACCEPTOR;
|
||||
serialize(obj, context, builder.forSequence(obj), errors);
|
||||
serialize(obj, context, builder.forSequence(context, obj), errors);
|
||||
ITextRegionAccess regionAccess = builder.create();
|
||||
return regionAccess;
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@ class RegionAccessTest {
|
|||
1 foo
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Simple'foo'
|
||||
Start Simple'foo' via Root
|
||||
0 1 Semantic "1" Simple:'1'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 3 Semantic "foo" Simple:name=ID
|
||||
End Simple'foo'
|
||||
End Simple'foo' via Root
|
||||
5 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -53,12 +53,13 @@ class RegionAccessTest {
|
|||
2 foo
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Delegation
|
||||
Start Delegation via Root
|
||||
0 1 Semantic "2" Delegation:'2'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start delegate=Delegate'foo'
|
||||
Start delegate=Delegate'foo' via Delegation:delegate=Delegate
|
||||
2 3 Semantic "foo" Delegate:name=ID
|
||||
End Delegation, delegate=Delegate'foo'
|
||||
End delegate=Delegate'foo' via Delegation:delegate=Delegate
|
||||
End Delegation via Root
|
||||
5 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -68,11 +69,11 @@ class RegionAccessTest {
|
|||
3 foo
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Delegate'foo'
|
||||
Start Delegate'foo' via Root
|
||||
0 1 Semantic "3" Unassigned:'3'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 3 Semantic "foo" Delegate:name=ID
|
||||
End Delegate'foo'
|
||||
End Delegate'foo' via Root
|
||||
5 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -82,14 +83,15 @@ class RegionAccessTest {
|
|||
4 prefix foo
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start PrefixedUnassigned
|
||||
Start PrefixedUnassigned via Root
|
||||
0 1 Semantic "4" PrefixedUnassigned:'4'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start delegate=Delegate'foo'
|
||||
Start delegate=Delegate'foo' via PrefixedUnassigned:delegate=PrefixedDelegate
|
||||
2 6 Semantic "prefix" PrefixedDelegate:'prefix'
|
||||
8 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
9 3 Semantic "foo" Delegate:name=ID
|
||||
End PrefixedUnassigned, delegate=Delegate'foo'
|
||||
End delegate=Delegate'foo' via PrefixedUnassigned:delegate=PrefixedDelegate
|
||||
End PrefixedUnassigned via Root
|
||||
12 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -99,18 +101,19 @@ class RegionAccessTest {
|
|||
5 a + b
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Add
|
||||
Start Add via Root
|
||||
0 1 Semantic "5" Root:'5'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start left=Named'a'
|
||||
Start left=Named'a' via Expression:{Add.left=}
|
||||
2 1 Semantic "a" Primary:name=ID
|
||||
End left=Named'a'
|
||||
End left=Named'a' via Expression:{Add.left=}
|
||||
3 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
4 1 Semantic "+" Expression:'+'
|
||||
5 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start right=Named'b'
|
||||
Start right=Named'b' via Expression:right=Primary
|
||||
6 1 Semantic "b" Primary:name=ID
|
||||
End Add, right=Named'b'
|
||||
End right=Named'b' via Expression:right=Primary
|
||||
End Add via Root
|
||||
7 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -120,30 +123,31 @@ class RegionAccessTest {
|
|||
5 (a + b) + c
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Add
|
||||
Start Add via Root
|
||||
0 1 Semantic "5" Root:'5'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start left=Add
|
||||
Start left=Add via Expression:{Add.left=}
|
||||
2 1 Semantic "(" Parenthesized:'('
|
||||
3 0 Hidden
|
||||
Start left=Named'a'
|
||||
Start left=Named'a' via Expression:{Add.left=}
|
||||
3 1 Semantic "a" Primary:name=ID
|
||||
End left=Named'a'
|
||||
End left=Named'a' via Expression:{Add.left=}
|
||||
4 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
5 1 Semantic "+" Expression:'+'
|
||||
6 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start right=Named'b'
|
||||
Start right=Named'b' via Expression:right=Primary
|
||||
7 1 Semantic "b" Primary:name=ID
|
||||
End right=Named'b'
|
||||
End right=Named'b' via Expression:right=Primary
|
||||
8 0 Hidden
|
||||
8 1 Semantic ")" Parenthesized:')'
|
||||
End left=Add
|
||||
End left=Add via Expression:{Add.left=}
|
||||
9 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
10 1 Semantic "+" Expression:'+'
|
||||
11 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start right=Named'c'
|
||||
Start right=Named'c' via Expression:right=Primary
|
||||
12 1 Semantic "c" Primary:name=ID
|
||||
End Add, right=Named'c'
|
||||
End right=Named'c' via Expression:right=Primary
|
||||
End Add via Root
|
||||
13 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -153,7 +157,7 @@ class RegionAccessTest {
|
|||
6 (unassigned foo)
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Action
|
||||
Start Action via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -163,7 +167,7 @@ class RegionAccessTest {
|
|||
14 3 Semantic "foo" Mixed:ID
|
||||
17 0 Hidden
|
||||
17 1 Semantic ")" Mixed:')'
|
||||
End Action
|
||||
End Action via Root
|
||||
18 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -173,7 +177,7 @@ class RegionAccessTest {
|
|||
6 (unassigned datatype foo)
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Action
|
||||
Start Action via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -183,7 +187,7 @@ class RegionAccessTest {
|
|||
14 12 Semantic "datatyp..." Mixed:Datatype
|
||||
26 0 Hidden
|
||||
26 1 Semantic ")" Mixed:')'
|
||||
End Action
|
||||
End Action via Root
|
||||
27 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -193,7 +197,7 @@ class RegionAccessTest {
|
|||
6 (unassigned datatype datatype foo)
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Action
|
||||
Start Action via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -203,7 +207,7 @@ class RegionAccessTest {
|
|||
14 21 Semantic "datatyp..." Mixed:Datatype
|
||||
35 0 Hidden
|
||||
35 1 Semantic ")" Mixed:')'
|
||||
End Action
|
||||
End Action via Root
|
||||
36 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -213,13 +217,13 @@ class RegionAccessTest {
|
|||
6 ()
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Action
|
||||
Start Action via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
3 0 Hidden
|
||||
3 1 Semantic ")" Mixed:')'
|
||||
End Action
|
||||
End Action via Root
|
||||
4 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -229,7 +233,7 @@ class RegionAccessTest {
|
|||
6 (())
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Action
|
||||
Start Action via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -239,7 +243,7 @@ class RegionAccessTest {
|
|||
4 1 Semantic ")" Mixed:')'
|
||||
5 0 Hidden
|
||||
5 1 Semantic ")" Mixed:')'
|
||||
End Action
|
||||
End Action via Root
|
||||
6 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -249,7 +253,7 @@ class RegionAccessTest {
|
|||
6 ((()))
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Action
|
||||
Start Action via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -263,7 +267,7 @@ class RegionAccessTest {
|
|||
6 1 Semantic ")" Mixed:')'
|
||||
7 0 Hidden
|
||||
7 1 Semantic ")" Mixed:')'
|
||||
End Action
|
||||
End Action via Root
|
||||
8 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -273,7 +277,7 @@ class RegionAccessTest {
|
|||
6 (((foo)))
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Mixed'foo'
|
||||
Start Mixed'foo' via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -289,7 +293,7 @@ class RegionAccessTest {
|
|||
9 1 Semantic ")" Mixed:')'
|
||||
10 0 Hidden
|
||||
10 1 Semantic ")" Mixed:')'
|
||||
End Mixed'foo'
|
||||
End Mixed'foo' via Root
|
||||
11 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -299,14 +303,14 @@ class RegionAccessTest {
|
|||
6 (child(((foo))))
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Mixed
|
||||
Start Mixed via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
3 0 Hidden
|
||||
3 5 Semantic "child" Mixed:'child'
|
||||
8 0 Hidden
|
||||
Start eobj=Mixed'foo'
|
||||
Start eobj=Mixed'foo' via Mixed:eobj=Mixed
|
||||
8 1 Semantic "(" Mixed:'('
|
||||
9 0 Hidden
|
||||
9 1 Semantic "(" Mixed:'('
|
||||
|
@ -320,10 +324,10 @@ class RegionAccessTest {
|
|||
15 1 Semantic ")" Mixed:')'
|
||||
16 0 Hidden
|
||||
16 1 Semantic ")" Mixed:')'
|
||||
End eobj=Mixed'foo'
|
||||
End eobj=Mixed'foo' via Mixed:eobj=Mixed
|
||||
17 0 Hidden
|
||||
17 1 Semantic ")" Mixed:')'
|
||||
End Mixed
|
||||
End Mixed via Root
|
||||
18 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -333,7 +337,7 @@ class RegionAccessTest {
|
|||
6 (datatype foo)
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Mixed
|
||||
Start Mixed via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -341,7 +345,7 @@ class RegionAccessTest {
|
|||
3 12 Semantic "datatyp..." Mixed:datatype=Datatype
|
||||
15 0 Hidden
|
||||
15 1 Semantic ")" Mixed:')'
|
||||
End Mixed
|
||||
End Mixed via Root
|
||||
16 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -351,7 +355,7 @@ class RegionAccessTest {
|
|||
6 (datatype datatype foo)
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Mixed
|
||||
Start Mixed via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -359,7 +363,7 @@ class RegionAccessTest {
|
|||
3 21 Semantic "datatyp..." Mixed:datatype=Datatype
|
||||
24 0 Hidden
|
||||
24 1 Semantic ")" Mixed:')'
|
||||
End Mixed
|
||||
End Mixed via Root
|
||||
25 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -369,20 +373,20 @@ class RegionAccessTest {
|
|||
6 (foo) action (ref foo) end
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start AssignedAction
|
||||
Start AssignedAction via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start child=Mixed'foo'
|
||||
Start child=Mixed'foo' via Mixed:{AssignedAction.child=}
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
3 0 Hidden
|
||||
3 3 Semantic "foo" Mixed:name=ID
|
||||
6 0 Hidden
|
||||
6 1 Semantic ")" Mixed:')'
|
||||
End child=Mixed'foo'
|
||||
End child=Mixed'foo' via Mixed:{AssignedAction.child=}
|
||||
7 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
8 6 Semantic "action" Mixed:'action'
|
||||
14 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start body=Mixed
|
||||
Start body=Mixed via Mixed:body=Mixed
|
||||
15 1 Semantic "(" Mixed:'('
|
||||
16 0 Hidden
|
||||
16 3 Semantic "ref" Mixed:'ref'
|
||||
|
@ -390,10 +394,10 @@ class RegionAccessTest {
|
|||
20 3 Semantic "foo" Mixed:ref=[Mixed|ID]
|
||||
23 0 Hidden
|
||||
23 1 Semantic ")" Mixed:')'
|
||||
End body=Mixed
|
||||
End body=Mixed via Mixed:body=Mixed
|
||||
24 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
25 3 Semantic "end" Mixed:'end'
|
||||
End AssignedAction
|
||||
End AssignedAction via Root
|
||||
28 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -403,7 +407,7 @@ class RegionAccessTest {
|
|||
6 (lit1)
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start Mixed
|
||||
Start Mixed via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
|
@ -411,7 +415,7 @@ class RegionAccessTest {
|
|||
3 4 Semantic "lit1" Mixed:lit=Enum
|
||||
7 0 Hidden
|
||||
7 1 Semantic ")" Mixed:')'
|
||||
End Mixed
|
||||
End Mixed via Root
|
||||
8 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -421,19 +425,19 @@ class RegionAccessTest {
|
|||
6 (foo) action
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start AssignedAction
|
||||
Start AssignedAction via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start child=Mixed'foo'
|
||||
Start child=Mixed'foo' via Mixed:{AssignedAction.child=}
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
3 0 Hidden
|
||||
3 3 Semantic "foo" Mixed:name=ID
|
||||
6 0 Hidden
|
||||
6 1 Semantic ")" Mixed:')'
|
||||
End child=Mixed'foo'
|
||||
End child=Mixed'foo' via Mixed:{AssignedAction.child=}
|
||||
7 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
8 6 Semantic "action" Mixed:'action'
|
||||
End AssignedAction
|
||||
End AssignedAction via Root
|
||||
14 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -443,22 +447,23 @@ class RegionAccessTest {
|
|||
6 (foo) action action
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start AssignedAction
|
||||
Start AssignedAction via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start child=AssignedAction, child=Mixed'foo'
|
||||
Start child=AssignedAction via Mixed:{AssignedAction.child=}
|
||||
Start child=Mixed'foo' via Mixed:{AssignedAction.child=}
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
3 0 Hidden
|
||||
3 3 Semantic "foo" Mixed:name=ID
|
||||
6 0 Hidden
|
||||
6 1 Semantic ")" Mixed:')'
|
||||
End child=Mixed'foo'
|
||||
End child=Mixed'foo' via Mixed:{AssignedAction.child=}
|
||||
7 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
8 6 Semantic "action" Mixed:'action'
|
||||
End child=AssignedAction
|
||||
End child=AssignedAction via Mixed:{AssignedAction.child=}
|
||||
14 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
15 6 Semantic "action" Mixed:'action'
|
||||
End AssignedAction
|
||||
End AssignedAction via Root
|
||||
21 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
@ -468,20 +473,21 @@ class RegionAccessTest {
|
|||
6 () action action
|
||||
'''.toString.trim === '''
|
||||
0 0 Hidden
|
||||
Start AssignedAction
|
||||
Start AssignedAction via Root
|
||||
0 1 Semantic "6" Root:'6'
|
||||
1 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
Start child=Action, child=AssignedAction
|
||||
Start child=AssignedAction via Mixed:{AssignedAction.child=}
|
||||
Start child=Action via Mixed:{AssignedAction.child=}
|
||||
2 1 Semantic "(" Mixed:'('
|
||||
3 0 Hidden
|
||||
3 1 Semantic ")" Mixed:')'
|
||||
End child=Action
|
||||
End child=Action via Mixed:{AssignedAction.child=}
|
||||
4 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
5 6 Semantic "action" Mixed:'action'
|
||||
End child=AssignedAction
|
||||
End child=AssignedAction via Mixed:{AssignedAction.child=}
|
||||
11 1 Hidden " " Whitespace:TerminalRule'WS'
|
||||
12 6 Semantic "action" Mixed:'action'
|
||||
End AssignedAction
|
||||
End AssignedAction via Root
|
||||
18 0 Hidden
|
||||
'''
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue