From c6e9930e7a182b8518e970801cbaad3b844b88c3 Mon Sep 17 00:00:00 2001 From: Moritz Eysholdt Date: Wed, 9 Nov 2011 13:03:32 +0100 Subject: [PATCH] [serializer] fixed bug 362581 Syntactic sequencer extension for serialization of optional keywords doesn't work --- .../xtext/GenerateAllTestLanguages.mwe2 | 4 +- .../serializer/SyntacticSequencerTest.java | 219 ++++++++++++------ .../SyntacticSequencerTestLanguage.xtext | 22 +- ...quencerTestLanguageSyntacticSequencer.java | 68 +++++- 4 files changed, 239 insertions(+), 74 deletions(-) diff --git a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/GenerateAllTestLanguages.mwe2 b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/GenerateAllTestLanguages.mwe2 index d5285d311..261ea1569 100644 --- a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/GenerateAllTestLanguages.mwe2 +++ b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/GenerateAllTestLanguages.mwe2 @@ -397,7 +397,9 @@ Workflow { } language = { uri = "classpath:/org/eclipse/xtext/serializer/SyntacticSequencerTestLanguage.xtext" - fragment = @TestLanguagesFragments auto-inject {} + fragment = @TestLanguagesFragments auto-inject { + srcGenOnly = false + } } language = { uri = "classpath:/org/eclipse/xtext/serializer/ContextFinderTestLanguage.xtext" diff --git a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTest.java b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTest.java index 28ecdb9c9..cf66f51d4 100644 --- a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTest.java +++ b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTest.java @@ -8,22 +8,24 @@ package org.eclipse.xtext.serializer; import java.util.List; -import java.util.Set; import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.AbstractElement; +import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Action; +import org.eclipse.xtext.CrossReference; +import org.eclipse.xtext.GrammarUtil; +import org.eclipse.xtext.Keyword; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.grammaranalysis.impl.GrammarElementTitleSwitch; import org.eclipse.xtext.junit.AbstractXtextTests; -import org.eclipse.xtext.junit.serializer.DebugSequenceAcceptor; import org.eclipse.xtext.nodemodel.ICompositeNode; import org.eclipse.xtext.nodemodel.ILeafNode; import org.eclipse.xtext.nodemodel.INode; import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.serializer.acceptor.ISemanticSequenceAcceptor; -import org.eclipse.xtext.serializer.analysis.IGrammarConstraintProvider; -import org.eclipse.xtext.serializer.analysis.IGrammarConstraintProvider.IConstraint; -import org.eclipse.xtext.serializer.analysis.IGrammarConstraintProvider.IConstraintContext; +import org.eclipse.xtext.serializer.acceptor.ISequenceAcceptor; import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic; import org.eclipse.xtext.serializer.sequencer.EmitterNodeIterator; import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer; @@ -32,7 +34,6 @@ import org.eclipse.xtext.serializer.sequencer.NodeModelSemanticSequencer; import com.google.common.base.Joiner; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.google.inject.Inject; import com.google.inject.Provider; @@ -41,6 +42,11 @@ import com.google.inject.Provider; */ public class SyntacticSequencerTest extends AbstractXtextTests { + @Override + protected boolean shouldTestSerializer(XtextResource resource) { + return false; + } + @Override protected void setUp() throws Exception { super.setUp(); @@ -48,20 +54,103 @@ public class SyntacticSequencerTest extends AbstractXtextTests { getInjector().injectMembers(this); } - private static class NoEnterNodesDebugSequenceAcceptor extends DebugSequenceAcceptor { + private static class Acceptor implements ISequenceAcceptor { - public NoEnterNodesDebugSequenceAcceptor(boolean printInstantly) { - super(printInstantly); + public List getResult() { + return result; + } + + private List result = Lists.newArrayList(); + + protected GrammarElementTitleSwitch titles = new GrammarElementTitleSwitch().showAssignments(); + + private void add(AbstractElement ele, String token) { + result.add(titles.doSwitch(ele) + " -> " + token.trim()); + } + + public void enterUnassignedParserRuleCall(RuleCall rc) { + } + + public void leaveUnssignedParserRuleCall(RuleCall rc) { + } + + public void acceptUnassignedAction(Action action) { + } + + public void acceptUnassignedDatatype(RuleCall datatypeRC, String token, ICompositeNode node) { + add(datatypeRC, token); + } + + public void acceptUnassignedEnum(RuleCall enumRC, String token, ICompositeNode node) { + add(enumRC, token); + } + + public void acceptUnassignedKeyword(Keyword keyword, String token, ILeafNode node) { + add(keyword, token); + } + + public void acceptUnassignedTerminal(RuleCall terminalRC, String token, ILeafNode node) { + add(terminalRC, token); + } + + public void acceptAssignedCrossRefDatatype(RuleCall datatypeRC, String token, EObject value, int index, + ICompositeNode node) { + add(datatypeRC, token); + } + + public void acceptAssignedCrossRefEnum(RuleCall enumRC, String token, EObject value, int index, + ICompositeNode node) { + add(enumRC, token); + } + + public void acceptAssignedCrossRefTerminal(RuleCall terminalRC, String token, EObject value, int index, + ILeafNode node) { + add(terminalRC, token); + } + + public void acceptAssignedDatatype(RuleCall datatypeRC, String token, Object value, int index, + ICompositeNode node) { + add(datatypeRC, token); + } + + public void acceptAssignedEnum(RuleCall enumRC, String token, Object value, int index, ICompositeNode node) { + add(enumRC, token); + } + + public void acceptAssignedKeyword(Keyword keyword, String token, Boolean value, int index, ILeafNode node) { + add(keyword, token); + } + + public void acceptAssignedKeyword(Keyword keyword, String token, String value, int index, ILeafNode node) { + add(keyword, token); + } + + public void acceptAssignedTerminal(RuleCall terminalRC, String token, Object value, int index, ILeafNode node) { + add(terminalRC, token); } - @Override public boolean enterAssignedAction(Action action, EObject semanticChild, ICompositeNode node) { - return super.enterAssignedAction(action, semanticChild, NO_NODE); + return true; } - @Override - public boolean enterAssignedParserRuleCall(RuleCall rc, EObject newCurrent, ICompositeNode node) { - return super.enterAssignedParserRuleCall(rc, newCurrent, NO_NODE); + public boolean enterAssignedParserRuleCall(RuleCall rc, EObject semanticChild, ICompositeNode node) { + return true; + } + + public void finish() { + + } + + public void leaveAssignedAction(Action action, EObject semanticChild) { + } + + public void leaveAssignedParserRuleCall(RuleCall rc, EObject semanticChild) { + } + + public void acceptComment(AbstractRule rule, String token, ILeafNode node) { + } + + public void acceptWhitespace(AbstractRule rule, String token, ILeafNode node) { } } @@ -70,61 +159,33 @@ public class SyntacticSequencerTest extends AbstractXtextTests { @Inject private Provider syntacticSequencerProvider; - - @Inject + + @Inject private NodeModelSemanticSequencer nmSequencer; private void testSequence(String stringModel) throws Exception { EObject model = getModel(stringModel); EObject context = nmSequencer.findContexts(model, true, null).iterator().next(); - DebugSequenceAcceptor actual = new NoEnterNodesDebugSequenceAcceptor(false); - ISemanticSequencer semanticSequencer = semanticSequencerProvider.get(); - ISyntacticSequencer syntacticSequencer = syntacticSequencerProvider.get(); - semanticSequencer - .init((ISemanticSequenceAcceptor) syntacticSequencer, ISerializationDiagnostic.STDERR_ACCEPTOR); - syntacticSequencer.init(context, model, actual, ISerializationDiagnostic.STDERR_ACCEPTOR); - semanticSequencer.createSequence(context, model); - - // ((IHiddenTokenSequencerOwner) recSequencer).setHiddenTokenSequencer(get(PassThroughHiddenTokenSequencer.class)); - // recSequencer.createSequence(context, model, actual, ISerializationDiagnostic.STDERR_ACCEPTOR); - // System.out.println(actual); - // System.out.println(NodeModelUtils.compactDump(NodeModelUtils.findActualNodeFor(model), false)); - assertEquals(Joiner.on("\n").join(getNodeSequence(model)), Joiner.on("\n").join(actual.getColumn(4))); + Acceptor actual = new Acceptor(); + ISemanticSequencer semanticSeq = semanticSequencerProvider.get(); + ISyntacticSequencer syntacticSeq = syntacticSequencerProvider.get(); + semanticSeq.init((ISemanticSequenceAcceptor) syntacticSeq, ISerializationDiagnostic.STDERR_ACCEPTOR); + syntacticSeq.init(context, model, actual, ISerializationDiagnostic.STDERR_ACCEPTOR); + semanticSeq.createSequence(context, model); + assertEquals(Joiner.on("\n").join(getNodeSequence(model)), Joiner.on("\n").join(actual.getResult())); } - // public void testXtext() throws Exception { - // with(XtextStandaloneSetup.class); - // Grammar model = (Grammar) new XtextResourceSet() - // .getResource(URI.createURI("classpath:/org/eclipse/xtext/Xtext.xtext"), true).getContents().get(0); - // IRecursiveSequencer recSequencer = get(IRecursiveSequencer.class); - // DebugSequenceAcceptor actual = new NoEnterNodesDebugSequenceAcceptor(false); - // ((IHiddenTokenSequencerOwner) recSequencer).setHiddenTokenSequencer(get(PassThroughHiddenTokenSequencer.class)); - // recSequencer.createSequence(/*syn, semSequencer,*/getGrammarAccess().getGrammar().getRules().get(0), model, - // actual, ISerializationDiagnostic.STDERR_ACCEPTOR); - // // System.out.println(actual); - // // System.out.println(NodeModelUtils.compactDump(NodeModelUtils.getNode(model), false)); - // assertEquals(Join.join("\n", getNodeSequence(model)), Join.join("\n", actual.getColumn(4))); - // } - - public void testMandatoryKeywords() throws Exception { - List ctxts = get(IGrammarConstraintProvider.class).getConstraints( - getGrammarAccess().getGrammar()); - List result = Lists.newArrayList(); - Set visited = Sets.newHashSet(); - for (IConstraintContext ctx : ctxts) { - result.add(ctx.toString()); - for (IConstraint c : ctx.getConstraints()) - if (visited.add(c)) - result.add(" " + c.toString()); - } - // System.out.println(Joiner.on("\n").join(result)); - - // SyntacticSequencerPDA2ExtendedDot.drawGrammar(get(ISyntacticSequencerPDAProvider.class), - // "pdf/syntacticSequencerTest-PDA.pdf", get(IGrammarAccess.class).getGrammar()); - // new SequenceParserPDA2Dot(get(ISyntacticSequencerPDAProvider.class)).draw(get(IGrammarAccess.class) - // .getGrammar(), "pdf/syntacticSequencerTest-PDA.pdf", "-T pdf"); - - testSequence("#1 a kw1 b kw2 kw3 c kw4"); + private void testSequence(String inModel, String outModel) throws Exception { + EObject inObj = getModel(inModel); + EObject outObj = getModel(outModel); + EObject context = nmSequencer.findContexts(inObj, true, null).iterator().next(); + Acceptor actual = new Acceptor(); + ISemanticSequencer semanticSeq = semanticSequencerProvider.get(); + ISyntacticSequencer syntacticSeq = syntacticSequencerProvider.get(); + semanticSeq.init((ISemanticSequenceAcceptor) syntacticSeq, ISerializationDiagnostic.STDERR_ACCEPTOR); + syntacticSeq.init(context, inObj, actual, ISerializationDiagnostic.STDERR_ACCEPTOR); + semanticSeq.createSequence(context, inObj); + assertEquals(Joiner.on("\n").join(getNodeSequence(outObj)), Joiner.on("\n").join(actual.getResult())); } private List getNodeSequence(EObject model) { @@ -133,14 +194,20 @@ public class SyntacticSequencerTest extends AbstractXtextTests { EmitterNodeIterator ni = new EmitterNodeIterator(NodeModelUtils.findActualNodeFor(model)); while (ni.hasNext()) { INode next = ni.next(); - if (next instanceof ILeafNode) - result.add(titleSwitch.doSwitch(next.getGrammarElement()) + " -> " + next.getText()); - if (next instanceof ICompositeNode) - result.add(titleSwitch.doSwitch(next.getGrammarElement())); + EObject ele = next.getGrammarElement() instanceof CrossReference ? ((CrossReference) next + .getGrammarElement()).getTerminal() : next.getGrammarElement(); + if (next instanceof ILeafNode || GrammarUtil.isDatatypeRuleCall(ele)) + result.add(titleSwitch.doSwitch(ele) + " -> " + next.getText().trim()); + else if (next instanceof ICompositeNode) + result.add(titleSwitch.doSwitch(ele)); } return result; } + public void testMandatoryKeywords() throws Exception { + testSequence("#1 a kw1 b kw2 kw3 c kw4"); + } + public void testExp0_a() throws Exception { testSequence("#2 a + b + c + d"); } @@ -200,4 +267,24 @@ public class SyntacticSequencerTest extends AbstractXtextTests { public void testBooleanAlternative_b() throws Exception { testSequence("#6 kw2"); } + + public void testUnassignedDatatype() throws Exception { + testSequence("#7 foo kw1", "#7 foo matched 1"); + } + + public void testOpionalSingleTransition() throws Exception { + testSequence("#8 kw1 foo", "#8 matched 2 foo"); + } + + public void testOpionalManyTransition() throws Exception { + testSequence("#9 kw1 foo", "#9 matched 3 foo"); + } + + public void testMandatoryManyTransition() throws Exception { + testSequence("#10 kw1 foo", "#10 matched 4 foo"); + } + + public void testAlternativeTransition() throws Exception { + testSequence("#11 kw1 foo", "#11 matched 5 foo"); + } } diff --git a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTestLanguage.xtext b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTestLanguage.xtext index bd9e65d27..e38a5e471 100644 --- a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTestLanguage.xtext +++ b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/SyntacticSequencerTestLanguage.xtext @@ -12,7 +12,8 @@ generate syntacticsequencertest "http://www.eclipse.org/2009/tmf/xtext/syntactic Model: x1=MandatoryKeywords | x2=Exp0 | x3=Exp1 | x4=Exp2 | x5=SingleCrossReference | x6=BooleanAlternative | - x7=UnassignedDatatype | x8=AmbiguousTransition; + x7=UnassignedDatatype | x8=OptionalSingleTransition | x9=OptionalManyTransition | x10=MandatoryManyTransition | + x11=AlternativeTransition; MandatoryKeywords: "#1" val1=ID "kw1" val2=ID "kw2" "kw3" val3=ID "kw4"; @@ -67,10 +68,19 @@ BooleanAlternativeLiteral: {BooleanAlternativeLiteral} ("kw1" | isTrue?="kw2"); UnassignedDatatype: - "#7" val=ID UnassignedDatatypeRule; + "#7" val=ID KW1; -UnassignedDatatypeRule: - "kw1"; +KW1: + "kw1" | "matched" INT?; -AmbiguousTransition: - "#8" "kw1"? val=ID; +OptionalSingleTransition: + "#8" KW1? val=ID; + +OptionalManyTransition: + "#9" KW1* val=ID; + +MandatoryManyTransition: + "#10" KW1+ val=ID; + +AlternativeTransition: + "#11" (KW1 | "kw2") val=ID; diff --git a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/serializer/SyntacticSequencerTestLanguageSyntacticSequencer.java b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/serializer/SyntacticSequencerTestLanguageSyntacticSequencer.java index b69a870e6..2048581ae 100644 --- a/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/serializer/SyntacticSequencerTestLanguageSyntacticSequencer.java +++ b/tests/org.eclipse.xtext.tests/src/org/eclipse/xtext/serializer/serializer/SyntacticSequencerTestLanguageSyntacticSequencer.java @@ -1,4 +1,70 @@ package org.eclipse.xtext.serializer.serializer; -public class SyntacticSequencerTestLanguageSyntacticSequencer extends AbstractSyntacticSequencerTestLanguageSyntacticSequencer { +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.IGrammarAccess; +import org.eclipse.xtext.RuleCall; +import org.eclipse.xtext.nodemodel.ICompositeNode; +import org.eclipse.xtext.nodemodel.INode; +import org.eclipse.xtext.serializer.analysis.ISyntacticSequencerPDAProvider.ISynNavigable; +import org.eclipse.xtext.serializer.services.SyntacticSequencerTestLanguageGrammarAccess; + +import com.google.inject.Inject; + +public class SyntacticSequencerTestLanguageSyntacticSequencer extends + AbstractSyntacticSequencerTestLanguageSyntacticSequencer { + + private SyntacticSequencerTestLanguageGrammarAccess ga; + + @Inject + protected void asetGa(IGrammarAccess ga) { + this.ga = (SyntacticSequencerTestLanguageGrammarAccess) ga; + } + + @Override + protected String getKW1Token(EObject semanticObject, RuleCall ruleCall, INode node) { + return "matched 1"; + } + + /** + * Syntax: 'kw2' | KW1 + */ + @Override + protected void emit_AlternativeTransition_KW1ParserRuleCall_1_0_or_Kw2Keyword_1_1(EObject semanticObject, + ISynNavigable transition, List nodes) { + ICompositeNode node = (ICompositeNode) nodes.get(0); + acceptUnassignedDatatype(ga.getAlternativeTransitionAccess().getKW1ParserRuleCall_1_0(), "matched 5", node); + } + + /** + * Syntax: KW1+ + */ + @Override + protected void emit_MandatoryManyTransition_KW1ParserRuleCall_1_p(EObject semanticObject, ISynNavigable transition, + List nodes) { + ICompositeNode node = (ICompositeNode) nodes.get(0); + acceptUnassignedDatatype(ga.getMandatoryManyTransitionAccess().getKW1ParserRuleCall_1(), "matched 4", node); + } + + /** + * Syntax: KW1* + */ + @Override + protected void emit_OptionalManyTransition_KW1ParserRuleCall_1_a(EObject semanticObject, ISynNavigable transition, + List nodes) { + ICompositeNode node = (ICompositeNode) nodes.get(0); + acceptUnassignedDatatype(ga.getOptionalManyTransitionAccess().getKW1ParserRuleCall_1(), "matched 3", node); + } + + /** + * Syntax: KW1? + */ + @Override + protected void emit_OptionalSingleTransition_KW1ParserRuleCall_1_q(EObject semanticObject, + ISynNavigable transition, List nodes) { + ICompositeNode node = (ICompositeNode) nodes.get(0); + acceptUnassignedDatatype(ga.getOptionalSingleTransitionAccess().getKW1ParserRuleCall_1(), "matched 2", node); + } + }