From 87c30892b77f75a2a41e73992181a9b5e9d3ca42 Mon Sep 17 00:00:00 2001 From: sefftinge Date: Mon, 7 Jul 2008 12:52:09 +0000 Subject: [PATCH] improved error handling in serializer --- .../reconstr/XtextSerializationException.java | 15 ++++++ .../WhitespacePreservingCallback.java | 31 ++++++------ .../reconstr/impl/InstanceDescription.java | 13 +++++ .../WhitespacePreservingCallbackTest.java | 47 +++++++++++++++++++ 4 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/XtextSerializationException.java diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/XtextSerializationException.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/XtextSerializationException.java new file mode 100644 index 000000000..6d935c928 --- /dev/null +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/XtextSerializationException.java @@ -0,0 +1,15 @@ +package org.eclipse.xtext.parsetree.reconstr; + +@SuppressWarnings("serial") +public class XtextSerializationException extends RuntimeException { + private IInstanceDescription desc; + + public XtextSerializationException(IInstanceDescription desc, String msg) { + super(msg); + this.desc = desc; + } + + public IInstanceDescription getDesc() { + return desc; + } +} diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/callbacks/WhitespacePreservingCallback.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/callbacks/WhitespacePreservingCallback.java index ca5427ead..dc0bc51b0 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/callbacks/WhitespacePreservingCallback.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/callbacks/WhitespacePreservingCallback.java @@ -10,6 +10,7 @@ import org.eclipse.xtext.conversion.IValueConverterService; import org.eclipse.xtext.parsetree.AbstractNode; import org.eclipse.xtext.parsetree.CompositeNode; import org.eclipse.xtext.parsetree.LeafNode; +import org.eclipse.xtext.parsetree.NodeAdapter; import org.eclipse.xtext.parsetree.NodeUtil; import org.eclipse.xtext.parsetree.reconstr.IInstanceDescription; @@ -26,8 +27,8 @@ public class WhitespacePreservingCallback extends SimpleSerializingCallback { Map map = null; if (numberOfOccurences.containsKey(node)) { map = numberOfOccurences.get(node); - } - if (map==null) + } + if (map == null) map = new HashMap(); Integer n = 0; if (map.containsKey(ele)) { @@ -37,7 +38,7 @@ public class WhitespacePreservingCallback extends SimpleSerializingCallback { n++; map.put(ele, n); numberOfOccurences.put(node, map); - return n-1; + return n - 1; } @Override @@ -60,17 +61,17 @@ public class WhitespacePreservingCallback extends SimpleSerializingCallback { @Override protected void before(IInstanceDescription desc, AbstractElement element) { CompositeNode rootNode = getEntryNode(desc); - - iterateChldren(element, rootNode); + if (rootNode != null) + iterateChldren(element, rootNode); } - // private String debugInfo(EObject grammarElement) { - // return grammarElement.toString(); - // } private CompositeNode getEntryNode(IInstanceDescription desc) { - CompositeNode rootNode = NodeUtil.getNodeAdapter(desc.getDelegate()).getParserNode(); + NodeAdapter nodeAdapter = NodeUtil.getNodeAdapter(desc.getDelegate()); + if (nodeAdapter == null) + return null; + CompositeNode rootNode = nodeAdapter.getParserNode(); // go up normalizable rulecalls - while (rootNode.getParent()!=null && rootNode.getParent().getElement()==null) + while (rootNode.getParent() != null && rootNode.getParent().getElement() == null) rootNode = rootNode.getParent(); return rootNode; } @@ -79,7 +80,7 @@ public class WhitespacePreservingCallback extends SimpleSerializingCallback { EList leafNodes = rootNode.getChildren(); boolean consumingMode = false; int skip = getOccurencesAndIncrease(rootNode, element); - for (int x = leafNodes.size()-1; x>=0;x--) { + for (int x = leafNodes.size() - 1; x >= 0; x--) { AbstractNode an = leafNodes.get(x); if (an instanceof LeafNode) { LeafNode n = (LeafNode) an; @@ -89,7 +90,7 @@ public class WhitespacePreservingCallback extends SimpleSerializingCallback { prepend(n.getText()); } if (n.getGrammarElement() == element) { - if (skip==0) { + if (skip == 0) { consumingMode = true; } else { skip--; @@ -97,12 +98,12 @@ public class WhitespacePreservingCallback extends SimpleSerializingCallback { } } else if (an instanceof CompositeNode) { CompositeNode cn = (CompositeNode) an; - if (rootNode.getElement()==null) { + if (rootNode.getElement() == null) { iterateChldren(element, cn); } } -// if (n.getGrammarElement() == element) -// log.info(debugInfo(n.getGrammarElement())); + // if (n.getGrammarElement() == element) + // log.info(debugInfo(n.getGrammarElement())); } } diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/impl/InstanceDescription.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/impl/InstanceDescription.java index 4586939d1..8d19774ff 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/impl/InstanceDescription.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parsetree/reconstr/impl/InstanceDescription.java @@ -8,7 +8,9 @@ *******************************************************************************/ package org.eclipse.xtext.parsetree.reconstr.impl; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -168,5 +170,16 @@ public class InstanceDescription implements IInstanceDescription { } return 1-featureConsumedCounter.get(feature); } + + public String uniqueStateString() { + StringBuffer buff = new StringBuffer(); + buff.append(getDelegate()); + List features = new ArrayList(featureConsumedCounter.keySet()); + Collections.sort(features); + for (String f : features) { + buff.append(f).append(featureConsumedCounter.get(f)); + } + return buff.toString(); + } } \ No newline at end of file diff --git a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/parsetree/reconstr/WhitespacePreservingCallbackTest.java b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/parsetree/reconstr/WhitespacePreservingCallbackTest.java index 62c00bb94..016cca2e3 100644 --- a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/parsetree/reconstr/WhitespacePreservingCallbackTest.java +++ b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/parsetree/reconstr/WhitespacePreservingCallbackTest.java @@ -1,6 +1,7 @@ package org.eclipse.xtext.parsetree.reconstr; import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.parser.IAstFactory; import org.eclipse.xtext.parsetree.reconstr.callbacks.WhitespacePreservingCallback; import org.eclipse.xtext.tests.AbstractGeneratorTest; @@ -19,15 +20,61 @@ public class WhitespacePreservingCallbackTest extends AbstractGeneratorTest { check("a \t /* foo bar */ + b"); } + public void testFail1() throws Exception { + IAstFactory f = getASTFactory(); + failsWith(f.create("Add"), XtextSerializationException.class); + } + + + public void testFail2() throws Exception { + IAstFactory f = getASTFactory(); + EObject add = f.create("Add"); + + // one operand INVALID + EObject atom1 = f.create("Atom"); + f.set(atom1, "name", "x"); + f.add(add, "addOperands", atom1); + failsWith(add, XtextSerializationException.class); + + // two operands VALID + EObject atom2 = f.create("Atom"); + f.set(atom2, "name", "x"); + f.add(add, "addOperands", atom2); + assertNotNull(serialize(add)); + + // three operands INVALID + EObject atom3 = f.create("Atom"); + f.set(atom3, "name", "x"); + f.add(add, "addOperands", atom3); + failsWith(add, XtextSerializationException.class); + } + private void check(String m1) throws Exception { assertEquals(m1, parseAndSerialize(m1)); } private String parseAndSerialize(String model) throws Exception { EObject result = (EObject) getModel(model); + return serialize(result); + } + + private String serialize(EObject result) { IParseTreeConstructor con = getParseTreeConstructor(); WhitespacePreservingCallback cb = new WhitespacePreservingCallback(getValueConverterService()); con.update(result, cb); return cb.toString(); } + + private void failsWith(EObject o, Class clazz) { + try { + IParseTreeConstructor con = getParseTreeConstructor(); + WhitespacePreservingCallback cb = new WhitespacePreservingCallback(getValueConverterService()); + con.update(o, cb); + fail("Should fail with "+clazz.getSimpleName()); + } catch (RuntimeException e) { + if (!clazz.isInstance(e)) { + throw e; + } + } + } }