This is an automated email from the ASF dual-hosted git repository.
tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
The following commit(s) were added to refs/heads/main by this push:
new 481e9a64d25 kie-issues#1185: In the Filter expression the reserved
Item variable should only be available in the last row (#2334)
481e9a64d25 is described below
commit 481e9a64d251e174714e565b877dae2167e3d1c7
Author: Daniel José dos Santos <[email protected]>
AuthorDate: Thu May 16 10:48:51 2024 -0300
kie-issues#1185: In the Filter expression the reserved Item variable should
only be available in the last row (#2334)
---
.../src/parser/FeelSyntacticSymbolNature.ts | 6 ++
.../src/parser/FeelVariablesParser.ts | 12 +++-
.../src/parser/VariablesRepository.ts | 11 ++--
packages/feel-input-component/src/FeelInput.tsx | 66 +++++++++++++++++++---
4 files changed, 77 insertions(+), 18 deletions(-)
diff --git
a/packages/dmn-feel-antlr4-parser/src/parser/FeelSyntacticSymbolNature.ts
b/packages/dmn-feel-antlr4-parser/src/parser/FeelSyntacticSymbolNature.ts
index 108b5443484..3ff35d3177e 100644
--- a/packages/dmn-feel-antlr4-parser/src/parser/FeelSyntacticSymbolNature.ts
+++ b/packages/dmn-feel-antlr4-parser/src/parser/FeelSyntacticSymbolNature.ts
@@ -47,4 +47,10 @@ export enum FeelSyntacticSymbolNature {
* Variables which the parser currently doesn't know if it is valid or not
because they are validated at runtime.
*/
DynamicVariable,
+
+ /**
+ * Invisible variables are variables used only for the tree structure
purpose of the VariablesRepository
+ * and are not available to the user.
+ */
+ InvisibleVariables,
}
diff --git a/packages/dmn-feel-antlr4-parser/src/parser/FeelVariablesParser.ts
b/packages/dmn-feel-antlr4-parser/src/parser/FeelVariablesParser.ts
index 78956e65279..7fc3ff11997 100644
--- a/packages/dmn-feel-antlr4-parser/src/parser/FeelVariablesParser.ts
+++ b/packages/dmn-feel-antlr4-parser/src/parser/FeelVariablesParser.ts
@@ -27,6 +27,7 @@ import { FeelVariable } from "./FeelVariable";
import { MapBackedType } from "./grammar/MapBackedType";
import { VariableContext } from "./VariableContext";
import { ParsedExpression } from "./ParsedExpression";
+import { FeelSyntacticSymbolNature } from "./FeelSyntacticSymbolNature";
export class FeelVariablesParser {
private variablesRepository: VariablesRepository;
@@ -121,13 +122,18 @@ export class FeelVariablesParser {
for (const inputVariableId of inputVariables) {
const inputVariable =
this.variablesRepository.variables.get(inputVariableId);
if (inputVariable) {
- this.addToParser(parser, inputVariable);
+ this.addToParser(parser, inputVariable, true);
}
}
}
- private addToParser(parser: FEEL_1_1Parser, context: VariableContext) {
- if (context.variable.value !== "") {
+ private addToParser(parser: FEEL_1_1Parser, context: VariableContext,
addInvisibleVariables?: boolean) {
+ if (
+ context.variable.value !== "" &&
+ ((!addInvisibleVariables &&
+ context.variable.feelSyntacticSymbolNature !=
FeelSyntacticSymbolNature.InvisibleVariables) ||
+ addInvisibleVariables)
+ ) {
parser.helper.defineVariable(
context.variable.value,
context.variable.typeRef ? this.createType(context.variable.typeRef) :
undefined,
diff --git a/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts
b/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts
index c34686d3c64..421834fa89a 100644
--- a/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts
+++ b/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts
@@ -258,7 +258,7 @@ export class VariablesRepository {
const parent = this.addVariable(
drg["@_id"] ?? "",
drg["@_name"],
- FeelSyntacticSymbolNature.GlobalVariable,
+ FeelSyntacticSymbolNature.InvisibleVariables,
undefined,
drg.variable?.["@_typeRef"]
);
@@ -514,7 +514,7 @@ export class VariablesRepository {
if (expression.in.expression) {
type = expression.in.expression["@_typeRef"];
}
- const localParent = this.addVariable(
+ return this.addVariable(
expression["@_id"] ?? "",
"item",
FeelSyntacticSymbolNature.LocalVariable,
@@ -522,8 +522,6 @@ export class VariablesRepository {
type,
true
);
-
- return localParent;
}
private addIteratorVariable(parent: VariableContext, expression: DmnFor |
DmnEvery | DmnSome) {
@@ -549,10 +547,11 @@ export class VariablesRepository {
}
private addFilter(parent: VariableContext, expression: DmnFilter) {
- const localParent = this.addFilterVariable(parent, expression);
if (expression.in.expression) {
- this.addInnerExpression(localParent, expression.in.expression);
+ this.addInnerExpression(parent, expression.in.expression);
}
+
+ const localParent = this.addFilterVariable(parent, expression);
if (expression.match.expression) {
this.addInnerExpression(localParent, expression.match.expression);
}
diff --git a/packages/feel-input-component/src/FeelInput.tsx
b/packages/feel-input-component/src/FeelInput.tsx
index ef75e673fec..9d5bc5e3631 100644
--- a/packages/feel-input-component/src/FeelInput.tsx
+++ b/packages/feel-input-component/src/FeelInput.tsx
@@ -136,6 +136,15 @@ export const FeelInput = React.forwardRef<FeelInputRef,
FeelInputProps>(
return lastValidSymbol;
}, []);
+ const getSymbolAtPosition = useCallback((currentParsedExpression:
ParsedExpression, position: number) => {
+ for (const feelVariable of currentParsedExpression.feelVariables) {
+ if (feelVariable.startIndex < position && position <=
feelVariable.startIndex + feelVariable.length) {
+ return feelVariable;
+ }
+ }
+ return undefined;
+ }, []);
+
const getDefaultCompletionItems = useCallback(
(
suggestionProvider:
@@ -173,7 +182,7 @@ export const FeelInput = React.forwardRef<FeelInputRef,
FeelInputProps>(
const completionItemProvider = useCallback(() => {
return {
- triggerCharacters: [" ", EXPRESSION_PROPERTIES_SEPARATOR],
+ triggerCharacters: [EXPRESSION_PROPERTIES_SEPARATOR],
provideCompletionItems: (model: Monaco.editor.ITextModel, position:
Monaco.Position) => {
const completionItems =
getDefaultCompletionItems(suggestionProvider, model, position);
const variablesSuggestions = new
Array<Monaco.languages.CompletionItem>();
@@ -183,11 +192,12 @@ export const FeelInput = React.forwardRef<FeelInputRef,
FeelInputProps>(
const expression = model.getValue();
const currentChar = expression.charAt(pos - 1);
- if (currentChar === EXPRESSION_PROPERTIES_SEPARATOR) {
+ if (currentChar === EXPRESSION_PROPERTIES_SEPARATOR || currentChar
=== " ") {
pos--;
}
const lastValidSymbol =
getLastValidSymbolAtPosition(currentParsedExpression, pos);
+
if (
lastValidSymbol &&
lastValidSymbol.feelSymbolNature !==
FeelSyntacticSymbolNature.Unknown &&
@@ -199,16 +209,48 @@ export const FeelInput = React.forwardRef<FeelInputRef,
FeelInputProps>(
label: scopeSymbol.name,
insertText: scopeSymbol.name,
detail: scopeSymbol.type,
+ range: {
+ startLineNumber: lastValidSymbol.startLine + 1,
+ endLineNumber: lastValidSymbol.endLine + 1,
+ startColumn: lastValidSymbol.startIndex +
lastValidSymbol.length + 2, // It is +2 because of the . (dot)
+ endColumn: lastValidSymbol.startIndex +
lastValidSymbol.length + 2 + scopeSymbol.name.length,
+ },
} as Monaco.languages.CompletionItem);
}
} else {
+ const currentSymbol =
getSymbolAtPosition(currentParsedExpression, pos);
for (const scopeSymbol of
currentParsedExpression.availableSymbols) {
- variablesSuggestions.push({
- kind: Monaco.languages.CompletionItemKind.Variable,
- label: scopeSymbol.name,
- insertText: scopeSymbol.name,
- detail: scopeSymbol.type,
- } as Monaco.languages.CompletionItem);
+ // Consider this scenario:
+ // 1. User typed: Tax In
+ // 2. Available symbols: [Tax Incoming, Tax Input, Tax
InSomethingElse, Tax Out, Tax Output]
+ // 3. "Tax In" is an invalid symbol (unrecognized symbol)
+ // In this case, we want to show all symbols that starts with
"Tax In"
+ if (currentSymbol &&
scopeSymbol.name.startsWith(currentSymbol.text)) {
+ variablesSuggestions.push({
+ kind: Monaco.languages.CompletionItemKind.Variable,
+ label: scopeSymbol.name,
+ insertText: scopeSymbol.name,
+ detail: scopeSymbol.type,
+ sortText: "1", // We want the variables to be at top of
autocomplete
+ // We want to replace the current symbol with the
available scopeSymbol (Tax Incoming, for example)
+ // Note: Monaco is NOT zero-indexed. It starts with 1 but
FEEL parser is zero indexed,
+ // that's why were incrementing 1 at each position.
+ range: {
+ startLineNumber: currentSymbol.startLine + 1,
+ endLineNumber: currentSymbol.endLine + 1,
+ startColumn: currentSymbol.startIndex + 1,
+ endColumn: currentSymbol.startIndex + 1 +
scopeSymbol.name.length,
+ },
+ } as Monaco.languages.CompletionItem);
+ } else {
+ variablesSuggestions.push({
+ kind: Monaco.languages.CompletionItemKind.Variable,
+ label: scopeSymbol.name,
+ insertText: scopeSymbol.name,
+ detail: scopeSymbol.type,
+ sortText: "2", // The others variables at second level
+ } as Monaco.languages.CompletionItem);
+ }
}
variablesSuggestions.push(...completionItems);
@@ -222,7 +264,13 @@ export const FeelInput = React.forwardRef<FeelInputRef,
FeelInputProps>(
};
},
};
- }, [currentParsedExpression, getDefaultCompletionItems,
getLastValidSymbolAtPosition, suggestionProvider]);
+ }, [
+ currentParsedExpression,
+ getDefaultCompletionItems,
+ getLastValidSymbolAtPosition,
+ getSymbolAtPosition,
+ suggestionProvider,
+ ]);
useEffect(() => {
if (!enabled) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]