From 04c54cd9dfbffbc16276a31d315284c894a1dd36 Mon Sep 17 00:00:00 2001 From: Toshiya Kobayashi Date: Wed, 15 May 2024 18:07:58 +0900 Subject: [PATCH] [incubator-kie-drools-5945] [new-parser] Broken named consequences inside OR (#5950) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Tests for incubator-kie-drools-5945 * [incubator-kie-drools-5945] [new-parser] Broken named consequences inside OR --------- Co-authored-by: Jiří Locker --- .../drl/parser/antlr4/MiscDRLParserTest.java | 92 +++++++++++++++++++ .../drl/parser/antlr4/DRLVisitorImpl.java | 15 ++- 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java b/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java index 8075c89aed6..bf553765e26 100644 --- a/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java +++ b/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java @@ -4657,6 +4657,98 @@ void namedConsequenceOrWithBindVariables() { assertThat(namedConsequenceDescr.getName()).isEqualTo("FoundMarkOrMario"); } + @Test + void testNamedConsequencesInsideOR1() { + final String text = + "import org.drools.mvel.compiler.Cheese;\n " + + "global java.util.List results;\n" + + "\n" + + "rule R1 when\n" + + " ( $a: Cheese ( type == \"stilton\" ) do[t1]\n" + + " or\n" + + " $b: Cheese ( type == \"gorgonzola\" ) )\n" + + " $c: Cheese ( type == \"cheddar\" )\n" + + "then\n" + + " results.add( $c.getType() );\n" + + "then[t1]\n" + + " results.add( $a.getType() );\n" + + "end\n"; + PackageDescr packageDescr = parseAndGetPackageDescr(text); + RuleDescr ruleDescr = packageDescr.getRules().get(0); + + assertThat(ruleDescr.getLhs().getDescrs()).hasSize(2); + assertThat(ruleDescr.getLhs().getDescrs()).first().isInstanceOfSatisfying(OrDescr.class, stiltonOrGorgonzola -> { + assertThat(stiltonOrGorgonzola.getDescrs()).hasSize(2); + assertThat(stiltonOrGorgonzola.getDescrs()).first().isInstanceOfSatisfying(AndDescr.class, andDescr -> { + assertThat(andDescr.getDescrs()).hasSize(2); + assertThat(andDescr.getDescrs()).first().isInstanceOfSatisfying(PatternDescr.class, stilton -> { + assertThat(stilton.getIdentifier()).isEqualTo("$a"); + assertThat(stilton.getObjectType()).isEqualTo("Cheese"); + assertThat(stilton.getConstraint().toString()).contains("stilton"); + }); + assertThat(andDescr.getDescrs()).last().isInstanceOfSatisfying(NamedConsequenceDescr.class, namedConsequenceDescr -> { + assertThat(namedConsequenceDescr.getName()).isEqualTo("t1"); + }); + }); + assertThat(stiltonOrGorgonzola.getDescrs()).last().isInstanceOfSatisfying(PatternDescr.class, gorgonzola -> { + assertThat(gorgonzola.getIdentifier()).isEqualTo("$b"); + assertThat(gorgonzola.getObjectType()).isEqualTo("Cheese"); + assertThat(gorgonzola.getConstraint().toString()).contains("gorgonzola"); + }); + }); + assertThat(ruleDescr.getLhs().getDescrs()).last().isInstanceOfSatisfying(PatternDescr.class, cheddar -> { + assertThat(cheddar.getIdentifier()).isEqualTo("$c"); + assertThat(cheddar.getObjectType()).isEqualTo("Cheese"); + assertThat(cheddar.getConstraint().toString()).contains("cheddar"); + }); + } + + @Test + void testNamedConsequencesInsideOR2() { + final String text = + "import org.drools.mvel.compiler.Cheese;\n " + + "global java.util.List results;\n" + + "\n" + + "rule R1 when\n" + + " ( $a: Cheese ( type == \"stilton\" )\n" + + " or\n" + + " $b: Cheese ( type == \"gorgonzola\" ) do[t1] )\n" + + " $c: Cheese ( type == \"cheddar\" )\n" + + "then\n" + + " results.add( $c.getType() );\n" + + "then[t1]\n" + + " results.add( $b.getType() );\n" + + "end\n"; + PackageDescr packageDescr = parseAndGetPackageDescr(text); + RuleDescr ruleDescr = packageDescr.getRules().get(0); + + assertThat(ruleDescr.getLhs().getDescrs()).hasSize(2); + assertThat(ruleDescr.getLhs().getDescrs()).first().isInstanceOfSatisfying(OrDescr.class, stiltonOrGorgonzola -> { + assertThat(stiltonOrGorgonzola.getDescrs()).hasSize(2); + assertThat(stiltonOrGorgonzola.getDescrs()).first().isInstanceOfSatisfying(PatternDescr.class, stilton -> { + assertThat(stilton.getIdentifier()).isEqualTo("$a"); + assertThat(stilton.getObjectType()).isEqualTo("Cheese"); + assertThat(stilton.getConstraint().toString()).contains("stilton"); + }); + assertThat(stiltonOrGorgonzola.getDescrs()).last().isInstanceOfSatisfying(AndDescr.class, andDescr -> { + assertThat(andDescr.getDescrs()).hasSize(2); + assertThat(andDescr.getDescrs()).first().isInstanceOfSatisfying(PatternDescr.class, gorgonzola -> { + assertThat(gorgonzola.getIdentifier()).isEqualTo("$b"); + assertThat(gorgonzola.getObjectType()).isEqualTo("Cheese"); + assertThat(gorgonzola.getConstraint().toString()).contains("gorgonzola"); + }); + assertThat(andDescr.getDescrs()).last().isInstanceOfSatisfying(NamedConsequenceDescr.class, namedConsequenceDescr -> { + assertThat(namedConsequenceDescr.getName()).isEqualTo("t1"); + }); + }); + }); + assertThat(ruleDescr.getLhs().getDescrs()).last().isInstanceOfSatisfying(PatternDescr.class, cheddar -> { + assertThat(cheddar.getIdentifier()).isEqualTo("$c"); + assertThat(cheddar.getObjectType()).isEqualTo("Cheese"); + assertThat(cheddar.getConstraint().toString()).contains("cheddar"); + }); + } + @Test public void queryComplexLhs() { final String text = "query isContainedIn(String x, String y)\n" + diff --git a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java index 49a527612ab..7001beed648 100644 --- a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java +++ b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java @@ -1078,8 +1078,19 @@ public BaseDescr visitLhsAndDef(DRLParser.LhsAndDefContext ctx) { } @Override - public List visitLhsUnary(DRLParser.LhsUnaryContext ctx) { - return visitDescrChildren(ctx); // lhsUnary may have consequenceInvocation, so not always a single child + public BaseDescr visitLhsUnary(DRLParser.LhsUnaryContext ctx) { + List children = visitDescrChildren(ctx); + if (children.size() > 1) { + // lhsUnary may have multiple children e.g. consequenceInvocation, connect with AND + AndDescr andDescr = BaseDescrFactory.builder(new AndDescr()) + .withParserRuleContext(ctx) + .build(); + children.forEach(andDescr::addDescr); + return andDescr; + } else { + // size == 1. children never be empty + return children.get(0); + } } /**