This is an automated email from the ASF dual-hosted git repository.

rantunes pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-kie-tools-temporary-rnd-do-not-use.git

commit 5d8b2ae53a5a1887223267a31dd4e72f4cd6a6f6
Author: Fabrizio Antonangeli <[email protected]>
AuthorDate: Mon Nov 13 18:18:46 2023 +0100

    KOGITO-9891: Language Service not available on the SWF Chrome extension 
(#2046)
---
 .../package.json                                   |  4 +
 .../src/api/SwfLanguageServiceChannelApiImpl.ts    | 42 ++++++++++
 .../src/github-content-script.ts                   | 44 +++++++++-
 .../ChromeExtensionSwfLanguageService.ts           | 97 ++++++++++++++++++++++
 .../src/app/components/common/GlobalContext.tsx    |  5 +-
 .../app/components/common/KogitoEditorIframe.tsx   | 12 ++-
 .../src/app/components/common/Main.tsx             |  7 +-
 .../src/app/components/single/singleEditorEdit.tsx |  2 +
 packages/chrome-extension/src/index.ts             | 20 ++++-
 pnpm-lock.yaml                                     | 12 +++
 10 files changed, 238 insertions(+), 7 deletions(-)

diff --git a/packages/chrome-extension-serverless-workflow-editor/package.json 
b/packages/chrome-extension-serverless-workflow-editor/package.json
index 974312bae3..1fde1c0d21 100644
--- a/packages/chrome-extension-serverless-workflow-editor/package.json
+++ b/packages/chrome-extension-serverless-workflow-editor/package.json
@@ -38,6 +38,8 @@
     "@kie-tools/serverless-workflow-combined-editor": "workspace:*",
     "@kie-tools/serverless-workflow-diagram-editor-assets": "workspace:*",
     "@kie-tools/serverless-workflow-diagram-editor-envelope": "workspace:*",
+    "@kie-tools/serverless-workflow-jq-expressions": "workspace:*",
+    "@kie-tools/serverless-workflow-language-service": "workspace:*",
     "@kie-tools/serverless-workflow-text-editor": "workspace:*",
     "@kie-tools/tsconfig": "workspace:*",
     "@types/chrome": "^0.0.193",
@@ -53,6 +55,8 @@
     "start-server-and-test": "^1.12.1",
     "ts-jest": "^26.5.6",
     "typescript": "^4.6.2",
+    "vscode-languageserver-textdocument": "^1.0.4",
+    "vscode-languageserver-types": "^3.16.0",
     "webpack": "^5.88.2",
     "webpack-cli": "^4.10.0",
     "webpack-dev-server": "^4.15.1",
diff --git 
a/packages/chrome-extension-serverless-workflow-editor/src/api/SwfLanguageServiceChannelApiImpl.ts
 
b/packages/chrome-extension-serverless-workflow-editor/src/api/SwfLanguageServiceChannelApiImpl.ts
new file mode 100644
index 0000000000..10950d28c2
--- /dev/null
+++ 
b/packages/chrome-extension-serverless-workflow-editor/src/api/SwfLanguageServiceChannelApiImpl.ts
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 { SwfLanguageServiceChannelApi } from 
"@kie-tools/serverless-workflow-language-service/dist/api";
+import {
+  SwfJsonLanguageService,
+  SwfYamlLanguageService,
+} from "@kie-tools/serverless-workflow-language-service/dist/channel";
+import { CodeLens, CompletionItem, Position, Range } from 
"vscode-languageserver-types";
+
+export class SwfLanguageServiceChannelApiImpl implements 
SwfLanguageServiceChannelApi {
+  constructor(private readonly ls: SwfJsonLanguageService | 
SwfYamlLanguageService) {}
+
+  public async kogitoSwfLanguageService__getCompletionItems(args: {
+    content: string;
+    uri: string;
+    cursorPosition: Position;
+    cursorWordRange: Range;
+  }): Promise<CompletionItem[]> {
+    return this.ls.getCompletionItems(args);
+  }
+
+  public async kogitoSwfLanguageService__getCodeLenses(args: { uri: string; 
content: string }): Promise<CodeLens[]> {
+    return this.ls.getCodeLenses(args);
+  }
+}
diff --git 
a/packages/chrome-extension-serverless-workflow-editor/src/github-content-script.ts
 
b/packages/chrome-extension-serverless-workflow-editor/src/github-content-script.ts
index 8eba2e3f59..c80e5b12d7 100644
--- 
a/packages/chrome-extension-serverless-workflow-editor/src/github-content-script.ts
+++ 
b/packages/chrome-extension-serverless-workflow-editor/src/github-content-script.ts
@@ -17,11 +17,52 @@
  * under the License.
  */
 
-import { ChromeRouter } from "./ChromeRouter";
 import { startExtension } from "@kie-tools-core/chrome-extension";
+import { FileInfo } from 
"@kie-tools-core/chrome-extension/dist/app/components/single/singleEditorView";
+import { Dependencies } from 
"@kie-tools-core/chrome-extension/dist/app/Dependencies";
+import { GitHubPageType } from 
"@kie-tools-core/chrome-extension/dist/app/github/GitHubPageType";
 import { EditorEnvelopeLocator, EnvelopeContentType, EnvelopeMapping } from 
"@kie-tools-core/editor/dist/api";
+import { EmbeddedEditorFile, StateControl } from 
"@kie-tools-core/editor/dist/channel";
+import { EmbeddedEditorChannelApiImpl } from 
"@kie-tools-core/editor/dist/embedded";
+import { SwfCombinedEditorChannelApiImpl } from 
"@kie-tools/serverless-workflow-combined-editor/dist/channel";
+import { getFileLanguage } from 
"@kie-tools/serverless-workflow-language-service/dist/api";
+import { SwfLanguageServiceChannelApiImpl } from 
"./api/SwfLanguageServiceChannelApiImpl";
+import { ChromeRouter } from "./ChromeRouter";
+import { ChromeExtensionSwfLanguageService } from 
"./languageService/ChromeExtensionSwfLanguageService";
+import { extractFileExtension, removeDirectories } from "./utils";
 
 const resourcesPathPrefix = new ChromeRouter().getResourcesPathPrefix();
+
+function getCustomChannelApiImpl(
+  pageType: GitHubPageType,
+  fileInfo: FileInfo,
+  stateControl: StateControl
+): SwfCombinedEditorChannelApiImpl | undefined {
+  if (!getFileLanguage(fileInfo.path) || pageType !== GitHubPageType.EDIT) {
+    return;
+  }
+
+  const dependencies = new Dependencies();
+
+  const embeddedEditorFile: EmbeddedEditorFile = {
+    path: fileInfo.path,
+    getFileContents: () => {
+      return 
Promise.resolve(dependencies.all.edit__githubTextAreaWithFileContents()?.textContent
 ?? "");
+    },
+    isReadOnly: false,
+    fileExtension: `sw.${extractFileExtension(fileInfo.path)}`,
+    fileName: `${removeDirectories(fileInfo.path)}`,
+  };
+  const channelApiImpl = new EmbeddedEditorChannelApiImpl(stateControl, 
embeddedEditorFile, "en", {});
+
+  const chromeExtensionSwfLanguageService = new 
ChromeExtensionSwfLanguageService();
+  const languageService = 
chromeExtensionSwfLanguageService.getLs(fileInfo.path);
+  return new SwfCombinedEditorChannelApiImpl({
+    defaultApiImpl: channelApiImpl,
+    swfLanguageServiceChannelApiImpl: new 
SwfLanguageServiceChannelApiImpl(languageService),
+  });
+}
+
 startExtension({
   name: "Kogito :: Serverless workflow editor",
   extensionIconUrl: 
chrome.runtime.getURL("/resources/kie_icon_rgb_fullcolor_default.svg"),
@@ -37,4 +78,5 @@ startExtension({
       },
     }),
   ]),
