Skip to content

kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces.#2490

Merged
tiagobento merged 7 commits intoapache:mainfrom
danielzhe:feel-spaces
Jul 31, 2024
Merged

kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces.#2490
tiagobento merged 7 commits intoapache:mainfrom
danielzhe:feel-spaces

Conversation

@danielzhe
Copy link
Copy Markdown
Contributor

@danielzhe danielzhe commented Jul 26, 2024

Closes: apache/incubator-kie-issues#1178

I found another edge case that is also fixed in this PR:
image

The other cases fixed are shown in the video below:
https://github.com/user-attachments/assets/608920b8-35c7-4724-9134-f61fe3a732b7

I also added more comments to the code, to make it easier to understand what is happening.

Sorry for the Portuguese in the pictures. Consider it as random chars to test the issues.

UPDATE: I'm attaching a file that shows the issues fixed if someone wants to use it to test it. About the other issue, reported in this comment here, you can test it with the "Loan Pre Qualification" example in Storybook or Online editor.
kie1178-english.dmn.txt

…entifiers with spaces should be treated as non-breaking spaces.
@danielzhe danielzhe requested a review from tiagobento as a code owner July 26, 2024 21:30
@danielzhe
Copy link
Copy Markdown
Contributor Author

P.S.: we NEED to add test coverage to this feature asap.

@danielzhe danielzhe requested a review from ljmotta July 26, 2024 21:31
const text = model.getValue();
const contentByLines = model.getLinesContent();
let startOfPreviousToken = 0;
let startOfPreviousVariable = 0;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change was to make the variable name more precise.

@danielzhe
Copy link
Copy Markdown
Contributor Author

I found a new issue, which will also be fixed with this PR, regarding line breaks. This issue happens only in some browsers and is related to the line ending (if it is *nix or Windows style). See in the video below a comparison between the broken behavior and the new one, @tiagobento

new.bug.mp4

The fix has not been pushed in the PR yet, it will come with the new unity tests.

@danielzhe
Copy link
Copy Markdown
Contributor Author

Changes applied! The issue about breaking lines, reported in the video above, it is also fixed.
I had to do some refactoring to make it easier to test and to organize the code. I'm testing only the SemanticTokensProvider that is what "translates" the parser result to the Monaco.

Let me know if the Jest tests are ok with our standards. I didn't found any case similar to this one in our codebase to compare. @tiagobento @ljmotta

Copy link
Copy Markdown
Contributor

@tiagobento tiagobento left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danielzhe Thanks! Love the comments and the changes you did. I'm a little extra picky when it comes to mocking, as I think we should only mock when absolutely necessary. If we could use the actual implementations instead it would be preferable! Thanks!

* limitations under the License.
*/

import { SemanticTokensProvider } from "../src/semanticTokensProvider";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls import it from @kie-tools/dmn-feel-antlr4-parser/dist/semanticTokensProvider instead of from src

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But semanticTokensProvider is in this project, it is not from the parser. It is inside the feel-input-component, where this test is. Its work is to provide the semantic tokens to Monaco using what the parser dmn-feel-antlr4-parser did. 😄

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, right. You can import it from itself then, to simulate usage as a 3rd party and avoid having to recompile the src code when executing tests, as tests run after compilation. You should be able to do @kie-tools/feel-input-component/dist/semanticTokensProvider

Comment on lines +28 to +40
const tokensFoundByParser: FeelVariable[] = [];
const mockedParser = FeelVariablesParser as jest.Mocked<typeof FeelVariablesParser>;
jest
.spyOn(mockedParser.prototype, "parse")
.mockReturnValue({ availableSymbols: [], feelVariables: tokensFoundByParser });

const mockedFeelVariables: jest.Mocked<typeof FeelVariables> = FeelVariables as jest.Mocked<typeof FeelVariables>;
jest.spyOn(mockedFeelVariables.prototype, "parser", "get").mockReturnValue(mockedParser.prototype);

const cancellationTokenMock = {
isCancellationRequested: false,
onCancellationRequested: jest.fn().mockImplementation(),
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use the actual implementations? Doing so would make this test easier to read and remove the parsedTokens parameter need, no?

@danielzhe
Copy link
Copy Markdown
Contributor Author

@tiagobento Changes applied! Now the test is testing all the stack, from feel-input-component to the dmn-feel-antlr4-parser.

Copy link
Copy Markdown
Contributor

@tiagobento tiagobento left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Please also integrate these new tests with the build:prod command... As they're currently not https://github.com/danielzhe/kie-tools/blob/feel-spaces/packages/feel-input-component/package.json

You can do

    "test": "rimraf dist-tests && run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"jest --silent --verbose --passWithNoTests\""

and add a && pnpm test at the end of the build:prod script.

@danielzhe
Copy link
Copy Markdown
Contributor Author

@tiagobento New tests integrated!

Copy link
Copy Markdown
Contributor

@ljmotta ljmotta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danielzhe I've made my review inline. The Apache header is the only comment that should be addressed, the others are optional as they're some observations regarding the test code.

Comment on lines +1 to +15
/*
* Copyright 2024 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.
* You may obtain a copy of the License at
*
* 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.
*/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be an Apache header?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ouch
I did a copy-paste. Nice catch.

Comment on lines +23 to +42
const cancellationTokenMock = {
isCancellationRequested: false,
onCancellationRequested: jest.fn().mockImplementation(),
};

const knownVariable =
"This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight";

/**
* The 'parsedTokens' are the tokens that parser should found in the provided 'expression'.
* The 'expected' are the Monaco Semantic Tokens that we are expecting to pass to Monaco to paint it on the screen.
*
* Each Monaco Semantic Tokens is an array of 5 positions
* 0 = The start line of the token RELATIVE TO THE PREVIOUS LINE
* 1 = The start index of the token relative to the START of the previous token
* 2 = The length of the token
* 3 = The type of the token (GlobalVariable, Unknown, Function Parameter, etc.). It determines the color of the token
* 4 = Token modifier. It's always zero since we don't have this feature.
*/
test.each([
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this and tests should be inside another test.describe block? I mean, the variable is specific to a very long variable name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense!

Comment on lines +140 to +148
function getDmnModel({
knownVariable,
expressionId,
expression,
}: {
knownVariable: string;
expressionId: string;
expression: string;
}) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I don't think the name and signature tells what this function do. It will get a DMN model with a context expression with one known entry (variable + expression). Also, you could add the return type to the function removing the necessity of creating a varible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any suggestions for the name? For us, it doesn't really matter what is inside the DMN Model, since we just need a model with a setup to test the expression.

Also, about the inline, I didn't because of this: microsoft/TypeScript#241

We've been using this pattern in BEE, like here, for example.

I'll add the comment to make clear why it wasn't inlined.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't know about this. Thanks for sharing! Regarding the name, just a few ideas:

getDmnModelWithContextExpression
getDmnModelWithContextEntry
generateDmnModelWithContextEntry

And some assignature examples:

getDmnModelWithContextEntry({
  entry: {
    variable: string,
    expression: {
      value: string,
      id: string
    }
  }
});
getDmnModelWithContextEntry({
  entry: {
    variable: string,
    expression: string,
    expressionId: string,
  }
});

cancellationTokenMock
);

const expectedSemanticMonacoTokens = expected.reduce((accumulator, value) => accumulator.concat(value), []);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use expected.flat() to archieve the same behavior.

@danielzhe
Copy link
Copy Markdown
Contributor Author

@tiagobento Ready to merge.

@tiagobento tiagobento merged commit eb0045d into apache:main Jul 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces.

3 participants