8000 [drools-lsp-52] Update grammars to the latest by tkobayas · Pull Request #54 · kiegroup/drools-lsp · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[drools-lsp-52] Update grammars to the latest #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/drools-lsp-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
java-version: [11]
java-version: [17]
maven-version: ['3.8.6']
fail-fast: false
runs-on: ${{ matrix.os }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Set up JDK 11
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '11'
java-version: '17'
distribution: 'adopt'

- uses: actions/checkout@v3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Set up JDK 11
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '11'
java-version: '17'
distribution: 'adopt'

- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Server Architecture
===

The server part is composed of three modules:
1. **drools-parser** - responsible for actual drl-syntax parsing, eventually invoking a JAVA-LSP engine to read the `RHS` content (that is plain Java code); it depends on `org.drools:drools-drl-ast`
1. **drools-parser** - responsible for actual drl-syntax parsing, eventually invoking a JAVA-LSP engine to read the `RHS` content (that is plain Java code); The antlr4 grammar files are taken from the latest drools.
2. **drools-completion** - used to provide completion suggestion using the C3 engine; it depends on `com.vmware.antlr4-c3:antlr4-c3` and on `drools-parser`
3. **drools-lsp-server** - the "gateway" between the client and th 4D32 e parsing/completion logic; by itself it should not implement any business logic, but should be concerned only with communication; it depends directly on `drools-completion`

Expand Down
2 changes: 1 addition & 1 deletion client/src/test/suite/completion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ suite('Completion tests', () => {
{ label: 'package', kind: vscode.CompletionItemKind.Keyword }
]
});
}).timeout(5000); // increase timeout from the default 2000ms because helper.activate waits 2000ms for server startup
}).timeout(20000); // increase timeout from the default 2000ms because helper.activate waits 2000ms for server startup
});