+  getCustomChannelApiImpl,
 });
diff --git 
a/packages/chrome-extension-serverless-workflow-editor/src/languageService/ChromeExtensionSwfLanguageService.ts
 
b/packages/chrome-extension-serverless-workflow-editor/src/languageService/ChromeExtensionSwfLanguageService.ts
new file mode 100644
index 0000000000..06e3f76c86
--- /dev/null
+++ 
b/packages/chrome-extension-serverless-workflow-editor/src/languageService/ChromeExtensionSwfLanguageService.ts
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 { FileLanguage, getFileLanguageOrThrow } from 
"@kie-tools/serverless-workflow-language-service/dist/api";
+import {
+  SwfJsonLanguageService,
+  SwfLanguageServiceArgs,
+  SwfYamlLanguageService,
+} from "@kie-tools/serverless-workflow-language-service/dist/channel";
+import { JqExpressionReadSchemasImpl } from 
"@kie-tools/serverless-workflow-jq-expressions/dist/impl";
+import { TextDocument } from "vscode-languageserver-textdocument";
+import { removeDuplicatedKeyValuePairs } from 
"@kie-tools/serverless-workflow-jq-expressions/dist/utils";
+
+export class ChromeExtensionSwfLanguageService {
+  constructor() {}
+
+  public getLs(relativePath: string): SwfJsonLanguageService | 
SwfYamlLanguageService {
+    const swfLanguageLsArgs = this.getDefaultLsArgs({});
+
+    const fileLanguage = getFileLanguageOrThrow(relativePath);
+    if (fileLanguage === FileLanguage.YAML) {
+      return new SwfYamlLanguageService(swfLanguageLsArgs);
+    } else if (fileLanguage === FileLanguage.JSON) {
+      return new SwfJsonLanguageService(swfLanguageLsArgs);
+    } else {
+      throw new Error(`Could not determine LS for ${relativePath}`);
+    }
+  }
+
+  private getDefaultLsArgs(
+    configOverrides: Partial<SwfLanguageServiceArgs["config"]>
+  ): Omit<SwfLanguageServiceArgs, "lang"> {
+    return {
+      fs: {},
+      serviceCatalog: {
+        global: {
+          getServices: async () => [],
+        },
+        relative: {
+          getServices: async (_textDocument) => [],
+        },
+        getServiceFileNameFromSwfServiceCatalogServiceId: async (
+          registryName: string,
+          swfServiceCatalogServiceId: string
+        ) => `${registryName}__${swfServiceCatalogServiceId}__latest.yaml`,
+      },
+      jqCompletions: {
+        remote: {
+          getJqAutocompleteProperties: async (args: {
+            textDocument: TextDocument;
+            schemaPaths: string[];
+          }): Promise<Record<string, string>[]> => {
+            const jqExpressionReadSchema = new JqExpressionReadSchemasImpl();
+            const contentArray = await 
jqExpressionReadSchema.getContentFromRemoteUrl(args.schemaPaths);
+            return 
removeDuplicatedKeyValuePairs(jqExpressionReadSchema.parseSchemaProperties(contentArray));
+          },
+        },
+        relative: {
+          getJqAutocompleteProperties: (_args: any) => Promise.resolve([]),
+        },
+      },
+      config: {
+        shouldDisplayServiceRegistriesIntegration: async () => false,
+        shouldIncludeJsonSchemaDiagnostics: async () => true,
+        shouldReferenceServiceRegistryFunctionsWithUrls: async () => true,
+        getSpecsDirPosixPaths: async (_textDocument) => ({
+          specsDirRelativePosixPath: "",
+          specsDirAbsolutePosixPath: "",
+        }),
+        getRoutesDirPosixPaths: async (_textDocument) => ({
+          routesDirRelativePosixPath: "",
+          routesDirAbsolutePosixPath: "",
+        }),
+        shouldConfigureServiceRegistries: () => false,
+        shouldServiceRegistriesLogIn: () => false,
+        canRefreshServices: () => true,
+        ...configOverrides,
+      },
+    };
+  }
+}
diff --git 
a/packages/chrome-extension/src/app/components/common/GlobalContext.tsx 
b/packages/chrome-extension/src/app/components/common/GlobalContext.tsx
index eb7c216fc0..9a11b26413 100644
--- a/packages/chrome-extension/src/app/components/common/GlobalContext.tsx
+++ b/packages/chrome-extension/src/app/components/common/GlobalContext.tsx
@@ -18,11 +18,12 @@
  */
 
 import * as React from "react";
