From 6d7097ef2427a8556df15192d721587be12ffbb9 Mon Sep 17 00:00:00 2001 From: Sebastian Zarnekow Date: Fri, 7 Aug 2020 12:10:11 +0200 Subject: [PATCH] Improved grammar validation in the context of unassigned rule calls Subsequent unassigned actions are not allowed if there was already a current instance present. Signed-off-by: Sebastian Zarnekow --- .../xtext/xtext/XtextValidationTest.java | 89 +++++++++++++++---- .../eclipse/xtext/xtext/XtextValidator.java | 5 +- 2 files changed, 74 insertions(+), 20 deletions(-) diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/XtextValidationTest.java b/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/XtextValidationTest.java index fdaa54fdc..996df3cd9 100644 --- a/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/XtextValidationTest.java +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/XtextValidationTest.java @@ -66,7 +66,6 @@ import org.eclipse.xtext.validation.CheckMode; import org.eclipse.xtext.validation.IResourceValidator; import org.eclipse.xtext.validation.Issue; import org.eclipse.xtext.validation.ValidationMessageAcceptor; -import org.junit.Ignore; import org.junit.Test; import com.google.common.base.Predicate; @@ -966,22 +965,6 @@ public class XtextValidationTest extends AbstractValidationMessageAcceptingTestC assertTrue(diag.getChildren().toString(), diag.getChildren().isEmpty()); } - @Test - @Ignore("TODO this one should yield a warning, because two different instances of a package (ecore itself) might be referenced.") - public void testBug_280413_03() throws Exception { - XtextResource resource = getResourceFromString( - "grammar org.foo.Bar with org.eclipse.xtext.common.Terminals\n" + - "import 'classpath:/org/eclipse/xtext/Xtext.ecore' as xtext\n" + - "ParserRule returns xtext::ParserRule: name = ID;"); - assertTrue(resource.getErrors().toString(), resource.getErrors().isEmpty()); - assertTrue(resource.getWarnings().toString(), resource.getWarnings().isEmpty()); - - Diagnostic diag = Diagnostician.INSTANCE.validate(resource.getContents().get(0)); - assertNotNull("diag", diag); - assertEquals(diag.getSeverity(), Diagnostic.OK); - assertTrue(diag.getChildren().toString(), diag.getChildren().isEmpty()); - } - @Test public void testBug_281660() throws Exception { XtextResource resource = getResourceFromStringAndExpect( "grammar org.foo.Bar with org.eclipse.xtext.common.Terminals\n" + @@ -1936,6 +1919,55 @@ public class XtextValidationTest extends AbstractValidationMessageAcceptingTestC messageAcceptor.validate(); } + @Test public void testRuleCallAllowed_13_481700() throws Exception { + String grammarAsText = + "grammar test with org.eclipse.xtext.common.Terminals\n" + + "generate test 'http://test'\n" + + "Model: val1=Obj Data {SubModel};\n" + + "Obj: {Obj};\n" + + "Data: 'data';"; + + Grammar grammar = (Grammar) getModel(grammarAsText); + ParserRule rule = (ParserRule) grammar.getRules().get(0); + RuleCall ruleCall = (RuleCall) ((Group) rule.getAlternatives()).getElements().get(1); + Action action = (Action) ((Group) rule.getAlternatives()).getElements().get(2); + XtextValidator validator = get(XtextValidator.class); + ValidatingMessageAcceptor messageAcceptor = new ValidatingMessageAcceptor(action, true, false); + validator.setMessageAcceptor(messageAcceptor); + validator.checkUnassignedRuleCallAllowed(ruleCall); + try { + validator.checkUnassignedActionAfterAssignment(action); + fail(); + } catch(RuntimeException e) { + assertEquals("org.eclipse.xtext.validation.GuardException", e.getClass().getName()); + } + messageAcceptor.validate(); + } + + @Test public void testRuleCallAllowed_14_481700() throws Exception { + String grammarAsText = + "grammar test with org.eclipse.xtext.common.Terminals\n" + + "generate test 'http://test'\n" + + "Model: val1=Obj ID {SubModel};\n" + + "Obj: {Obj};"; + + Grammar grammar = (Grammar) getModel(grammarAsText); + ParserRule rule = (ParserRule) grammar.getRules().get(0); + RuleCall ruleCall = (RuleCall) ((Group) rule.getAlternatives()).getElements().get(1); + Action action = (Action) ((Group) rule.getAlternatives()).getElements().get(2); + XtextValidator validator = get(XtextValidator.class); + ValidatingMessageAcceptor messageAcceptor = new ValidatingMessageAcceptor(action, true, false); + validator.setMessageAcceptor(messageAcceptor); + validator.checkUnassignedRuleCallAllowed(ruleCall); + try { + validator.checkUnassignedActionAfterAssignment(action); + fail(); + } catch(RuntimeException e) { + assertEquals("org.eclipse.xtext.validation.GuardException", e.getClass().getName()); + } + messageAcceptor.validate(); + } + @Test public void testActionAllowed_01() throws Exception { String grammarAsText = "grammar test with org.eclipse.xtext.common.Terminals\n" + @@ -1975,6 +2007,29 @@ public class XtextValidationTest extends AbstractValidationMessageAcceptingTestC messageAcceptor.validate(); } + @Test public void testActionAllowed_03() throws Exception { + String grammarAsText = + "grammar test with org.eclipse.xtext.common.Terminals\n" + + "generate test 'http://test'\n" + + "import \"http://www.eclipse.org/emf/2002/Ecore\" as ecore\n" + + "Model: Data {Sub.sub=current};\n" + + "Data returns ecore::EString: 'data';"; + + Grammar grammar = (Grammar) getModel(grammarAsText); + ParserRule rule = (ParserRule) grammar.getRules().get(0); + Action action = (Action) ((Group) rule.getAlternatives()).getElements().get(1); + XtextValidator validator = get(XtextValidator.class); + ValidatingMessageAcceptor messageAcceptor = new ValidatingMessageAcceptor(action, true, false); + validator.setMessageAcceptor(messageAcceptor); + try { + validator.checkAssignedActionAfterAssignment(action); + fail(); + } catch(RuntimeException e) { + assertEquals("org.eclipse.xtext.validation.GuardException", e.getClass().getName()); + } + messageAcceptor.validate(); + } + @Test public void testPredicatedUnorderedGroup_01() throws Exception { String grammarAsText = "grammar test with org.eclipse.xtext.common.Terminals\n" + diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/xtext/XtextValidator.java b/org.eclipse.xtext/src/org/eclipse/xtext/xtext/XtextValidator.java index b98a4b3f4..e258beaca 100644 --- a/org.eclipse.xtext/src/org/eclipse/xtext/xtext/XtextValidator.java +++ b/org.eclipse.xtext/src/org/eclipse/xtext/xtext/XtextValidator.java @@ -895,13 +895,12 @@ public class XtextValidator extends AbstractDeclarativeValidator { @Override public Boolean caseParserRule(ParserRule object) { - isNull = GrammarUtil.isDatatypeRule(object); + isNull &= GrammarUtil.isDatatypeRule(object); return isNull; } @Override public Boolean caseTerminalRule(TerminalRule object) { - isNull = true; return isNull; } @@ -977,7 +976,7 @@ public class XtextValidator extends AbstractDeclarativeValidator { public Boolean caseAction(Action object) { if (object == action) { if (!assignedActionAllowed) { - error("An action is not allowed in fragments and when the current may still be unassigned.", null); + error("An action is not allowed in fragments and when the current may still be unassigned.", object, null); checkDone(); } }