async function testCompletion(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@
*/
package org.drools.completion;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.vmware.antlr4c3.CodeCompletionCore;
import org.drools.parser.DRLParser;
import org.drools.drl.parser.antlr4.DRL10Parser;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.services.LanguageClient;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.drools.parser.DRLParserHelper.computeTokenIndex;
import static org.drools.parser.DRLParserHelper.createDrlParser;
import static org.drools.drl.parser.antlr4.DRLParserHelper.computeTokenIndex;
import static org.drools.drl.parser.antlr4.DRLParserHelper.createDrlParser;

public class DRLCompletionHelper {

private DRLCompletionHelper() {
}

public static List<CompletionItem> getCompletionItems(String text, Position caretPosition, LanguageClient client) {
DRLParser drlParser = createDrlParser(text);
DRL10Parser drlParser = createDrlParser(text);

int row = caretPosition == null ? -1 : caretPosition.getLine() + 1; // caret line position is zero based
int col = caretPosition == null ? -1 : caretPosition.getCharacter();
Expand All @@ -46,7 +46,7 @@ public static List<CompletionItem> getCompletionItems(String text, Position care
return getCompletionItems(drlParser, nodeIndex);
}

static List<CompletionItem> getCompletionItems(DRLParser drlParser, int nodeIndex) {
static List<CompletionItem> getCompletionItems(DRL10Parser drlParser, int nodeIndex) {
CodeCompletionCore core = new CodeCompletionCore(drlParser, null, null);
CodeCompletionCore.CandidatesCollection candidates = core.collectCandidates(nodeIndex, null);

Expand Down
34 changes: 18 additions & 16 deletions drools-completion/src/main/java/org/drools/completion/Tokens.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
package org.drools.completion;

import org.antlr.v4.runtime.Token;
import org.drools.parser.DRLLexer;

import java.util.Set;

import org.antlr.v4.runtime.Token;
import org.drools.drl.parser.antlr4.DRL10Lexer;

public class Tokens {

public static Set<Integer> IGNORED = Set.of(
Token.EPSILON, Token.EOF, Token.INVALID_TYPE,

DRLLexer.TIME_INTERVAL, DRLLexer.HASH, DRLLexer.DRL_UNIFY, DRLLexer.NULL_SAFE_DOT, DRLLexer.QUESTION_DIV, DRLLexer.MISC,
DRL10Lexer.TIME_INTERVAL, DRL10Lexer.HASH, DRL10Lexer.DRL_UNIFY, DRL10Lexer.NULL_SAFE_DOT, DRL10Lexer.QUESTION_DIV, DRL10Lexer.MISC,

DRL10Lexer.DECIMAL_LITERAL, DRL10Lexer.HEX_LITERAL,
DRL10Lexer.OCT_LITERAL, DRL10Lexer.BINARY_LITERAL, DRL10Lexer.FLOAT_LITERAL, DRL10Lexer.HEX_FLOAT_LITERAL,
DRL10Lexer.BOOL_LITERAL, DRL10Lexer.CHAR_LITERAL, DRL10Lexer.STRING_LITERAL, DRL10Lexer.TEXT_BLOCK,
DRL10Lexer.NULL_LITERAL, DRL10Lexer.LPAREN, DRL10Lexer.RPAREN, DRL10Lexer.LBRACE, DRL10Lexer.RBRACE, DRL10Lexer.LBRACK,
DRL10Lexer.RBRACK, DRL10Lexer.SEMI, DRL10Lexer.COMMA, DRL10Lexer.DOT, DRL10Lexer.ASSIGN, DRL10Lexer.GT, DRL10Lexer.LT,
DRL10Lexer.BANG, DRL10Lexer.TILDE, DRL10Lexer.QUESTION, DRL10Lexer.COLON, DRL10Lexer.EQUAL, DRL10Lexer.LE, DRL10Lexer.GE,
DRL10Lexer.NOTEQUAL, DRL10Lexer.AND, DRL10Lexer.OR, DRL10Lexer.INC, DRL10Lexer.DEC, DRL10Lexer.ADD, DRL10Lexer.SUB, DRL10Lexer.MUL,
DRL10Lexer.DIV, DRL10Lexer.BITAND, DRL10Lexer.BITOR, DRL10Lexer.CARET, DRL10Lexer.MOD, DRL10Lexer.ADD_ASSIGN, DRL10Lexer.SUB_ASSIGN,
DRL10Lexer.MUL_ASSIGN, DRL10Lexer.DIV_ASSIGN, DRL10Lexer.AND_ASSIGN, DRL10Lexer.OR_ASSIGN, DRL10Lexer.XOR_ASSIGN,
DRL10Lexer.MOD_ASSIGN, DRL10Lexer.LSHIFT_ASSIGN, DRL10Lexer.RSHIFT_ASSIGN, DRL10Lexer.URSHIFT_ASSIGN,
DRL10Lexer.ARROW, DRL10Lexer.COLONCOLON, DRL10Lexer.AT, DRL10Lexer.ELLIPSIS, DRL10Lexer.WS, DRL10Lexer.COMMENT,
DRL10Lexer.LINE_COMMENT, DRL10Lexer.IDENTIFIER, DRL10Lexer.TEXT,

DRLLexer.DECIMAL_LITERAL, DRLLexer.HEX_LITERAL,
DRLLexer.OCT_LITERAL, DRLLexer.BINARY_LITERAL, DRLLexer.FLOAT_LITERAL, DRLLexer.HEX_FLOAT_LITERAL,
DRLLexer.BOOL_LITERAL, DRLLexer.CHAR_LITERAL, DRLLexer.STRING_LITERAL, DRLLexer.TEXT_BLOCK,
DRLLexer.NULL_LITERAL, DRLLexer.LPAREN, DRLLexer.RPAREN, DRLLexer.LBRACE, DRLLexer.RBRACE, DRLLexer.LBRACK,
DRLLexer.RBRACK, DRLLexer.SEMI, DRLLexer.COMMA, DRLLexer.DOT, DRLLexer.ASSIGN, DRLLexer.GT, DRLLexer.LT,
DRLLexer.BANG, DRLLexer.TILDE, DRLLexer.QUESTION, DRLLexer.COLON, DRLLexer.EQUAL, DRLLexer.LE, DRLLexer.GE,
DRLLexer.NOTEQUAL, DRLLexer.AND, DRLLexer.OR, DRLLexer.INC, DRLLexer.DEC, DRLLexer.ADD, DRLLexer.SUB, DRLLexer.MUL,
DRLLexer.DIV, DRLLexer.BITAND, DRLLexer.BITOR, DRLLexer.CARET, DRLLexer.MOD, DRLLexer.ADD_ASSIGN, DRLLexer.SUB_ASSIGN,
DRLLexer.MUL_ASSIGN, DRLLexer.DIV_ASSIGN, DRLLexer.AND_ASSIGN, DRLLexer.OR_ASSIGN, DRLLexer.XOR_ASSIGN,
DRLLexer.MOD_ASSIGN, DRLLexer.LSHIFT_ASSIGN, DRLLexer.RSHIFT_ASSIGN, DRLLexer.URSHIFT_ASSIGN,
DRLLexer.ARROW, DRLLexer.COLONCOLON, DRLLexer.AT, DRLLexer.ELLIPSIS, DRLLexer.WS, DRLLexer.COMMENT,
DRLLexer.LINE_COMMENT, DRLLexer.IDENTIFIER, DRLLexer.TEXT, DRLLexer.RHS_CHUNK
DRL10Lexer.RHS_COMMENT, DRL10Lexer.RHS_LINE_COMMENT, DRL10Lexer.RHS_STRING_LITERAL, DRL10Lexer.RHS_NAMED_CONSEQUENCE_THEN, DRL10Lexer.RHS_CHUNK
);
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package org.drools.lsp.server;

import org.drools.completion.DRLCompletionHelper;
import org.drools.drl.ast.descr.PackageDescr;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.TextDocumentService;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

import static org.drools.parser.DRLParserHelper.parse;
import org.drools.completion.DRLCompletionHelper;
import org.drools.drl.parser.antlr4.DRLParserHelper;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.CompletionParams;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
import org.eclipse.lsp4j.DidSaveTextDocumentParams;
import org.eclipse.lsp4j.MessageParams;
import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.TextDocumentService;

public class DroolsLspDocumentService implements TextDocumentService {

Expand Down Expand Up @@ -54,8 +63,7 @@ public void didChange(DidChangeTextDocumentParams params) {

public String getRuleName(CompletionParams completionParams) {
String text = sourcesMap.get(completionParams.getTextDocument().getUri());
PackageDescr packageDescr = parse(text);
return packageDescr.getRules().get(0).getName();
return DRLParserHelper.getFirstRuleName(text);
}

@Override
Expand Down
31 changes: 2 additions & 29 deletions drools-parser/Developer_Notes.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,8 @@
## drools-parser

This module is a reimplementation of the DRL (Drools Rule Language) parser based on ANTLR4.
Parser development has been done on drools main branch, so this module just takes the antlr4 grammar files from drools.

The current [DRL6Parser](https://github.com/apache/incubator-kie-drools/blob/main/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/lang/DRL6Parser.java) is based on ANTLR3 and contains a lot of custom modifications, which is hard to maintain. This new module should keep the separation between the parser syntax (`DRLParser.g4`) and the Descr generation (`DRLVisitorImpl.java`).

This module started with a part of LSP to develop DRL editors, but it is not limited to that. This module will also replace DRL6Parser in the drools code base.

### How is this developed?

1. The starting point is [DRL6Parser](https://github.com/apache/incubator-kie-drools/blob/main/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/lang/DRL6Parser.java). While it contains lots of customizations, we can map its javadoc (e.g. `packageStatement := PACKAGE qualifiedIdentifier SEMICOLON?`) to `DRLParser.g4` (e.g. `packagedef : PACKAGE name=drlQualifiedName SEMI? ;`).
2. `DRLLexer.g4` is written to define tokens for DRL.
3. `DRLLexer.g4` imports `JavaLexer.g4` to reuse Java tokens. `DRLParser.g4` imports `JavaParser.g4` to reuse Java grammar. These Java parser files are distributed by ANTLR4 under BSD license.
4. In `DRLLexer.g4`, basically define tokens with a prefix "DRL_" to clarify they are DRL keywords.
5. In `DRLParser.g4`, define parser rules with a prefix "drl" if the rule name conflicts with `JavaParser.g4`. Sometimes we need to do that, because such a rule may contain DRL keywords.
6. (As of 2023/10/31) this parser doesn't deeply parse rule RHS (just multiple `RHS_CHUNK`s), because Drools passes RHS text to drools-compiler as-is. In case of developing DRL editors, we may need to integrate another Java LSP to support RHS code completion, etc.
7. LHS constraint (e.g. `age > 30`) is also handled as text. Further processing will be done in the later compiler phase.
8. `DRLParser` processes a DRL text and produces an AST(abstract syntax tree). Then apply `DRLVisitorImpl` to generate PackageDescr following the visitor pattern. So the main work would be implementing `DRLParser.g4` and `DRLVisitorImpl`.
9. Errors are handled by `DRLErrorListener`
10. (As of 2023/10/31) We have 2 test classes. `DRLParserTest` is a very basic test to check if the parser can parse DRL. `MiscDRLParserTest` contains various DRL syntax to check if the parser generates correct Descr objects. `MiscDRLParserTest` was ported from [RuleParserTest](https://github.com/apache/incubator-kie-drools/blob/main/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/compiler/lang/RuleParserTest.java) so that we can ensure the compatibility of generated Descr objects between the current implementation and the new one.
11. As `DRL6Parser` contains hard-coded customizations, sometimes we need to read and understand the `DRL6Parser` source codes to meet the compatibility.
12. (As of 2023/10/31) `MiscDRLParserTest` still has several test cases with `@Disabled` which are relatively lower priority or edge cases. They need to be resolved at some point in the future. To fix the issues, file a JIRA, remove the `@Disabled` annotation, and fix the implementation to pass the test case.

### Next steps

1. Create a feature branch in drools repo and replace `DRL6Parser` with this new parser.
2. We will detect issues in the new parser by running the existing tests in drools repo. If we find any issues, we will fix them in the new parser and add new tests to cover them. Such tests would be more or less Descr comparison tests, so we would add a new test class which is similar to `MiscDRLParserTest`.

### Refactoring candidates
- `DRLParserHelper` and `DRLParserWrapper` have some duplicated code and purpose. We can merge them into one class.
- `MiscDRLParserTest` can be cleaner and fixed to align with SonarLint suggestions.
- Constraint related parser rules after `conditionalOrExpression` are written in antlr3 style. They could be refactored to antlr4 style (like `lhsExpression`).
At the moment, the antlr4 grammar files are the same as the ones in drools main branch except for cleaning up unused java codes. In the future, we may need to customize the grammar files and/or add some drools dependencies to support requirements from lsp clients (DRL Editor) .

### Development tips
- IntelliJ IDEA has an ANTLR4 plugin, which "ANTLR Preview" window displays a parse tree. It is very useful to debug the parser rules.
Expand Down
14 changes: 2 additions & 12 deletions drools-parser/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,6 @@
<name>Drools :: Parser</name>

<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-drl-ast</artifactId>
<version>${version.drools-drl-ast}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-util</artifactId>
<version>${version.drools-drl-ast}</version>
</dependency>

<!-- External dependencies -->
<dependency>
Expand Down Expand Up @@ -84,9 +74,9 @@
<goal>antlr4</goal>
</goals>
<configuration>
<visitor>true</visitor>
<visitor>false</visitor>
<listener>false</listener>
<libDirectory>src/main/antlr4/org/drools/parser/</libDirectory>
<libDirectory>src/main/antlr4/org/drools/drl/parser/antlr4</libDirectory>
</configuration>
</execution>
</executions>
Expand Down
Loading
0