apache / incubator-kie-drools

Drools is a rule engine, DMN engine and complex event processing (CEP) engine for Java.
http://www.drools.org
5.85k stars 2.49k forks source link

[new-parser] Anonymous classes not supported #5932

Closed yurloc closed 4 months ago

yurloc commented 4 months ago

Parent issue

Failing tests

Notes

At the end of line 3, a semi is expected instead of class body. This is because DRL6Expressions.g4 overrides the classCreatorRest rule and does not allow classBody?.

Rule code snippet

import java.util.function.Function
function Function<String, Integer> f() {
    return new Function<String, Integer>() {
        public Integer apply(String s) {
            return s.length();
        }
    };
}

Error output

### parse : ANTLR4_PARSER_ENABLED = true
line 3:43 missing ';' at '{'
line 4:23 missing '.' at 'apply'
line 4:28 mismatched input '(' expecting '.'
line 4:36 extraneous input 's' expecting ')'
line 4:39 extraneous input '{' expecting {'abstract', 'class', 'final', 'interface', 'private', 'protected', 'public', 'static', 'strictfp', 'module', 'open', 'requires', 'exports', 'opens', 'to', 'uses', 'provides', 'with', 'transitive', 'var', 'yield', 'record', 'sealed', 'permits', 'non-sealed', '@', IDENTIFIER}
11:06:45.941 [main] ERROR o.d.c.k.b.impl.AbstractKieProject.buildKnowledgePackages:280 - Unable to build KieBaseModel:KieBaseModelName
[3,43]: missing ';' at '{'
[4,23]: missing '.' at 'apply'
[4,28]: mismatched input '(' expecting '.'
[4,36]: extraneous input 's' expecting ')'
[4,39]: extraneous input '{' expecting {'abstract', 'class', 'final', 'interface', 'private', 'protected', 'public', 'static', 'strictfp', 'module', 'open', 'requires', 'exports', 'opens', 'to', 'uses', 'provides', 'with', 'transitive', 'var', 'yield', 'record', 'sealed', 'permits', 'non-sealed', '@', IDENTIFIER}
[0,0]: Parser returned a null Package

11:06:45.949 [main] ERROR o.d.testcoverage.common.util.KieUtil.getKieBuilderFromKieFileSystem:165 - KieBuilder errors: [Message [id=1, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=3, column=0
   text=missing ';' at '{'], Message [id=2, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=missing '.' at 'apply'], Message [id=3, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=mismatched input '(' expecting '.'], Message [id=4, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=extraneous input 's' expecting ')'], Message [id=5, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=extraneous input '{' expecting {'abstract', 'class', 'final', 'interface', 'private', 'protected', 'public', 'static', 'strictfp', 'module', 'open', 'requires', 'exports', 'opens', 'to', 'uses', 'provides', 'with', 'transitive', 'var', 'yield', 'record', 'sealed', 'permits', 'non-sealed', '@', IDENTIFIER}], Message [id=6, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=0, column=0
   text=Parser returned a null Package]]

java.lang.AssertionError: [[Message [id=1, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=3, column=0
   text=missing ';' at '{'], Message [id=2, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=missing '.' at 'apply'], Message [id=3, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=mismatched input '(' expecting '.'], Message [id=4, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=extraneous input 's' expecting ')'], Message [id=5, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=extraneous input '{' expecting {'abstract', 'class', 'final', 'interface', 'private', 'protected', 'public', 'static', 'strictfp', 'module', 'open', 'requires', 'exports', 'opens', 'to', 'uses', 'provides', 'with', 'transitive', 'var', 'yield', 'record', 'sealed', 'permits', 'non-sealed', '@', IDENTIFIER}], Message [id=6, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=0, column=0
   text=Parser returned a null Package]]] 
Expecting empty but was: [Message [id=1, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=3, column=0
   text=missing ';' at '{'],
    Message [id=2, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=missing '.' at 'apply'],
    Message [id=3, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=mismatched input '(' expecting '.'],
    Message [id=4, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=extraneous input 's' expecting ')'],
    Message [id=5, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=4, column=0
   text=extraneous input '{' expecting {'abstract', 'class', 'final', 'interface', 'private', 'protected', 'public', 'static', 'strictfp', 'module', 'open', 'requires', 'exports', 'opens', 'to', 'uses', 'provides', 'with', 'transitive', 'var', 'yield', 'record', 'sealed', 'permits', 'non-sealed', '@', IDENTIFIER}],
    Message [id=6, kieBase=KieBaseModelName, level=ERROR, path=rules1.drl, line=0, column=0
   text=Parser returned a null Package]]

    at org.drools.testcoverage.common.util.KieUtil.getKieBuilderFromKieFileSystem(KieUtil.java:169)
    at org.drools.testcoverage.common.util.KieUtil.getKieBuilderFromKieFileSystem(KieUtil.java:134)
    at org.drools.testcoverage.common.util.KieUtil.buildAndInstallKieModuleIntoRepo(KieUtil.java:78)
    at org.drools.testcoverage.common.util.KieUtil.buildAndInstallKieModuleIntoRepo(KieUtil.java:72)
    at org.drools.testcoverage.common.util.KieUtil.getKieModuleFromResources(KieUtil.java:249)
    at org.drools.testcoverage.common.util.KieUtil.getKieModuleFromResources(KieUtil.java:238)
    at org.drools.testcoverage.common.util.KieBaseUtil.getKieBaseFromKieModuleFromResources(KieBaseUtil.java:102)
    at org.drools.testcoverage.common.util.KieBaseUtil.getKieBaseFromKieModuleFromDrl(KieBaseUtil.java:115)
    at org.drools.mvel.integrationtests.Misc2Test.testJittingFunctionReturningAnInnerClass(Misc2Test.java:8019)
yurloc commented 4 months ago

good-first-issue

tkobayas commented 4 months ago
functiondef : DRL_FUNCTION typeTypeOrVoid? drlIdentifier formalParameters drlBlock ;

Probably drlBlock can be replaced with LBRACE chunk? RBRACE just like old parser.

yurloc commented 4 months ago
functiondef : DRL_FUNCTION typeTypeOrVoid? drlIdentifier formalParameters drlBlock ;

Probably drlBlock can be replaced with LBRACE chunk? RBRACE just like old parser.

That's the easy solution. I'm not against it as our goal for the ANTL4 rewrite is not to improve the parser's capability.

But another solution exists.

parseTree

If you traverse the parser rules according to the parse tree above, you'll find out that classCreatorRest is declared in DRL6Expressions.g4 and it effectively overrides a rule with the same name in JavaParser.g4. The difference between the two rules is that the one in DRL6Expressions.g4 does not allow class body: https://github.com/apache/incubator-kie-drools/blob/899795609c10d5c8e182449fc1b4684ec93bca01/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRL6Expressions.g4#L843-L845

The obvious fix would be to uncomment classBody? but that would be an unnecessary change in the DRL6Expressions.g4 grammar. I would prefer simply renaming the classCreatorRest rule in DRL6Expressions.g4 leaving its behavior unchanged and letting the drlCreator rule in DRLParser.g4 use the classCreatorRest from JavaParser.g4.

tkobayas commented 4 months ago

Fixed by https://github.com/apache/incubator-kie-drools/pull/5979