You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by "danielzhe (via GitHub)" <gi...@apache.org> on 2024/07/26 21:30:45 UTC
[PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
danielzhe opened a new pull request, #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490
Closes: https://github.com/apache/incubator-kie-issues/issues/1178
I found another edge case that is also fixed in this PR:

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.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#issuecomment-2256828706
@tiagobento Changes applied! Now the test is testing all the stack, from `feel-input-component` to the `dmn-feel-antlr4-parser`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "tiagobento (via GitHub)" <gi...@apache.org>.
tiagobento commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1695593263
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
Review Comment:
Pls import it from `@kie-tools/dmn-feel-antlr4-parser/dist/semanticTokensProvider` instead of from `src`
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
+import {
+ FeelSyntacticSymbolNature,
+ FeelVariable,
+ FeelVariables,
+ FeelVariablesParser,
+} from "@kie-tools/dmn-feel-antlr4-parser";
+
+import * as Monaco from "@kie-tools-core/monaco-editor";
+
+describe("Semantic Tokens Provider", () => {
+ 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(),
+ };
Review Comment:
Could we use the actual implementations? Doing so would make this test easier to read and remove the `parsedTokens` parameter need, no?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#issuecomment-2254774418
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
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#issuecomment-2253534528
P.S.: we NEED to add test coverage to this feature asap.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1693627636
##########
packages/feel-input-component/src/FeelInput.tsx:
##########
@@ -299,57 +299,92 @@ export const FeelInput = React.forwardRef<FeelInputRef, FeelInputProps>(
if (feelVariables) {
const text = model.getValue();
const contentByLines = model.getLinesContent();
- let startOfPreviousToken = 0;
+ let startOfPreviousVariable = 0;
Review Comment:
This change was to make the variable name more precise.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#issuecomment-2254661704
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
https://github.com/user-attachments/assets/147e966f-0c05-4680-a5dd-6aa90857a8bd
*The fix has not been pushed in the PR yet, it will come with the new unity tests.*
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#issuecomment-2257304340
@tiagobento New tests integrated!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "ljmotta (via GitHub)" <gi...@apache.org>.
ljmotta commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1697143218
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
+import { FeelVariables, DmnDefinitions } from "@kie-tools/dmn-feel-antlr4-parser";
+
+import * as Monaco from "@kie-tools-core/monaco-editor";
+
+describe("Semantic Tokens Provider", () => {
+ 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([
+ {
+ expression:
+ 'This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight + "bar"',
+ expected: [[0, 0, 102, 5, 0]],
+ },
+ {
+ expression: `This is a variable with a very long
+name to reproduce the issue thousand
+one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 36, 5, 0],
+ [1, 0, 37, 5, 0],
+ [1, 0, 29, 5, 0],
+ ],
+ },
+ {
+ expression: `"aaaaaa" +
+This is a variable with a very
+long name to
+ reproduce the issue thousand
+ one hundred and seventy-eight + "bar" + "NICE" + This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight`,
+ expected: [
+ [1, 0, 31, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 30, 5, 0],
+ [1, 0, 30, 5, 0],
+ [0, 50, 102, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce
+the issue
+thousand
+one hundred
+and
+seventy-eight + "bar`,
+ expected: [
+ [0, 0, 44, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 9, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 4, 5, 0],
+ [1, 0, 13, 5, 0],
+ ],
+ },
+ {
+ expression: `"My " + This is a variable with a very long name to reproduce
+ the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 8, 89, 5, 0],
+ [1, 0, 104, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 43, 5, 0],
+ [1, 0, 58, 5, 0],
+ ],
+ },
+ {
+ expression: `VeryLongVariableWithoutSpaces
+ThatShouldFailWhenBreakLine`,
+ expected: [
+ [0, 0, 29, 7, 0],
+ [1, 0, 27, 7, 0],
+ ],
+ },
+ ])("multiline variables", async ({ expression, expected }) => {
+ const modelMock = {
+ getValue: jest.fn().mockReturnValue(expression),
+ getLinesContent: jest.fn().mockReturnValue(expression.split("\n")),
+ };
+
+ const id = "expressionId";
+ const dmnDefinitions = getDmnModel({ knownVariable: knownVariable, expressionId: id, expression: expression });
+
+ const feelVariables = new FeelVariables(dmnDefinitions, new Map());
+ const semanticTokensProvider = new SemanticTokensProvider(feelVariables, id, () => {});
+
+ const semanticMonacoTokens = await semanticTokensProvider.provideDocumentSemanticTokens(
+ modelMock as unknown as Monaco.editor.ITextModel,
+ null,
+ cancellationTokenMock
+ );
+
+ const expectedSemanticMonacoTokens = expected.reduce((accumulator, value) => accumulator.concat(value), []);
+
+ for (let i = 0; i < expectedSemanticMonacoTokens.length; i++) {
+ expect(semanticMonacoTokens?.data[i]).toEqual(expectedSemanticMonacoTokens[i]);
+ }
+ });
+});
+
+function getDmnModel({
+ knownVariable,
+ expressionId,
+ expression,
+}: {
+ knownVariable: string;
+ expressionId: string;
+ expression: string;
+}) {
Review Comment:
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,
}
});
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1695812370
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
Review Comment:
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. 😄
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "tiagobento (via GitHub)" <gi...@apache.org>.
tiagobento commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1695995019
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
Review Comment:
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`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#issuecomment-2260496735
@tiagobento Ready to merge.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1697079681
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
+import { FeelVariables, DmnDefinitions } from "@kie-tools/dmn-feel-antlr4-parser";
+
+import * as Monaco from "@kie-tools-core/monaco-editor";
+
+describe("Semantic Tokens Provider", () => {
+ 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([
Review Comment:
Makes sense!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "tiagobento (via GitHub)" <gi...@apache.org>.
tiagobento merged PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "ljmotta (via GitHub)" <gi...@apache.org>.
ljmotta commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1696728113
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
+import { FeelVariables, DmnDefinitions } from "@kie-tools/dmn-feel-antlr4-parser";
+
+import * as Monaco from "@kie-tools-core/monaco-editor";
+
+describe("Semantic Tokens Provider", () => {
+ 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([
+ {
+ expression:
+ 'This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight + "bar"',
+ expected: [[0, 0, 102, 5, 0]],
+ },
+ {
+ expression: `This is a variable with a very long
+name to reproduce the issue thousand
+one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 36, 5, 0],
+ [1, 0, 37, 5, 0],
+ [1, 0, 29, 5, 0],
+ ],
+ },
+ {
+ expression: `"aaaaaa" +
+This is a variable with a very
+long name to
+ reproduce the issue thousand
+ one hundred and seventy-eight + "bar" + "NICE" + This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight`,
+ expected: [
+ [1, 0, 31, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 30, 5, 0],
+ [1, 0, 30, 5, 0],
+ [0, 50, 102, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce
+the issue
+thousand
+one hundred
+and
+seventy-eight + "bar`,
+ expected: [
+ [0, 0, 44, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 9, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 4, 5, 0],
+ [1, 0, 13, 5, 0],
+ ],
+ },
+ {
+ expression: `"My " + This is a variable with a very long name to reproduce
+ the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 8, 89, 5, 0],
+ [1, 0, 104, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 43, 5, 0],
+ [1, 0, 58, 5, 0],
+ ],
+ },
+ {
+ expression: `VeryLongVariableWithoutSpaces
+ThatShouldFailWhenBreakLine`,
+ expected: [
+ [0, 0, 29, 7, 0],
+ [1, 0, 27, 7, 0],
+ ],
+ },
+ ])("multiline variables", async ({ expression, expected }) => {
+ const modelMock = {
+ getValue: jest.fn().mockReturnValue(expression),
+ getLinesContent: jest.fn().mockReturnValue(expression.split("\n")),
+ };
+
+ const id = "expressionId";
+ const dmnDefinitions = getDmnModel({ knownVariable: knownVariable, expressionId: id, expression: expression });
+
+ const feelVariables = new FeelVariables(dmnDefinitions, new Map());
+ const semanticTokensProvider = new SemanticTokensProvider(feelVariables, id, () => {});
+
+ const semanticMonacoTokens = await semanticTokensProvider.provideDocumentSemanticTokens(
+ modelMock as unknown as Monaco.editor.ITextModel,
+ null,
+ cancellationTokenMock
+ );
+
+ const expectedSemanticMonacoTokens = expected.reduce((accumulator, value) => accumulator.concat(value), []);
+
+ for (let i = 0; i < expectedSemanticMonacoTokens.length; i++) {
+ expect(semanticMonacoTokens?.data[i]).toEqual(expectedSemanticMonacoTokens[i]);
+ }
+ });
+});
+
+function getDmnModel({
+ knownVariable,
+ expressionId,
+ expression,
+}: {
+ knownVariable: string;
+ expressionId: string;
+ expression: string;
+}) {
Review Comment:
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.
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
+import { FeelVariables, DmnDefinitions } from "@kie-tools/dmn-feel-antlr4-parser";
+
+import * as Monaco from "@kie-tools-core/monaco-editor";
+
+describe("Semantic Tokens Provider", () => {
+ 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([
Review Comment:
Maybe this and tests should be inside another test.describe block? I mean, the variable is specific to a very long variable name.
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
+import { FeelVariables, DmnDefinitions } from "@kie-tools/dmn-feel-antlr4-parser";
+
+import * as Monaco from "@kie-tools-core/monaco-editor";
+
+describe("Semantic Tokens Provider", () => {
+ 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([
+ {
+ expression:
+ 'This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight + "bar"',
+ expected: [[0, 0, 102, 5, 0]],
+ },
+ {
+ expression: `This is a variable with a very long
+name to reproduce the issue thousand
+one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 36, 5, 0],
+ [1, 0, 37, 5, 0],
+ [1, 0, 29, 5, 0],
+ ],
+ },
+ {
+ expression: `"aaaaaa" +
+This is a variable with a very
+long name to
+ reproduce the issue thousand
+ one hundred and seventy-eight + "bar" + "NICE" + This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight`,
+ expected: [
+ [1, 0, 31, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 30, 5, 0],
+ [1, 0, 30, 5, 0],
+ [0, 50, 102, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce
+the issue
+thousand
+one hundred
+and
+seventy-eight + "bar`,
+ expected: [
+ [0, 0, 44, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 9, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 4, 5, 0],
+ [1, 0, 13, 5, 0],
+ ],
+ },
+ {
+ expression: `"My " + This is a variable with a very long name to reproduce
+ the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 8, 89, 5, 0],
+ [1, 0, 104, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 43, 5, 0],
+ [1, 0, 58, 5, 0],
+ ],
+ },
+ {
+ expression: `VeryLongVariableWithoutSpaces
+ThatShouldFailWhenBreakLine`,
+ expected: [
+ [0, 0, 29, 7, 0],
+ [1, 0, 27, 7, 0],
+ ],
+ },
+ ])("multiline variables", async ({ expression, expected }) => {
+ const modelMock = {
+ getValue: jest.fn().mockReturnValue(expression),
+ getLinesContent: jest.fn().mockReturnValue(expression.split("\n")),
+ };
+
+ const id = "expressionId";
+ const dmnDefinitions = getDmnModel({ knownVariable: knownVariable, expressionId: id, expression: expression });
+
+ const feelVariables = new FeelVariables(dmnDefinitions, new Map());
+ const semanticTokensProvider = new SemanticTokensProvider(feelVariables, id, () => {});
+
+ const semanticMonacoTokens = await semanticTokensProvider.provideDocumentSemanticTokens(
+ modelMock as unknown as Monaco.editor.ITextModel,
+ null,
+ cancellationTokenMock
+ );
+
+ const expectedSemanticMonacoTokens = expected.reduce((accumulator, value) => accumulator.concat(value), []);
Review Comment:
You could use `expected.flat()` to archieve the same behavior.
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
Review Comment:
Shouldn't it be an Apache header?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1696959628
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
Review Comment:
ouch
I did a copy-paste. Nice catch.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#1178: On the DMN Editor's Boxed Expression Editor, FEEL identifiers with spaces should be treated as non-breaking spaces. [incubator-kie-tools]
Posted by "danielzhe (via GitHub)" <gi...@apache.org>.
danielzhe commented on code in PR #2490:
URL: https://github.com/apache/incubator-kie-tools/pull/2490#discussion_r1697093156
##########
packages/feel-input-component/tests/semanticTokensProvider.test.ts:
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+import { SemanticTokensProvider } from "../src/semanticTokensProvider";
+import { FeelVariables, DmnDefinitions } from "@kie-tools/dmn-feel-antlr4-parser";
+
+import * as Monaco from "@kie-tools-core/monaco-editor";
+
+describe("Semantic Tokens Provider", () => {
+ 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([
+ {
+ expression:
+ 'This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight + "bar"',
+ expected: [[0, 0, 102, 5, 0]],
+ },
+ {
+ expression: `This is a variable with a very long
+name to reproduce the issue thousand
+one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 36, 5, 0],
+ [1, 0, 37, 5, 0],
+ [1, 0, 29, 5, 0],
+ ],
+ },
+ {
+ expression: `"aaaaaa" +
+This is a variable with a very
+long name to
+ reproduce the issue thousand
+ one hundred and seventy-eight + "bar" + "NICE" + This is a variable with a very long name to reproduce the issue thousand one hundred and seventy-eight`,
+ expected: [
+ [1, 0, 31, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 30, 5, 0],
+ [1, 0, 30, 5, 0],
+ [0, 50, 102, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce
+the issue
+thousand
+one hundred
+and
+seventy-eight + "bar`,
+ expected: [
+ [0, 0, 44, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 10, 5, 0],
+ [1, 0, 9, 5, 0],
+ [1, 0, 12, 5, 0],
+ [1, 0, 4, 5, 0],
+ [1, 0, 13, 5, 0],
+ ],
+ },
+ {
+ expression: `"My " + This is a variable with a very long name to reproduce
+ the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 8, 89, 5, 0],
+ [1, 0, 104, 5, 0],
+ ],
+ },
+ {
+ expression: `This is a variable with a very long name to
+reproduce the issue thousand one hundred and seventy-eight + "bar"`,
+ expected: [
+ [0, 0, 43, 5, 0],
+ [1, 0, 58, 5, 0],
+ ],
+ },
+ {
+ expression: `VeryLongVariableWithoutSpaces
+ThatShouldFailWhenBreakLine`,
+ expected: [
+ [0, 0, 29, 7, 0],
+ [1, 0, 27, 7, 0],
+ ],
+ },
+ ])("multiline variables", async ({ expression, expected }) => {
+ const modelMock = {
+ getValue: jest.fn().mockReturnValue(expression),
+ getLinesContent: jest.fn().mockReturnValue(expression.split("\n")),
+ };
+
+ const id = "expressionId";
+ const dmnDefinitions = getDmnModel({ knownVariable: knownVariable, expressionId: id, expression: expression });
+
+ const feelVariables = new FeelVariables(dmnDefinitions, new Map());
+ const semanticTokensProvider = new SemanticTokensProvider(feelVariables, id, () => {});
+
+ const semanticMonacoTokens = await semanticTokensProvider.provideDocumentSemanticTokens(
+ modelMock as unknown as Monaco.editor.ITextModel,
+ null,
+ cancellationTokenMock
+ );
+
+ const expectedSemanticMonacoTokens = expected.reduce((accumulator, value) => accumulator.concat(value), []);
+
+ for (let i = 0; i < expectedSemanticMonacoTokens.length; i++) {
+ expect(semanticMonacoTokens?.data[i]).toEqual(expectedSemanticMonacoTokens[i]);
+ }
+ });
+});
+
+function getDmnModel({
+ knownVariable,
+ expressionId,
+ expression,
+}: {
+ knownVariable: string;
+ expressionId: string;
+ expression: string;
+}) {
Review Comment:
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: https://github.com/microsoft/TypeScript/issues/241
We've been using this pattern in BEE, like [here](https://github.com/apache/incubator-kie-tools/blob/50fdffba48bf923c87274d242aebcbb01dd31eba/packages/boxed-expression-component/src/expressions/DecisionTableExpression/DecisionTableExpression.tsx#L508), for example.
I'll add the comment to make clear why it wasn't inlined.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org