Skip to content

Commit

Permalink
KOGITO-7367: [SWF Editor] Investigate on different ways to search a n…
Browse files Browse the repository at this point in the history
…ode name in TextEditor (#33)

* SwfOffsetsApi and SwfJsonOffsets implementations

* Fixed test offsets after json inputs linted

* Add yaml test files

* Add SwfYamlOffsets and make test more readable

* Call SwfJsonOffsets from TextEditor

* Removed temporary fix of editor.content

* Adapted and tested textEditor with yaml

* Moved the logic to the SwfTextEditorController and cached the offsets to avoid recalcs

* Use SwfOffsetsApi in vscode extension

* Check SwfOffsetsApi found an offset

* Moved offsets caching logic to SwfOffsetsApi for performance
improvements

* Code review

* Fixed import

* Fixes comment: https://github.com/caponetto/kie-tools/pull/33#discussion_r902625512
https://github.com/caponetto/kie-tools/pull/33#discussion_r902626199
https://github.com/caponetto/kie-tools/pull/33#discussion_r902626495

* Fixes comment: https://github.com/caponetto/kie-tools/pull/33#discussion_r902933312
https://github.com/caponetto/kie-tools/pull/33#discussion_r902956817

* Fixes comment: https://github.com/caponetto/kie-tools/pull/33#discussion_r902952369

* Closes #discussion_r903696115
  • Loading branch information
fantonangeli authored Jun 22, 2022
1 parent eff856f commit 3751f2f
Show file tree
Hide file tree
Showing 20 changed files with 1,193 additions and 170 deletions.
6 changes: 5 additions & 1 deletion packages/serverless-workflow-language-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
"build:prod": "pnpm lint && rimraf dist && tsc -p tsconfig.prod.json && pnpm test"
},
"dependencies": {
"@kie-tools/serverless-workflow-service-catalog": "0.0.0"
"@kie-tools/serverless-workflow-service-catalog": "0.0.0",
"json-to-ast": "^2.1.0",
"jsonata": "^1.8.3",
"yaml-language-server-parser": "^0.1.3"
},
"devDependencies": {
"@kie-tools/build-env": "0.0.0",
"@kie-tools-core/run-script-if": "0.0.0",
"vscode-languageserver-types": "^3.16.0",
"@types/json-to-ast": "^2.1.2",
"jsonc-parser": "^3.0.0",
"vscode-languageserver-textdocument": "^1.0.4",
"vscode-json-languageservice": "^4.2.1"
Expand Down
133 changes: 133 additions & 0 deletions packages/serverless-workflow-language-service/src/api/SwfOffsetsApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright 2022 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 * as jsonata from "jsonata";

export type StateBlockOffset = {
start: number;
end: number;
};

export type StateOffsets = {
stateNameOffset: number;
offset: StateBlockOffset;
};

export type StatesOffsets = {
[key: string]: StateOffsets;
};

/**
* type for the object with the coordinates of the full document
*/
export type FullTextOffsets = {
states: StatesOffsets;
};

/**
* Api to work with offsets
*/
export abstract class SwfOffsetsApi {
protected fullText: string;
protected fullTextOffsets: FullTextOffsets | undefined;

constructor(protected astTransformQuery: string, public documentUri = "") {}

/**
* Parses the content of a file
*
* @param fullText -
* @returns this for chaining
*/
parseContent(fullText: string): SwfOffsetsApi {
if (!fullText) {
this.fullText = "";
this.fullTextOffsets = undefined;
return this;
}

if (this.fullText === fullText) {
return this;
}

this.fullText = fullText;
this.fullTextOffsets = this.getAllOffsets();

return this;
}

/**
* Get the full AST object from the fullText
*/
abstract getFullAST(): any;

/**
* Get All Offsets for easy access.
*
* @returns the resulting FullTextOffsets
*/
getAllOffsets(): FullTextOffsets {
if (!this.fullText) {
return { states: {} };
}

const fullAST = this.getFullAST();

if (!fullAST) {
return { states: {} };
}

try {
return jsonata(this.astTransformQuery).evaluate(fullAST);
} catch (e) {
return { states: {} };
}
}

/**
* Get the Offset of a State Name.
*
* @param stateName
* @returns the offset found, -1 otherwise
*/
getStateNameOffset(stateName: string): number | undefined {
if (!stateName) {
return undefined;
}

return this.fullTextOffsets?.states[stateName]?.stateNameOffset || undefined;
}

/**
* Get State Name from a given Offset, checking the whole state block.
*
* @param offset
* @returns the stateName found, null otherwise
*/
getStateNameFromOffset(offset: number): string | null {
if (!offset) {
return null;
}

for (const stateName in this.fullTextOffsets?.states) {
const blockOffset = this.fullTextOffsets!.states[stateName].offset;
if (offset >= blockOffset.start && offset <= blockOffset.end) {
return stateName;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./SwfLanguageServiceChannelApi";
export * from "./SwfOffsetsApi";
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2022 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 * as jsonParse from "json-to-ast";
import { SwfOffsetsApi } from "../api/SwfOffsetsApi";

const astTransformQuery = `children[key.value='states'].value.children {
"states":{
children[key.value='name'].value.value:{
"stateNameOffset": children[key.value='name'].loc.start.offset,
"offset": $.loc{
"start":start.offset,
"end":end.offset
}
}
}
}
`;

export class SwfJsonOffsets extends SwfOffsetsApi {
constructor(documentUri?: string) {
super(astTransformQuery, documentUri);
}

getFullAST(): any {
if (!this.fullText) {
return null;
}

try {
return jsonParse(this.fullText);
} catch (e) {
console.error(`Received an exeption parsing the content: ${e.message}`);
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2022 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 { load } from "yaml-language-server-parser";
import { SwfOffsetsApi } from "../api/SwfOffsetsApi";

const astTransformQuery = `mappings[key.value="states"].value.items{
"states":{
mappings[key.value="name"].value.value:{
"stateNameOffset":startPosition,
"offset": {
"start":startPosition,
"end":endPosition
}
}
}
}
`;

export class SwfYamlOffsets extends SwfOffsetsApi {
constructor(documentUri?: string) {
super(astTransformQuery, documentUri);
}

getFullAST(): any {
const errorLogMsg = (message: string) => `Received an exeption parsing the content: ${message}`;

if (!this.fullText) {
return null;
}

try {
const ast = load(this.fullText);

// check if the yaml is not valid
if (ast.errors && ast.errors.length) {
console.error(errorLogMsg(ast.errors[0].message));
return null;
}

return ast;
} catch (e) {
console.error(errorLogMsg(e.message));
return null;
}
}
}
45 changes: 3 additions & 42 deletions packages/serverless-workflow-language-service/src/editor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,48 +22,6 @@ export enum FileLanguage {
YAML = "yaml",
}

/**
* Position with coordinates in a text editor.
*/
export type Position = {
line: number;
character: number;
};

/**
* Find position (row number) of a node in a JSON by state name.
*
* @param fullText the full text where to search
* @param stateName the name of the node
* @param fileLanguage the current file type
* @returns the position of the node, null if not found
*/
export const findPositionByStateName = (
fullText: string,
stateName: string,
fileLanguage = FileLanguage.JSON
): Position | null => {
if (!fullText || !stateName) {
return null;
}

const fullTextSplit = fullText.split("\n");
const nameRegExp = new RegExp(
fileLanguage === FileLanguage.YAML ? `name\\s*:\\s*${stateName}` : `"name"\\s*:\\s*"${stateName}"`
);

for (let lineNum = 0, end = fullTextSplit.length; lineNum < end; lineNum++) {
const line = fullTextSplit[lineNum];

if (nameRegExp.test(line)) {
const charNum = line.indexOf("name") - 1;
return { line: lineNum + 1, character: charNum + 1 };
}
}

return null;
};

/**
* Get the file language from a filename or path
*
Expand All @@ -81,3 +39,6 @@ export const getFileLanguage = (fileName: string): FileLanguage | null => {

return null;
};

export * from "./SwfJsonOffsets";
export * from "./SwfYamlOffsets";
Loading

0 comments on commit 3751f2f

Please sign in to comment.