mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 16:28:56 +00:00
[serializer/performance] improved performance of node model traversal
this change deprecates EmitterNodeIterator since it relies on expensive calls to iNode.getOffset(). Furthermore, it simplifies the implementation because - lazy behavior does not provide advantages here - 'allowHidden' and 'passAbsorber' were always false. Signed-off-by: Moritz Eysholdt <moritz.eysholdt@typefox.io>
This commit is contained in:
parent
b717ec5b87
commit
17a85f155d
4 changed files with 96 additions and 10 deletions
|
@ -251,9 +251,8 @@ public abstract class AbstractSyntacticSequencer implements ISyntacticSequencer,
|
|||
|
||||
protected void acceptNodes(ISynNavigable fromState, INode fromNode, INode toNode) {
|
||||
RuleCallStack stack = contexts.peek().stack.clone();
|
||||
EmitterNodeIterator ni = new EmitterNodeIterator(fromNode, toNode, false, false);
|
||||
while (ni.hasNext()) {
|
||||
INode next = ni.next();
|
||||
List<INode> nodes = collectNodes(fromNode, toNode);
|
||||
for (INode next : nodes) {
|
||||
List<ISynState> path = fromState.getShortestPathTo((AbstractElement) next.getGrammarElement(), stack);
|
||||
if (path != null) {
|
||||
if (path.get(path.size() - 1) instanceof ISynEmitterState)
|
||||
|
@ -319,7 +318,7 @@ public abstract class AbstractSyntacticSequencer implements ISyntacticSequencer,
|
|||
protected List<INode> collectNodes(INode fromNode, INode toNode) {
|
||||
if (fromNode == null)
|
||||
return null;
|
||||
return Lists.newArrayList(new EmitterNodeIterator(fromNode, toNode, false, false));
|
||||
return EmitterNodeUtil.collectEmitterNodes(fromNode, toNode);
|
||||
}
|
||||
|
||||
protected abstract void emitUnassignedTokens(EObject semanticObject, ISynTransition transition, INode fromNode,
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.serializer.sequencer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.xtext.AbstractElement;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
|
||||
|
@ -15,20 +17,24 @@ import org.eclipse.xtext.nodemodel.INode;
|
|||
*/
|
||||
public class EmitterNodeFinder {
|
||||
|
||||
@Deprecated
|
||||
protected INode toNode;
|
||||
private List<INode> emitters;
|
||||
private int index;
|
||||
|
||||
public EmitterNodeFinder(INode node) {
|
||||
this.toNode = node;
|
||||
this.emitters = EmitterNodeUtil.collectEmitterNodes(node, null);
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
public INode next(AbstractElement grammarElement) {
|
||||
if (toNode == null)
|
||||
return null;
|
||||
EmitterNodeIterator ni = new EmitterNodeIterator(toNode, null, false, false);
|
||||
while (ni.hasNext()) {
|
||||
INode next = ni.next();
|
||||
if (next.getGrammarElement() == grammarElement)
|
||||
for (int i = index; i < emitters.size(); i++) {
|
||||
INode next = emitters.get(i);
|
||||
if (next.getGrammarElement() == grammarElement) {
|
||||
index = i + 1;
|
||||
return toNode = next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,10 @@ import com.google.common.collect.Lists;
|
|||
|
||||
/**
|
||||
* @author Moritz Eysholdt - Initial contribution and API
|
||||
*
|
||||
* @deprecated use {@link org.eclipse.xtext.serializer.sequencer.EmitterNodeUtil}
|
||||
*/
|
||||
@Deprecated
|
||||
public class EmitterNodeIterator implements Iterator<INode> {
|
||||
|
||||
protected NodeIterator iterator;
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.serializer.sequencer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.emf.common.util.TreeIterator;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.CrossReference;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.parsetree.reconstr.impl.NodeIterator;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author Moritz Eysholdt - Initial contribution and API
|
||||
*/
|
||||
public class EmitterNodeUtil {
|
||||
|
||||
private static boolean isEmitter(INode node, EObject grammarElement) {
|
||||
if (node instanceof ILeafNode) {
|
||||
ILeafNode leaf = (ILeafNode) node;
|
||||
if (leaf.isHidden())
|
||||
return false;
|
||||
return true;
|
||||
} else if (node instanceof ICompositeNode) {
|
||||
return GrammarUtil.isDatatypeRuleCall(grammarElement) || grammarElement instanceof CrossReference;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isAbsorber(EObject grammarElement) {
|
||||
return grammarElement != null && GrammarUtil.isAssigned(grammarElement);
|
||||
}
|
||||
|
||||
public static List<INode> collectEmitterNodes(INode from, INode to) {
|
||||
if (from == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
TreeIterator<INode> iterator;
|
||||
if (from == to) {
|
||||
iterator = from.getAsTreeIterable().iterator();
|
||||
iterator.next();
|
||||
} else {
|
||||
iterator = new NodeIterator(from);
|
||||
}
|
||||
List<INode> result = null;
|
||||
while (iterator.hasNext()) {
|
||||
INode next = iterator.next();
|
||||
if (next == to)
|
||||
break;
|
||||
EObject grammarElement = next.getGrammarElement();
|
||||
if (isEmitter(next, grammarElement)) {
|
||||
if (isAbsorber(grammarElement))
|
||||
break;
|
||||
iterator.prune();
|
||||
if (result == null) {
|
||||
result = Lists.newArrayList();
|
||||
}
|
||||
result.add(next);
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue