From 79fc650472dfc0b67885070cd9a84bb889256e58 Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Fri, 9 Sep 2022 20:00:14 +1000 Subject: [PATCH 01/16] feat: add webview command --- .../vscode-ui5-language-assistant/package.json | 6 ++++++ .../src/constants.ts | 1 + .../src/extension.ts | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/vscode-ui5-language-assistant/package.json b/packages/vscode-ui5-language-assistant/package.json index 2f5ee44bd..58da8d962 100644 --- a/packages/vscode-ui5-language-assistant/package.json +++ b/packages/vscode-ui5-language-assistant/package.json @@ -20,6 +20,12 @@ "*" ], "contributes": { + "commands": [ + { + "command": "UI5LanguageAssistant.command.webView", + "title": "UI5 Say Hello" + } + ], "jsonValidation": [ { "fileMatch": [ diff --git a/packages/vscode-ui5-language-assistant/src/constants.ts b/packages/vscode-ui5-language-assistant/src/constants.ts index 799dfcb08..38f33538d 100644 --- a/packages/vscode-ui5-language-assistant/src/constants.ts +++ b/packages/vscode-ui5-language-assistant/src/constants.ts @@ -1,2 +1,3 @@ export const COMMAND_OPEN_DEMOKIT = "UI5LanguageAssistant.command.openDemokit"; +export const COMMAND_OPEN_WEBVIEW = "UI5LanguageAssistant.command.webView"; export const LOGGING_LEVEL_CONFIG_PROP = "UI5LanguageAssistant.logging.level"; diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index 52b85cfb8..a0bd28e36 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -22,7 +22,11 @@ import { SERVER_PATH, ServerInitializationOptions, } from "@ui5-language-assistant/language-server"; -import { COMMAND_OPEN_DEMOKIT, LOGGING_LEVEL_CONFIG_PROP } from "./constants"; +import { + COMMAND_OPEN_DEMOKIT, + COMMAND_OPEN_WEBVIEW, + LOGGING_LEVEL_CONFIG_PROP, +} from "./constants"; type UI5Model = { url: string; framework: string; version: string }; @@ -125,6 +129,18 @@ function updateCurrentModel(model: UI5Model | undefined) { } } +function createWebView(context: ExtensionContext) { + const command = "myExtension.sayHello"; + + const commandHandler = (name: string = "world") => { + console.log(`Hello ${name}!!!`); + }; + + context.subscriptions.push( + commands.registerCommand(COMMAND_OPEN_WEBVIEW, commandHandler) + ); +} + export function deactivate(): Thenable | undefined { if (!client) { return undefined; From e3d82a27461f237789a0fd72cc104c68e9b7e383 Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Mon, 12 Sep 2022 14:32:04 +1000 Subject: [PATCH 02/16] feat: handle go to definition to create webview --- packages/language-server/src/server.ts | 22 +++ .../package.json | 10 +- .../src/constants.ts | 1 + .../src/extension.ts | 104 ++++++++++++-- .../vscode-ui5-language-assistant/src/util.ts | 132 ++++++++++++++++++ 5 files changed, 257 insertions(+), 12 deletions(-) create mode 100644 packages/vscode-ui5-language-assistant/src/util.ts diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index 76a0deb72..e147fc1f1 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -94,6 +94,8 @@ connection.onInitialize((params: InitializeParams) => { commands.QUICK_FIX_STABLE_ID_FILE_ERRORS.name, ], }, + referencesProvider: false, + definitionProvider: true, }, }; }); @@ -108,6 +110,26 @@ connection.onInitialized(async () => { } }); +connection.onDefinition((params) => { + getLogger().debug("`onDefinition` event", {}); + // const documentUri = params.textDocument.uri; + // const document = documents.get(documentUri); + // if (document) { + // const documentPath = URI.parse(documentUri).fsPath; + // const minUI5Version = getMinUI5VersionForXMLFile(documentPath); + // const framework = getUI5FrameworkForXMLFile(documentPath); + // const model = await getSemanticModel( + // initializationOptions?.modelCachePath, + // framework, + // minUI5Version + // ); + // const ui5Url = getCDNBaseUrl(framework, model.version) + + // } + connection.sendNotification("UI5LanguageAssistant/ui5Definition", {}); + return undefined; +}); + connection.onCompletion( async ( textDocumentPosition: TextDocumentPositionParams diff --git a/packages/vscode-ui5-language-assistant/package.json b/packages/vscode-ui5-language-assistant/package.json index 58da8d962..e2cb5aa83 100644 --- a/packages/vscode-ui5-language-assistant/package.json +++ b/packages/vscode-ui5-language-assistant/package.json @@ -23,7 +23,15 @@ "commands": [ { "command": "UI5LanguageAssistant.command.webView", - "title": "UI5 Say Hello" + "title": "UI5-Language-Assistant: View API Reference" + } + ], + "keybindings": [ + { + "command": "UI5LanguageAssistant.command.webView", + "key": "F12", + "mac": "F12", + "when": "resourceLangId == xml" } ], "jsonValidation": [ diff --git a/packages/vscode-ui5-language-assistant/src/constants.ts b/packages/vscode-ui5-language-assistant/src/constants.ts index 38f33538d..5fa15288d 100644 --- a/packages/vscode-ui5-language-assistant/src/constants.ts +++ b/packages/vscode-ui5-language-assistant/src/constants.ts @@ -1,3 +1,4 @@ export const COMMAND_OPEN_DEMOKIT = "UI5LanguageAssistant.command.openDemokit"; export const COMMAND_OPEN_WEBVIEW = "UI5LanguageAssistant.command.webView"; export const LOGGING_LEVEL_CONFIG_PROP = "UI5LanguageAssistant.logging.level"; +export const REPLACE_GO_TO_DEFINITION = "editor.action.goToDeclaration"; diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index a0bd28e36..20cbed9e3 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -1,5 +1,6 @@ /* istanbul ignore file */ import { resolve } from "path"; +import { URL } from "url"; import { readFileSync } from "fs"; import { workspace, @@ -10,6 +11,8 @@ import { commands, env, Uri, + WebviewPanel, + ViewColumn, } from "vscode"; import { LanguageClient, @@ -26,25 +29,39 @@ import { COMMAND_OPEN_DEMOKIT, COMMAND_OPEN_WEBVIEW, LOGGING_LEVEL_CONFIG_PROP, + REPLACE_GO_TO_DEFINITION, } from "./constants"; +import { utils } from "./util"; type UI5Model = { url: string; framework: string; version: string }; let client: LanguageClient; let statusBarItem: StatusBarItem; let currentModel: UI5Model | undefined; - +let currentPanel: WebviewPanel | undefined; +let context: ExtensionContext | undefined; export async function activate(context: ExtensionContext): Promise { // create the LanguageClient (+Server) client = createLanguageClient(context); - + context = context; // create the StatusBarItem which displays the used UI5 version statusBarItem = createStatusBarItem(context); + createWebView(context); // show/hide and update the status bar client.onReady().then(() => { - client.onNotification("UI5LanguageAssistant/ui5Model", (model: UI5Model) => - updateCurrentModel(model) + client.onNotification( + "UI5LanguageAssistant/ui5Model", + (model: UI5Model) => { + updateCurrentModel(model); + } + ); + + client.onNotification( + "UI5LanguageAssistant/ui5Definition", + (model: UI5Model) => { + showWebView(); + } ); }); window.onDidChangeActiveTextEditor(() => { @@ -56,7 +73,7 @@ export async function activate(context: ExtensionContext): Promise { function createLanguageClient(context: ExtensionContext): LanguageClient { const debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; - + console.log(SERVER_PATH); const serverOptions: ServerOptions = { run: { module: SERVER_PATH, transport: TransportKind.ipc }, debug: { @@ -130,15 +147,80 @@ function updateCurrentModel(model: UI5Model | undefined) { } function createWebView(context: ExtensionContext) { - const command = "myExtension.sayHello"; + context.subscriptions.push( + commands.registerCommand(COMMAND_OPEN_WEBVIEW, showWebView) + ); + context.subscriptions.push( + commands.registerCommand(REPLACE_GO_TO_DEFINITION, showWebView) + ); +} - const commandHandler = (name: string = "world") => { - console.log(`Hello ${name}!!!`); +function showWebView() { + const columnToShowIn = window.activeTextEditor + ? window.activeTextEditor.viewColumn! + 1 + : ViewColumn.One; + const control = new utils().findControl(window.activeTextEditor); + const ui5Url = `${new URL(currentModel!.url).href}${ + control ? "#/api/" + control : "" + }`; + + const createWebView = () => { + currentPanel = window.createWebviewPanel( + "ui5APIRef", + "UI5 API Reference", + columnToShowIn, + { + enableScripts: true, + } + ); + currentPanel.webview.html = getWebviewContent(ui5Url); + + // Reset when the current panel is closed + currentPanel.onDidDispose( + () => { + currentPanel = undefined; + }, + null, + context!.subscriptions + ); }; + if (currentPanel) { + // If the panel is disposed, then create a new one. + try { + currentPanel.webview.postMessage({ url: ui5Url }); + + currentPanel.reveal(columnToShowIn); + } catch (error) { + currentPanel = undefined; + // Otherwise, create a new panel. + createWebView(); + } + } else { + createWebView(); + } +} - context.subscriptions.push( - commands.registerCommand(COMMAND_OPEN_WEBVIEW, commandHandler) - ); +function getWebviewContent(ui5Url: string) { + //Check if we are in a tag + + return ` + + + + + + + + + + `; } export function deactivate(): Thenable | undefined { diff --git a/packages/vscode-ui5-language-assistant/src/util.ts b/packages/vscode-ui5-language-assistant/src/util.ts new file mode 100644 index 000000000..dd137be22 --- /dev/null +++ b/packages/vscode-ui5-language-assistant/src/util.ts @@ -0,0 +1,132 @@ +/*--------------------------------------------------------- + * Copyright (C) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------*/ + +"use strict"; + +import { Uri } from "vscode"; +import vscode = require("vscode"); +export const extensionId = "vscode-ui5-language-assistant"; +export const GO_MODE: vscode.DocumentFilter = { + language: "go", + scheme: "file", +}; + +export class utils { + getNamespace(text, editor): string { + const namespace = text.includes(":") ? text.split(":")[0] : ""; + text = text.includes(":") ? text.split(":")[1] : text; + + let xmlns = editor.document + .getText() + .split("\n") + .find((line) => { + return namespace === "" + ? line.includes("xmlns=") + : line.includes("xmlns") && line.includes(namespace); + }) + .trim(); + + xmlns = xmlns.includes(">") ? xmlns.slice(0, -1) : xmlns; + const regex = new RegExp( + namespace === "" ? `xmlns="(.*?)"` : `xmlns:${namespace}="(.*?)\"` + ); + xmlns = xmlns.match(regex)[0].match(/\"(.*?)\"/)[1]; + + return `${xmlns}.${text}`; + } + + findControl(editor) { + const isLowerCase = (string) => { + return /^[a-z]*$/.test(string); + }; + + const cursorPosition = editor.selection.active; + let line = editor.document.lineAt(cursorPosition.line); + let text = line.text.trim(); + + if (text.includes("<")) { + //If the first character after the < is lowercase, then it's an aggregation + if ( + isLowerCase(text.charAt(1) === "/" ? text.charAt(2) : text.charAt(1)) && + isLowerCase( + text.indexOf(":") === -1 ? true : text.charAt(text.indexOf(":") + 1) + ) + ) { + let foundControl = false; + let count = 1; + const navigator = text.charAt(1) === "/" ? "-" : "+"; + + while (foundControl === false) { + count = + navigator === "+" + ? cursorPosition.line - count + : cursorPosition.line + count; + line = editor.document.lineAt(count); + text = line.text.trim(); + if ( + text.includes("<") && + !isLowerCase( + text.charAt(1) === "/" ? text.charAt(2) : text.charAt(1) + ) + ) { + foundControl = true; + } else { + count++; + } + } + } + + //just for good measure, check if it's the end tag + const tagSplit = text.includes("") + ? ">" + : "\n"; + text = text.split(tagSplit)[1].split(endSplit)[0]; + } else { + let count = cursorPosition.line - 1; + text = ""; + + while (!text) { + line = editor.document.lineAt(count); + text = line.text.trim(); + + if (text.includes("<")) { + const endSplit = text.includes(">") + ? ">" + : text.includes(" ") + ? " " + : "\n"; + text = text.split("<")[1].split(endSplit)[0]; + } else { + count = count - 1; + } + } + } + + text = text.includes(">") ? text.slice(0, -1) : text; + + return this.getNamespace(text, editor); + } + + public getWebviewContent( + control: string | undefined, + ui5Url: string + ): string { + return ` + + + + + + + + + `; + } +} From d37f620653f93be51bb73a494df7aa91b86e396b Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Mon, 12 Sep 2022 20:37:33 +1000 Subject: [PATCH 03/16] refactor: moved code to language server --- .vscode/launch.json | 3 +- packages/language-server/api.d.ts | 12 +- packages/language-server/src/api.ts | 27 ++++ packages/language-server/src/documentation.ts | 32 +++++ packages/language-server/src/hover.ts | 33 ++--- packages/language-server/src/server.ts | 64 ++++++--- .../test/documentation-spec.ts | 62 +++++++- packages/language-server/test/hover-spec.ts | 56 ++++---- .../src/constants.ts | 2 +- .../src/extension.ts | 77 ++++++---- .../vscode-ui5-language-assistant/src/util.ts | 132 ------------------ 11 files changed, 270 insertions(+), 230 deletions(-) delete mode 100644 packages/vscode-ui5-language-assistant/src/util.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 7c03cce50..dca73dbc3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,8 @@ "name": "Launch Client", "runtimeExecutable": "${execPath}", "args": [ - "--extensionDevelopmentPath=${workspaceRoot}/packages/vscode-ui5-language-assistant" + "--extensionDevelopmentPath=${workspaceRoot}/packages/vscode-ui5-language-assistant", + "--disable-extensions" ], "outFiles": [ "${workspaceRoot}/packages/vscode-ui5-language-assistant/lib/src/**/*.js" diff --git a/packages/language-server/api.d.ts b/packages/language-server/api.d.ts index 87ec846c9..da46efae0 100644 --- a/packages/language-server/api.d.ts +++ b/packages/language-server/api.d.ts @@ -2,8 +2,11 @@ * Absolute path to the server's "main" module * This is useful when launching the server in a separate process (e.g via spawn). */ +import { + BaseUI5Node, + UI5SemanticModel, +} from "@ui5-language-assistant/semantic-model-types"; import { LogLevel } from "@vscode-logging/types"; - export declare const SERVER_PATH: string; export type ServerInitializationOptions = { @@ -25,6 +28,13 @@ export type ServerInitializationOptions = { logLevel?: LogLevel; }; +export function getNodeName( + text: string, + offsetAt: number, + cachePath?: string, + framework?: string, + ui5Version?: string +): Promise; export type FetchResponse = { ok: boolean; status: number; diff --git a/packages/language-server/src/api.ts b/packages/language-server/src/api.ts index cfc5daf8d..e7546d3b9 100644 --- a/packages/language-server/src/api.ts +++ b/packages/language-server/src/api.ts @@ -1,5 +1,10 @@ import { resolve } from "path"; import { existsSync } from "fs"; +import { + BaseUI5Node, + UI5SemanticModel, +} from "@ui5-language-assistant/semantic-model-types"; +import { getNodeDetail, getUI5NodeName } from "./documentation"; // for use in productive flows const bundledPath = resolve(__dirname, "..", "..", "dist", "server.js"); @@ -19,3 +24,25 @@ export const SERVER_PATH: string = isDevelopmentRun ? /* istanbul ignore else - no tests (yet?) on bundled artifacts */ sourcesPath : bundledPath; + +export async function getNodeName( + text: string, + offsetAt: number, + cachePath?: string | undefined, + framework?: string | undefined, + ui5Version?: string | undefined +): Promise { + const ui5Node = await getUI5NodeName( + offsetAt, + text, + undefined, + cachePath, + framework, + ui5Version + ); + return ui5Node + ? ui5Node.kind !== "UI5Class" + ? `${ui5Node.parent?.library}.${ui5Node.parent?.name}` + : getNodeDetail(ui5Node) + : undefined; +} diff --git a/packages/language-server/src/documentation.ts b/packages/language-server/src/documentation.ts index 2f4a8894d..5b39b3380 100644 --- a/packages/language-server/src/documentation.ts +++ b/packages/language-server/src/documentation.ts @@ -17,6 +17,11 @@ import { getLink, } from "@ui5-language-assistant/logic-utils"; import { GENERATED_LIBRARY } from "@ui5-language-assistant/semantic-model"; +import { DocumentCstNode, parse } from "@xml-tools/parser"; +import { buildAst } from "@xml-tools/ast"; +import { astPositionAtOffset } from "@xml-tools/ast-position"; +import { findUI5HoverNodeAtOffset } from "@ui5-language-assistant/xml-views-tooltip"; +import { getSemanticModel } from "./ui5-model"; export function getNodeDocumentation( node: BaseUI5Node, @@ -108,3 +113,30 @@ export function getNodeDetail(node: BaseUI5Node): string { return node.name; } } + +export async function getUI5NodeName( + offsetAt: number, + text: string, + model?: UI5SemanticModel, + cachePath?: string, + framework?: string, + ui5Version?: string +): Promise { + const documentText = text; + const { cst, tokenVector } = parse(documentText); + const ast = buildAst(cst as DocumentCstNode, tokenVector); + const offset = offsetAt; + const astPosition = astPositionAtOffset(ast, offset); + if (!model) { + model = await fetchModel(cachePath, framework, ui5Version); + } + if (astPosition !== undefined) { + return findUI5HoverNodeAtOffset(astPosition, model); + } + return undefined; +} + +async function fetchModel(cachePath, framework, ui5Version) { + const ui5Model = await getSemanticModel(cachePath, framework, ui5Version); + return ui5Model; +} diff --git a/packages/language-server/src/hover.ts b/packages/language-server/src/hover.ts index 04b92f80c..04ba66a8f 100644 --- a/packages/language-server/src/hover.ts +++ b/packages/language-server/src/hover.ts @@ -5,33 +5,30 @@ import { MarkupContent, MarkupKind, } from "vscode-languageserver"; -import { parse, DocumentCstNode } from "@xml-tools/parser"; -import { buildAst } from "@xml-tools/ast"; -import { astPositionAtOffset } from "@xml-tools/ast-position"; import { UI5SemanticModel, BaseUI5Node, } from "@ui5-language-assistant/semantic-model-types"; -import { findUI5HoverNodeAtOffset } from "@ui5-language-assistant/xml-views-tooltip"; -import { getNodeDocumentation, getNodeDetail } from "./documentation"; +import { + getNodeDocumentation, + getNodeDetail, + getUI5NodeName, +} from "./documentation"; import { track } from "./swa"; -export function getHoverResponse( +export async function getHoverResponse( model: UI5SemanticModel, textDocumentPosition: TextDocumentPositionParams, document: TextDocument -): Hover | undefined { - const documentText = document.getText(); - const { cst, tokenVector } = parse(documentText); - const ast = buildAst(cst as DocumentCstNode, tokenVector); - const offset = document.offsetAt(textDocumentPosition.position); - const astPosition = astPositionAtOffset(ast, offset); - if (astPosition !== undefined) { - const ui5Node = findUI5HoverNodeAtOffset(astPosition, model); - if (ui5Node !== undefined) { - track("XML_UI5_DOC_HOVER", ui5Node.kind); - return transformToLspHover(ui5Node, model); - } +): Promise { + const ui5Node = await getUI5NodeName( + document.offsetAt(textDocumentPosition.position), + document.getText(), + model + ); + if (ui5Node !== undefined) { + track("XML_UI5_DOC_HOVER", ui5Node.kind); + return transformToLspHover(ui5Node, model); } return undefined; diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index e147fc1f1..dd3b0de64 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -10,6 +10,7 @@ import { InitializeParams, Hover, DidChangeConfigurationNotification, + DefinitionParams, } from "vscode-languageserver"; import { URI } from "vscode-uri"; import { TextDocument } from "vscode-languageserver-textdocument"; @@ -45,6 +46,7 @@ import { executeCommand } from "./commands"; import { initSwa } from "./swa"; import { getLogger, setLogLevel } from "./logger"; import { getCDNBaseUrl } from "./ui5-helper"; +import { getUI5NodeName } from "./documentation"; const connection = createConnection(ProposedFeatures.all); const documents = new TextDocuments(TextDocument); @@ -110,24 +112,44 @@ connection.onInitialized(async () => { } }); -connection.onDefinition((params) => { - getLogger().debug("`onDefinition` event", {}); - // const documentUri = params.textDocument.uri; - // const document = documents.get(documentUri); - // if (document) { - // const documentPath = URI.parse(documentUri).fsPath; - // const minUI5Version = getMinUI5VersionForXMLFile(documentPath); - // const framework = getUI5FrameworkForXMLFile(documentPath); - // const model = await getSemanticModel( - // initializationOptions?.modelCachePath, - // framework, - // minUI5Version - // ); - // const ui5Url = getCDNBaseUrl(framework, model.version) - - // } - connection.sendNotification("UI5LanguageAssistant/ui5Definition", {}); - return undefined; +connection.onDefinition(async (params: DefinitionParams) => { + const documentUri = params.textDocument.uri; + const document = documents.get(documentUri); + if (document) { + const documentPath = URI.parse(documentUri).fsPath; + const minUI5Version = getMinUI5VersionForXMLFile(documentPath); + const framework = getUI5FrameworkForXMLFile(documentPath); + const model = await getSemanticModel( + initializationOptions?.modelCachePath, + framework, + minUI5Version + ); + + const ui5Url = getCDNBaseUrl(framework, model.version); + + getLogger().debug("`onDefinition` event", { + url: ui5Url, + }); + + // const documentUri = params.textDocument.uri; + // const document = documents.get(documentUri); + // if (document) { + // const documentPath = URI.parse(documentUri).fsPath; + // const minUI5Version = getMinUI5VersionForXMLFile(documentPath); + // const framework = getUI5FrameworkForXMLFile(documentPath); + // const model = await getSemanticModel( + // initializationOptions?.modelCachePath, + // framework, + // minUI5Version + // ); + // const ui5Url = getCDNBaseUrl(framework, model.version) + + // } + connection.sendNotification("UI5LanguageAssistant/ui5Definition", { + url: ui5Url, + }); + } + return null; }); connection.onCompletion( @@ -150,6 +172,7 @@ connection.onCompletion( minUI5Version ); connection.sendNotification("UI5LanguageAssistant/ui5Model", { + cachePath: initializationOptions?.modelCachePath, url: getCDNBaseUrl(framework, model.version), framework, version: model.version, @@ -194,6 +217,7 @@ connection.onHover( minUI5Version ); connection.sendNotification("UI5LanguageAssistant/ui5Model", { + cachePath: initializationOptions?.modelCachePath, url: getCDNBaseUrl(framework, ui5Model.version), framework, version: ui5Model.version, @@ -248,6 +272,8 @@ documents.onDidChangeContent(async (changeEvent) => { minUI5Version ); connection.sendNotification("UI5LanguageAssistant/ui5Model", { + cachePath: initializationOptions?.modelCachePath, + url: getCDNBaseUrl(framework, ui5Model.version), framework, version: ui5Model.version, @@ -280,6 +306,8 @@ connection.onCodeAction(async (params) => { minUI5Version ); connection.sendNotification("UI5LanguageAssistant/ui5Model", { + cachePath: initializationOptions?.modelCachePath, + url: getCDNBaseUrl(framework, ui5Model.version), framework, version: ui5Model.version, diff --git a/packages/language-server/test/documentation-spec.ts b/packages/language-server/test/documentation-spec.ts index ae9a548db..39317b453 100644 --- a/packages/language-server/test/documentation-spec.ts +++ b/packages/language-server/test/documentation-spec.ts @@ -5,7 +5,13 @@ import { } from "@ui5-language-assistant/test-utils"; import { generate } from "@ui5-language-assistant/semantic-model"; import { UI5SemanticModel } from "@ui5-language-assistant/semantic-model-types"; -import { getNodeDocumentation } from "../src/documentation"; +import { + getNodeDetail, + getNodeDocumentation, + getUI5NodeName, +} from "../src/documentation"; +import { Position } from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; describe("The @ui5-language-assistant/language-server function", () => { let ui5SemanticModel: UI5SemanticModel; @@ -89,5 +95,59 @@ describe("The @ui5-language-assistant/language-server fun const result = getNodeDocumentation(ui5Enum, ui5SemanticModel); expect(result.value).to.include("Experimental."); }); + + it("get the UI5 node name with a model", async () => { + const xmlSnippet = ` + + + + + + `; + const { document, position } = getXmlSnippet(xmlSnippet); + + const result = await getUI5NodeName( + document.offsetAt(position), + document.getText(), + ui5SemanticModel + ); + expect(getNodeDetail(result!)).to.equal("sap.m.Input"); + }); + + // it("get the UI5 node name without a model", async () => { + // const xmlText = ` + // + // + // + // + // + // ` + + // const result = await getUI5NodeName(132, xmlText, undefined, "OPENUI5", ); + // expect(result?.name).to.equal("sap.m.Input"); + // }); }); + + function getXmlSnippet( + xmlSnippet: string + ): { document: TextDocument; position: Position } { + const xmlText = xmlSnippet.replace("⇶", ""); + const offset = xmlSnippet.indexOf("Input"); + const document: TextDocument = createTextDocument("xml", xmlText); + const position: Position = document.positionAt(offset); + return { document, position }; + } + + function createTextDocument( + languageId: string, + content: string + ): TextDocument { + return TextDocument.create("uri", languageId, 0, content); + } }); diff --git a/packages/language-server/test/hover-spec.ts b/packages/language-server/test/hover-spec.ts index 6f9d3d8ec..447613cf6 100644 --- a/packages/language-server/test/hover-spec.ts +++ b/packages/language-server/test/hover-spec.ts @@ -28,7 +28,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { }); context("hover on attribute key", () => { - it("will get hover content UI5 property", () => { + it("will get hover content UI5 property", async () => { const xmlSnippet = ` @@ -36,7 +36,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -44,13 +44,13 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { ); }); - it("will get hover content UI5 association", () => { + it("will get hover content UI5 association", async () => { const xmlSnippet = ` `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -58,12 +58,12 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { ); }); - it("will get hover content UI5 event", () => { + it("will get hover content UI5 event", async () => { const xmlSnippet = ` `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -71,7 +71,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { ); }); - it("will get hover content UI5 property - incorrect property", () => { + it("will get hover content UI5 property - incorrect property", async () => { const xmlSnippet = ` @@ -79,13 +79,13 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expect(response).to.not.exist; }); }); - context("hover on attribute value", () => { - it("will get hover content UI5 enum", () => { + context("hover on attribute value", async () => { + it("will get hover content UI5 enum", async () => { const xmlSnippet = ` @@ -93,7 +93,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -101,7 +101,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { ); }); - it("will get hover content UI5 namespace in xmlns attribute", () => { + it("will get hover content UI5 namespace in xmlns attribute", async () => { const xmlSnippet = ` @@ -109,7 +109,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -119,7 +119,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { }); context("hover on element open tag name", () => { - it("will get hover content UI5 class", () => { + it("will get hover content UI5 class", async () => { const xmlSnippet = ` @@ -127,7 +127,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -135,7 +135,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { ); }); - it("will get hover content UI5 Aggregation", () => { + it("will get hover content UI5 Aggregation", async () => { const xmlSnippet = ` @@ -143,7 +143,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include("Child Controls of the view"); @@ -151,7 +151,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { }); context("hover on element close tag name", () => { - it("will get hover content UI5 class", () => { + it("will get hover content UI5 class", async () => { const xmlSnippet = ` @@ -159,7 +159,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -167,7 +167,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { ); }); - it("will get hover content UI5 Aggregation", () => { + it("will get hover content UI5 Aggregation", async () => { const xmlSnippet = ` @@ -175,20 +175,20 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include("Child Controls of the view"); }); }); - it("will get hover content - open tag is different from close tag", () => { + it("will get hover content - open tag is different from close tag", async () => { const xmlSnippet = ` `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expectExists(response, "Hover item"); assertMarkup(response.contents); expect(response.contents.value).to.include( @@ -196,7 +196,7 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { ); }); - it("will get undefined hover content", () => { + it("will get undefined hover content", async () => { const xmlSnippet = ` @@ -204,15 +204,15 @@ describe("the UI5 language assistant Hover Tooltip Service", () => { `; - const response = getHoverItem(xmlSnippet, ui5SemanticModel); + const response = await getHoverItem(xmlSnippet, ui5SemanticModel); expect(response).to.not.exist; }); }); -export function getHoverItem( +export async function getHoverItem( xmlSnippet: string, ui5SemanticModel: UI5SemanticModel -): Hover | undefined { +): Promise { const { document, position } = getXmlSnippet(xmlSnippet); const uri: TextDocumentIdentifier = { uri: "uri" }; const textDocPositionParams: TextDocumentPositionParams = { @@ -220,7 +220,7 @@ export function getHoverItem( position: position, }; - const hoverItem = getHoverResponse( + const hoverItem = await getHoverResponse( ui5SemanticModel, textDocPositionParams, document diff --git a/packages/vscode-ui5-language-assistant/src/constants.ts b/packages/vscode-ui5-language-assistant/src/constants.ts index 5fa15288d..ee96afa3f 100644 --- a/packages/vscode-ui5-language-assistant/src/constants.ts +++ b/packages/vscode-ui5-language-assistant/src/constants.ts @@ -1,4 +1,4 @@ export const COMMAND_OPEN_DEMOKIT = "UI5LanguageAssistant.command.openDemokit"; export const COMMAND_OPEN_WEBVIEW = "UI5LanguageAssistant.command.webView"; export const LOGGING_LEVEL_CONFIG_PROP = "UI5LanguageAssistant.logging.level"; -export const REPLACE_GO_TO_DEFINITION = "editor.action.goToDeclaration"; +// export const REPLACE_GO_TO_DEFINITION = "editor.action.goToDeclaration"; diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index 20cbed9e3..30dd81eab 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -24,30 +24,34 @@ import { LogLevel } from "@vscode-logging/types"; import { SERVER_PATH, ServerInitializationOptions, + getNodeName, } from "@ui5-language-assistant/language-server"; import { COMMAND_OPEN_DEMOKIT, COMMAND_OPEN_WEBVIEW, LOGGING_LEVEL_CONFIG_PROP, - REPLACE_GO_TO_DEFINITION, } from "./constants"; -import { utils } from "./util"; +import { UI5SemanticModel } from "@ui5-language-assistant/semantic-model-types"; -type UI5Model = { url: string; framework: string; version: string }; +type UI5Model = { + cachePath: string; + url: string; + framework: string; + version: string; +}; let client: LanguageClient; let statusBarItem: StatusBarItem; let currentModel: UI5Model | undefined; let currentPanel: WebviewPanel | undefined; -let context: ExtensionContext | undefined; +let extContext: ExtensionContext | undefined; export async function activate(context: ExtensionContext): Promise { // create the LanguageClient (+Server) client = createLanguageClient(context); - context = context; + extContext = context; // create the StatusBarItem which displays the used UI5 version statusBarItem = createStatusBarItem(context); createWebView(context); - // show/hide and update the status bar client.onReady().then(() => { client.onNotification( @@ -57,12 +61,9 @@ export async function activate(context: ExtensionContext): Promise { } ); - client.onNotification( - "UI5LanguageAssistant/ui5Definition", - (model: UI5Model) => { - showWebView(); - } - ); + client.onNotification("UI5LanguageAssistant/ui5Definition", (params) => { + showWebView(params.url); + }); }); window.onDidChangeActiveTextEditor(() => { updateCurrentModel(undefined); @@ -131,6 +132,12 @@ function createStatusBarItem(context: ExtensionContext): StatusBarItem { return statusBarItem; } +function createWebView(context: ExtensionContext) { + context.subscriptions.push( + commands.registerCommand(COMMAND_OPEN_WEBVIEW, showWebView) + ); +} + function updateCurrentModel(model: UI5Model | undefined) { currentModel = model; if (statusBarItem) { @@ -146,23 +153,33 @@ function updateCurrentModel(model: UI5Model | undefined) { } } -function createWebView(context: ExtensionContext) { - context.subscriptions.push( - commands.registerCommand(COMMAND_OPEN_WEBVIEW, showWebView) - ); - context.subscriptions.push( - commands.registerCommand(REPLACE_GO_TO_DEFINITION, showWebView) - ); -} - -function showWebView() { - const columnToShowIn = window.activeTextEditor - ? window.activeTextEditor.viewColumn! + 1 - : ViewColumn.One; - const control = new utils().findControl(window.activeTextEditor); - const ui5Url = `${new URL(currentModel!.url).href}${ - control ? "#/api/" + control : "" - }`; +async function showWebView(url?: string | undefined) { + const columnToShowIn = + window.activeTextEditor && window.activeTextEditor.viewColumn + ? window.activeTextEditor.viewColumn + 1 + : ViewColumn.One; + const apiRefUrl = url || currentModel?.url; + if (!apiRefUrl) throw Error("Model not initialised"); + const document = window.activeTextEditor?.document; + let name: string | undefined; + if ( + currentModel?.framework && + currentModel.version && + window.activeTextEditor?.selection.active && + document + ) { + name = await getNodeName( + document.getText(), + document.offsetAt(window.activeTextEditor?.selection.active), + currentModel.cachePath, + currentModel.framework, + currentModel.version + ).catch((Error) => { + console.log(Error); + return undefined; + }); + } + const ui5Url = `${new URL(apiRefUrl).href}${name ? "#/api/" + name : ""}`; const createWebView = () => { currentPanel = window.createWebviewPanel( @@ -181,7 +198,7 @@ function showWebView() { currentPanel = undefined; }, null, - context!.subscriptions + extContext?.subscriptions ); }; if (currentPanel) { diff --git a/packages/vscode-ui5-language-assistant/src/util.ts b/packages/vscode-ui5-language-assistant/src/util.ts deleted file mode 100644 index dd137be22..000000000 --- a/packages/vscode-ui5-language-assistant/src/util.ts +++ /dev/null @@ -1,132 +0,0 @@ -/*--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE in the project root for license information. - *--------------------------------------------------------*/ - -"use strict"; - -import { Uri } from "vscode"; -import vscode = require("vscode"); -export const extensionId = "vscode-ui5-language-assistant"; -export const GO_MODE: vscode.DocumentFilter = { - language: "go", - scheme: "file", -}; - -export class utils { - getNamespace(text, editor): string { - const namespace = text.includes(":") ? text.split(":")[0] : ""; - text = text.includes(":") ? text.split(":")[1] : text; - - let xmlns = editor.document - .getText() - .split("\n") - .find((line) => { - return namespace === "" - ? line.includes("xmlns=") - : line.includes("xmlns") && line.includes(namespace); - }) - .trim(); - - xmlns = xmlns.includes(">") ? xmlns.slice(0, -1) : xmlns; - const regex = new RegExp( - namespace === "" ? `xmlns="(.*?)"` : `xmlns:${namespace}="(.*?)\"` - ); - xmlns = xmlns.match(regex)[0].match(/\"(.*?)\"/)[1]; - - return `${xmlns}.${text}`; - } - - findControl(editor) { - const isLowerCase = (string) => { - return /^[a-z]*$/.test(string); - }; - - const cursorPosition = editor.selection.active; - let line = editor.document.lineAt(cursorPosition.line); - let text = line.text.trim(); - - if (text.includes("<")) { - //If the first character after the < is lowercase, then it's an aggregation - if ( - isLowerCase(text.charAt(1) === "/" ? text.charAt(2) : text.charAt(1)) && - isLowerCase( - text.indexOf(":") === -1 ? true : text.charAt(text.indexOf(":") + 1) - ) - ) { - let foundControl = false; - let count = 1; - const navigator = text.charAt(1) === "/" ? "-" : "+"; - - while (foundControl === false) { - count = - navigator === "+" - ? cursorPosition.line - count - : cursorPosition.line + count; - line = editor.document.lineAt(count); - text = line.text.trim(); - if ( - text.includes("<") && - !isLowerCase( - text.charAt(1) === "/" ? text.charAt(2) : text.charAt(1) - ) - ) { - foundControl = true; - } else { - count++; - } - } - } - - //just for good measure, check if it's the end tag - const tagSplit = text.includes("") - ? ">" - : "\n"; - text = text.split(tagSplit)[1].split(endSplit)[0]; - } else { - let count = cursorPosition.line - 1; - text = ""; - - while (!text) { - line = editor.document.lineAt(count); - text = line.text.trim(); - - if (text.includes("<")) { - const endSplit = text.includes(">") - ? ">" - : text.includes(" ") - ? " " - : "\n"; - text = text.split("<")[1].split(endSplit)[0]; - } else { - count = count - 1; - } - } - } - - text = text.includes(">") ? text.slice(0, -1) : text; - - return this.getNamespace(text, editor); - } - - public getWebviewContent( - control: string | undefined, - ui5Url: string - ): string { - return ` - - - - - - - - - `; - } -} From aaf056efb159c022e021bafe6fd739e73a616758 Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Mon, 12 Sep 2022 20:46:23 +1000 Subject: [PATCH 04/16] refactor: updated tests --- .../test/documentation-spec.ts | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/language-server/test/documentation-spec.ts b/packages/language-server/test/documentation-spec.ts index 39317b453..4cd7ab913 100644 --- a/packages/language-server/test/documentation-spec.ts +++ b/packages/language-server/test/documentation-spec.ts @@ -10,8 +10,11 @@ import { getNodeDocumentation, getUI5NodeName, } from "../src/documentation"; +import { dir as tempDir, file as tempFile } from "tmp-promise"; + import { Position } from "vscode-languageserver"; import { TextDocument } from "vscode-languageserver-textdocument"; +import { getSemanticModel } from "../src/ui5-model"; describe("The @ui5-language-assistant/language-server function", () => { let ui5SemanticModel: UI5SemanticModel; @@ -117,21 +120,38 @@ describe("The @ui5-language-assistant/language-server fun expect(getNodeDetail(result!)).to.equal("sap.m.Input"); }); - // it("get the UI5 node name without a model", async () => { - // const xmlText = ` - // - // - // - // - // - // ` + it("get the UI5 node name without a model", async () => { + const xmlSnippet = ` + + + + + + `; - // const result = await getUI5NodeName(132, xmlText, undefined, "OPENUI5", ); - // expect(result?.name).to.equal("sap.m.Input"); - // }); + const cachePath = await tempDir(); + const ui5Model = await getSemanticModel( + cachePath.path, + "SAPUI5", + undefined, + true + ); + + const { document, position } = getXmlSnippet(xmlSnippet); + + const result = await getUI5NodeName( + document.offsetAt(position), + document.getText(), + undefined, + cachePath.path, + "SAPUI5", + ui5Model.version + ); + expect(getNodeDetail(result!)).to.equal("sap.m.Input"); + }); }); function getXmlSnippet( From 6837eaa13e14b3b1c57884fb7bc81d7fd80bee49 Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Mon, 12 Sep 2022 21:12:09 +1000 Subject: [PATCH 05/16] refactor: updated tests, linting and logo --- packages/language-server/api.d.ts | 5 +---- packages/language-server/src/api.ts | 4 ---- packages/language-server/src/server.ts | 1 - .../language-server/test/documentation-spec.ts | 13 ++++++++++--- .../resources/logo_ui5.png | Bin 0 -> 2463 bytes .../src/extension.ts | 7 +++++-- 6 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 packages/vscode-ui5-language-assistant/resources/logo_ui5.png diff --git a/packages/language-server/api.d.ts b/packages/language-server/api.d.ts index da46efae0..6aed2f0d5 100644 --- a/packages/language-server/api.d.ts +++ b/packages/language-server/api.d.ts @@ -2,10 +2,7 @@ * Absolute path to the server's "main" module * This is useful when launching the server in a separate process (e.g via spawn). */ -import { - BaseUI5Node, - UI5SemanticModel, -} from "@ui5-language-assistant/semantic-model-types"; + import { LogLevel } from "@vscode-logging/types"; export declare const SERVER_PATH: string; diff --git a/packages/language-server/src/api.ts b/packages/language-server/src/api.ts index e7546d3b9..e5576d85f 100644 --- a/packages/language-server/src/api.ts +++ b/packages/language-server/src/api.ts @@ -1,9 +1,5 @@ import { resolve } from "path"; import { existsSync } from "fs"; -import { - BaseUI5Node, - UI5SemanticModel, -} from "@ui5-language-assistant/semantic-model-types"; import { getNodeDetail, getUI5NodeName } from "./documentation"; // for use in productive flows diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index dd3b0de64..3bce10dbd 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -46,7 +46,6 @@ import { executeCommand } from "./commands"; import { initSwa } from "./swa"; import { getLogger, setLogLevel } from "./logger"; import { getCDNBaseUrl } from "./ui5-helper"; -import { getUI5NodeName } from "./documentation"; const connection = createConnection(ProposedFeatures.all); const documents = new TextDocuments(TextDocument); diff --git a/packages/language-server/test/documentation-spec.ts b/packages/language-server/test/documentation-spec.ts index 4cd7ab913..fb505a263 100644 --- a/packages/language-server/test/documentation-spec.ts +++ b/packages/language-server/test/documentation-spec.ts @@ -10,7 +10,7 @@ import { getNodeDocumentation, getUI5NodeName, } from "../src/documentation"; -import { dir as tempDir, file as tempFile } from "tmp-promise"; +import { dir as tempDir } from "tmp-promise"; import { Position } from "vscode-languageserver"; import { TextDocument } from "vscode-languageserver-textdocument"; @@ -117,7 +117,11 @@ describe("The @ui5-language-assistant/language-server fun document.getText(), ui5SemanticModel ); - expect(getNodeDetail(result!)).to.equal("sap.m.Input"); + if (result) { + expect(getNodeDetail(result)).to.equal("sap.m.Input"); + } else { + expect(result).to.equal("sap.m.Input"); + } }); it("get the UI5 node name without a model", async () => { @@ -150,7 +154,10 @@ describe("The @ui5-language-assistant/language-server fun "SAPUI5", ui5Model.version ); - expect(getNodeDetail(result!)).to.equal("sap.m.Input"); + if (result) expect(getNodeDetail(result)).to.equal("sap.m.Input"); + else { + expect(result).to.equal("sap.m.Input"); + } }); }); diff --git a/packages/vscode-ui5-language-assistant/resources/logo_ui5.png b/packages/vscode-ui5-language-assistant/resources/logo_ui5.png new file mode 100644 index 0000000000000000000000000000000000000000..627798ea1f700182e4f89b704f1c6a0ec4859564 GIT binary patch literal 2463 zcmX|DXIK-+77fy*1Xz(G8V#W@B?&#Dg(ip)P(VP)5+K2Zl7x^DASwaDh3AU+5JhRB zNfDzWAjME52#QOSUSw5Nq^=YxQFy`U?tI_OoqO;3&i&4rKa=Kxb^=PONCE%=;0b4k z(}JkIxA%()&OdhQBLM)RM?^1Qny;HHGK3sy5QHNK;|*dXDS|!#U}+Oe2?`0v)4;*_ zb3~FAWVxvY0w&_DAU-B;FgJ=lo1(Ox0(;UNed#Kv0EG8QQyh{V%^z_F1L zq-bQU732pmQgGiZLm}WF5L&nu#CC5W*w@ViY)_`*!6pW#`XO*5bFdl00B(XXH#F7* z8^YkGP#6LVH`a&2kuU@j1_%FK5Nk=WB^4KnJneA&=P*HL1tHLA6eJYNU@#0AMh0Z+ zIVc=~KtN%JP(wp~0YX1IjzkNJ)h9)(?NR)n!vP;1LM2jYL^27y#~Bn%rqiq-5J4aO zkCI5rzvQIopKb|!gT@9?pl|~i^aog=9%)a-2hqq>FETmeACVpeGL0NfAXC8h_Iskt zz}jv>Aw<$%Q3nFulLGyzMPMTIUl#?*zwdx23CyPoT>h$zvH}3aD^57rdikdOnH?T+ z#7Chsfe{+RZ5rED=uG#tuno%@FumG@cGd6_B9`tK5s^@pTNFG=@cQRnsn&rE(1n~6 z*IJT`F@gO(Baa~0?k%UkGOpgO1K{0T61y;AyR$YbmlntxjQ60G7aFObOy6*QxUuom zPlaD{9H3hj@Mn?TgVDu6$HJ!!{)Gpb`I~zC_REo)T}sy5!w56m5lj_M@Yoc&t0(Js z=RosoLr=pw6u?~9^zdUgUwK^km4=ehg{?ag?rXh`W$=2QWOZgjY4&fOO?i}jBKHV$f5wmf4bnDplh7|=sFvGG`CVyuqLD;8`OYiU- z@Z4y~U}+N;xlW+NoPqT!otteA7Gv`x7;{mncx$6T3Lsh0I@wTE$e1nqUwLx3*|6^u zksEEiUk7eIIOSRkMlGbT&uu*l?Coe-nCF)-I8P!bmgku5Mm)t9kKtlKNH~y{VV@u_Kfu=u*+~H6r$O?wlSz@+|KW&lzM4tS?l`` z>s3l=UrPH>V!%x)o&pwrl%UTp=0#ubM&}p9L*Pd^>)~ zgXwAbU>NX{bMexvT87*rRHl}bBR}~@d>LYr4`FhZfXY3^>QK!WWp`{p%#jR>&z*;n z$6wFmx>-VhNe$>6dEVnN9#)C>GRZ+m%_j_aJ4aM4LuuyO1^mAXP_+nMQ0kG zs7Ok27%PdhG}l;SOq_CU-c@{AITux3nxL>1P+#dG0y{YSOwAgca@AV}fWqX0mJ*>E z{7*R!RIyXQps0=_R*gg*^{sSbQBso7ao>>RW;Y@&5!j477mJTPdO7PSnHwN`!z6n* zb-KUXb0ozg1NNesuL1{#cH~!4)y^@I2V|?T^=SWFGUdhXM8MWKDtT?que#!E_1gpL z_5YzPJd`EOSX35iv4$DKwa?ISR7p835t3mB4zI@+p>!#h=AC?wf-5G$({w$Lr^CUm zd^=ksBK%IqJ~8P1hjwAF@yh;0&-2pd#rAZWo5#*+Zd)SM(ALqpgSAfcIQF}yqySB{ z>FRpU1L1MKjNq-teHq-TXQjdGc4`ZKlb|#9?Q~BJ0=LRdP^T{zHe$0($zo!1riFig z;rw2MjCw)4!fUO#if!XXHOK3k1FE{DhS0*1#V$x8o2;yfIsHLam`fu8(5RDEIl1sz zGwwrjgg>ZBgMIT%i==L=mnf>@f~|f)7fVK#&BHqMZnI(*+-rQTeYdW^SH|6aBXu+} z?08IQL6f_;6Y;hLNV6Oz&q)rKu+3o+b~TN$$rnEgyKJgU@!TCtue(-W8JsDJz+g6J z)erl8&vvaYBiYC&9u>c-JzK*zndz00LMj+5OwqF_`%>3EwH03U?8tpg*{36=xwySg z5j?PM{dV-8HeKTWvX<3%k(7uM&a9iLmDpOCvyhL%Xd^Pd^oF=6nU^^?!_>#409#+V zE$z7h-R2p$&i)>Kzo$-4kIHtl7s+m0yk$nQy;LC<2;j%oLh477%165}y4ify(*un3CdeaLNSB_45DyVj{ ziasOtyz|nO?xW~M*or4(U)bfTiuI0}U+hYR&V6p5>zX~LvQH#qQ8$5=Kk7RqLmGm( z6!=T0GW$%IJd5&yPS|H6L$$wwth_f^mh;CL^qE(hUK>wd>hulX)!57dxZRc2dN~px zCxh~n3tZ`np!Bsi9U7~PSLjGUoE;u|$Dq_6TDaYlbY$!1Q972k61sDk z8CMh4%GTMiU-2qE0S#8-IvbRa$xL t+Ln%c*#3zS77v8Gm$$3=kUD!406A-0nPsMzGxz>gCmhiZ96M~%{{ZwbVbTBq literal 0 HcmV?d00001 diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index 30dd81eab..be0fe3d62 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -31,7 +31,6 @@ import { COMMAND_OPEN_WEBVIEW, LOGGING_LEVEL_CONFIG_PROP, } from "./constants"; -import { UI5SemanticModel } from "@ui5-language-assistant/semantic-model-types"; type UI5Model = { cachePath: string; @@ -159,7 +158,8 @@ async function showWebView(url?: string | undefined) { ? window.activeTextEditor.viewColumn + 1 : ViewColumn.One; const apiRefUrl = url || currentModel?.url; - if (!apiRefUrl) throw Error("Model not initialised"); + if (!apiRefUrl) + throw Error("UI5-Language-Assistant: Model not initialised, try again"); const document = window.activeTextEditor?.document; let name: string | undefined; if ( @@ -190,6 +190,9 @@ async function showWebView(url?: string | undefined) { enableScripts: true, } ); + currentPanel.iconPath = Uri.file( + resolve(__dirname, "..", "..", "resources", "logo_ui5.png") + ); currentPanel.webview.html = getWebviewContent(ui5Url); // Reset when the current panel is closed From 5e0c21e23fcfe3b4885dce8d6e25f57a1df83fc9 Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Wed, 12 Oct 2022 23:17:58 +1000 Subject: [PATCH 06/16] feat: added settings for open in browser --- .../package.json | 13 +++- .../src/constants.ts | 3 +- .../src/extension.ts | 71 ++++++++++--------- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/packages/vscode-ui5-language-assistant/package.json b/packages/vscode-ui5-language-assistant/package.json index 0d95d1e0a..dfe84921a 100644 --- a/packages/vscode-ui5-language-assistant/package.json +++ b/packages/vscode-ui5-language-assistant/package.json @@ -29,8 +29,8 @@ "keybindings": [ { "command": "UI5LanguageAssistant.command.webView", - "key": "F12", - "mac": "F12", + "key": "ctrl+alt+d", + "mac": "ctrl+opt+d", "when": "resourceLangId == xml" } ], @@ -48,6 +48,15 @@ "type": "object", "title": "UI5 Language Assistant", "properties": { + "UI5LanguageAssistant.View.API_Reference": { + "type": "string", + "enum": [ + "browser", + "vscode" + ], + "default": "vscode", + "description": "How to open the API reference, in a browser window or webview inside vscode" + }, "UI5LanguageAssistant.logging.level": { "type": "string", "enum": [ diff --git a/packages/vscode-ui5-language-assistant/src/constants.ts b/packages/vscode-ui5-language-assistant/src/constants.ts index ee96afa3f..998648b67 100644 --- a/packages/vscode-ui5-language-assistant/src/constants.ts +++ b/packages/vscode-ui5-language-assistant/src/constants.ts @@ -1,4 +1,5 @@ export const COMMAND_OPEN_DEMOKIT = "UI5LanguageAssistant.command.openDemokit"; export const COMMAND_OPEN_WEBVIEW = "UI5LanguageAssistant.command.webView"; -export const LOGGING_LEVEL_CONFIG_PROP = "UI5LanguageAssistant.logging.level"; +export const COMMAND_OPEN_WEBVIEW = "UI5LanguageAssistant.command.webView"; +export const VIEW_API_REF = "UI5LanguageAssistant.View.API_Reference"; // export const REPLACE_GO_TO_DEFINITION = "editor.action.goToDeclaration"; diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index a13830b1a..5471575cd 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -30,6 +30,7 @@ import { COMMAND_OPEN_DEMOKIT, COMMAND_OPEN_WEBVIEW, LOGGING_LEVEL_CONFIG_PROP, + VIEW_API_REF, } from "./constants"; type UI5Model = { @@ -177,43 +178,47 @@ async function showWebView(url?: string | undefined) { }); } const ui5Url = `${new URL(apiRefUrl).href}${name ? "#/api/" + name : ""}`; - - const createWebView = () => { - currentPanel = window.createWebviewPanel( - "ui5APIRef", - "UI5 API Reference", - columnToShowIn, - { - enableScripts: true, - } - ); - currentPanel.iconPath = Uri.file( - resolve(__dirname, "..", "..", "resources", "logo_ui5.png") - ); - currentPanel.webview.html = getWebviewContent(ui5Url); - - // Reset when the current panel is closed - currentPanel.onDidDispose( - () => { + const openIn = workspace.getConfiguration().get(VIEW_API_REF); + if (openIn === "vscode") { + const createWebView = () => { + currentPanel = window.createWebviewPanel( + "ui5APIRef", + "UI5 API Reference", + columnToShowIn, + { + enableScripts: true, + } + ); + currentPanel.iconPath = Uri.file( + resolve(__dirname, "..", "..", "resources", "logo_ui5.png") + ); + currentPanel.webview.html = getWebviewContent(ui5Url); + + // Reset when the current panel is closed + currentPanel.onDidDispose( + () => { + currentPanel = undefined; + }, + null, + extContext?.subscriptions + ); + }; + if (currentPanel) { + // If the panel is disposed, then create a new one. + try { + currentPanel.webview.postMessage({ url: ui5Url }); + + currentPanel.reveal(columnToShowIn); + } catch (error) { currentPanel = undefined; - }, - null, - extContext?.subscriptions - ); - }; - if (currentPanel) { - // If the panel is disposed, then create a new one. - try { - currentPanel.webview.postMessage({ url: ui5Url }); - - currentPanel.reveal(columnToShowIn); - } catch (error) { - currentPanel = undefined; - // Otherwise, create a new panel. + // Otherwise, create a new panel. + createWebView(); + } + } else { createWebView(); } } else { - createWebView(); + env.openExternal(Uri.parse(ui5Url)); } } From ad36c1219b94f8ca438c9d15b654e1d572b361ba Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Wed, 12 Oct 2022 23:38:48 +1000 Subject: [PATCH 07/16] feat: added context menu --- packages/semantic-model/test/api-spec.ts | 3 +++ packages/vscode-ui5-language-assistant/package.json | 9 +++++++++ packages/vscode-ui5-language-assistant/src/constants.ts | 2 +- packages/vscode-ui5-language-assistant/src/extension.ts | 6 +++--- yarn.lock | 5 ----- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/semantic-model/test/api-spec.ts b/packages/semantic-model/test/api-spec.ts index 1257242fe..f1318b75a 100644 --- a/packages/semantic-model/test/api-spec.ts +++ b/packages/semantic-model/test/api-spec.ts @@ -352,6 +352,7 @@ context("The ui5-language-assistant semantic model package API", () => { it("cannot remove first-level property from the model", () => { expect(() => { + // @ts-ignore delete model.namespaces; }).to.throw(TypeError, cannotDeleteMatcher); }); @@ -361,6 +362,8 @@ context("The ui5-language-assistant semantic model package API", () => { expect(firstClass).to.exist; expect(firstClass.name).to.exist; expect(() => { + // @ts-ignore + delete firstClass.name; }).to.throw(TypeError, cannotDeleteMatcher); }); diff --git a/packages/vscode-ui5-language-assistant/package.json b/packages/vscode-ui5-language-assistant/package.json index dfe84921a..87e9aba28 100644 --- a/packages/vscode-ui5-language-assistant/package.json +++ b/packages/vscode-ui5-language-assistant/package.json @@ -26,6 +26,15 @@ "title": "UI5-Language-Assistant: View API Reference" } ], + "menus": { + "editor/context": [ + { + "when": "resourceLangId == xml", + "command": "UI5LanguageAssistant.command.webView", + "group": "navigation" + } + ] + }, "keybindings": [ { "command": "UI5LanguageAssistant.command.webView", diff --git a/packages/vscode-ui5-language-assistant/src/constants.ts b/packages/vscode-ui5-language-assistant/src/constants.ts index 998648b67..c5b42b462 100644 --- a/packages/vscode-ui5-language-assistant/src/constants.ts +++ b/packages/vscode-ui5-language-assistant/src/constants.ts @@ -1,5 +1,5 @@ export const COMMAND_OPEN_DEMOKIT = "UI5LanguageAssistant.command.openDemokit"; export const COMMAND_OPEN_WEBVIEW = "UI5LanguageAssistant.command.webView"; -export const COMMAND_OPEN_WEBVIEW = "UI5LanguageAssistant.command.webView"; +export const LOGGING_LEVEL_CONFIG_PROP = "UI5LanguageAssistant.logging.level"; export const VIEW_API_REF = "UI5LanguageAssistant.View.API_Reference"; // export const REPLACE_GO_TO_DEFINITION = "editor.action.goToDeclaration"; diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index 5471575cd..d4ec81261 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -59,7 +59,7 @@ export async function activate(context: ExtensionContext): Promise { ); client.onNotification("UI5LanguageAssistant/ui5Definition", (params) => { - showWebView(params.url); + showWebView(); }); }); window.onDidChangeActiveTextEditor(() => { @@ -150,12 +150,12 @@ function updateCurrentModel(model: UI5Model | undefined) { } } -async function showWebView(url?: string | undefined) { +async function showWebView() { const columnToShowIn = window.activeTextEditor && window.activeTextEditor.viewColumn ? window.activeTextEditor.viewColumn + 1 : ViewColumn.One; - const apiRefUrl = url || currentModel?.url; + const apiRefUrl = currentModel?.url; if (!apiRefUrl) throw Error("UI5-Language-Assistant: Model not initialised, try again"); const document = window.activeTextEditor?.document; diff --git a/yarn.lock b/yarn.lock index 8f3b42bd1..9c8b5952a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8841,11 +8841,6 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - "traverse@>=0.3.0 <0.4": version "0.3.9" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" From 37f9155dafd2fffec972c943da0c355c04e1e8af Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Wed, 12 Oct 2022 23:41:13 +1000 Subject: [PATCH 08/16] fix: remove go to definition functionality --- packages/language-server/src/server.ts | 40 -------------------------- 1 file changed, 40 deletions(-) diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index 4ab33ffa7..6b137a1b0 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -111,46 +111,6 @@ connection.onInitialized(async () => { } }); -connection.onDefinition(async (params: DefinitionParams) => { - const documentUri = params.textDocument.uri; - const document = documents.get(documentUri); - if (document) { - const documentPath = URI.parse(documentUri).fsPath; - const minUI5Version = getMinUI5VersionForXMLFile(documentPath); - const framework = getUI5FrameworkForXMLFile(documentPath); - const model = await getSemanticModel( - initializationOptions?.modelCachePath, - framework, - minUI5Version - ); - - const ui5Url = getCDNBaseUrl(framework, model.version); - - getLogger().debug("`onDefinition` event", { - url: ui5Url, - }); - - // const documentUri = params.textDocument.uri; - // const document = documents.get(documentUri); - // if (document) { - // const documentPath = URI.parse(documentUri).fsPath; - // const minUI5Version = getMinUI5VersionForXMLFile(documentPath); - // const framework = getUI5FrameworkForXMLFile(documentPath); - // const model = await getSemanticModel( - // initializationOptions?.modelCachePath, - // framework, - // minUI5Version - // ); - // const ui5Url = getCDNBaseUrl(framework, model.version) - - // } - connection.sendNotification("UI5LanguageAssistant/ui5Definition", { - url: ui5Url, - }); - } - return null; -}); - connection.onCompletion( async ( textDocumentPosition: TextDocumentPositionParams From b700af1bdcf3785e78a0857af9dd2488b88a2c86 Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Thu, 13 Oct 2022 07:21:02 +1000 Subject: [PATCH 09/16] refactor: changed wording from vscode to editor --- packages/vscode-ui5-language-assistant/package.json | 6 +++--- packages/vscode-ui5-language-assistant/src/extension.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vscode-ui5-language-assistant/package.json b/packages/vscode-ui5-language-assistant/package.json index 87e9aba28..5f9181baa 100644 --- a/packages/vscode-ui5-language-assistant/package.json +++ b/packages/vscode-ui5-language-assistant/package.json @@ -61,10 +61,10 @@ "type": "string", "enum": [ "browser", - "vscode" + "editor" ], - "default": "vscode", - "description": "How to open the API reference, in a browser window or webview inside vscode" + "default": "editor", + "description": "How to open the API reference, in a browser window or webview inside the editor" }, "UI5LanguageAssistant.logging.level": { "type": "string", diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index d4ec81261..bad958375 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -179,7 +179,7 @@ async function showWebView() { } const ui5Url = `${new URL(apiRefUrl).href}${name ? "#/api/" + name : ""}`; const openIn = workspace.getConfiguration().get(VIEW_API_REF); - if (openIn === "vscode") { + if (openIn === "editor") { const createWebView = () => { currentPanel = window.createWebviewPanel( "ui5APIRef", From 4b0a8bc42242e1bb2ade89c674e9dbad502e28da Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Thu, 13 Oct 2022 07:24:40 +1000 Subject: [PATCH 10/16] refactor: remove // @ts-ignore from local eslint --- packages/semantic-model/test/api-spec.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/semantic-model/test/api-spec.ts b/packages/semantic-model/test/api-spec.ts index f1318b75a..1257242fe 100644 --- a/packages/semantic-model/test/api-spec.ts +++ b/packages/semantic-model/test/api-spec.ts @@ -352,7 +352,6 @@ context("The ui5-language-assistant semantic model package API", () => { it("cannot remove first-level property from the model", () => { expect(() => { - // @ts-ignore delete model.namespaces; }).to.throw(TypeError, cannotDeleteMatcher); }); @@ -362,8 +361,6 @@ context("The ui5-language-assistant semantic model package API", () => { expect(firstClass).to.exist; expect(firstClass.name).to.exist; expect(() => { - // @ts-ignore - delete firstClass.name; }).to.throw(TypeError, cannotDeleteMatcher); }); From 3179ebd7b3b7dc2d7090c8e6dfa50d30862eb09c Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Thu, 13 Oct 2022 07:27:41 +1000 Subject: [PATCH 11/16] refactor: remove unused dependency --- packages/language-server/src/server.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index 6b137a1b0..70b636d17 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -45,7 +45,6 @@ import { executeCommand } from "./commands"; import { initSwa } from "./swa"; import { getLogger, setLogLevel } from "./logger"; import { getCDNBaseUrl } from "./ui5-helper"; -import { DefinitionParams } from "vscode-languageserver"; const connection = createConnection(ProposedFeatures.all); const documents = new TextDocuments(TextDocument); From ce2251ff761cbe97fef7b0c9765913500c1e64f0 Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Thu, 13 Oct 2022 07:37:42 +1000 Subject: [PATCH 12/16] refactor: remove unused param --- packages/vscode-ui5-language-assistant/src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index bad958375..9152a918d 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -58,7 +58,7 @@ export async function activate(context: ExtensionContext): Promise { updateCurrentModel(model) ); - client.onNotification("UI5LanguageAssistant/ui5Definition", (params) => { + client.onNotification("UI5LanguageAssistant/ui5Definition", () => { showWebView(); }); }); From d09feb1b094f983df89e9dc8282bb8bccfbf2a7e Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Thu, 13 Oct 2022 13:47:43 +1000 Subject: [PATCH 13/16] refactor: changed tests for new settings --- packages/settings/api.d.ts | 18 +++++++++++++++++- packages/settings/src/api.ts | 5 +++++ packages/settings/src/settings.ts | 1 + packages/settings/test/settings-spec.ts | 14 ++++++++++++++ .../vscode-ui5-language-assistant/package.json | 2 +- 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/settings/api.d.ts b/packages/settings/api.d.ts index a5b06bdac..c92949139 100644 --- a/packages/settings/api.d.ts +++ b/packages/settings/api.d.ts @@ -1,5 +1,8 @@ import Thenable from "vscode-languageserver"; -export type Settings = CodeAssistSettings & TraceSettings & LoggingSettings; +export type Settings = CodeAssistSettings & + TraceSettings & + LoggingSettings & + API_Reference; export interface CodeAssistSettings { codeAssist: { @@ -14,12 +17,25 @@ export interface TraceSettings { }; } +export interface API_Reference { + view: { + API_Reference: keyof IValidApiReferenceValues; + }; +} + export interface IValidTraceServerValues { off: true; messages: true; verbose: true; } +export interface IValidApiReferenceValues { + editor: true; + browser: true; +} + +export const validViewApiReferenceValues: IValidApiReferenceValues; + export const validTraceServerValues: IValidTraceServerValues; export interface LoggingSettings { diff --git a/packages/settings/src/api.ts b/packages/settings/src/api.ts index 738697e90..b49487c46 100644 --- a/packages/settings/src/api.ts +++ b/packages/settings/src/api.ts @@ -14,6 +14,11 @@ export const validTraceServerValues = { verbose: true as const, }; +export const validViewApiReferenceValues = { + editor: true as const, + browser: true as const, +}; + export const validLoggingLevelValues = { off: true as const, fatal: true as const, diff --git a/packages/settings/src/settings.ts b/packages/settings/src/settings.ts index 0df5b54fc..2a9bfbd28 100644 --- a/packages/settings/src/settings.ts +++ b/packages/settings/src/settings.ts @@ -7,6 +7,7 @@ const defaultSettings: Settings = { codeAssist: { deprecated: false, experimental: false }, trace: { server: "off" }, logging: { level: "error" }, + view: { API_Reference: "editor" }, }; deepFreezeStrict(defaultSettings); diff --git a/packages/settings/test/settings-spec.ts b/packages/settings/test/settings-spec.ts index cc238a1b5..9bd2fc55c 100644 --- a/packages/settings/test/settings-spec.ts +++ b/packages/settings/test/settings-spec.ts @@ -41,6 +41,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: false }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setGlobalSettings(globalSettings); const docSettings = await getSettingsForDocument("doc1"); @@ -52,6 +53,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: false }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setGlobalSettings(globalSettings); const docSettings = await getSettingsForDocument("doc1"); @@ -65,6 +67,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setSettingsForDocument("doc1", Promise.resolve(docSettings)); const result = await getSettingsForDocument("doc1"); @@ -80,6 +83,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }) ); expect(hasSettingsForDocument("doc1")).to.be.true; @@ -95,6 +99,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }) ); expect(hasSettingsForDocument("doc1")).to.be.false; @@ -107,6 +112,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setSettingsForDocument("doc1", Promise.resolve(docSettings)); expect(await getSettingsForDocument("doc1")).to.deep.equal(docSettings); @@ -117,11 +123,13 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; const docSettings2 = { codeAssist: { deprecated: true, experimental: false }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setSettingsForDocument("doc1", Promise.resolve(docSettings1)); setSettingsForDocument("doc1", Promise.resolve(docSettings2)); @@ -140,11 +148,13 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; const docSettings2 = { codeAssist: { deprecated: true, experimental: false }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setSettingsForDocument("doc1", Promise.resolve(docSettings1)); setSettingsForDocument("doc2", Promise.resolve(docSettings2)); @@ -169,6 +179,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setSettingsForDocument("doc1", Promise.resolve(docSettings)); @@ -183,11 +194,13 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; const docSettings2 = { codeAssist: { deprecated: true, experimental: false }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setSettingsForDocument("doc1", Promise.resolve(docSettings1)); setSettingsForDocument("doc2", Promise.resolve(docSettings2)); @@ -203,6 +216,7 @@ context("settings utilities", () => { codeAssist: { deprecated: true, experimental: true }, trace: { server: "off" as const }, logging: { level: "off" as const }, + view: { API_Reference: "editor" as const }, }; setGlobalSettings(globalSettings); expect(await getSettingsForDocument("doc1")).to.deep.equal( diff --git a/packages/vscode-ui5-language-assistant/package.json b/packages/vscode-ui5-language-assistant/package.json index 5f9181baa..bade74fbd 100644 --- a/packages/vscode-ui5-language-assistant/package.json +++ b/packages/vscode-ui5-language-assistant/package.json @@ -57,7 +57,7 @@ "type": "object", "title": "UI5 Language Assistant", "properties": { - "UI5LanguageAssistant.View.API_Reference": { + "UI5LanguageAssistant.view.API_Reference": { "type": "string", "enum": [ "browser", From edd0ae7f18294ebab165e255df322e36fe8a0f04 Mon Sep 17 00:00:00 2001 From: Jakob Marius Kjaer Date: Thu, 20 Oct 2022 21:36:46 +1000 Subject: [PATCH 14/16] chore: updated readme with api reference settings --- packages/vscode-ui5-language-assistant/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/vscode-ui5-language-assistant/README.md b/packages/vscode-ui5-language-assistant/README.md index ede258d6b..0bfaddbb9 100644 --- a/packages/vscode-ui5-language-assistant/README.md +++ b/packages/vscode-ui5-language-assistant/README.md @@ -124,6 +124,15 @@ The feature is available in the following: ![](https://raw.githubusercontent.com/SAP/ui5-language-assistant/master/packages/vscode-ui5-language-assistant/resources/readme/preview-manifest-json.gif) +### Quick navigation to API Reference + +Right click a tag in the XML file and use the View API reference shortcut to navigate directly to the API reference. Use the setting +``` +"UI5LanguageAssistant.view.API_Reference": "browser" | "editor" +``` + +The default setting is editor which opens the API reference in a new editor to the side. + #### Description: Implemented using the UI5 [manifest.json schema](https://github.com/SAP/ui5-manifest/blob/master/schema.json). From 2f7711d63d9e246e0f026311d240fe6a059e3fce Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Wed, 26 Oct 2022 21:08:15 +1000 Subject: [PATCH 15/16] refactor: removed console.log --- packages/vscode-ui5-language-assistant/src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vscode-ui5-language-assistant/src/extension.ts b/packages/vscode-ui5-language-assistant/src/extension.ts index 9152a918d..d9dd9ab82 100644 --- a/packages/vscode-ui5-language-assistant/src/extension.ts +++ b/packages/vscode-ui5-language-assistant/src/extension.ts @@ -71,7 +71,7 @@ export async function activate(context: ExtensionContext): Promise { function createLanguageClient(context: ExtensionContext): LanguageClient { const debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; - console.log(SERVER_PATH); + const serverOptions: ServerOptions = { run: { module: SERVER_PATH, transport: TransportKind.ipc }, debug: { From 4cf274dcb9e5c941409491b187dd2cfab5c88c6d Mon Sep 17 00:00:00 2001 From: Jakob Kjaer Date: Wed, 26 Oct 2022 21:25:16 +1000 Subject: [PATCH 16/16] chore: ran formatting --- packages/vscode-ui5-language-assistant/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vscode-ui5-language-assistant/README.md b/packages/vscode-ui5-language-assistant/README.md index 0bfaddbb9..fd52bd667 100644 --- a/packages/vscode-ui5-language-assistant/README.md +++ b/packages/vscode-ui5-language-assistant/README.md @@ -126,7 +126,8 @@ The feature is available in the following: ### Quick navigation to API Reference -Right click a tag in the XML file and use the View API reference shortcut to navigate directly to the API reference. Use the setting +Right click a tag in the XML file and use the View API reference shortcut to navigate directly to the API reference. Use the setting + ``` "UI5LanguageAssistant.view.API_Reference": "browser" | "editor" ```