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]

Reply via email to