-import { EditorEnvelopeLocator } from "@kie-tools-core/editor/dist/api";
+import { EditorEnvelopeLocator, KogitoEditorChannelApi } from 
"@kie-tools-core/editor/dist/api";
 import { Logger } from "../../../Logger";
 import { ExternalEditorManager } from "../../../ExternalEditorManager";
 import { ResourceContentServiceFactory } from "./ChromeResourceContentService";
 import { Dependencies } from "../../Dependencies";
+import { StateControl } from "@kie-tools-core/editor/dist/channel";
 
 export interface GlobalContextType {
   id: string;
@@ -33,6 +34,8 @@ export interface GlobalContextType {
   extensionIconUrl: string;
   resourceContentServiceFactory: ResourceContentServiceFactory;
   externalEditorManager?: ExternalEditorManager;
+  stateControl?: StateControl;
+  customChannelApiImpl?: KogitoEditorChannelApi;
 }
 
 export const GlobalContext = React.createContext<GlobalContextType>({} as any);
diff --git 
a/packages/chrome-extension/src/app/components/common/KogitoEditorIframe.tsx 
b/packages/chrome-extension/src/app/components/common/KogitoEditorIframe.tsx
index 610d75fbea..f932473485 100644
--- a/packages/chrome-extension/src/app/components/common/KogitoEditorIframe.tsx
+++ b/packages/chrome-extension/src/app/components/common/KogitoEditorIframe.tsx
@@ -28,6 +28,7 @@ import { useGlobals } from "./GlobalContext";
 import { IsolatedEditorContext } from "./IsolatedEditorContext";
 import { IsolatedEditorRef } from "./IsolatedEditorRef";
 import { useChromeExtensionI18n } from "../../i18n";
+import { StateControl } from "@kie-tools-core/editor/dist/channel";
 
 interface Props {
   openFileExtension: string;
@@ -43,11 +44,18 @@ const RefForwardingKogitoEditorIframe: 
React.ForwardRefRenderFunction<IsolatedEd
 ) => {
   const githubApi = useGitHubApi();
   const { editor, editorRef } = useEditorRef();
-  const { envelopeLocator, resourceContentServiceFactory } = useGlobals();
+  const {
+    envelopeLocator,
+    resourceContentServiceFactory,
+    customChannelApiImpl,
+    stateControl: globalStateControl,
+  } = useGlobals();
   const { repoInfo, textMode, fullscreen, onEditorReady } = 
useContext(IsolatedEditorContext);
   const { locale } = useChromeExtensionI18n();
   const wasOnTextMode = usePrevious(textMode);
 
+  const stateControl = useMemo(() => globalStateControl || new StateControl(), 
[globalStateControl]);
+
   const resourceContentService = useMemo(() => {
     return resourceContentServiceFactory.createNew(githubApi.octokit(), 
repoInfo);
   }, [repoInfo]);
@@ -126,6 +134,8 @@ const RefForwardingKogitoEditorIframe: 
React.ForwardRefRenderFunction<IsolatedEd
           kogitoEditor_setContentError={props.onSetContentError}
           editorEnvelopeLocator={envelopeLocator}
           locale={locale}
+          customChannelApiImpl={customChannelApiImpl}
+          stateControl={stateControl}
         />
       </div>
     </>
diff --git a/packages/chrome-extension/src/app/components/common/Main.tsx 
b/packages/chrome-extension/src/app/components/common/Main.tsx
index 784aada68b..95896a8356 100644
--- a/packages/chrome-extension/src/app/components/common/Main.tsx
+++ b/packages/chrome-extension/src/app/components/common/Main.tsx
@@ -27,9 +27,10 @@ import { Dependencies } from "../../Dependencies";
 import { kogitoMenuContainer } from "../../utils";
 import { ExternalEditorManager } from "../../../ExternalEditorManager";
 import { ResourceContentServiceFactory } from "./ChromeResourceContentService";
-import { EditorEnvelopeLocator } from "@kie-tools-core/editor/dist/api";
+import { EditorEnvelopeLocator, KogitoEditorChannelApi } from 
"@kie-tools-core/editor/dist/api";
 import { I18nDictionariesProvider } from 
"@kie-tools-core/i18n/dist/react-components";
 import { chromeExtensionI18nDictionaries, chromeExtensionI18nDefaults, 
ChromeExtensionI18nContext } from "../../i18n";
+import { StateControl } from "@kie-tools-core/editor/dist/channel";
 
 export interface Globals {
   id: string;
@@ -40,6 +41,8 @@ export interface Globals {
   extensionIconUrl: string;
   resourceContentServiceFactory: ResourceContentServiceFactory;
   externalEditorManager?: ExternalEditorManager;
+  customChannelApiImpl?: KogitoEditorChannelApi;
+  stateControl?: StateControl;
 }
 
 function KogitoMenuPortal(props: { id: string }) {
@@ -85,6 +88,8 @@ export const Main: React.FunctionComponent<Globals> = (props) 
=> {
           extensionIconUrl: props.extensionIconUrl,
           resourceContentServiceFactory: props.resourceContentServiceFactory,
           externalEditorManager: props.externalEditorManager,
+          customChannelApiImpl: props.customChannelApiImpl,
+          stateControl: props.stateControl,
         }}
       >
         <GitHubContextProvider>
diff --git 
a/packages/chrome-extension/src/app/components/single/singleEditorEdit.tsx 
b/packages/chrome-extension/src/app/components/single/singleEditorEdit.tsx
index 967e01f83f..659fce1f7b 100644
--- a/packages/chrome-extension/src/app/components/single/singleEditorEdit.tsx
+++ b/packages/chrome-extension/src/app/components/single/singleEditorEdit.tsx
@@ -72,6 +72,8 @@ export async function renderSingleEditorApp(args: Globals & { 
fileInfo: FileInfo
       extensionIconUrl={args.extensionIconUrl}
       resourceContentServiceFactory={args.resourceContentServiceFactory}
       externalEditorManager={args.externalEditorManager}
+      customChannelApiImpl={args.customChannelApiImpl}
+      stateControl={args.stateControl}
     >
       <SingleEditorEditApp openFileExtension={openFileExtension} 
fileInfo={args.fileInfo} />
     </Main>,
diff --git a/packages/chrome-extension/src/index.ts 
b/packages/chrome-extension/src/index.ts
index a208ab9e80..68101799e1 100644
--- a/packages/chrome-extension/src/index.ts
+++ b/packages/chrome-extension/src/index.ts
@@ -19,18 +19,19 @@
 
 import { GitHubPageType } from "./app/github/GitHubPageType";
 import { renderSingleEditorApp } from 
"./app/components/single/singleEditorEdit";
-import { iframeContainer, renderSingleEditorReadonlyApp } from 
"./app/components/single/singleEditorView";
+import { FileInfo, iframeContainer, renderSingleEditorReadonlyApp } from 
"./app/components/single/singleEditorView";
 import { renderPrEditorsApp } from "./app/components/pr/prEditors";
 import { mainContainer, runAfterUriChange } from "./app/utils";
 import { Dependencies } from "./app/Dependencies";
 import * as ReactDOM from "react-dom";
-import { EditorEnvelopeLocator } from "@kie-tools-core/editor/dist/api";
+import { EditorEnvelopeLocator, KogitoEditorChannelApi } from 
"@kie-tools-core/editor/dist/api";
 import "../resources/style.css";
 import { Logger } from "./Logger";
 import { Globals } from "./app/components/common/Main";
 import { ExternalEditorManager } from "./ExternalEditorManager";
 import { ResourceContentServiceFactory } from 
"./app/components/common/ChromeResourceContentService";
 import { renderOpenRepoInExternalEditorApp } from 
"./app/components/openRepoInExternalEditor/openRepoInExternalEditorApp";
+import { StateControl } from "@kie-tools-core/editor/dist/channel";
 
 /**
  * Starts a Kogito extension.
@@ -40,6 +41,7 @@ import { renderOpenRepoInExternalEditorApp } from 
"./app/components/openRepoInEx
  *  @param args.githubAuthTokenCookieName The name of the cookie that will 
hold a GitHub PAT for your extension.
  *  @param args.editorEnvelopeLocator The file extension mapping to the 
provided Editors.
  *  @param args.externalEditorManager The implementation of 
ExternalEditorManager for your extension.
+ *  @param args.customChannelApiImpl Optional channelApi implementation.
  */
 export function startExtension(args: {
   name: string;
@@ -47,12 +49,21 @@ export function startExtension(args: {
   githubAuthTokenCookieName: string;
   editorEnvelopeLocator: EditorEnvelopeLocator;
   externalEditorManager?: ExternalEditorManager;
+  getCustomChannelApiImpl?: (
+    pageType: GitHubPageType,
+    fileInfo: FileInfo,
+    stateControl: StateControl
+  ) => KogitoEditorChannelApi | undefined;
 }) {
   const logger = new Logger(args.name);
   const resourceContentServiceFactory = new ResourceContentServiceFactory();
   const dependencies = new Dependencies();
 
-  const runInit = () =>
+  const runInit = () => {
+    const pageType = discoverCurrentGitHubPageType();
+    const fileInfo = extractFileInfoFromUrl();
+    const stateControl = new StateControl();
+
     init({
       id: chrome.runtime.id,
       logger: logger,
@@ -62,7 +73,10 @@ export function startExtension(args: {
       editorEnvelopeLocator: args.editorEnvelopeLocator,
       resourceContentServiceFactory: resourceContentServiceFactory,
       externalEditorManager: args.externalEditorManager,
+      stateControl,
+      customChannelApiImpl: args.getCustomChannelApiImpl?.(pageType, fileInfo, 
stateControl),
     });
+  };
 
   runAfterUriChange(logger, () => setTimeout(runInit, 0));
   setTimeout(runInit, 0);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6f7f6080bc..2f94ffe73e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1282,6 +1282,12 @@ importers:
       "@kie-tools/serverless-workflow-diagram-editor-envelope":
         specifier: workspace:*
         version: link:../serverless-workflow-diagram-editor-envelope
+      "@kie-tools/serverless-workflow-jq-expressions":
+        specifier: workspace:*
+        version: link:../serverless-workflow-jq-expressions
+      "@kie-tools/serverless-workflow-language-service":
+        specifier: workspace:*
+        version: link:../serverless-workflow-language-service
       "@kie-tools/serverless-workflow-text-editor":
         specifier: workspace:*
         version: link:../serverless-workflow-text-editor
@@ -1327,6 +1333,12 @@ importers:
       typescript:
         specifier: ^4.6.2
         version: 4.8.4
+      vscode-languageserver-textdocument:
+        specifier: ^1.0.4
+        version: 1.0.7
+      vscode-languageserver-types:
+        specifier: ^3.16.0
+        version: 3.17.2
       webpack:
         specifier: ^5.88.2
         version: 5.88.2([email protected])


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to