diff --git a/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4 b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4 index 4684804a10f1..5c81fff36620 100644 --- a/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4 +++ b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4 @@ -34,9 +34,9 @@ globaldef : DRL_GLOBAL type drlIdentifier SEMI? ; // rule := RULE stringId (EXTENDS stringId)? annotation* attributes? lhs? rhs END -ruledef : DRL_RULE name=stringId (EXTENDS stringId)? drlAnnotation* attributes? DRL_WHEN lhs DRL_THEN rhs DRL_END ; +ruledef : DRL_RULE name=stringId (EXTENDS stringId)? drlAnnotation* attributes? lhs rhs DRL_END ; -lhs : lhsExpression? ; +lhs : DRL_WHEN lhsExpression? ; lhsExpression : lhsOr+ ; lhsOr : LPAREN DRL_OR lhsAnd+ RPAREN | lhsAnd (DRL_OR lhsAnd)* ; lhsAnd : LPAREN DRL_AND lhsUnary+ RPAREN | lhsUnary (DRL_AND lhsUnary)* ; @@ -260,7 +260,9 @@ lhsExists : DRL_EXISTS lhsPatternBind ; */ lhsNot : DRL_NOT lhsPatternBind ; -rhs : drlRhsBlockStatement* ; +rhs : DRL_THEN consequence ; + +consequence : drlRhsBlockStatement* ; stringId : ( IDENTIFIER | DRL_STRING_LITERAL ) ; diff --git a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java index a152733d179d..e9585a9ab107 100644 --- a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java +++ b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java @@ -9,6 +9,7 @@ import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; +import org.drools.drl.ast.descr.AndDescr; import org.drools.drl.ast.descr.AnnotationDescr; import org.drools.drl.ast.descr.AttributeDescr; import org.drools.drl.ast.descr.BaseDescr; @@ -115,7 +116,6 @@ public Object visitFunctiondef(DRLParser.FunctiondefContext ctx) { @Override public Object visitRuledef(DRLParser.RuledefContext ctx) { currentRule = new RuleDescr(safeStripStringDelimiters(ctx.name.getText())); - currentRule.setConsequence(ParserStringUtils.getTextPreservingWhitespace(ctx.rhs())); packageDescr.addRule(currentRule); Object result = super.visitRuledef(ctx); @@ -137,7 +137,8 @@ public Object visitLhs(DRLParser.LhsContext ctx) { public Object visitLhsPatternBind(DRLParser.LhsPatternBindContext ctx) { if (ctx.lhsPattern().size() == 1) { Object result = super.visitLhsPatternBind(ctx); - PatternDescr patternDescr = (PatternDescr) currentConstructStack.peek().getDescrs().get(0); + ConditionalElementDescr parentDescr = currentConstructStack.peek(); + PatternDescr patternDescr = (PatternDescr) parentDescr.getDescrs().get(parentDescr.getDescrs().size() - 1); if (ctx.label() != null) { patternDescr.setIdentifier(ctx.label().IDENTIFIER().getText()); } @@ -175,7 +176,7 @@ public Object visitLhsPattern(DRLParser.LhsPatternContext ctx) { currentPattern.setSource(from); } Object result = super.visitLhsPattern(ctx); - currentConstructStack.peek().addDescr(currentPattern); + currentConstructStack.peek().addDescr(currentPattern); currentPattern = null; return result; } @@ -184,7 +185,12 @@ public Object visitLhsPattern(DRLParser.LhsPatternContext ctx) { public Object visitConstraint(DRLParser.ConstraintContext ctx) { Object constraint = super.visitConstraint(ctx); if (constraint != null) { - ExprConstraintDescr constr = new ExprConstraintDescr(constraint.toString()); + String constraintString = constraint.toString(); + DRLParser.LabelContext label = ctx.label(); + if (label != null) { + constraintString = label.getText() + constraintString; + } + ExprConstraintDescr constr = new ExprConstraintDescr(constraintString); constr.setType(ExprConstraintDescr.Type.NAMED); currentPattern.addConstraint(constr); } @@ -292,6 +298,13 @@ public Object visitLhsOr(DRLParser.LhsOrContext ctx) { } } + @Override + public Object visitRhs(DRLParser.RhsContext ctx) { + currentRule.setConsequenceLocation(ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine()); // location of "then" + currentRule.setConsequence(ParserStringUtils.getTextPreservingWhitespace(ctx.consequence())); + return super.visitChildren(ctx); + } + public PackageDescr getPackageDescr() { return packageDescr; } diff --git a/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/DRLParserTest.java b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/DRLParserTest.java index cec1ac92b473..4b9497b422ab 100644 --- a/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/DRLParserTest.java +++ b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/DRLParserTest.java @@ -31,7 +31,7 @@ class DRLParserTest { "end\n"; @Test - void testParse() { + void parse_basicRule() { PackageDescr packageDescr = parse(drl); assertThat(packageDescr.getName()).isEqualTo("org.test"); @@ -72,7 +72,7 @@ void testParse() { } @Test - void testComputeTokenIndex() { + void computeTokenIndex_basicRule() { DRLParser parser = createDrlParser(drl); parser.compilationUnit(); diff --git a/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java index 77f2485ae46b..82404dee71aa 100644 --- a/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java +++ b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java @@ -57,15 +57,26 @@ private String readResource(final String filename) throws Exception { return sb.toString(); } + private RuleDescr parseAndGetFirstRule(String drl) { + PackageDescr pkg = parser.parse(drl); + assertThat(parser.hasErrors()).as(parser.getErrorMessages().toString()).isFalse(); + assertThat(pkg.getRules()).isNotEmpty(); + return pkg.getRules().get(0); + } + + private RuleDescr parseAndGetFirstRuleFromFile(String filename) throws Exception { + return parseAndGetFirstRule(readResource(filename)); + } + @Test - void testPackage() { + void parse_validPackage() { final String source = "package foo.bar.baz"; final PackageDescr pkg = parser.parse(source); assertThat(pkg.getName()).isEqualTo("foo.bar.baz"); } @Test - void testPackageWithErrorNode() { + void parse_packageWithErrorNode() { final String source = "package 12 foo.bar.baz"; final PackageDescr pkg = parser.parse(source); assertThat(parser.hasErrors()).isTrue(); @@ -73,20 +84,20 @@ void testPackageWithErrorNode() { } @Test - void testPackageWithAllErrorNode() { + void parse_packageWithAllErrorNode() { final String source = "package 12 12312 231"; final PackageDescr pkg = parser.parse(source); assertThat(parser.hasErrors()).isTrue(); - assertThat(pkg.getName()).isEqualTo(""); + assertThat(pkg.getName()).isEmpty(); } @Test - void testCompilationUnit() { + void parse_import() { final String source = "package foo; import com.foo.Bar; import com.foo.Baz;"; PackageDescr pkg = parser.parse(source); assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse(); assertThat(pkg.getName()).isEqualTo("foo"); - assertThat(pkg.getImports().size()).isEqualTo(2); + assertThat(pkg.getImports()).hasSize(2); ImportDescr impdescr = pkg.getImports().get(0); assertThat(impdescr.getTarget()).isEqualTo("com.foo.Bar"); assertThat(impdescr.getStartCharacter()).isEqualTo(source.indexOf("import " + impdescr.getTarget())); @@ -99,7 +110,7 @@ void testCompilationUnit() { } @Test - void testFunctionImport() { + void parse_functionImport() { final String source = "package foo\n" + "import function java.lang.Math.max\n" + "import function java.lang.Math.min;\n" + @@ -108,7 +119,7 @@ void testFunctionImport() { PackageDescr pkg = parser.parse(source); assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse(); assertThat(pkg.getName()).isEqualTo("foo"); - assertThat(pkg.getImports().size()).isEqualTo(2); + assertThat(pkg.getImports()).hasSize(2); ImportDescr impdescr = pkg.getImports().get(0); assertThat(impdescr.getTarget()).isEqualTo("foo.bar.*"); assertThat(impdescr.getStartCharacter()).isEqualTo(source.indexOf("import " + impdescr.getTarget())); @@ -120,7 +131,7 @@ void testFunctionImport() { assertThat(impdescr.getStartCharacter()).isEqualTo(source.indexOf("import " + impdescr.getTarget())); assertThat(impdescr.getEndCharacter()).isEqualTo(source.indexOf("import " + impdescr.getTarget()) + ("import " + impdescr.getTarget()).length() - 1); - assertThat(pkg.getFunctionImports().size()).isEqualTo(2); + assertThat(pkg.getFunctionImports()).hasSize(2); impdescr = pkg.getFunctionImports().get(0); assertThat(impdescr.getTarget()).isEqualTo("java.lang.Math.max"); assertThat(impdescr.getStartCharacter()).isEqualTo(source.indexOf("import function " + impdescr.getTarget())); @@ -133,7 +144,7 @@ void testFunctionImport() { } @Test - void testGlobalWithComplexType() { + void parse_globalWithComplexType() { final String source = "package foo.bar.baz\n" + "import com.foo.Bar\n" + "global java.util.List> aList;\n" + @@ -141,14 +152,14 @@ void testGlobalWithComplexType() { PackageDescr pkg = parser.parse(source); assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse(); assertThat(pkg.getName()).isEqualTo("foo.bar.baz"); - assertThat(pkg.getImports().size()).isEqualTo(1); + assertThat(pkg.getImports()).hasSize(1); ImportDescr impdescr = pkg.getImports().get(0); assertThat(impdescr.getTarget()).isEqualTo("com.foo.Bar"); assertThat(impdescr.getStartCharacter()).isEqualTo(source.indexOf("import " + impdescr.getTarget())); assertThat(impdescr.getEndCharacter()).isEqualTo(source.indexOf("import " + impdescr.getTarget()) + ("import " + impdescr.getTarget()).length() - 1); - assertThat(pkg.getGlobals().size()).isEqualTo(2); + assertThat(pkg.getGlobals()).hasSize(2); GlobalDescr global = pkg.getGlobals().get(0); assertThat(global.getType()).isEqualTo("java.util.List>"); @@ -166,17 +177,17 @@ void testGlobalWithComplexType() { } @Test - void testGlobalWithOrWithoutSemi() throws Exception { + void parse_globalWithOrWithoutSemi() throws Exception { String source = readResource("globals.drl"); PackageDescr pkg = parser.parse(source); - assertThat(pkg.getRules().size()).isEqualTo(1); + assertThat(pkg.getRules()).hasSize(1); final RuleDescr rule = (RuleDescr) pkg.getRules().get(0); - assertThat(rule.getLhs().getDescrs().size()).isEqualTo(1); + assertThat(rule.getLhs().getDescrs()).hasSize(1); - assertThat(pkg.getImports().size()).isEqualTo(1); - assertThat(pkg.getGlobals().size()).isEqualTo(2); + assertThat(pkg.getImports()).hasSize(1); + assertThat(pkg.getGlobals()).hasSize(2); final GlobalDescr foo = (GlobalDescr) pkg.getGlobals().get(0); assertThat(foo.getType()).isEqualTo("java.lang.String"); @@ -187,22 +198,22 @@ void testGlobalWithOrWithoutSemi() throws Exception { } @Test - void testFunctionImportWithNotExist() throws Exception { + void parse_functionImportWithNotExist() throws Exception { String source = readResource("test_FunctionImport.drl"); PackageDescr pkg = parser.parse(source); - assertThat(pkg.getFunctionImports().size()).isEqualTo(2); + assertThat(pkg.getFunctionImports()).hasSize(2); assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(0)).getTarget()).isEqualTo("abd.def.x"); - assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(0)).getStartCharacter() == -1).isFalse(); - assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(0)).getEndCharacter() == -1).isFalse(); + assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(0)).getStartCharacter()).isNotSameAs(-1); + assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(0)).getEndCharacter()).isNotSameAs(-1); assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(1)).getTarget()).isEqualTo("qed.wah.*"); - assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(1)).getStartCharacter() == -1).isFalse(); - assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(1)).getEndCharacter() == -1).isFalse(); + assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(1)).getStartCharacter()).isNotSameAs(-1); + assertThat(((FunctionImportDescr) pkg.getFunctionImports().get(1)).getEndCharacter()).isNotSameAs(-1); } @Test - void testFromComplexAcessor() { + void parse_fromComplexAccessor() { String source = "rule \"Invalid customer id\" ruleflow-group \"validate\" lock-on-active true \n" + " when \n" + " o: Order( ) \n" + @@ -219,7 +230,7 @@ void testFromComplexAcessor() { RuleDescr rule = (RuleDescr) pkg.getRules().get(0); assertThat(rule.getName()).isEqualTo("Invalid customer id"); - assertThat(rule.getLhs().getDescrs().size()).isEqualTo(2); + assertThat(rule.getLhs().getDescrs()).hasSize(2); NotDescr not = (NotDescr) rule.getLhs().getDescrs().get(1); PatternDescr customer = (PatternDescr) not.getDescrs().get(0); @@ -229,7 +240,7 @@ void testFromComplexAcessor() { } @Test - void testFromWithInlineList() { + void parse_fromWithInlineList() { String source = "rule XYZ \n" + " when \n" + " o: Order( ) \n" + @@ -249,7 +260,7 @@ void testFromWithInlineList() { } @Test - void testFromWithInlineListMethod() { + void parse_fromWithInlineListMethod() { String source = "rule XYZ \n" + " when \n" + " o: Order( ) \n" + @@ -271,7 +282,7 @@ void testFromWithInlineListMethod() { } @Test - void testFromWithInlineListIndex() { + void parse_fromWithInlineListIndex() { String source = "rule XYZ \n" + " when \n" + " o: Order( ) \n" + @@ -293,7 +304,7 @@ void testFromWithInlineListIndex() { } @Test - void testRuleWithoutEnd() { + void parse_ruleWithoutEnd() { String source = "rule \"Invalid customer id\" \n" + " when \n" + " o: Order( ) \n" + @@ -304,7 +315,7 @@ void testRuleWithoutEnd() { } @Test - void testOrWithSpecialBind() { + void parse_orWithSpecialBind() { String source = "rule \"A and (B or C or D)\" \n" + " when \n" + " pdo1 : ParametricDataObject( paramID == 101, stringValue == \"1000\" ) and \n" + @@ -319,20 +330,20 @@ void testOrWithSpecialBind() { RuleDescr rule = pkg.getRules().get(0); AndDescr lhs = rule.getLhs(); - assertThat(lhs.getDescrs().size()).isEqualTo(2); + assertThat(lhs.getDescrs()).hasSize(2); PatternDescr pdo1 = (PatternDescr) lhs.getDescrs().get(0); assertThat(pdo1.getIdentifier()).isEqualTo("pdo1"); OrDescr or = (OrDescr) rule.getLhs().getDescrs().get(1); - assertThat(or.getDescrs().size()).isEqualTo(3); + assertThat(or.getDescrs()).hasSize(3); for (BaseDescr pdo2 : or.getDescrs()) { assertThat(((PatternDescr) pdo2).getIdentifier()).isEqualTo("pdo2"); } } @Test - void testCompatibleRestriction() { + void parse_compatibleRestriction() { String source = "package com.sample rule test when Test( ( text == null || text2 matches \"\" ) ) then end"; PackageDescr pkg = parser.parse(source); @@ -344,7 +355,7 @@ void testCompatibleRestriction() { } @Test - void testSimpleConstraint() { + void parse_simpleConstraint() { String source = "package com.sample rule test when Cheese( type == 'stilton', price > 10 ) then end"; PackageDescr pkg = parser.parse(source); @@ -352,33 +363,33 @@ void testSimpleConstraint() { RuleDescr rule = (RuleDescr) pkg.getRules().get(0); assertThat(rule.getName()).isEqualTo("test"); - assertThat(rule.getLhs().getDescrs().size()).isEqualTo(1); + assertThat(rule.getLhs().getDescrs()).hasSize(1); PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get(0); AndDescr constraint = (AndDescr) pattern.getConstraint(); - assertThat(constraint.getDescrs().size()).isEqualTo(2); - assertThat(constraint.getDescrs().get(0).toString()).isEqualTo("type == \"stilton\""); - assertThat(constraint.getDescrs().get(1).toString()).isEqualTo("price > 10"); + assertThat(constraint.getDescrs()).hasSize(2); + assertThat(constraint.getDescrs().get(0)).hasToString("type == \"stilton\""); + assertThat(constraint.getDescrs().get(1)).hasToString("price > 10"); } @Test - void testStringEscapes() { + void parse_stringEscapes() { String source = "package com.sample rule test when Cheese( type matches \"\\..*\\\\.\" ) then end"; PackageDescr pkg = parser.parse(source); assertThat(pkg.getName()).isEqualTo("com.sample"); RuleDescr rule = (RuleDescr) pkg.getRules().get(0); assertThat(rule.getName()).isEqualTo("test"); - assertThat(rule.getLhs().getDescrs().size()).isEqualTo(1); + assertThat(rule.getLhs().getDescrs()).hasSize(1); PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get(0); AndDescr constraint = (AndDescr) pattern.getConstraint(); - assertThat(constraint.getDescrs().size()).isEqualTo(1); - assertThat(constraint.getDescrs().get(0).toString()).isEqualTo("type matches \"\\..*\\\\.\""); + assertThat(constraint.getDescrs()).hasSize(1); + assertThat(constraint.getDescrs().get(0)).hasToString("type matches \"\\..*\\\\.\""); } @Test - void testDialect() { + void parse_dialectWithSingleQuotation() { final String source = "dialect 'mvel'"; PackageDescr pkg = parser.parse(source); AttributeDescr attr = (AttributeDescr) pkg.getAttributes().get(0); @@ -387,7 +398,7 @@ void testDialect() { } @Test - void testDialect2() { + void parse_dialectWithDoubleQuotation() { final String source = "dialect \"mvel\""; PackageDescr pkg = parser.parse(source); AttributeDescr attr = pkg.getAttributes().get(0); @@ -396,7 +407,7 @@ void testDialect2() { } @Test - void testEmptyRuleWithoutWhen() throws Exception { + void parse_emptyRuleWithoutWhen() throws Exception { String source = readResource("empty_rule.drl"); // without WHEN PackageDescr pkg = parser.parse(source); @@ -406,7 +417,7 @@ void testEmptyRuleWithoutWhen() throws Exception { } @Test - void testKeywordCollisions() throws Exception { + void parse_keywordCollisions() throws Exception { String source = readResource("eol_funny_business.drl"); // keywords everywhere // Note: eol_funny_business.drl is modified from the one under drools-test-coverage to be more realistic. @@ -416,22 +427,22 @@ void testKeywordCollisions() throws Exception { assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse(); - assertThat(pkg.getRules().size()).isEqualTo(1); + assertThat(pkg.getRules()).hasSize(1); } @Test - void testTernaryExpression() throws Exception { + void parse_ternaryExpression() throws Exception { String source = readResource("ternary_expression.drl"); PackageDescr pkg = parser.parse(source); final RuleDescr rule = (RuleDescr) pkg.getRules().get(0); - assertThat(pkg.getRules().size()).isEqualTo(1); + assertThat(pkg.getRules()).hasSize(1); assertThat((String) rule.getConsequence()).isEqualToIgnoringWhitespace("if (speed > speedLimit ? true : false;) pullEmOver();"); } @Test - void testFunctionWithArrays() throws Exception { + void parse_functionWithArrays() throws Exception { String source = readResource("function_arrays.drl"); // Note: function_arrays.drl is modified from the one under drools-test-coverage to be more realistic. @@ -441,7 +452,7 @@ void testFunctionWithArrays() throws Exception { PackageDescr pkg = parser.parse(source); assertThat(pkg.getName()).isEqualTo("foo"); - assertThat(pkg.getRules().size()).isEqualTo(1); + assertThat(pkg.getRules()).hasSize(1); final RuleDescr rule = (RuleDescr) pkg.getRules().get(0); @@ -455,7 +466,7 @@ void testFunctionWithArrays() throws Exception { } @Test - void testAlmostEmptyRule() throws Exception { + void parse_almostEmptyRule() throws Exception { String source = readResource("almost_empty_rule.drl"); PackageDescr pkg = parser.parse(source); @@ -466,11 +477,11 @@ void testAlmostEmptyRule() throws Exception { assertThat(rule.getName()).isEqualTo("almost_empty"); assertThat(rule.getLhs()).isNotNull(); - assertThat(((String) rule.getConsequence()).trim()).isEqualTo(""); + assertThat(((String) rule.getConsequence()).trim()).isEmpty(); } @Test - void testQuotedStringNameRule() throws Exception { + void parse_quotedStringNameRule() throws Exception { String source = readResource("quoted_string_name_rule.drl"); PackageDescr pkg = parser.parse(source); @@ -481,11 +492,11 @@ void testQuotedStringNameRule() throws Exception { assertThat(rule.getName()).isEqualTo("quoted string name"); assertThat(rule.getLhs()).isNotNull(); - assertThat(((String) rule.getConsequence()).trim()).isEqualTo(""); + assertThat(((String) rule.getConsequence()).trim()).isEmpty(); } @Test - void testNoLoop() throws Exception { + void parse_noLoop() throws Exception { String source = readResource("no-loop.drl"); PackageDescr pkg = parser.parse(source); @@ -501,7 +512,7 @@ void testNoLoop() throws Exception { } @Test - void testAutofocus() throws Exception { + void parse_autofocus() throws Exception { String source = readResource("autofocus.drl"); PackageDescr pkg = parser.parse(source); @@ -517,7 +528,7 @@ void testAutofocus() throws Exception { } @Test - void testRuleFlowGroup() throws Exception { + void parse_ruleFlowGroup() throws Exception { String source = readResource("ruleflowgroup.drl"); PackageDescr pkg = parser.parse(source); @@ -533,7 +544,7 @@ void testRuleFlowGroup() throws Exception { } @Test - void testConsequenceWithDeclaration() throws Exception { + void parse_consequenceWithDeclaration() throws Exception { String source = readResource("declaration-in-consequence.drl"); PackageDescr pkg = parser.parse(source); @@ -564,7 +575,7 @@ void testConsequenceWithDeclaration() throws Exception { } @Test - void testRuleParseLhs() { + void parse_or() { final String text = "rule X when Person(age < 42, location==\"atlanta\") \nor\nPerson(name==\"bob\") then end"; PackageDescr pkg = parser.parse(text); RuleDescr rule = (RuleDescr) pkg.getRules().get(0); @@ -574,12 +585,12 @@ void testRuleParseLhs() { assertThat(rule).isNotNull(); AndDescr lhs = rule.getLhs(); - assertThat(lhs.getDescrs().size()).isEqualTo(1); - assertThat(((OrDescr) lhs.getDescrs().get(0)).getDescrs().size()).isEqualTo(2); + assertThat(lhs.getDescrs()).hasSize(1); + assertThat(((OrDescr) lhs.getDescrs().get(0)).getDescrs()).hasSize(2); } @Test - void testRuleParseLhsWithStringQuotes() { + void parse_lhsWithStringQuotes() { final String text = "rule X when Person( location==\"atlanta\\\"\") then end\n"; PackageDescr pkg = parser.parse(text); RuleDescr rule = (RuleDescr) pkg.getRules().get(0); @@ -595,7 +606,7 @@ void testRuleParseLhsWithStringQuotes() { } @Test - void testRuleParseLhsWithStringQuotes2() { + void parse_lhsWithStringQuotesEscapeChars() { final String text = "rule X when Cheese( $x: type, type == \"s\\tti\\\"lto\\nn\" ) then end\n"; PackageDescr pkg = parser.parse(text); RuleDescr rule = (RuleDescr) pkg.getRules().get(0); @@ -610,12 +621,8 @@ void testRuleParseLhsWithStringQuotes2() { } @Test - void testLiteralBoolAndNegativeNumbersRule() throws Exception { - String source = readResource("literal_bool_and_negative.drl"); - PackageDescr pkg = parser.parse(source); - RuleDescr rule = (RuleDescr) pkg.getRules().get(0); - - assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse(); + void parse_literalBoolAndNegativeNumbersRule() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("literal_bool_and_negative.drl"); assertThat(rule).isNotNull(); @@ -625,16 +632,16 @@ void testLiteralBoolAndNegativeNumbersRule() throws Exception { assertThat((String) rule.getConsequence()).isEqualToIgnoringWhitespace("cons();"); final AndDescr lhs = rule.getLhs(); - assertThat(lhs.getDescrs().size()).isEqualTo(3); + assertThat(lhs.getDescrs()).hasSize(3); PatternDescr pattern = (PatternDescr) lhs.getDescrs().get(0); - assertThat(pattern.getConstraint().getDescrs().size()).isEqualTo(1); + assertThat(pattern.getConstraint().getDescrs()).hasSize(1); AndDescr fieldAnd = (AndDescr) pattern.getConstraint(); ExprConstraintDescr fld = (ExprConstraintDescr) fieldAnd.getDescrs().get(0); assertThat(fld.getExpression()).isEqualToIgnoringWhitespace("bar == false"); pattern = (PatternDescr) lhs.getDescrs().get(1); - assertThat(pattern.getConstraint().getDescrs().size()).isEqualTo(1); + assertThat(pattern.getConstraint().getDescrs()).hasSize(1); fieldAnd = (AndDescr) pattern.getConstraint(); fld = (ExprConstraintDescr) fieldAnd.getDescrs().get(0); @@ -642,7 +649,7 @@ void testLiteralBoolAndNegativeNumbersRule() throws Exception { assertThat(fld.getText()).isEqualToIgnoringWhitespace("boo > -42"); pattern = (PatternDescr) lhs.getDescrs().get(2); - assertThat(pattern.getConstraint().getDescrs().size()).isEqualTo(1); + assertThat(pattern.getConstraint().getDescrs()).hasSize(1); fieldAnd = (AndDescr) pattern.getConstraint(); fld = (ExprConstraintDescr) fieldAnd.getDescrs().get(0); @@ -651,32 +658,129 @@ void testLiteralBoolAndNegativeNumbersRule() throws Exception { } @Test - void testEmptyPattern() throws Exception { + void parse_emptyPattern() throws Exception { String source = readResource("test_EmptyPattern.drl"); PackageDescr pkg = parser.parse(source); assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse(); - assertThat(pkg.getRules().size()).isEqualTo(1); + assertThat(pkg.getRules()).hasSize(1); final RuleDescr ruleDescr = (RuleDescr) pkg.getRules().get(0); assertThat(ruleDescr.getName()).isEqualTo("simple rule"); assertThat(ruleDescr.getLhs()).isNotNull(); - assertThat(ruleDescr.getLhs().getDescrs().size()).isEqualTo(1); + assertThat(ruleDescr.getLhs().getDescrs()).hasSize(1); final PatternDescr patternDescr = (PatternDescr) ruleDescr.getLhs().getDescrs().get(0); - assertThat(patternDescr.getConstraint().getDescrs().size()).isEqualTo(0); // this + assertThat(patternDescr.getConstraint().getDescrs()).isEmpty(); // this assertThat(patternDescr.getObjectType()).isEqualTo("Cheese"); } @Test - void testSimpleMethodCallWithFrom() throws Exception { - String source = readResource("test_SimpleMethodCallWithFrom.drl"); - PackageDescr pkg = parser.parse(source); - assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse(); - RuleDescr rule = (RuleDescr) pkg.getRules().get(0); + void parse_simpleMethodCallWithFrom() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("test_SimpleMethodCallWithFrom.drl"); final PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get(0); final FromDescr from = (FromDescr) pattern.getSource(); final MVELExprDescr method = (MVELExprDescr) from.getDataSource(); assertThat(method.getExpression()).isEqualToIgnoringWhitespace("something.doIt( foo,bar,42,\"hello\",[ a : \"b\", \"something\" : 42, \"a\" : foo, x : [x:y]],\"end\", [a, \"b\", 42] )"); } + + @Test + void parse_simpleFunctionCallWithFrom() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("test_SimpleFunctionCallWithFrom.drl"); + final PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get(0); + final FromDescr from = (FromDescr) pattern.getSource(); + final MVELExprDescr func = (MVELExprDescr) from.getDataSource(); + + assertThat(func.getExpression()).isEqualToIgnoringWhitespace("doIt( foo,bar,42,\"hello\",[ a : \"b\", \"something\" : 42, \"a\" : foo, x : [x:y]],\"end\", [a, \"b\", 42] )"); + } + + @Test + void parse_simpleAccessorWithFrom() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("test_SimpleAccessorWithFrom.drl"); + final PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get( 0 ); + final FromDescr from = (FromDescr) pattern.getSource(); + final MVELExprDescr accessor = (MVELExprDescr) from.getDataSource(); + + assertThat(accessor.getExpression()).isEqualTo("something.doIt"); + } + + @Test + void parse_simpleAccessorAndArgWithFrom() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("test_SimpleAccessorArgWithFrom.drl"); + final PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get( 0 ); + final FromDescr from = (FromDescr) pattern.getSource(); + final MVELExprDescr accessor = (MVELExprDescr) from.getDataSource(); + + assertThat(accessor.getExpression()).isEqualTo("something.doIt[\"key\"]"); + } + + @Test + void parse_complexChainedAccessor() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("test_ComplexChainedCallWithFrom.drl"); + + final PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get( 0 ); + final FromDescr from = (FromDescr) pattern.getSource(); + final MVELExprDescr accessor = (MVELExprDescr) from.getDataSource(); + + assertThat(accessor.getExpression()).isEqualToIgnoringWhitespace("doIt1( foo,bar,42,\"hello\",[ a : \"b\"], [a, \"b\", 42] ).doIt2(bar, [a, \"b\", 42]).field[\"key\"]"); + } + + @Test + void parse_from() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("from.drl"); + assertThat(rule).isNotNull(); + + assertThat(rule.getName()).isEqualTo("using_from"); + + assertThat(rule.getLhs().getDescrs()).hasSize(9); + } + + @Test + void parse_simpleRuleWithBindings() throws Exception { + RuleDescr rule = parseAndGetFirstRuleFromFile("simple_rule.drl"); + assertThat(rule).isNotNull(); + + assertThat(rule.getName()).isEqualTo("simple_rule"); + + assertThat(rule.getConsequenceLine()).isEqualTo(22); + assertThat(rule.getConsequencePattern()).isEqualTo(2); + + final AndDescr lhs = rule.getLhs(); + + assertThat(lhs).isNotNull(); + + assertThat(lhs.getDescrs()).hasSize(3); + + // Check first pattern + final PatternDescr first = (PatternDescr) lhs.getDescrs().get(0); + assertThat(first.getIdentifier()).isEqualTo("foo3"); + assertThat(first.getObjectType()).isEqualTo("Bar"); + + assertThat(first.getConstraint().getDescrs()).hasSize(1); + + AndDescr fieldAnd = (AndDescr) first.getConstraint(); + ExprConstraintDescr constraint = (ExprConstraintDescr) fieldAnd.getDescrs().get(0); + assertThat(constraint).isNotNull(); + + assertThat(constraint.getExpression()).isEqualToIgnoringWhitespace("a==3"); + + // Check second pattern + final PatternDescr second = (PatternDescr) lhs.getDescrs().get(1); + assertThat(second.getIdentifier()).isEqualTo("foo4"); + assertThat(second.getObjectType()).isEqualTo("Bar"); + + // no constraints, only a binding + fieldAnd = (AndDescr) second.getConstraint(); + assertThat(fieldAnd.getDescrs()).hasSize(1); + + final ExprConstraintDescr binding = (ExprConstraintDescr) second.getConstraint().getDescrs().get(0); + assertThat(binding.getExpression()).isEqualToIgnoringWhitespace("a4:a==4"); + + // Check third pattern + final PatternDescr third = (PatternDescr) lhs.getDescrs().get(2); + assertThat(third.getIdentifier()).isNull(); + assertThat(third.getObjectType()).isEqualTo("Baz"); + + assertThat((String) rule.getConsequence()).isEqualToIgnoringWhitespace("if ( a == b ) { " + " assert( foo3 );" + "} else {" + " retract( foo4 );" + "}" + " System.out.println( a4 );"); + } } diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/from.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/from.drl new file mode 100644 index 000000000000..5c3f9e9775f8 --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/from.drl @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +rule using_from + when + Foo() from bar.baz + Foo() from bar.baz["key"] + Foo() from bar.baz[$key] + Foo() from bar.baz[1] + Whee(bar=="baz") from whee("y") + f: Foo(la==2) from bar.la(x) + Bam() from wa() + Kah() from la.wa(42, 42.42, false, null) + Bam(a=="c") + then + whee(); +end diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/simple_rule.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/simple_rule.drl new file mode 100644 index 000000000000..7f6a6c4b6a41 --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/simple_rule.drl @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +rule simple_rule + when + foo3 : Bar(a==3) + foo4 : Bar(a4:a==4) + Baz() + then + if ( a == b ) { + assert( foo3 ); + } else { + retract( foo4 ); + } + System.out.println( a4 ); +end \ No newline at end of file diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_ComplexChainedCallWithFrom.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_ComplexChainedCallWithFrom.drl new file mode 100755 index 000000000000..f8029cd90266 --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_ComplexChainedCallWithFrom.drl @@ -0,0 +1,22 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +rule blah + when + Col1() from doIt1( foo,bar,42,"hello",[ a : "b"], [a, "b", 42] ).doIt2(bar, [a, "b", 42]).field["key"] + Col2() + then + partay(); +end diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleAccessorArgWithFrom.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleAccessorArgWithFrom.drl new file mode 100644 index 000000000000..40289b97d4bd --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleAccessorArgWithFrom.drl @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +rule blah + + when + + Col1() from something.doIt["key"] + Col2() + then + partay(); +end diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleAccessorWithFrom.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleAccessorWithFrom.drl new file mode 100644 index 000000000000..375fe578fe4a --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleAccessorWithFrom.drl @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +rule blah + + when + + Col1() from something.doIt + Col2() + then + partay(); +end diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleFunctionCallWithFrom.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleFunctionCallWithFrom.drl new file mode 100644 index 000000000000..8729e98d029f --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleFunctionCallWithFrom.drl @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +rule blah + + when + + Col1() from doIt( foo,bar,42,"hello",[ a : "b", "something" : 42, "a" : foo, x : [x:y]],"end", [a, "b", 42] ) + Col2() + then + partay(); +end