mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 00:38:56 +00:00
[nodemodel] Make node model serializable
applied patch https://bugs.eclipse.org/bugs/attachment.cgi?id=212979 see https://bugs.eclipse.org/bugs/show_bug.cgi?id=359824
This commit is contained in:
parent
0791813424
commit
f56b26ff2d
16 changed files with 1147 additions and 94 deletions
|
@ -1,90 +1,90 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.xtext;singleton:=true
|
||||
Bundle-Version: 2.3.0.qualifier
|
||||
Bundle-ClassPath: .
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
Export-Package: org.eclipse.xtext,
|
||||
org.eclipse.xtext.common,
|
||||
org.eclipse.xtext.common.parseTreeConstruction,
|
||||
org.eclipse.xtext.common.parser.packrat;x-internal:=true,
|
||||
org.eclipse.xtext.common.parser.packrat.consumers;x-internal:=true,
|
||||
org.eclipse.xtext.common.services,
|
||||
org.eclipse.xtext.conversion,
|
||||
org.eclipse.xtext.conversion.impl,
|
||||
org.eclipse.xtext.debug;x-internal:=true,
|
||||
org.eclipse.xtext.diagnostics,
|
||||
org.eclipse.xtext.documentation,
|
||||
org.eclipse.xtext.documentation.impl,
|
||||
org.eclipse.xtext.formatting,
|
||||
org.eclipse.xtext.formatting.impl,
|
||||
org.eclipse.xtext.generator,
|
||||
org.eclipse.xtext.generator.trace;x-internal:=true,
|
||||
org.eclipse.xtext.grammaranalysis;x-internal:=true,
|
||||
org.eclipse.xtext.grammaranalysis.impl;x-internal:=true,
|
||||
org.eclipse.xtext.impl,
|
||||
org.eclipse.xtext.internal;x-internal:=true,
|
||||
org.eclipse.xtext.linking,
|
||||
org.eclipse.xtext.linking.impl,
|
||||
org.eclipse.xtext.linking.lazy,
|
||||
org.eclipse.xtext.mwe,
|
||||
org.eclipse.xtext.naming,
|
||||
org.eclipse.xtext.nodemodel,
|
||||
org.eclipse.xtext.nodemodel.impl,
|
||||
org.eclipse.xtext.nodemodel.util,
|
||||
org.eclipse.xtext.parseTreeConstruction;x-internal:=true,
|
||||
org.eclipse.xtext.parser,
|
||||
org.eclipse.xtext.parser.antlr,
|
||||
org.eclipse.xtext.parser.antlr.internal;x-internal:=true,
|
||||
org.eclipse.xtext.parser.impl,
|
||||
org.eclipse.xtext.parser.packrat;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.consumers;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.debug;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.internal;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.matching;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.tokens;x-internal:=true,
|
||||
org.eclipse.xtext.parsetree.reconstr,
|
||||
org.eclipse.xtext.parsetree.reconstr.impl,
|
||||
org.eclipse.xtext.resource,
|
||||
org.eclipse.xtext.resource.containers,
|
||||
org.eclipse.xtext.resource.generic,
|
||||
org.eclipse.xtext.resource.impl,
|
||||
org.eclipse.xtext.scoping,
|
||||
org.eclipse.xtext.scoping.impl,
|
||||
org.eclipse.xtext.serializer,
|
||||
org.eclipse.xtext.serializer.acceptor;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.analysis;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.diagnostic;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.impl;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.sequencer;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.tokens;x-internal:=true,
|
||||
org.eclipse.xtext.service,
|
||||
org.eclipse.xtext.services;x-internal:=true,
|
||||
org.eclipse.xtext.util,
|
||||
org.eclipse.xtext.validation,
|
||||
org.eclipse.xtext.validation.impl,
|
||||
org.eclipse.xtext.xtext;x-internal:=true,
|
||||
org.eclipse.xtext.xtext.ecoreInference;x-internal:=true
|
||||
Require-Bundle: org.eclipse.emf.ecore.xmi;visibility:=reexport,
|
||||
org.eclipse.emf.ecore;bundle-version="2.5.0";visibility:=reexport,
|
||||
org.eclipse.xtext.util;bundle-version="2.0.0";visibility:=reexport,
|
||||
org.antlr.runtime;bundle-version="[3.2.0,3.2.1)";visibility:=reexport,
|
||||
com.google.inject;bundle-version="2.0.0";resolution:=optional;visibility:=reexport,
|
||||
org.eclipse.emf.codegen;bundle-version="2.5.0";resolution:=optional,
|
||||
org.eclipse.emf.codegen.ecore;bundle-version="2.5.0";resolution:=optional,
|
||||
org.eclipse.emf.mwe.core;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
|
||||
org.eclipse.emf.mwe.utils;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
|
||||
org.eclipse.emf.common,
|
||||
org.eclipse.xtend;bundle-version="1.1.0";resolution:=optional,
|
||||
org.eclipse.xtend.typesystem.emf;bundle-version="1.0.1";resolution:=optional,
|
||||
org.eclipse.core.runtime;bundle-version="3.5.0";resolution:=optional,
|
||||
org.eclipse.core.resources;bundle-version="3.5.0";resolution:=optional,
|
||||
org.eclipse.jdt.annotation;bundle-version="1.0.0";resolution:=optional,
|
||||
org.eclipse.xtext.smap;bundle-version="2.3.0";resolution:=optional
|
||||
Import-Package: org.apache.log4j;version="1.2.15"
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Activator: org.eclipse.xtext.internal.Activator
|
||||
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.xtext;singleton:=true
|
||||
Bundle-Version: 2.3.0.qualifier
|
||||
Bundle-ClassPath: .
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
Export-Package: org.eclipse.xtext,
|
||||
org.eclipse.xtext.common,
|
||||
org.eclipse.xtext.common.parseTreeConstruction,
|
||||
org.eclipse.xtext.common.parser.packrat;x-internal:=true,
|
||||
org.eclipse.xtext.common.parser.packrat.consumers;x-internal:=true,
|
||||
org.eclipse.xtext.common.services,
|
||||
org.eclipse.xtext.conversion,
|
||||
org.eclipse.xtext.conversion.impl,
|
||||
org.eclipse.xtext.debug;x-internal:=true,
|
||||
org.eclipse.xtext.diagnostics,
|
||||
org.eclipse.xtext.documentation,
|
||||
org.eclipse.xtext.documentation.impl,
|
||||
org.eclipse.xtext.formatting,
|
||||
org.eclipse.xtext.formatting.impl,
|
||||
org.eclipse.xtext.generator,
|
||||
org.eclipse.xtext.generator.trace;x-internal:=true,
|
||||
org.eclipse.xtext.grammaranalysis;x-internal:=true,
|
||||
org.eclipse.xtext.grammaranalysis.impl;x-internal:=true,
|
||||
org.eclipse.xtext.impl,
|
||||
org.eclipse.xtext.internal;x-internal:=true,
|
||||
org.eclipse.xtext.linking,
|
||||
org.eclipse.xtext.linking.impl,
|
||||
org.eclipse.xtext.linking.lazy,
|
||||
org.eclipse.xtext.mwe,
|
||||
org.eclipse.xtext.naming,
|
||||
org.eclipse.xtext.nodemodel,
|
||||
org.eclipse.xtext.nodemodel.impl,
|
||||
org.eclipse.xtext.nodemodel.serialization;x-friends:="org.eclipse.xtext.builder,org.eclipse.xtext.tests",
|
||||
org.eclipse.xtext.nodemodel.util,
|
||||
org.eclipse.xtext.parseTreeConstruction;x-internal:=true,
|
||||
org.eclipse.xtext.parser,
|
||||
org.eclipse.xtext.parser.antlr,
|
||||
org.eclipse.xtext.parser.antlr.internal;x-internal:=true,
|
||||
org.eclipse.xtext.parser.impl,
|
||||
org.eclipse.xtext.parser.packrat;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.consumers;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.debug;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.internal;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.matching;x-internal:=true,
|
||||
org.eclipse.xtext.parser.packrat.tokens;x-internal:=true,
|
||||
org.eclipse.xtext.parsetree.reconstr,
|
||||
org.eclipse.xtext.parsetree.reconstr.impl,
|
||||
org.eclipse.xtext.resource,
|
||||
org.eclipse.xtext.resource.containers,
|
||||
org.eclipse.xtext.resource.generic,
|
||||
org.eclipse.xtext.resource.impl,
|
||||
org.eclipse.xtext.scoping,
|
||||
org.eclipse.xtext.scoping.impl,
|
||||
org.eclipse.xtext.serializer,
|
||||
org.eclipse.xtext.serializer.acceptor;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.analysis;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.diagnostic;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.impl;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.sequencer;x-internal:=true,
|
||||
org.eclipse.xtext.serializer.tokens;x-internal:=true,
|
||||
org.eclipse.xtext.service,
|
||||
org.eclipse.xtext.services;x-internal:=true,
|
||||
org.eclipse.xtext.util,
|
||||
org.eclipse.xtext.validation,
|
||||
org.eclipse.xtext.validation.impl,
|
||||
org.eclipse.xtext.xtext;x-internal:=true,
|
||||
org.eclipse.xtext.xtext.ecoreInference;x-internal:=true
|
||||
Require-Bundle: org.eclipse.emf.ecore.xmi;visibility:=reexport,
|
||||
org.eclipse.emf.ecore;bundle-version="2.5.0";visibility:=reexport,
|
||||
org.eclipse.xtext.util;bundle-version="2.0.0";visibility:=reexport,
|
||||
org.antlr.runtime;bundle-version="[3.2.0,3.2.1)";visibility:=reexport,
|
||||
com.google.inject;bundle-version="2.0.0";resolution:=optional;visibility:=reexport,
|
||||
org.eclipse.emf.codegen;bundle-version="2.5.0";resolution:=optional,
|
||||
org.eclipse.emf.codegen.ecore;bundle-version="2.5.0";resolution:=optional,
|
||||
org.eclipse.emf.mwe.core;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
|
||||
org.eclipse.emf.mwe.utils;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
|
||||
org.eclipse.emf.common,
|
||||
org.eclipse.xtend;bundle-version="1.1.0";resolution:=optional,
|
||||
org.eclipse.xtend.typesystem.emf;bundle-version="1.0.1";resolution:=optional,
|
||||
org.eclipse.core.runtime;bundle-version="3.5.0";resolution:=optional,
|
||||
org.eclipse.core.resources;bundle-version="3.5.0";resolution:=optional,
|
||||
org.eclipse.jdt.annotation;bundle-version="1.0.0";resolution:=optional,
|
||||
org.eclipse.xtext.smap;bundle-version="2.3.0";resolution:=optional
|
||||
Import-Package: org.apache.log4j;version="1.2.15"
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Activator: org.eclipse.xtext.internal.Activator
|
||||
|
|
|
@ -7,10 +7,17 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.nodemodel.BidiIterator;
|
||||
import org.eclipse.xtext.nodemodel.BidiTreeIterable;
|
||||
import org.eclipse.xtext.nodemodel.BidiTreeIterator;
|
||||
|
@ -18,6 +25,9 @@ import org.eclipse.xtext.nodemodel.ICompositeNode;
|
|||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeTreeIterator;
|
||||
import org.eclipse.xtext.nodemodel.util.ReversedBidiTreeIterable;
|
||||
import org.eclipse.xtext.util.Strings;
|
||||
|
@ -26,6 +36,7 @@ import com.google.common.collect.Iterators;
|
|||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public abstract class AbstractNode implements INode, BidiTreeIterable<INode> {
|
||||
|
@ -174,7 +185,7 @@ public abstract class AbstractNode implements INode, BidiTreeIterable<INode> {
|
|||
public ICompositeNode getRootNode() {
|
||||
if (parent == null)
|
||||
return null;
|
||||
CompositeNode candidate = parent;
|
||||
AbstractNode candidate = parent;
|
||||
while(candidate.basicGetParent() != null)
|
||||
candidate = candidate.basicGetParent();
|
||||
return candidate.getRootNode();
|
||||
|
@ -266,4 +277,109 @@ public abstract class AbstractNode implements INode, BidiTreeIterable<INode> {
|
|||
return prev != this;
|
||||
}
|
||||
|
||||
enum NodeType {
|
||||
CompositeNode, LeafNode, CompositeNodeWithSemanticElement, CompositeNodeWithSyntaxError, CompositeNodeWithSemanticElementAndSyntaxError, RootNode, HiddenLeafNode, HiddenLeafNodeWithSyntaxError, LeafNodeWithSyntaxError
|
||||
}
|
||||
|
||||
abstract NodeType getNodeId();
|
||||
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
int length = SerializationUtil.readInt(in, true);
|
||||
|
||||
if (length == 1) {
|
||||
int grammarId = SerializationUtil.readInt(in, true);
|
||||
grammarElementOrArray = context.getGrammarElement(grammarId);
|
||||
} else {
|
||||
if (length > 0) {
|
||||
EObject[] grammarElements = new EObject[length];
|
||||
for (int i = 0; i < length; ++i) {
|
||||
int grammarId = SerializationUtil.readInt(in, true);
|
||||
EObject grammarElement = context.getGrammarElement(grammarId);
|
||||
grammarElements[i] = grammarElement;
|
||||
}
|
||||
grammarElementOrArray = grammarElements;
|
||||
} else {
|
||||
if (length != -1) {
|
||||
throw new IllegalStateException("Read unexpected length of grammar element array from stream: "
|
||||
+ length);
|
||||
}
|
||||
|
||||
grammarElementOrArray = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
if (grammarElementOrArray instanceof EObject) {
|
||||
EObject eObject = (EObject) grammarElementOrArray;
|
||||
SerializationUtil.writeInt(out, 1, true);
|
||||
writeGrammarId(out, scc, eObject);
|
||||
} else {
|
||||
if (grammarElementOrArray instanceof EObject[]) {
|
||||
EObject[] eObjects = (EObject[]) grammarElementOrArray;
|
||||
SerializationUtil.writeInt(out, eObjects.length, true);
|
||||
|
||||
for (EObject eObject : eObjects) {
|
||||
writeGrammarId(out, scc, eObject);
|
||||
}
|
||||
} else {
|
||||
SerializationUtil.writeInt(out, -1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeGrammarId(DataOutputStream out, SerializationConversionContext scc, EObject eObject)
|
||||
throws IOException {
|
||||
Integer grammarId = scc.getGrammarElementId(eObject);
|
||||
if (grammarId == null) {
|
||||
throw new IllegalStateException("Must write a grammar element but got an unknown EMF object of class "
|
||||
+ eObject.getClass().getName());
|
||||
}
|
||||
|
||||
SerializationUtil.writeInt(out, grammarId.intValue(), true);
|
||||
}
|
||||
|
||||
int fillGrammarElementToIdMap(int currentId, Map<EObject, Integer> grammarElementToIdMap,
|
||||
List<String> grammarIdToURIMap) {
|
||||
if (grammarElementOrArray != null) {
|
||||
if (grammarElementOrArray instanceof EObject) {
|
||||
EObject grammarElement = (EObject) grammarElementOrArray;
|
||||
currentId = updateMapping(currentId, grammarElementToIdMap, grammarIdToURIMap, grammarElement);
|
||||
}
|
||||
|
||||
if (grammarElementOrArray instanceof EObject[]) {
|
||||
EObject[] grammarElements = (EObject[]) grammarElementOrArray;
|
||||
for (EObject grammarElement : grammarElements) {
|
||||
currentId = updateMapping(currentId, grammarElementToIdMap, grammarIdToURIMap, grammarElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentId;
|
||||
}
|
||||
|
||||
private int updateMapping(int currentId, Map<EObject, Integer> grammarElementToIdMap,
|
||||
List<String> grammarIdToURIMap, EObject grammarElement) {
|
||||
if (!grammarElementToIdMap.containsKey(grammarElement)) {
|
||||
URI uri = EcoreUtil.getURI(grammarElement);
|
||||
if (uri == null) {
|
||||
throw new IllegalStateException("While building the map of grammar elements to an ID, "
|
||||
+ "got a grammar element that does not have an URI. The " + "grammar element has class "
|
||||
+ grammarElement.eClass().getName());
|
||||
}
|
||||
grammarElementToIdMap.put(grammarElement, currentId);
|
||||
grammarIdToURIMap.add(uri.toString());
|
||||
++currentId;
|
||||
}
|
||||
|
||||
if (currentId != grammarIdToURIMap.size()) {
|
||||
throw new IllegalStateException("The next id for a grammar element will be " + currentId
|
||||
+ " but the number of elements in "
|
||||
+ "the map of grammar elements to IDs contains a different number of elements: "
|
||||
+ grammarIdToURIMap.size());
|
||||
}
|
||||
|
||||
return currentId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,18 +7,28 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.nodemodel.BidiIterable;
|
||||
import org.eclipse.xtext.nodemodel.BidiTreeIterator;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
import org.eclipse.xtext.nodemodel.util.EmptyBidiIterable;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeIterable;
|
||||
import org.eclipse.xtext.nodemodel.util.SingletonBidiIterable;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class CompositeNode extends AbstractNode implements ICompositeNode {
|
||||
|
@ -70,7 +80,7 @@ public class CompositeNode extends AbstractNode implements ICompositeNode {
|
|||
public int getTotalOffset() {
|
||||
if (firstChild != null)
|
||||
return firstChild.getTotalOffset();
|
||||
CompositeNode compositeWithSiblings = this;
|
||||
AbstractNode compositeWithSiblings = this;
|
||||
while(!compositeWithSiblings.basicHasNextSibling() && compositeWithSiblings.basicGetParent() != null) {
|
||||
compositeWithSiblings = compositeWithSiblings.basicGetParent();
|
||||
}
|
||||
|
@ -153,5 +163,131 @@ public class CompositeNode extends AbstractNode implements ICompositeNode {
|
|||
EObject[] grammarElements = (EObject[]) grammarElementOrArray;
|
||||
return grammarElements[0];
|
||||
}
|
||||
|
||||
private static final NodeType[] NODE_TYPE_VALUES = NodeType.values();
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
|
||||
int childNodeCount = SerializationUtil.readInt(in, true);
|
||||
|
||||
if (childNodeCount > 0) {
|
||||
AbstractNode child = null;
|
||||
AbstractNode prevChild = null;
|
||||
for (int i = 0; i < childNodeCount; ++i) {
|
||||
int nodeId = SerializationUtil.readInt(in, true);
|
||||
NodeType nodeType = NODE_TYPE_VALUES[nodeId];
|
||||
child = createChildNode(nodeType);
|
||||
child.readData(in, context);
|
||||
|
||||
if (firstChild == null) {
|
||||
firstChild = child;
|
||||
}
|
||||
|
||||
child.basicSetParent(this);
|
||||
child.basicSetPreviousSibling(prevChild);
|
||||
|
||||
prevChild = child;
|
||||
}
|
||||
|
||||
firstChild.basicSetPreviousSibling(child);
|
||||
|
||||
// All left links are fine, now the right ones
|
||||
|
||||
child = firstChild.basicGetPreviousSibling();
|
||||
prevChild = firstChild;
|
||||
|
||||
while (child != firstChild) {
|
||||
child.basicSetNextSibling(prevChild);
|
||||
prevChild = child;
|
||||
child = child.basicGetPreviousSibling();
|
||||
}
|
||||
|
||||
firstChild.basicSetNextSibling(prevChild);
|
||||
}
|
||||
|
||||
lookAhead = SerializationUtil.readInt(in, true);
|
||||
}
|
||||
|
||||
private AbstractNode createChildNode(AbstractNode.NodeType type) {
|
||||
switch (type) {
|
||||
case CompositeNode:
|
||||
return new CompositeNode();
|
||||
case CompositeNodeWithSemanticElement:
|
||||
return new CompositeNodeWithSemanticElement();
|
||||
case CompositeNodeWithSemanticElementAndSyntaxError:
|
||||
return new CompositeNodeWithSemanticElementAndSyntaxError();
|
||||
case CompositeNodeWithSyntaxError:
|
||||
return new CompositeNodeWithSyntaxError();
|
||||
case HiddenLeafNode:
|
||||
return new HiddenLeafNode();
|
||||
case HiddenLeafNodeWithSyntaxError:
|
||||
return new HiddenLeafNodeWithSyntaxError();
|
||||
case LeafNode:
|
||||
return new LeafNode();
|
||||
case LeafNodeWithSyntaxError:
|
||||
return new LeafNodeWithSyntaxError();
|
||||
case RootNode:
|
||||
return new RootNode();
|
||||
default:
|
||||
throw new IllegalArgumentException("Trying to construct a non-existing INode");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
super.write(out, scc);
|
||||
|
||||
int childNodeCount = getChildCount();
|
||||
SerializationUtil.writeInt(out, childNodeCount, true);
|
||||
|
||||
AbstractNode it = firstChild;
|
||||
|
||||
for (int i = 0; i < childNodeCount; ++i) {
|
||||
SerializationUtil.writeInt(out, it.getNodeId().ordinal(), true);
|
||||
it.write(out, scc);
|
||||
it = it.basicGetNextSibling();
|
||||
}
|
||||
|
||||
SerializationUtil.writeInt(out, lookAhead, true);
|
||||
}
|
||||
|
||||
private int getChildCount() {
|
||||
if (firstChild == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AbstractNode it = firstChild;
|
||||
int count = 0;
|
||||
|
||||
do {
|
||||
++count;
|
||||
it = it.basicGetNextSibling();
|
||||
} while (it != firstChild);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
int fillGrammarElementToIdMap(int currentId, Map<EObject, Integer> grammarElementToIdMap,
|
||||
List<String> grammarIdToURIMap) {
|
||||
currentId = super.fillGrammarElementToIdMap(currentId, grammarElementToIdMap, grammarIdToURIMap);
|
||||
|
||||
if (firstChild != null) {
|
||||
AbstractNode it = firstChild;
|
||||
|
||||
do {
|
||||
currentId = it.fillGrammarElementToIdMap(currentId, grammarElementToIdMap, grammarIdToURIMap);
|
||||
it = it.basicGetNextSibling();
|
||||
} while (it != firstChild);
|
||||
}
|
||||
|
||||
return currentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.CompositeNode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,22 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.emf.common.notify.Adapter;
|
||||
import org.eclipse.emf.common.notify.Notification;
|
||||
import org.eclipse.emf.common.notify.Notifier;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class CompositeNodeWithSemanticElement extends CompositeNode implements Adapter {
|
||||
|
@ -55,5 +63,37 @@ public class CompositeNodeWithSemanticElement extends CompositeNode implements A
|
|||
public boolean isAdapterForType(Object type) {
|
||||
return type instanceof Class<?> && INode.class.isAssignableFrom((Class<?>)type);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
|
||||
boolean isNull = in.readBoolean();
|
||||
|
||||
if (!isNull) {
|
||||
int id = SerializationUtil.readInt(in, true);
|
||||
|
||||
semanticElement = context.getSemanticObject(id);
|
||||
semanticElement.eAdapters().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
super.write(out, scc);
|
||||
|
||||
boolean isNull = semanticElement == null;
|
||||
|
||||
out.writeBoolean(isNull);
|
||||
|
||||
if (!isNull) {
|
||||
Integer id = scc.getEObjectId(semanticElement);
|
||||
SerializationUtil.writeInt(out, id, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.CompositeNodeWithSemanticElement;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,18 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class CompositeNodeWithSemanticElementAndSyntaxError extends CompositeNodeWithSemanticElement {
|
||||
|
@ -25,4 +33,22 @@ public class CompositeNodeWithSemanticElementAndSyntaxError extends CompositeNod
|
|||
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
|
||||
this.syntaxErrorMessage = syntaxErrorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
|
||||
context.setHasErrors(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
super.write(out, scc);
|
||||
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.CompositeNodeWithSemanticElementAndSyntaxError;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,19 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class CompositeNodeWithSyntaxError extends CompositeNode {
|
||||
|
@ -25,5 +34,24 @@ public class CompositeNodeWithSyntaxError extends CompositeNode {
|
|||
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
|
||||
this.syntaxErrorMessage = syntaxErrorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
|
||||
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
|
||||
context.setHasErrors(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
super.write(out, scc);
|
||||
|
||||
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.CompositeNodeWithSyntaxError;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.eclipse.xtext.nodemodel.impl;
|
|||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class HiddenLeafNode extends LeafNode {
|
||||
|
@ -18,4 +19,8 @@ public class HiddenLeafNode extends LeafNode {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.HiddenLeafNode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,18 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class HiddenLeafNodeWithSyntaxError extends HiddenLeafNode {
|
||||
|
@ -25,5 +33,24 @@ public class HiddenLeafNodeWithSyntaxError extends HiddenLeafNode {
|
|||
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
|
||||
this.syntaxErrorMessage = syntaxErrorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
|
||||
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
|
||||
context.setHasErrors(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
super.write(out, scc);
|
||||
|
||||
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.HiddenLeafNodeWithSyntaxError;
|
||||
}
|
||||
}
|
|
@ -7,12 +7,19 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class LeafNode extends AbstractNode implements ILeafNode {
|
||||
|
@ -56,4 +63,22 @@ public class LeafNode extends AbstractNode implements ILeafNode {
|
|||
return Collections.<ILeafNode>singletonList(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
|
||||
totalLength = SerializationUtil.readInt(in, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
super.write(out, scc);
|
||||
|
||||
SerializationUtil.writeInt (out, totalLength, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.LeafNode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,18 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class LeafNodeWithSyntaxError extends LeafNode {
|
||||
|
@ -25,5 +33,22 @@ public class LeafNodeWithSyntaxError extends LeafNode {
|
|||
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
|
||||
this.syntaxErrorMessage = syntaxErrorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
|
||||
context.setHasErrors(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
super.write(out, scc);
|
||||
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.LeafNodeWithSyntaxError;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,15 +7,21 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author Mark Christiaens - Serialization support
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class RootNode extends CompositeNodeWithSemanticElementAndSyntaxError {
|
||||
|
@ -168,5 +174,61 @@ public class RootNode extends CompositeNodeWithSemanticElementAndSyntaxError {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
super.readData(in, context);
|
||||
|
||||
basicSetCompleteContent(context.getCompleteContent());
|
||||
|
||||
int totalLength = fixupOffsets(this, 0);
|
||||
|
||||
if (totalLength != getCompleteContent().length()) {
|
||||
throw new IllegalStateException("The length of the resource's content was " + getCompleteContent().length()
|
||||
+ " but the length calculated based upon the serialized form of the RootNode was " + totalLength);
|
||||
}
|
||||
}
|
||||
|
||||
private int fixupOffsets(INode node, int nodeOffset) {
|
||||
if (node instanceof LeafNode) {
|
||||
LeafNode leafNode = (LeafNode) node;
|
||||
leafNode.basicSetTotalOffset(nodeOffset);
|
||||
return leafNode.getTotalLength() + nodeOffset;
|
||||
}
|
||||
|
||||
if (node instanceof CompositeNode) {
|
||||
CompositeNode compositeNode = (CompositeNode) node;
|
||||
|
||||
int currentOffset = nodeOffset;
|
||||
|
||||
AbstractNode firstChild = compositeNode.basicGetFirstChild();
|
||||
|
||||
if (firstChild != null) {
|
||||
AbstractNode it = firstChild;
|
||||
|
||||
do {
|
||||
currentOffset = fixupOffsets(it, currentOffset);
|
||||
it = it.basicGetNextSibling();
|
||||
} while (it != firstChild);
|
||||
}
|
||||
|
||||
return currentOffset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
NodeType getNodeId() {
|
||||
return NodeType.RootNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
public void fillGrammarElementToIdMap(Map<EObject, Integer> grammarElementToIdMap,
|
||||
List<String> grammarIdToURIMap) {
|
||||
fillGrammarElementToIdMap(0, grammarElementToIdMap, grammarIdToURIMap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) 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.nodemodel.impl;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
|
||||
/**
|
||||
* @author Mark Christiaens - Initial contribution
|
||||
*
|
||||
* @since 2.3
|
||||
* @noinstantiate This class is not intended to be instantiated by clients.
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class SerializableNodeModel {
|
||||
public int formatVersion;
|
||||
public Date date;
|
||||
public RootNode root;
|
||||
|
||||
public SerializableNodeModel(XtextResource resource) {
|
||||
ICompositeNode rootNode = resource.getParseResult().getRootNode();
|
||||
|
||||
if (rootNode != null) {
|
||||
root = (RootNode) rootNode;
|
||||
}
|
||||
|
||||
formatVersion = 1;
|
||||
date = new Date();
|
||||
}
|
||||
|
||||
public SerializableNodeModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
public void writeObjectData(DataOutputStream out, SerializationConversionContext scc) throws IOException {
|
||||
String[] grammarIdToURIMap = scc.getGrammarIdToURIMap();
|
||||
|
||||
out.writeInt(grammarIdToURIMap.length);
|
||||
for (String string : grammarIdToURIMap) {
|
||||
out.writeUTF(string);
|
||||
}
|
||||
|
||||
root.write(out, scc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
public void readObjectData(DataInputStream in, DeserializationConversionContext context) throws IOException {
|
||||
int grammarIdToURIMapLength = in.readInt();
|
||||
|
||||
String[] grammarIdToURIMap = new String[grammarIdToURIMapLength];
|
||||
for (int i = 0; i < grammarIdToURIMapLength; ++i) {
|
||||
grammarIdToURIMap[i] = in.readUTF();
|
||||
if (grammarIdToURIMap[i] == null) {
|
||||
throw new IllegalStateException("During deserialzing the grammar id to URI map got a null reference. ");
|
||||
}
|
||||
}
|
||||
|
||||
context.setGrammarIdToURIMap(grammarIdToURIMap);
|
||||
|
||||
root = new RootNode();
|
||||
root.readData(in, context);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) 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.nodemodel.serialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||||
import org.eclipse.xtext.IGrammarAccess;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author mark.christiaens - Initial contribution and API
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
public class DeserializationConversionContext {
|
||||
private EObject[] grammarIdToGrammarElementMap;
|
||||
|
||||
final private List<EObject> idToEObjectMap;
|
||||
|
||||
final private IGrammarAccess grammarAccess;
|
||||
|
||||
final private String completeContent;
|
||||
|
||||
private boolean hasErrors;
|
||||
|
||||
public DeserializationConversionContext(XtextResource xr, String completeContent) throws IOException {
|
||||
this.grammarAccess = xr.getResourceServiceProvider().get(IGrammarAccess.class);
|
||||
this.idToEObjectMap = Lists.newArrayList();
|
||||
this.completeContent = completeContent;
|
||||
this.hasErrors = false;
|
||||
fillIdToEObjectMap(xr);
|
||||
}
|
||||
|
||||
public void setGrammarIdToURIMap(String[] grammarIdToURIMap) {
|
||||
grammarIdToGrammarElementMap = new EObject[grammarIdToURIMap.length];
|
||||
|
||||
ResourceSet grammarResourceSet = grammarAccess.getGrammar().eResource().getResourceSet();
|
||||
for (int grammarId = 0; grammarId < grammarIdToURIMap.length; ++grammarId) {
|
||||
URI uri = URI.createURI(grammarIdToURIMap[grammarId], true);
|
||||
EObject grammarElement = grammarResourceSet.getEObject(uri, true);
|
||||
|
||||
if (grammarElement == null) {
|
||||
throw new IllegalStateException(
|
||||
"Apparently the grammar has changed so that it's no longer possible to identify the "
|
||||
+ "serialized grammar elements. The following grammar element URI is no longer valid: "
|
||||
+ uri.toString());
|
||||
}
|
||||
|
||||
grammarIdToGrammarElementMap[grammarId] = grammarElement;
|
||||
}
|
||||
}
|
||||
|
||||
public EObject getGrammarElement(int grammarId) {
|
||||
if (grammarId >= grammarIdToGrammarElementMap.length) {
|
||||
throw new IllegalStateException(
|
||||
"Trying to obtain a grammar element that does not (or no longer) exists with id: " + grammarId);
|
||||
}
|
||||
|
||||
EObject result = grammarIdToGrammarElementMap[grammarId];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void fillIdToEObjectMap(Resource resource) {
|
||||
SerializationUtil.fillIdToEObjectMap(resource, idToEObjectMap);
|
||||
}
|
||||
|
||||
public EObject getSemanticObject(int id) {
|
||||
EObject eObject = idToEObjectMap.get(id);
|
||||
|
||||
if (eObject == null) {
|
||||
throw new IllegalStateException(
|
||||
"Trying to get an EMF object in the EMF resource that does not exist. We are looking for id: "
|
||||
+ id);
|
||||
}
|
||||
|
||||
return eObject;
|
||||
}
|
||||
|
||||
public void setHasErrors(boolean hasErrors) {
|
||||
this.hasErrors = hasErrors;
|
||||
}
|
||||
|
||||
boolean hasErrors() {
|
||||
return hasErrors;
|
||||
}
|
||||
|
||||
public String getCompleteContent() {
|
||||
return completeContent;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) 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.nodemodel.serialization;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.xtext.nodemodel.impl.RootNode;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
|
||||
/**
|
||||
* @author Mark Christiaens - Initial contribution
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
|
||||
public class SerializationConversionContext {
|
||||
final private Map<EObject, Integer> grammarElementToIdMap;
|
||||
final private ArrayList<String> grammarIdToURIMap;
|
||||
final private Map<EObject, Integer> eObjectToIdMap;
|
||||
|
||||
public SerializationConversionContext(XtextResource resource) {
|
||||
grammarElementToIdMap = new IdentityHashMap<EObject, Integer>();
|
||||
grammarIdToURIMap = new ArrayList<String>();
|
||||
eObjectToIdMap = new IdentityHashMap<EObject, Integer>();
|
||||
|
||||
fillEObjectToIdMap(resource);
|
||||
fillGrammarElementToIdMap(resource);
|
||||
}
|
||||
|
||||
public Integer getGrammarElementId(EObject grammarElement) {
|
||||
final Integer id = grammarElementToIdMap.get(grammarElement);
|
||||
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Trying to fetch a grammar element that does not (no longer) exists with id: " + id);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
protected void fillEObjectToIdMap(Resource resource) {
|
||||
ArrayList<EObject> idToEObjectMap = new ArrayList<EObject>();
|
||||
|
||||
SerializationUtil.fillIdToEObjectMap(resource, idToEObjectMap);
|
||||
|
||||
for (int id = 0; id < idToEObjectMap.size(); ++id) {
|
||||
eObjectToIdMap.put(idToEObjectMap.get(id), id);
|
||||
}
|
||||
}
|
||||
|
||||
protected void fillGrammarElementToIdMap(XtextResource r) {
|
||||
RootNode it = (RootNode) r.getParseResult().getRootNode();
|
||||
it.fillGrammarElementToIdMap(grammarElementToIdMap, grammarIdToURIMap);
|
||||
}
|
||||
|
||||
public Integer getEObjectId(EObject eObject) {
|
||||
Integer id = eObjectToIdMap.get(eObject);
|
||||
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("Tryin to fetch an EMF object that does not exist (no longer) with id: "
|
||||
+ id);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public String[] getGrammarIdToURIMap() {
|
||||
String[] map = grammarIdToURIMap.toArray(new String[0]);
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 itemis AG (http://www.itemis.eu) 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.nodemodel.serialization;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.emf.common.util.TreeIterator;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.resource.URIConverter;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.resource.XtextResourceSet;
|
||||
|
||||
/**
|
||||
* @author mark.christiaens - Initial contribution and API
|
||||
*
|
||||
* @since 2.3
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
* @noinstantiate This class is not intended to be instantiated by clients.
|
||||
*/
|
||||
public class SerializationUtil {
|
||||
public static final int KIB = 1024;
|
||||
|
||||
public static void fillIdToEObjectMap(Resource resource, List<EObject> map) {
|
||||
TreeIterator<EObject> allContents = EcoreUtil.getAllContents(resource, false);
|
||||
|
||||
if (allContents.hasNext()) {
|
||||
EObject root = allContents.next();
|
||||
fillIdToEObjectMap(root, map);
|
||||
}
|
||||
}
|
||||
|
||||
public static void fillIdToEObjectMap(EObject eObject, List<EObject> map) {
|
||||
map.add(eObject);
|
||||
|
||||
EList<EObject> eContents = eObject.eContents();
|
||||
|
||||
for (EObject child : eContents) {
|
||||
fillIdToEObjectMap(child, map);
|
||||
}
|
||||
}
|
||||
|
||||
public static long milliDiff(long startLoad, long doneLoad) {
|
||||
return (doneLoad - startLoad) / 1000000;
|
||||
}
|
||||
|
||||
public static String getCompleteContent(XtextResource xr) throws IOException, UnsupportedEncodingException {
|
||||
XtextResourceSet resourceSet = (XtextResourceSet) xr.getResourceSet();
|
||||
URIConverter uriConverter = resourceSet.getURIConverter();
|
||||
URI uri = xr.getURI();
|
||||
String encoding = xr.getEncoding();
|
||||
|
||||
InputStream inputStream = null;
|
||||
|
||||
try {
|
||||
inputStream = uriConverter.createInputStream(uri);
|
||||
|
||||
return getCompleteContent(encoding, inputStream);
|
||||
} finally {
|
||||
tryClose(inputStream, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getCompleteContent(String encoding, InputStream inputStream)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, encoding);
|
||||
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
char[] buffer = new char[128 * KIB];
|
||||
|
||||
int n = inputStreamReader.read(buffer);
|
||||
|
||||
while (n != -1) {
|
||||
sb.append (buffer, 0, n);
|
||||
n = inputStreamReader.read(buffer);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static byte [] getCompleteContent(InputStream inputStream)
|
||||
throws IOException {
|
||||
byte[] buffer = new byte[128 * KIB];
|
||||
int nextFreePos = 0;
|
||||
int n = inputStream.read(buffer, nextFreePos, buffer.length - nextFreePos);
|
||||
while (n != -1) {
|
||||
nextFreePos += n;
|
||||
if (nextFreePos >= buffer.length) {
|
||||
buffer = copyOf(buffer, buffer.length*2);
|
||||
}
|
||||
n = inputStream.read(buffer, nextFreePos, buffer.length - nextFreePos);
|
||||
}
|
||||
|
||||
return copyOf(buffer, nextFreePos);
|
||||
}
|
||||
|
||||
static byte[] copyOf(byte[] original, int newLength) {
|
||||
byte[] copy = new byte[newLength];
|
||||
System.arraycopy(original, 0, copy, 0,
|
||||
Math.min(original.length, newLength));
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static void writeSyntaxErrorMessage(DataOutputStream out, SerializationConversionContext scc,
|
||||
SyntaxErrorMessage syntaxErrorMessage) throws IOException {
|
||||
if (syntaxErrorMessage == null) {
|
||||
out.writeBoolean(true);
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
SerializationUtil.writeString(out, syntaxErrorMessage.getMessage());
|
||||
SerializationUtil.writeString(out, syntaxErrorMessage.getIssueCode());
|
||||
SerializationUtil.writeStringArray(out, syntaxErrorMessage.getIssueData());
|
||||
}
|
||||
}
|
||||
|
||||
public static SyntaxErrorMessage readSyntaxErrorMessage(DataInputStream in, DeserializationConversionContext context)
|
||||
throws IOException {
|
||||
boolean isNull = in.readBoolean();
|
||||
if (isNull)
|
||||
return null;
|
||||
String message = SerializationUtil.readString(in);
|
||||
String issueCode = SerializationUtil.readString(in);
|
||||
String[] issueData = SerializationUtil.readStringArray(in);
|
||||
SyntaxErrorMessage result = new SyntaxErrorMessage(message, issueCode, issueData);
|
||||
return result;
|
||||
}
|
||||
|
||||
static public int writeInt(DataOutputStream out, int value, boolean optimizePositive) throws IOException {
|
||||
if (!optimizePositive)
|
||||
value = (value << 1) ^ (value >> 31);
|
||||
if ((value & ~0x7F) == 0) {
|
||||
out.writeByte((byte) value);
|
||||
return 1;
|
||||
}
|
||||
out.writeByte((byte) ((value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
if ((value & ~0x7F) == 0) {
|
||||
out.writeByte((byte) value);
|
||||
return 2;
|
||||
}
|
||||
out.writeByte((byte) ((value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
if ((value & ~0x7F) == 0) {
|
||||
out.writeByte((byte) value);
|
||||
return 3;
|
||||
}
|
||||
out.writeByte((byte) ((value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
if ((value & ~0x7F) == 0) {
|
||||
out.writeByte((byte) value);
|
||||
return 4;
|
||||
}
|
||||
out.writeByte((byte) ((value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
out.writeByte((byte) value);
|
||||
return 5;
|
||||
}
|
||||
|
||||
static public int readInt(DataInputStream in, boolean optimizePositive) throws IOException {
|
||||
for (int offset = 0, result = 0; offset < 32; offset += 7) {
|
||||
int b = in.readByte();
|
||||
result |= (b & 0x7F) << offset;
|
||||
if ((b & 0x80) == 0) {
|
||||
if (!optimizePositive)
|
||||
result = (result >>> 1) ^ -(result & 1);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new IOException("Malformed integer");
|
||||
}
|
||||
|
||||
public static final void writeString(DataOutputStream out, String s) throws IOException {
|
||||
boolean isNull = s == null;
|
||||
|
||||
out.writeBoolean(isNull);
|
||||
|
||||
if (!isNull) {
|
||||
out.writeUTF(s);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String readString(DataInputStream in) throws IOException {
|
||||
boolean isNull = in.readBoolean();
|
||||
|
||||
if (isNull) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String string = in.readUTF();
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
public static void writeStringArray(DataOutputStream out, String[] ss) throws IOException {
|
||||
out.writeBoolean(ss == null);
|
||||
if (ss != null) {
|
||||
writeInt(out, ss.length, true);
|
||||
for (String data : ss) {
|
||||
writeString(out, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] readStringArray(DataInputStream in) throws IOException {
|
||||
boolean isIssueDataNull = in.readBoolean();
|
||||
String[] result = null;
|
||||
|
||||
if (!isIssueDataNull) {
|
||||
int issueDataLength = readInt(in, true);
|
||||
result = new String[issueDataLength];
|
||||
|
||||
for (int i = 0; i < issueDataLength; ++i) {
|
||||
result[i] = readString(in);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void tryClose(Closeable stream, Logger logger) throws IOException {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
if (logger != null) {
|
||||
logger.error("Could not close an stream for a cache entry: " + e, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) 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.nodemodel.serialization;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/** @author Mark Christiaens */
|
||||
|
||||
public class SerializationUtilTest extends Assert {
|
||||
|
||||
@Test
|
||||
public void testSyntaxErrorMessage() throws IOException {
|
||||
final String message = "hi";
|
||||
String [] issueCodes = { null, "issue" };
|
||||
String [][] issueDatas = { null, {null}, {"issue data"}};
|
||||
|
||||
for (String[] issueData : issueDatas) {
|
||||
for (String issueCode : issueCodes) {
|
||||
SyntaxErrorMessage sem = new SyntaxErrorMessage(message, issueCode, issueData);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream ();
|
||||
DataOutputStream dout = new DataOutputStream(out);
|
||||
SerializationUtil.writeSyntaxErrorMessage(dout, null, sem);
|
||||
dout.close();
|
||||
byte[] array = out.toByteArray();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(array);
|
||||
DataInputStream din = new DataInputStream(in);
|
||||
SyntaxErrorMessage sem2 = SerializationUtil.readSyntaxErrorMessage(din, null);
|
||||
assertEquals(sem, sem2);
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream ();
|
||||
DataOutputStream dout = new DataOutputStream(out);
|
||||
SerializationUtil.writeSyntaxErrorMessage(dout, null, null);
|
||||
dout.close();
|
||||
byte[] array = out.toByteArray();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(array);
|
||||
DataInputStream din = new DataInputStream(in);
|
||||
SyntaxErrorMessage readMessage = SerializationUtil.readSyntaxErrorMessage(din, null);
|
||||
assertNull(readMessage);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue