From 04a13a8404f56aa0813e8c55758fddea7f8e5ce2 Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 13 Nov 2024 17:00:16 +0300 Subject: [PATCH 01/36] load workspace content inside tree --- .../src/providers/workspaceTreeProvider.ts | 94 ++++++++++++++++--- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 0f7ec33fa7..28fa0ba00d 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -5,44 +5,110 @@ import * as fs from 'fs'; import { KIOTA_WORKSPACE_FILE } from '../constants'; import { getWorkspaceJsonPath } from '../util'; +interface WorkspaceContent { + version: string; + clients: Record; + plugins: Record; +} + +class WorkspaceTreeItem extends vscode.TreeItem { + constructor( + public readonly label: string, + public readonly collapsibleState: vscode.TreeItemCollapsibleState, + public readonly type: 'root' | 'category' | 'item', + public command?: vscode.Command + ) { + super(label, collapsibleState); + this.contextValue = type; + } +} + export class WorkspaceTreeProvider implements vscode.TreeDataProvider { - public isWSPresent: boolean; + public isWorkspacePresent: boolean; private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + private workspaceContent: WorkspaceContent | null = null; + constructor(isWSPresent: boolean) { - this.isWSPresent = isWSPresent; + this.isWorkspacePresent = isWSPresent; + void this.loadWorkspaceContent(); } async refreshView(): Promise { + this.loadWorkspaceContent(); this._onDidChangeTreeData.fire(); } - async getChildren(element?: vscode.TreeItem): Promise { - if (!this.isWSPresent) { + async getChildren(element?: WorkspaceTreeItem): Promise { + if (!this.isWorkspacePresent) { return []; } + if (!element) { - return [new vscode.TreeItem(KIOTA_WORKSPACE_FILE, vscode.TreeItemCollapsibleState.None)]; + return [ + new WorkspaceTreeItem(KIOTA_WORKSPACE_FILE, vscode.TreeItemCollapsibleState.Expanded, 'root') + ]; + } + + if (this.workspaceContent) { + if (element.label === KIOTA_WORKSPACE_FILE) { + return [ + new WorkspaceTreeItem('Clients', vscode.TreeItemCollapsibleState.Collapsed, 'category'), + new WorkspaceTreeItem('Plugins', vscode.TreeItemCollapsibleState.Collapsed, 'category') + ]; + } + + if (element.label === 'Clients') { + return Object.keys(this.workspaceContent.clients).map(clientName => + new WorkspaceTreeItem(clientName, vscode.TreeItemCollapsibleState.None, 'item') + ); + } + + if (element.label === 'Plugins') { + return Object.keys(this.workspaceContent.plugins).map(pluginName => + new WorkspaceTreeItem(pluginName, vscode.TreeItemCollapsibleState.None, 'item') + ); + } } return []; } - getTreeItem(element: vscode.TreeItem): vscode.TreeItem { + getTreeItem(element: WorkspaceTreeItem): WorkspaceTreeItem { if (element) { - element.command = { - command: 'kiota.workspace.openWorkspaceFile', - title: vscode.l10n.t("Open File"), - arguments: [vscode.Uri.file(getWorkspaceJsonPath())] - }; - element.contextValue = 'file'; + if (element.type === 'root') { + element.command = { + command: 'kiota.workspace.openWorkspaceFile', + title: vscode.l10n.t("Open File"), + arguments: [vscode.Uri.file(getWorkspaceJsonPath())] + }; + element.contextValue = 'folder'; + } } return element; } + + public loadWorkspaceContent(): void { + if (!this.isWorkspacePresent) { + this.workspaceContent = null; + return; + } + try { + const workspaceJson = vscode.workspace.textDocuments.find(doc => doc.fileName.endsWith(KIOTA_WORKSPACE_FILE)); + if (!workspaceJson) { + throw new Error('Workspace file not found'); + } + const content = workspaceJson.getText(); + this.workspaceContent = JSON.parse(content); + } catch (error) { + console.error('Error loading workspace.json:', error); + } + } } async function openResource(resource: vscode.Uri): Promise { await vscode.window.showTextDocument(resource); } + async function isKiotaWorkspaceFilePresent(): Promise { if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) { return false; @@ -59,13 +125,13 @@ async function isKiotaWorkspaceFilePresent(): Promise { export async function loadTreeView(context: vscode.ExtensionContext): Promise { const treeDataProvider = new WorkspaceTreeProvider(await isKiotaWorkspaceFilePresent()); context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(async () => { - treeDataProvider.isWSPresent = await isKiotaWorkspaceFilePresent(); + treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await vscode.commands.executeCommand('kiota.workspace.refresh'); // Refresh the tree view when workspace folders change })); context.subscriptions.push(vscode.window.createTreeView('kiota.workspace', { treeDataProvider })); context.subscriptions.push(vscode.commands.registerCommand('kiota.workspace.openWorkspaceFile', openResource)); context.subscriptions.push(vscode.commands.registerCommand('kiota.workspace.refresh', async () => { - treeDataProvider.isWSPresent = await isKiotaWorkspaceFilePresent(); + treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await treeDataProvider.refreshView(); })); } From 2c31d690fd6d891869962951ef4b13530ddccac8 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Thu, 14 Nov 2024 16:50:38 +0300 Subject: [PATCH 02/36] expand node if item is available --- vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 28fa0ba00d..7bee0df1ff 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -53,8 +53,8 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider 0 ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.Collapsed, 'category'), + new WorkspaceTreeItem('Plugins', Object.keys(this.workspaceContent.plugins).length > 0 ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.Collapsed, 'category') ]; } From 7465f160781a588fd7f74ac390dc8489c3c62573 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Thu, 14 Nov 2024 23:15:37 +0300 Subject: [PATCH 03/36] expand if items exist --- .../src/providers/workspaceTreeProvider.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 7bee0df1ff..f075977fce 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -82,6 +82,15 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider Date: Fri, 15 Nov 2024 00:29:51 +0300 Subject: [PATCH 04/36] add view action buttons to the items --- vscode/microsoft-kiota/package.json | 22 +++++++++++++++++++ vscode/microsoft-kiota/src/extension.ts | 15 +++++++++++++ .../src/providers/workspaceTreeProvider.ts | 8 +++---- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/vscode/microsoft-kiota/package.json b/vscode/microsoft-kiota/package.json index 30d5f23de7..c4491dbf24 100644 --- a/vscode/microsoft-kiota/package.json +++ b/vscode/microsoft-kiota/package.json @@ -301,6 +301,16 @@ "command": "kiota.openApiExplorer.removeAllFromSelectedEndpoints", "when": "view == kiota.openApiExplorer && viewItem != clientNameOrPluginName", "group": "inline@5" + }, + { + "command": "kiota.workspace.regenerate", + "when": "viewItem == item", + "group": "inline@1" + }, + { + "command": "kiota.workspace.deleteItem", + "when": "viewItem == item", + "group": "inline@2" } ], "commandPalette": [ @@ -437,6 +447,18 @@ { "command": "kiota.migrateFromLockFile", "title": "%kiota.migrateClients.title%" + }, + { + "command": "kiota.workspace.regenerate", + "title": "Regenerate", + "category": "Kiota", + "icon": "$(debug-rerun)" + }, + { + "command": "kiota.workspace.deleteItem", + "title": "Delete", + "category": "Kiota", + "icon": "$(trash)" } ], "languages": [ diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index 5728e823c7..20a97848b1 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -125,6 +125,21 @@ export async function activate( await regenerateCommand.execute({ clientOrPluginKey, clientOrPluginObject, generationType }); }), registerCommandWithTelemetry(reporter, migrateFromLockFileCommand.getName(), async (uri: vscode.Uri) => await migrateFromLockFileCommand.execute(uri)), + + ); + + context.subscriptions.push( + vscode.commands.registerCommand('kiota.workspace.regenerate', (item) => { + // Implement edit item logic here + vscode.window.showInformationMessage(`Edit item: ${item.label}`); + }) + ); + + context.subscriptions.push( + vscode.commands.registerCommand('kiota.workspace.delete', (item) => { + // Implement delete item logic here + vscode.window.showInformationMessage(`Delete item: ${item.label}`); + }) ); // create a new status bar item that we can now manage diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index f075977fce..fae20f6857 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -4,11 +4,12 @@ import * as fs from 'fs'; import { KIOTA_WORKSPACE_FILE } from '../constants'; import { getWorkspaceJsonPath } from '../util'; +import { ClientOrPluginProperties } from '../kiotaInterop'; interface WorkspaceContent { version: string; - clients: Record; - plugins: Record; + clients: Record; + plugins: Record; } class WorkspaceTreeItem extends vscode.TreeItem { @@ -83,8 +84,7 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider Date: Fri, 15 Nov 2024 09:02:34 +0300 Subject: [PATCH 05/36] activate selecting the path from the tree --- .../src/providers/workspaceTreeProvider.ts | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index fae20f6857..e9a524f178 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -17,6 +17,8 @@ class WorkspaceTreeItem extends vscode.TreeItem { public readonly label: string, public readonly collapsibleState: vscode.TreeItemCollapsibleState, public readonly type: 'root' | 'category' | 'item', + public readonly category?: string, + public readonly properties?: ClientOrPluginProperties, public command?: vscode.Command ) { super(label, collapsibleState); @@ -61,37 +63,53 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider - new WorkspaceTreeItem(clientName, vscode.TreeItemCollapsibleState.None, 'item') + new WorkspaceTreeItem(clientName, vscode.TreeItemCollapsibleState.None, 'item', 'Clients', this.getProperties(clientName, 'Clients')) ); } if (element.label === 'Plugins') { return Object.keys(this.workspaceContent.plugins).map(pluginName => - new WorkspaceTreeItem(pluginName, vscode.TreeItemCollapsibleState.None, 'item') + new WorkspaceTreeItem(pluginName, vscode.TreeItemCollapsibleState.None, 'item', 'Plugins', this.getProperties(pluginName, 'Plugins')) ); } } return []; } + getProperties(name: string, category: string): ClientOrPluginProperties | undefined { + if (category && category === 'Plugins') { + return this.workspaceContent?.plugins[name]; + } + return this.workspaceContent?.clients[name]; + } + getTreeItem(element: WorkspaceTreeItem): WorkspaceTreeItem { - if (element) { - if (element.type === 'root') { + if (!element) { + return element; + } + + switch (element.type) { + case 'root': element.command = { command: 'kiota.workspace.openWorkspaceFile', title: vscode.l10n.t("Open File"), arguments: [vscode.Uri.file(getWorkspaceJsonPath())] }; element.contextValue = 'folder'; - } else if (element.type === 'item') { + break; + + case 'item': + const key = element.label; + const properties = element.properties; + const generationType = element.category; + element.iconPath = new vscode.ThemeIcon('folder'); element.command = { - command: 'kiota.workspace.playItem', - title: vscode.l10n.t("Play Item"), - arguments: [element.label] + command: 'kiota.editPaths', + title: vscode.l10n.t("Select"), + arguments: [key, properties, generationType] }; - element.contextValue = 'item'; - } + break; } return element; } From 9b7ec58bd2ebb49d5cf3013f62baf58ffe1f9962 Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 15 Nov 2024 09:05:59 +0300 Subject: [PATCH 06/36] reorder panels in view --- vscode/microsoft-kiota/package.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/vscode/microsoft-kiota/package.json b/vscode/microsoft-kiota/package.json index c4491dbf24..56846528dd 100644 --- a/vscode/microsoft-kiota/package.json +++ b/vscode/microsoft-kiota/package.json @@ -217,12 +217,14 @@ "views": { "kiota-openapi-explorer": [ { - "id": "kiota.openApiExplorer", - "name": "%kiota.openApiExplorer.name%" + "id": "kiota.workspace", + "name": "%kiota.workspace.name%", + "order": 1 }, { - "id": "kiota.workspace", - "name": "%kiota.workspace.name%" + "id": "kiota.openApiExplorer", + "name": "%kiota.openApiExplorer.name%", + "order": 2 } ], "kiota-dependencies-info": [ From 14259aaaa105f693d3cd82139ca53b425fae5aca Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 15 Nov 2024 09:13:25 +0300 Subject: [PATCH 07/36] When no clients or plugins, open root collapsed --- .../microsoft-kiota/src/providers/workspaceTreeProvider.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index e9a524f178..2f89bdd6c9 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -48,8 +48,11 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider 0; + const hasPlugins = this.workspaceContent?.plugins && Object.keys(this.workspaceContent.plugins).length > 0; + const collapsibleState = (hasClients || hasPlugins) ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.Collapsed; return [ - new WorkspaceTreeItem(KIOTA_WORKSPACE_FILE, vscode.TreeItemCollapsibleState.Expanded, 'root') + new WorkspaceTreeItem(KIOTA_WORKSPACE_FILE, collapsibleState, 'root') ]; } From 2287b59f8362ebd76265c1f1b1fede02a58acb76 Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 15 Nov 2024 09:20:54 +0300 Subject: [PATCH 08/36] only show the category if it has items --- .../src/providers/workspaceTreeProvider.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 2f89bdd6c9..298dabdf49 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -58,10 +58,14 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider 0 ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.Collapsed, 'category'), - new WorkspaceTreeItem('Plugins', Object.keys(this.workspaceContent.plugins).length > 0 ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.Collapsed, 'category') - ]; + const children: WorkspaceTreeItem[] = []; + if (Object.keys(this.workspaceContent.clients).length > 0) { + children.push(new WorkspaceTreeItem('Clients', vscode.TreeItemCollapsibleState.Expanded, 'category')); + } + if (Object.keys(this.workspaceContent.plugins).length > 0) { + children.push(new WorkspaceTreeItem('Plugins', vscode.TreeItemCollapsibleState.Expanded, 'category')); + } + return children; } if (element.label === 'Clients') { From 52c0bba3cd9ac778eb6c3f0006b31324d63b0295 Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 15 Nov 2024 09:40:01 +0300 Subject: [PATCH 09/36] access properties from extension command --- vscode/microsoft-kiota/src/extension.ts | 11 +++++------ .../src/providers/workspaceTreeProvider.ts | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index 20a97848b1..9ebca34292 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -30,7 +30,7 @@ import { import { CodeLensProvider } from './providers/codelensProvider'; import { DependenciesViewProvider } from "./providers/dependenciesViewProvider"; import { OpenApiTreeNode, OpenApiTreeProvider } from "./providers/openApiTreeProvider"; -import { loadTreeView } from './providers/workspaceTreeProvider'; +import { loadTreeView, WorkspaceTreeItem } from './providers/workspaceTreeProvider'; import { getExtensionSettings } from "./types/extensionSettings"; import { GeneratedOutputState } from './types/GeneratedOutputState'; import { WorkspaceGenerationContext } from "./types/WorkspaceGenerationContext"; @@ -129,16 +129,15 @@ export async function activate( ); context.subscriptions.push( - vscode.commands.registerCommand('kiota.workspace.regenerate', (item) => { + vscode.commands.registerCommand('kiota.workspace.regenerate', (workspaceTreeItem: WorkspaceTreeItem) => { // Implement edit item logic here - vscode.window.showInformationMessage(`Edit item: ${item.label}`); + vscode.window.showInformationMessage(`Regenerate item: ${workspaceTreeItem.label}`); }) ); context.subscriptions.push( - vscode.commands.registerCommand('kiota.workspace.delete', (item) => { - // Implement delete item logic here - vscode.window.showInformationMessage(`Delete item: ${item.label}`); + vscode.commands.registerCommand('kiota.workspace.delete', (workspaceTreeItem: WorkspaceTreeItem) => { + vscode.window.showInformationMessage(`Delete item: ${workspaceTreeItem.label}`); }) ); diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 298dabdf49..55876520fc 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -12,7 +12,7 @@ interface WorkspaceContent { plugins: Record; } -class WorkspaceTreeItem extends vscode.TreeItem { +export class WorkspaceTreeItem extends vscode.TreeItem { constructor( public readonly label: string, public readonly collapsibleState: vscode.TreeItemCollapsibleState, From ffe44e81afb72eaf9110a36d31205ac4fb246880 Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 15 Nov 2024 11:45:38 +0300 Subject: [PATCH 10/36] show open folder icon when plugin/client selected --- .../src/commands/editPathsCommand.ts | 6 ++- vscode/microsoft-kiota/src/extension.ts | 12 ++++-- .../src/providers/openApiTreeProvider.ts | 9 ++++- .../src/providers/sharedService.ts | 36 ++++++++++++++++++ .../src/providers/workspaceTreeProvider.ts | 38 +++++++------------ vscode/microsoft-kiota/src/util.ts | 13 +++++++ 6 files changed, 83 insertions(+), 31 deletions(-) create mode 100644 vscode/microsoft-kiota/src/providers/sharedService.ts diff --git a/vscode/microsoft-kiota/src/commands/editPathsCommand.ts b/vscode/microsoft-kiota/src/commands/editPathsCommand.ts index 311215a8ab..7246478a43 100644 --- a/vscode/microsoft-kiota/src/commands/editPathsCommand.ts +++ b/vscode/microsoft-kiota/src/commands/editPathsCommand.ts @@ -1,6 +1,7 @@ import { extensionId, treeViewId } from "../constants"; import { ClientOrPluginProperties } from "../kiotaInterop"; import { OpenApiTreeProvider } from "../providers/openApiTreeProvider"; +import { WorkspaceTreeProvider } from "../providers/workspaceTreeProvider"; import { WorkspaceGenerationContext } from "../types/WorkspaceGenerationContext"; import { updateTreeViewIcons } from "../util"; import { openTreeViewWithProgress } from "../utilities/progress"; @@ -9,10 +10,12 @@ import { Command } from "./Command"; export class EditPathsCommand extends Command { private _openApiTreeProvider: OpenApiTreeProvider; + private _workspaceTreeProvider: WorkspaceTreeProvider; - public constructor(openApiTreeProvider: OpenApiTreeProvider) { + public constructor(openApiTreeProvider: OpenApiTreeProvider, workspaceTreeProvider: WorkspaceTreeProvider) { super(); this._openApiTreeProvider = openApiTreeProvider; + this._workspaceTreeProvider = workspaceTreeProvider; } public getName(): string { @@ -23,6 +26,7 @@ export class EditPathsCommand extends Command { await this.loadEditPaths(clientOrPluginKey!, clientOrPluginObject!); this._openApiTreeProvider.resetInitialState(); await updateTreeViewIcons(treeViewId, false, true); + await this._workspaceTreeProvider.refreshView(); } private async loadEditPaths(clientOrPluginKey: string, clientOrPluginObject: ClientOrPluginProperties) { diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index 9ebca34292..6a6186f843 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -30,10 +30,12 @@ import { import { CodeLensProvider } from './providers/codelensProvider'; import { DependenciesViewProvider } from "./providers/dependenciesViewProvider"; import { OpenApiTreeNode, OpenApiTreeProvider } from "./providers/openApiTreeProvider"; -import { loadTreeView, WorkspaceTreeItem } from './providers/workspaceTreeProvider'; +import { SharedService } from './providers/sharedService'; +import { loadTreeView, WorkspaceTreeItem, WorkspaceTreeProvider } from './providers/workspaceTreeProvider'; import { getExtensionSettings } from "./types/extensionSettings"; import { GeneratedOutputState } from './types/GeneratedOutputState'; import { WorkspaceGenerationContext } from "./types/WorkspaceGenerationContext"; +import { isKiotaWorkspaceFilePresent } from './util'; import { IntegrationParams } from './utilities/deep-linking'; import { loadWorkspaceFile } from './utilities/file'; import { updateStatusBarItem } from './utilities/status'; @@ -50,11 +52,13 @@ export async function activate( kiotaOutputChannel = vscode.window.createOutputChannel("Kiota", { log: true, }); - const openApiTreeProvider = new OpenApiTreeProvider(context, () => getExtensionSettings(extensionId)); + const sharedService = SharedService.getInstance(); + const openApiTreeProvider = new OpenApiTreeProvider(context, () => getExtensionSettings(extensionId), sharedService); const dependenciesInfoProvider = new DependenciesViewProvider( context.extensionUri ); const reporter = new TelemetryReporter(context.extension.packageJSON.telemetryInstrumentationKey); + const workspaceTreeProvider = new WorkspaceTreeProvider(await isKiotaWorkspaceFilePresent(), sharedService); const setWorkspaceGenerationContext = (params: Partial) => { workspaceGenerationContext = { ...workspaceGenerationContext, ...params }; @@ -68,7 +72,7 @@ export async function activate( const removeFromSelectedEndpointsCommand = new RemoveFromSelectedEndpointsCommand(openApiTreeProvider); const filterDescriptionCommand = new FilterDescriptionCommand(openApiTreeProvider); const openDocumentationPageCommand = new OpenDocumentationPageCommand(); - const editPathsCommand = new EditPathsCommand(openApiTreeProvider); + const editPathsCommand = new EditPathsCommand(openApiTreeProvider, workspaceTreeProvider); const searchOrOpenApiDescriptionCommand = new SearchOrOpenApiDescriptionCommand(openApiTreeProvider, context); const generateClientCommand = new GenerateClientCommand(openApiTreeProvider, context, dependenciesInfoProvider, setWorkspaceGenerationContext); const regenerateCommand = new RegenerateCommand(context, openApiTreeProvider); @@ -78,7 +82,7 @@ export async function activate( const selectLockCommand = new SelectLockCommand(openApiTreeProvider); const updateClientsCommand = new UpdateClientsCommand(context); - await loadTreeView(context); + await loadTreeView(context, workspaceTreeProvider); await checkForLockFileAndPrompt(context); let codeLensProvider = new CodeLensProvider(); context.subscriptions.push( diff --git a/vscode/microsoft-kiota/src/providers/openApiTreeProvider.ts b/vscode/microsoft-kiota/src/providers/openApiTreeProvider.ts index 26386edcb1..56622108b4 100644 --- a/vscode/microsoft-kiota/src/providers/openApiTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/openApiTreeProvider.ts @@ -21,20 +21,24 @@ import { } from '../kiotaInterop'; import { ExtensionSettings } from '../types/extensionSettings'; import { updateTreeViewIcons } from '../util'; +import { SharedService } from './sharedService'; export class OpenApiTreeProvider implements vscode.TreeDataProvider { private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; public apiTitle?: string; private initialStateHash: string = ''; + constructor( private readonly context: vscode.ExtensionContext, private readonly settingsGetter: () => ExtensionSettings, + private readonly sharedService: SharedService, private _descriptionUrl?: string, public includeFilters: string[] = [], - public excludeFilters: string[] = []) { - + public excludeFilters: string[] = [], + ) { } + private _workspaceFilePath?: string; private _workspaceFile?: ConfigurationFile | Partial = {}; public get isWorkspaceFileLoaded(): boolean { @@ -332,6 +336,7 @@ export class OpenApiTreeProvider implements vscode.TreeDataProvider = new Map(); + + private constructor() { } + + public static getInstance(): SharedService { + if (!SharedService.instance) { + SharedService.instance = new SharedService(); + } + return SharedService.instance; + } + + public get(key: K): SharedState[K] | undefined { + return this.state.get(key); + } + + public set(key: K, value: SharedState[K]): void { + console.log(`Setting ${key} to ${value}`); + this.state.set(key, value); + } + + public clear(key: K): void { + this.state.delete(key); + } + + // Method to reset the singleton instance for testing + public static resetInstance(): void { + SharedService.instance = new SharedService(); + } +} \ No newline at end of file diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 55876520fc..8f396343dd 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -1,10 +1,9 @@ import * as vscode from 'vscode'; -import * as path from 'path'; -import * as fs from 'fs'; import { KIOTA_WORKSPACE_FILE } from '../constants'; -import { getWorkspaceJsonPath } from '../util'; import { ClientOrPluginProperties } from '../kiotaInterop'; +import { getWorkspaceJsonPath, isKiotaWorkspaceFilePresent } from '../util'; +import { SharedService } from './sharedService'; interface WorkspaceContent { version: string; @@ -26,19 +25,20 @@ export class WorkspaceTreeItem extends vscode.TreeItem { } } -export class WorkspaceTreeProvider implements vscode.TreeDataProvider { +export class WorkspaceTreeProvider implements vscode.TreeDataProvider { public isWorkspacePresent: boolean; - private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); - readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); + readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; private workspaceContent: WorkspaceContent | null = null; + private sharedService: SharedService; - constructor(isWSPresent: boolean) { + constructor(isWSPresent: boolean, _sharedService: SharedService) { this.isWorkspacePresent = isWSPresent; + this.sharedService = _sharedService; void this.loadWorkspaceContent(); } async refreshView(): Promise { - this.loadWorkspaceContent(); this._onDidChangeTreeData.fire(); } @@ -110,7 +110,11 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider { await vscode.window.showTextDocument(resource); } -async function isKiotaWorkspaceFilePresent(): Promise { - if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) { - return false; - } - const workspaceFileDir = path.resolve(getWorkspaceJsonPath()); - try { - await fs.promises.access(workspaceFileDir); - } catch (error) { - return false; - } - return true; -} - -export async function loadTreeView(context: vscode.ExtensionContext): Promise { - const treeDataProvider = new WorkspaceTreeProvider(await isKiotaWorkspaceFilePresent()); +export async function loadTreeView(context: vscode.ExtensionContext, treeDataProvider: WorkspaceTreeProvider): Promise { context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(async () => { treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await vscode.commands.executeCommand('kiota.workspace.refresh'); // Refresh the tree view when workspace folders change diff --git a/vscode/microsoft-kiota/src/util.ts b/vscode/microsoft-kiota/src/util.ts index c61ab8fcb4..ef66cfc201 100644 --- a/vscode/microsoft-kiota/src/util.ts +++ b/vscode/microsoft-kiota/src/util.ts @@ -171,3 +171,16 @@ export function isValidUrl(url: string): boolean { return false; } } + +export async function isKiotaWorkspaceFilePresent(): Promise { + if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) { + return false; + } + const workspaceFileDir = path.resolve(getWorkspaceJsonPath()); + try { + await fs.promises.access(workspaceFileDir); + } catch (error) { + return false; + } + return true; +} From 1aadd1f560ba313698ef832933fa49448dba4105 Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 15 Nov 2024 12:45:29 +0300 Subject: [PATCH 11/36] reuse the regeneration command --- vscode/microsoft-kiota/src/extension.ts | 9 +----- .../src/providers/workspaceTreeProvider.ts | 28 ++++++++++++------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index 6a6186f843..1a8cbbd433 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -82,7 +82,7 @@ export async function activate( const selectLockCommand = new SelectLockCommand(openApiTreeProvider); const updateClientsCommand = new UpdateClientsCommand(context); - await loadTreeView(context, workspaceTreeProvider); + await loadTreeView(context, workspaceTreeProvider, regenerateCommand); await checkForLockFileAndPrompt(context); let codeLensProvider = new CodeLensProvider(); context.subscriptions.push( @@ -132,13 +132,6 @@ export async function activate( ); - context.subscriptions.push( - vscode.commands.registerCommand('kiota.workspace.regenerate', (workspaceTreeItem: WorkspaceTreeItem) => { - // Implement edit item logic here - vscode.window.showInformationMessage(`Regenerate item: ${workspaceTreeItem.label}`); - }) - ); - context.subscriptions.push( vscode.commands.registerCommand('kiota.workspace.delete', (workspaceTreeItem: WorkspaceTreeItem) => { vscode.window.showInformationMessage(`Delete item: ${workspaceTreeItem.label}`); diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 8f396343dd..620163b669 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -1,8 +1,9 @@ import * as vscode from 'vscode'; -import { KIOTA_WORKSPACE_FILE } from '../constants'; +import { RegenerateCommand } from '../commands/regenerate/regenerateCommand'; +import { CLIENTS, KIOTA_WORKSPACE_FILE, PLUGINS } from '../constants'; import { ClientOrPluginProperties } from '../kiotaInterop'; -import { getWorkspaceJsonPath, isKiotaWorkspaceFilePresent } from '../util'; +import { getWorkspaceJsonPath, isClientType, isKiotaWorkspaceFilePresent, isPluginType } from '../util'; import { SharedService } from './sharedService'; interface WorkspaceContent { @@ -60,23 +61,23 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider 0) { - children.push(new WorkspaceTreeItem('Clients', vscode.TreeItemCollapsibleState.Expanded, 'category')); + children.push(new WorkspaceTreeItem(CLIENTS, vscode.TreeItemCollapsibleState.Expanded, 'category')); } if (Object.keys(this.workspaceContent.plugins).length > 0) { - children.push(new WorkspaceTreeItem('Plugins', vscode.TreeItemCollapsibleState.Expanded, 'category')); + children.push(new WorkspaceTreeItem(PLUGINS, vscode.TreeItemCollapsibleState.Expanded, 'category')); } return children; } - if (element.label === 'Clients') { + if (isClientType(element.label)) { return Object.keys(this.workspaceContent.clients).map(clientName => - new WorkspaceTreeItem(clientName, vscode.TreeItemCollapsibleState.None, 'item', 'Clients', this.getProperties(clientName, 'Clients')) + new WorkspaceTreeItem(clientName, vscode.TreeItemCollapsibleState.None, 'item', CLIENTS, this.getProperties(clientName, CLIENTS)) ); } - if (element.label === 'Plugins') { + if (isPluginType(element.label)) { return Object.keys(this.workspaceContent.plugins).map(pluginName => - new WorkspaceTreeItem(pluginName, vscode.TreeItemCollapsibleState.None, 'item', 'Plugins', this.getProperties(pluginName, 'Plugins')) + new WorkspaceTreeItem(pluginName, vscode.TreeItemCollapsibleState.None, 'item', PLUGINS, this.getProperties(pluginName, CLIENTS)) ); } } @@ -84,7 +85,7 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider { await vscode.window.showTextDocument(resource); } -export async function loadTreeView(context: vscode.ExtensionContext, treeDataProvider: WorkspaceTreeProvider): Promise { +export async function loadTreeView(context: vscode.ExtensionContext, treeDataProvider: WorkspaceTreeProvider, regenerateCommand: RegenerateCommand): Promise { context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(async () => { treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await vscode.commands.executeCommand('kiota.workspace.refresh'); // Refresh the tree view when workspace folders change @@ -158,4 +159,11 @@ export async function loadTreeView(context: vscode.ExtensionContext, treeDataPro treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await treeDataProvider.refreshView(); })); + context.subscriptions.push( + vscode.commands.registerCommand('kiota.workspace.regenerate', async (workspaceTreeItem: WorkspaceTreeItem) => { + const { label, properties, category } = workspaceTreeItem; + await regenerateCommand.execute({ clientOrPluginKey: label, clientOrPluginObject: properties!, generationType: category! }); + }) + ); + } From 711294c0d74c3142841f0b421aad3bdcac7e6d65 Mon Sep 17 00:00:00 2001 From: thewahome Date: Mon, 18 Nov 2024 22:56:46 +0300 Subject: [PATCH 12/36] [partial] delete workspace item --- .../commands/deleteWorkspaceItemCommand.ts | 36 +++++++++++++++++++ vscode/microsoft-kiota/src/extension.ts | 9 ++--- 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts new file mode 100644 index 0000000000..8e93385a26 --- /dev/null +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts @@ -0,0 +1,36 @@ +import * as vscode from "vscode"; +import * as rpc from "vscode-jsonrpc/node"; + +import { extensionId } from "../constants"; +import { WorkspaceTreeItem } from "../providers/workspaceTreeProvider"; +import { Command } from "./Command"; +import { connectToKiota, KiotaLogEntry } from "../kiotaInterop"; +import { isPluginType } from "../util"; + +export class DeleteWorkspaceItemCommand extends Command { + constructor(private _context: vscode.ExtensionContext) { + super(); + } + + public getName(): string { + return `${extensionId}.workspace.deleteItem`; + } + + public async execute(workspaceTreeItem: WorkspaceTreeItem): Promise { + const result = await deleteItem(this._context, isPluginType(workspaceTreeItem.category!) ? "plugin" : "client", workspaceTreeItem.label); + vscode.window.showInformationMessage(`Delete item: ${workspaceTreeItem.label}`); + } +} + +export function deleteItem(context: vscode.ExtensionContext, workspaceItemType: string, key: string): Promise { + return connectToKiota(context, async (connection) => { + const request = new rpc.RequestType1( + workspaceItemType + ); + const result = await connection.sendRequest( + request, + key + ); + return result; + }); +}; \ No newline at end of file diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index 1a8cbbd433..e2fabe9b9b 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -4,6 +4,7 @@ import TelemetryReporter from '@vscode/extension-telemetry'; import * as vscode from "vscode"; import { CloseDescriptionCommand } from './commands/closeDescriptionCommand'; +import { DeleteWorkspaceItemCommand } from './commands/deleteWorkspaceItemCommand'; import { EditPathsCommand } from './commands/editPathsCommand'; import { GenerateClientCommand } from './commands/generate/generateClientCommand'; import { displayGenerationResults } from './commands/generate/generation-util'; @@ -81,6 +82,7 @@ export async function activate( const statusCommand = new StatusCommand(); const selectLockCommand = new SelectLockCommand(openApiTreeProvider); const updateClientsCommand = new UpdateClientsCommand(context); + const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context); await loadTreeView(context, workspaceTreeProvider, regenerateCommand); await checkForLockFileAndPrompt(context); @@ -129,15 +131,10 @@ export async function activate( await regenerateCommand.execute({ clientOrPluginKey, clientOrPluginObject, generationType }); }), registerCommandWithTelemetry(reporter, migrateFromLockFileCommand.getName(), async (uri: vscode.Uri) => await migrateFromLockFileCommand.execute(uri)), + registerCommandWithTelemetry(reporter, deleteWorkspaceItemCommand.getName(), async (workspaceTreeItem: WorkspaceTreeItem) => await deleteWorkspaceItemCommand.execute(workspaceTreeItem)), ); - context.subscriptions.push( - vscode.commands.registerCommand('kiota.workspace.delete', (workspaceTreeItem: WorkspaceTreeItem) => { - vscode.window.showInformationMessage(`Delete item: ${workspaceTreeItem.label}`); - }) - ); - // create a new status bar item that we can now manage kiotaStatusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Right, From ab673e537852a59fac4ba62f918fb78c09550e08 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Tue, 19 Nov 2024 13:14:30 +0300 Subject: [PATCH 13/36] reuse item generation --- .../commands/deleteWorkspaceItemCommand.ts | 150 ++++++++++++++++-- 1 file changed, 133 insertions(+), 17 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts index 8e93385a26..057ea525d0 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts @@ -1,11 +1,20 @@ import * as vscode from "vscode"; -import * as rpc from "vscode-jsonrpc/node"; -import { extensionId } from "../constants"; +import { extensionId, treeViewFocusCommand } from "../constants"; import { WorkspaceTreeItem } from "../providers/workspaceTreeProvider"; import { Command } from "./Command"; -import { connectToKiota, KiotaLogEntry } from "../kiotaInterop"; -import { isPluginType } from "../util"; +import { ConsumerOperation, generationLanguageToString, getLogEntriesForLevel, KiotaLogEntry, LogLevel } from "../kiotaInterop"; +import { getWorkspaceJsonDirectory, isPluginType, parseGenerationLanguage, parsePluginType } from "../util"; +import { generateClient } from "./generate/generateClient"; +import TelemetryReporter from "@vscode/extension-telemetry"; +import { getDeepLinkParams } from "../handlers/deepLinkParamsHandler"; +import { GenerateState } from "../modules/steps/generateSteps"; +import { KiotaPluginType, KiotaGenerationLanguage } from "../types/enums"; +import { ExtensionSettings } from "../types/extensionSettings"; +import { exportLogsAndShowErrors } from "../utilities/logging"; +import { generatePlugin } from "./generate/generatePlugin"; +import { checkForSuccess } from "./generate/generation-util"; +import { getLanguageInformationForDescription } from "./generate/getLanguageInformation"; export class DeleteWorkspaceItemCommand extends Command { constructor(private _context: vscode.ExtensionContext) { @@ -17,20 +26,127 @@ export class DeleteWorkspaceItemCommand extends Command { } public async execute(workspaceTreeItem: WorkspaceTreeItem): Promise { - const result = await deleteItem(this._context, isPluginType(workspaceTreeItem.category!) ? "plugin" : "client", workspaceTreeItem.label); + const result = await this.deleteItem(isPluginType(workspaceTreeItem.category!) ? "plugin" : "client", workspaceTreeItem); vscode.window.showInformationMessage(`Delete item: ${workspaceTreeItem.label}`); } -} -export function deleteItem(context: vscode.ExtensionContext, workspaceItemType: string, key: string): Promise { - return connectToKiota(context, async (connection) => { - const request = new rpc.RequestType1( - workspaceItemType - ); - const result = await connection.sendRequest( - request, - key - ); + private async generatePluginAndRefreshUI(config: Partial, outputPath: string, descriptionLocation: string): Promise { + const pluginTypes = Array.isArray(config.pluginTypes) ? parsePluginType(config.pluginTypes) : [KiotaPluginType.ApiPlugin]; + const result = await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + cancellable: false, + title: vscode.l10n.t("Generating plugin...") + }, async (progress, _) => { + const start = performance.now(); + const result = await generatePlugin( + this._context, + descriptionLocation, + outputPath, + pluginTypes, + [], + [], + typeof config.pluginName === "string" + ? config.pluginName + : "ApiClient", + true, + true, + [], + ConsumerOperation.Remove, + config.workingDirectory + ); + const duration = performance.now() - start; + const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; + const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); + reporter.sendRawTelemetryEvent(`${extensionId}.generatePlugin.completed`, { + "pluginType": pluginTypes.toString(), + "errorsCount": errorsCount.toString(), + }, { + "duration": duration, + }); + return result; + }); + if (result) { + const isSuccess = await checkForSuccess(result); + if (!isSuccess) { + await exportLogsAndShowErrors(result); + } + const deepLinkParams = getDeepLinkParams(); + const isttkIntegration = deepLinkParams.source?.toLowerCase() === 'ttk'; + if (!isttkIntegration) { + void vscode.window.showInformationMessage(vscode.l10n.t('Plugin generated successfully.')); + } + } return result; - }); -}; \ No newline at end of file + } + private async generateClientAndRefreshUI(config: Partial, outputPath: string, descriptionLocation: string): Promise { + const language = + typeof config.language === "string" + ? parseGenerationLanguage(config.language) + : KiotaGenerationLanguage.CSharp; + const result = await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + cancellable: false, + title: vscode.l10n.t("Generating client...") + }, async (progress, _) => { + const start = performance.now(); + const result = await generateClient( + this._context, + descriptionLocation, + outputPath, + language, + [], + [], + typeof config.clientClassName === "string" + ? config.clientClassName + : "ApiClient", + typeof config.clientNamespaceName === "string" + ? config.clientNamespaceName + : "ApiSdk", + true, + true, + true, + true, + [], + [], + [], + [], + true, + ConsumerOperation.Remove, + config.workingDirectory + ); + const duration = performance.now() - start; + const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; + const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); + reporter.sendRawTelemetryEvent(`${extensionId}.generateClient.completed`, { + "language": generationLanguageToString(language), + "errorsCount": errorsCount.toString(), + }, { + "duration": duration, + }); + return result; + }); + + if (result) { + const isSuccess = await checkForSuccess(result); + if (!isSuccess) { + await exportLogsAndShowErrors(result); + } + void vscode.window.showInformationMessage(vscode.l10n.t('Generation completed successfully.')); + } + return result; + } + + private async deleteItem(type: string, workspaceTreeItem: WorkspaceTreeItem): Promise { + const outputPath = workspaceTreeItem.properties?.outputPath!; + const descriptionUrl = workspaceTreeItem.properties?.descriptionLocation!; + const config: Partial = { + pluginTypes: [workspaceTreeItem.properties?.types!], + workingDirectory: getWorkspaceJsonDirectory(), + }; + if (type === "plugin") { + return await this.generatePluginAndRefreshUI(config, outputPath, descriptionUrl); + } else { + return await this.generateClientAndRefreshUI(config, outputPath, descriptionUrl); + } + } +} \ No newline at end of file From 232f108661d8152208a6bf554ca9204eca470d7c Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 19 Nov 2024 14:54:17 +0300 Subject: [PATCH 14/36] support workspace tree provider --- .../commands/deleteWorkspaceItemCommand.ts | 115 ++++++++---------- vscode/microsoft-kiota/src/extension.ts | 2 +- 2 files changed, 53 insertions(+), 64 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts index 057ea525d0..9818439c6c 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts @@ -1,23 +1,21 @@ +import * as path from 'path'; import * as vscode from "vscode"; -import { extensionId, treeViewFocusCommand } from "../constants"; -import { WorkspaceTreeItem } from "../providers/workspaceTreeProvider"; -import { Command } from "./Command"; -import { ConsumerOperation, generationLanguageToString, getLogEntriesForLevel, KiotaLogEntry, LogLevel } from "../kiotaInterop"; -import { getWorkspaceJsonDirectory, isPluginType, parseGenerationLanguage, parsePluginType } from "../util"; -import { generateClient } from "./generate/generateClient"; import TelemetryReporter from "@vscode/extension-telemetry"; -import { getDeepLinkParams } from "../handlers/deepLinkParamsHandler"; +import { extensionId } from "../constants"; +import { ClientObjectProperties, ConsumerOperation, generationLanguageToString, getLogEntriesForLevel, KiotaLogEntry, LogLevel, PluginObjectProperties } from "../kiotaInterop"; import { GenerateState } from "../modules/steps/generateSteps"; -import { KiotaPluginType, KiotaGenerationLanguage } from "../types/enums"; -import { ExtensionSettings } from "../types/extensionSettings"; +import { WorkspaceTreeItem, WorkspaceTreeProvider } from "../providers/workspaceTreeProvider"; +import { KiotaGenerationLanguage, KiotaPluginType } from "../types/enums"; +import { getWorkspaceJsonDirectory, isPluginType, parseGenerationLanguage, parsePluginType } from "../util"; import { exportLogsAndShowErrors } from "../utilities/logging"; +import { Command } from "./Command"; +import { generateClient } from "./generate/generateClient"; import { generatePlugin } from "./generate/generatePlugin"; import { checkForSuccess } from "./generate/generation-util"; -import { getLanguageInformationForDescription } from "./generate/getLanguageInformation"; export class DeleteWorkspaceItemCommand extends Command { - constructor(private _context: vscode.ExtensionContext) { + constructor(private _context: vscode.ExtensionContext, private _workspaceTreeProvider: WorkspaceTreeProvider) { super(); } @@ -27,15 +25,45 @@ export class DeleteWorkspaceItemCommand extends Command { public async execute(workspaceTreeItem: WorkspaceTreeItem): Promise { const result = await this.deleteItem(isPluginType(workspaceTreeItem.category!) ? "plugin" : "client", workspaceTreeItem); - vscode.window.showInformationMessage(`Delete item: ${workspaceTreeItem.label}`); + if (result) { + const isSuccess = await checkForSuccess(result); + if (isSuccess) { + await this._workspaceTreeProvider.refreshView(); + void vscode.window.showInformationMessage(vscode.l10n.t(`${workspaceTreeItem.label} removed successfully.`)); + } else { + await exportLogsAndShowErrors(result); + } + } + } + + private async deleteItem(type: string, workspaceTreeItem: WorkspaceTreeItem): Promise { + const outputPath = workspaceTreeItem.properties?.outputPath!; + const descriptionUrl = workspaceTreeItem.properties?.descriptionLocation!; + + const config: Partial = { + workingDirectory: getWorkspaceJsonDirectory(), + }; + const absoluteOutputPath = path.join(config.workingDirectory!, outputPath); + + if (type === "plugin") { + const properties = workspaceTreeItem.properties as PluginObjectProperties; + config.pluginTypes = properties.types; + config.pluginName = workspaceTreeItem.label; + return await this.removePlugin(config, absoluteOutputPath, descriptionUrl); + } else { + const properties = workspaceTreeItem.properties as ClientObjectProperties; + config.clientClassName = workspaceTreeItem.label; + config.clientNamespaceName = properties.clientNamespaceName; + return await this.removeClient(config, absoluteOutputPath, descriptionUrl); + } } - private async generatePluginAndRefreshUI(config: Partial, outputPath: string, descriptionLocation: string): Promise { + private async removePlugin(config: Partial, outputPath: string, descriptionLocation: string): Promise { const pluginTypes = Array.isArray(config.pluginTypes) ? parsePluginType(config.pluginTypes) : [KiotaPluginType.ApiPlugin]; const result = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, - title: vscode.l10n.t("Generating plugin...") + title: vscode.l10n.t("Removing plugin...") }, async (progress, _) => { const start = performance.now(); const result = await generatePlugin( @@ -45,9 +73,7 @@ export class DeleteWorkspaceItemCommand extends Command { pluginTypes, [], [], - typeof config.pluginName === "string" - ? config.pluginName - : "ApiClient", + config.pluginName!, true, true, [], @@ -57,7 +83,7 @@ export class DeleteWorkspaceItemCommand extends Command { const duration = performance.now() - start; const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); - reporter.sendRawTelemetryEvent(`${extensionId}.generatePlugin.completed`, { + reporter.sendRawTelemetryEvent(`${extensionId}.removePlugin.completed`, { "pluginType": pluginTypes.toString(), "errorsCount": errorsCount.toString(), }, { @@ -65,20 +91,9 @@ export class DeleteWorkspaceItemCommand extends Command { }); return result; }); - if (result) { - const isSuccess = await checkForSuccess(result); - if (!isSuccess) { - await exportLogsAndShowErrors(result); - } - const deepLinkParams = getDeepLinkParams(); - const isttkIntegration = deepLinkParams.source?.toLowerCase() === 'ttk'; - if (!isttkIntegration) { - void vscode.window.showInformationMessage(vscode.l10n.t('Plugin generated successfully.')); - } - } return result; } - private async generateClientAndRefreshUI(config: Partial, outputPath: string, descriptionLocation: string): Promise { + private async removeClient(config: Partial, outputPath: string, descriptionLocation: string): Promise { const language = typeof config.language === "string" ? parseGenerationLanguage(config.language) @@ -86,7 +101,7 @@ export class DeleteWorkspaceItemCommand extends Command { const result = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, - title: vscode.l10n.t("Generating client...") + title: vscode.l10n.t("Removing client...") }, async (progress, _) => { const start = performance.now(); const result = await generateClient( @@ -96,28 +111,24 @@ export class DeleteWorkspaceItemCommand extends Command { language, [], [], - typeof config.clientClassName === "string" - ? config.clientClassName - : "ApiClient", - typeof config.clientNamespaceName === "string" - ? config.clientNamespaceName - : "ApiSdk", - true, - true, + config.clientClassName!, + config.clientNamespaceName! as string, + false, true, true, + false, [], [], [], [], - true, + false, ConsumerOperation.Remove, config.workingDirectory ); const duration = performance.now() - start; const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); - reporter.sendRawTelemetryEvent(`${extensionId}.generateClient.completed`, { + reporter.sendRawTelemetryEvent(`${extensionId}.removeClient.completed`, { "language": generationLanguageToString(language), "errorsCount": errorsCount.toString(), }, { @@ -125,28 +136,6 @@ export class DeleteWorkspaceItemCommand extends Command { }); return result; }); - - if (result) { - const isSuccess = await checkForSuccess(result); - if (!isSuccess) { - await exportLogsAndShowErrors(result); - } - void vscode.window.showInformationMessage(vscode.l10n.t('Generation completed successfully.')); - } return result; } - - private async deleteItem(type: string, workspaceTreeItem: WorkspaceTreeItem): Promise { - const outputPath = workspaceTreeItem.properties?.outputPath!; - const descriptionUrl = workspaceTreeItem.properties?.descriptionLocation!; - const config: Partial = { - pluginTypes: [workspaceTreeItem.properties?.types!], - workingDirectory: getWorkspaceJsonDirectory(), - }; - if (type === "plugin") { - return await this.generatePluginAndRefreshUI(config, outputPath, descriptionUrl); - } else { - return await this.generateClientAndRefreshUI(config, outputPath, descriptionUrl); - } - } } \ No newline at end of file diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index e2fabe9b9b..a379dbedc0 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -82,7 +82,7 @@ export async function activate( const statusCommand = new StatusCommand(); const selectLockCommand = new SelectLockCommand(openApiTreeProvider); const updateClientsCommand = new UpdateClientsCommand(context); - const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context); + const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context, workspaceTreeProvider); await loadTreeView(context, workspaceTreeProvider, regenerateCommand); await checkForLockFileAndPrompt(context); From 5096870d71b6635051a9067e5604b9dc68453a75 Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 19 Nov 2024 15:02:31 +0300 Subject: [PATCH 15/36] don't clean output --- .../src/commands/deleteWorkspaceItemCommand.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts index 9818439c6c..63b0590d3b 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts @@ -75,7 +75,7 @@ export class DeleteWorkspaceItemCommand extends Command { [], config.pluginName!, true, - true, + false, [], ConsumerOperation.Remove, config.workingDirectory @@ -115,7 +115,7 @@ export class DeleteWorkspaceItemCommand extends Command { config.clientNamespaceName! as string, false, true, - true, + false, false, [], [], From 4ee59e7cb1c74dc0240e3d03b59509fe7f2b10e4 Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 19 Nov 2024 15:38:53 +0300 Subject: [PATCH 16/36] add remove client async and remove plugin async functions to the RPC server --- src/kiota/Rpc/IServer.cs | 2 ++ src/kiota/Rpc/Server.cs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/kiota/Rpc/IServer.cs b/src/kiota/Rpc/IServer.cs index de7a284c0a..2ec90beb7a 100644 --- a/src/kiota/Rpc/IServer.cs +++ b/src/kiota/Rpc/IServer.cs @@ -14,4 +14,6 @@ internal interface IServer Task InfoForDescriptionAsync(string descriptionPath, bool clearCache, CancellationToken cancellationToken); Task> GeneratePluginAsync(string openAPIFilePath, string outputPath, PluginType[] pluginTypes, string[] includePatterns, string[] excludePatterns, string clientClassName, bool cleanOutput, bool clearCache, string[] disabledValidationRules, ConsumerOperation operation, CancellationToken cancellationToken); Task> MigrateFromLockFileAsync(string lockDirectoryPath, CancellationToken cancellationToken); + Task> RemoveClientAsync(string clientName, bool cleanOutput, CancellationToken cancellationToken); + Task> RemovePluginAsync(string pluginName, bool cleanOutput, CancellationToken cancellationToken); } diff --git a/src/kiota/Rpc/Server.cs b/src/kiota/Rpc/Server.cs index e866eab942..4fd6690283 100644 --- a/src/kiota/Rpc/Server.cs +++ b/src/kiota/Rpc/Server.cs @@ -299,4 +299,38 @@ private static string NormalizeSlashesInPath(string path) return path.Replace('/', '\\'); return path.Replace('\\', '/'); } + + public async Task> RemoveClientAsync(string clientName, bool cleanOutput, CancellationToken cancellationToken) + { + ArgumentException.ThrowIfNullOrEmpty(clientName); + var logger = new ForwardedLogger(); + try + { + var workspaceManagementService = new WorkspaceManagementService(logger, httpClient, IsConfigPreviewEnabled.Value); + await workspaceManagementService.RemoveClientAsync(clientName, cleanOutput, cancellationToken).ConfigureAwait(false); + logger.LogInformation($"Client {clientName} removed successfully!"); + } + catch (Exception ex) + { + logger.LogCritical(ex, "error removing the plugin: {exceptionMessage}", ex.Message); + } + return logger.LogEntries; + } + + public async Task> RemovePluginAsync(string pluginName, bool cleanOutput, CancellationToken cancellationToken) + { + ArgumentException.ThrowIfNullOrEmpty(pluginName); + var logger = new ForwardedLogger(); + try + { + var workspaceManagementService = new WorkspaceManagementService(logger, httpClient, IsConfigPreviewEnabled.Value); + await workspaceManagementService.RemovePluginAsync(pluginName, cleanOutput, cancellationToken).ConfigureAwait(false); + logger.LogInformation($"Plugin {pluginName} removed successfully!"); + } + catch (Exception ex) + { + logger.LogCritical(ex, "error removing the plugin: {exceptionMessage}", ex.Message); + } + return logger.LogEntries; + } } From 0a6763f834ef0f5620e265242ccedff945ec22a4 Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 19 Nov 2024 16:23:00 +0300 Subject: [PATCH 17/36] connect to kiota rpc functions --- .../commands/deleteWorkspaceItemCommand.ts | 104 +++++++----------- 1 file changed, 42 insertions(+), 62 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts index 63b0590d3b..5228b8556b 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts @@ -1,17 +1,13 @@ -import * as path from 'path'; import * as vscode from "vscode"; +import * as rpc from "vscode-jsonrpc/node"; import TelemetryReporter from "@vscode/extension-telemetry"; import { extensionId } from "../constants"; -import { ClientObjectProperties, ConsumerOperation, generationLanguageToString, getLogEntriesForLevel, KiotaLogEntry, LogLevel, PluginObjectProperties } from "../kiotaInterop"; -import { GenerateState } from "../modules/steps/generateSteps"; +import { connectToKiota, getLogEntriesForLevel, KiotaLogEntry, LogLevel } from "../kiotaInterop"; import { WorkspaceTreeItem, WorkspaceTreeProvider } from "../providers/workspaceTreeProvider"; -import { KiotaGenerationLanguage, KiotaPluginType } from "../types/enums"; -import { getWorkspaceJsonDirectory, isPluginType, parseGenerationLanguage, parsePluginType } from "../util"; +import { isPluginType } from "../util"; import { exportLogsAndShowErrors } from "../utilities/logging"; import { Command } from "./Command"; -import { generateClient } from "./generate/generateClient"; -import { generatePlugin } from "./generate/generatePlugin"; import { checkForSuccess } from "./generate/generation-util"; export class DeleteWorkspaceItemCommand extends Command { @@ -37,54 +33,30 @@ export class DeleteWorkspaceItemCommand extends Command { } private async deleteItem(type: string, workspaceTreeItem: WorkspaceTreeItem): Promise { - const outputPath = workspaceTreeItem.properties?.outputPath!; - const descriptionUrl = workspaceTreeItem.properties?.descriptionLocation!; - - const config: Partial = { - workingDirectory: getWorkspaceJsonDirectory(), - }; - const absoluteOutputPath = path.join(config.workingDirectory!, outputPath); - if (type === "plugin") { - const properties = workspaceTreeItem.properties as PluginObjectProperties; - config.pluginTypes = properties.types; - config.pluginName = workspaceTreeItem.label; - return await this.removePlugin(config, absoluteOutputPath, descriptionUrl); + return await this.deletePlugin(workspaceTreeItem.label); } else { - const properties = workspaceTreeItem.properties as ClientObjectProperties; - config.clientClassName = workspaceTreeItem.label; - config.clientNamespaceName = properties.clientNamespaceName; - return await this.removeClient(config, absoluteOutputPath, descriptionUrl); + return await this.deleteClient(workspaceTreeItem.label); } } - private async removePlugin(config: Partial, outputPath: string, descriptionLocation: string): Promise { - const pluginTypes = Array.isArray(config.pluginTypes) ? parsePluginType(config.pluginTypes) : [KiotaPluginType.ApiPlugin]; + private async deletePlugin(pluginName: string): Promise { const result = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, title: vscode.l10n.t("Removing plugin...") }, async (progress, _) => { const start = performance.now(); - const result = await generatePlugin( + const result = await removePlugin( this._context, - descriptionLocation, - outputPath, - pluginTypes, - [], - [], - config.pluginName!, - true, + pluginName!, false, - [], - ConsumerOperation.Remove, - config.workingDirectory ); const duration = performance.now() - start; const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); reporter.sendRawTelemetryEvent(`${extensionId}.removePlugin.completed`, { - "pluginType": pluginTypes.toString(), + "pluginType": pluginName, "errorsCount": errorsCount.toString(), }, { "duration": duration, @@ -93,43 +65,23 @@ export class DeleteWorkspaceItemCommand extends Command { }); return result; } - private async removeClient(config: Partial, outputPath: string, descriptionLocation: string): Promise { - const language = - typeof config.language === "string" - ? parseGenerationLanguage(config.language) - : KiotaGenerationLanguage.CSharp; + private async deleteClient(clientName: string): Promise { const result = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, title: vscode.l10n.t("Removing client...") }, async (progress, _) => { const start = performance.now(); - const result = await generateClient( + const result = await removeClient( this._context, - descriptionLocation, - outputPath, - language, - [], - [], - config.clientClassName!, - config.clientNamespaceName! as string, - false, - true, - false, - false, - [], - [], - [], - [], + clientName, false, - ConsumerOperation.Remove, - config.workingDirectory ); const duration = performance.now() - start; const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); reporter.sendRawTelemetryEvent(`${extensionId}.removeClient.completed`, { - "language": generationLanguageToString(language), + "client": clientName, "errorsCount": errorsCount.toString(), }, { "duration": duration, @@ -138,4 +90,32 @@ export class DeleteWorkspaceItemCommand extends Command { }); return result; } -} \ No newline at end of file +} + +export function removePlugin(context: vscode.ExtensionContext, pluginName: string, cleanOutput: boolean): Promise { + return connectToKiota(context, async (connection) => { + const request = new rpc.RequestType2( + "RemovePlugin" + ); + const result = await connection.sendRequest( + request, + pluginName, + cleanOutput + ); + return result; + }); +}; + +export function removeClient(context: vscode.ExtensionContext, clientName: string, cleanOutput: boolean): Promise { + return connectToKiota(context, async (connection) => { + const request = new rpc.RequestType2( + "RemoveClient" + ); + const result = await connection.sendRequest( + request, + clientName, + cleanOutput + ); + return result; + }); +}; \ No newline at end of file From a10437277074ed953dcc5f5f2359f42dd991acd2 Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 19 Nov 2024 16:43:16 +0300 Subject: [PATCH 18/36] isolate in folder --- .../deleteWorkspaceItemCommand.ts | 43 ++++--------------- .../deleteWorkspaceItem/removeItem.ts | 32 ++++++++++++++ vscode/microsoft-kiota/src/extension.ts | 2 +- 3 files changed, 41 insertions(+), 36 deletions(-) rename vscode/microsoft-kiota/src/commands/{ => deleteWorkspaceItem}/deleteWorkspaceItemCommand.ts (69%) create mode 100644 vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/removeItem.ts diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts similarity index 69% rename from vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts rename to vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index 5228b8556b..3bbf73fe44 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -1,14 +1,14 @@ import * as vscode from "vscode"; -import * as rpc from "vscode-jsonrpc/node"; import TelemetryReporter from "@vscode/extension-telemetry"; -import { extensionId } from "../constants"; -import { connectToKiota, getLogEntriesForLevel, KiotaLogEntry, LogLevel } from "../kiotaInterop"; -import { WorkspaceTreeItem, WorkspaceTreeProvider } from "../providers/workspaceTreeProvider"; -import { isPluginType } from "../util"; -import { exportLogsAndShowErrors } from "../utilities/logging"; -import { Command } from "./Command"; -import { checkForSuccess } from "./generate/generation-util"; +import { extensionId } from "../../constants"; +import { getLogEntriesForLevel, KiotaLogEntry, LogLevel } from "../../kiotaInterop"; +import { WorkspaceTreeItem, WorkspaceTreeProvider } from "../../providers/workspaceTreeProvider"; +import { isPluginType } from "../../util"; +import { exportLogsAndShowErrors } from "../../utilities/logging"; +import { Command } from "../Command"; +import { checkForSuccess } from "../generate/generation-util"; +import { removeClient, removePlugin } from "./removeItem"; export class DeleteWorkspaceItemCommand extends Command { constructor(private _context: vscode.ExtensionContext, private _workspaceTreeProvider: WorkspaceTreeProvider) { @@ -92,30 +92,3 @@ export class DeleteWorkspaceItemCommand extends Command { } } -export function removePlugin(context: vscode.ExtensionContext, pluginName: string, cleanOutput: boolean): Promise { - return connectToKiota(context, async (connection) => { - const request = new rpc.RequestType2( - "RemovePlugin" - ); - const result = await connection.sendRequest( - request, - pluginName, - cleanOutput - ); - return result; - }); -}; - -export function removeClient(context: vscode.ExtensionContext, clientName: string, cleanOutput: boolean): Promise { - return connectToKiota(context, async (connection) => { - const request = new rpc.RequestType2( - "RemoveClient" - ); - const result = await connection.sendRequest( - request, - clientName, - cleanOutput - ); - return result; - }); -}; \ No newline at end of file diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/removeItem.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/removeItem.ts new file mode 100644 index 0000000000..8b906d30e9 --- /dev/null +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/removeItem.ts @@ -0,0 +1,32 @@ +import * as vscode from "vscode"; +import * as rpc from "vscode-jsonrpc/node"; + +import { connectToKiota, KiotaLogEntry } from "../../kiotaInterop"; + +export function removePlugin(context: vscode.ExtensionContext, pluginName: string, cleanOutput: boolean): Promise { + return connectToKiota(context, async (connection) => { + const request = new rpc.RequestType2( + "RemovePlugin" + ); + const result = await connection.sendRequest( + request, + pluginName, + cleanOutput + ); + return result; + }); +}; + +export function removeClient(context: vscode.ExtensionContext, clientName: string, cleanOutput: boolean): Promise { + return connectToKiota(context, async (connection) => { + const request = new rpc.RequestType2( + "RemoveClient" + ); + const result = await connection.sendRequest( + request, + clientName, + cleanOutput + ); + return result; + }); +}; \ No newline at end of file diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index a379dbedc0..7428af4906 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -4,7 +4,7 @@ import TelemetryReporter from '@vscode/extension-telemetry'; import * as vscode from "vscode"; import { CloseDescriptionCommand } from './commands/closeDescriptionCommand'; -import { DeleteWorkspaceItemCommand } from './commands/deleteWorkspaceItemCommand'; +import { DeleteWorkspaceItemCommand } from './commands/deleteWorkspaceItem/deleteWorkspaceItemCommand'; import { EditPathsCommand } from './commands/editPathsCommand'; import { GenerateClientCommand } from './commands/generate/generateClientCommand'; import { displayGenerationResults } from './commands/generate/generation-util'; From bca6af028d74c1cc608c864f04f9ae1526fa3b97 Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 19 Nov 2024 17:11:53 +0300 Subject: [PATCH 19/36] remove regeneration, change icon, call select --- vscode/microsoft-kiota/package.json | 8 ++++---- vscode/microsoft-kiota/src/extension.ts | 2 +- .../src/providers/workspaceTreeProvider.ts | 16 ++++------------ 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/vscode/microsoft-kiota/package.json b/vscode/microsoft-kiota/package.json index 0ed9c93241..6d456d855a 100644 --- a/vscode/microsoft-kiota/package.json +++ b/vscode/microsoft-kiota/package.json @@ -305,7 +305,7 @@ "group": "inline@5" }, { - "command": "kiota.workspace.regenerate", + "command": "kiota.workspace.selectItem", "when": "viewItem == item", "group": "inline@1" }, @@ -451,10 +451,10 @@ "title": "%kiota.migrateClients.title%" }, { - "command": "kiota.workspace.regenerate", - "title": "Regenerate", + "command": "kiota.workspace.selectItem", + "title": "Select", "category": "Kiota", - "icon": "$(debug-rerun)" + "icon": "$(bracket)" }, { "command": "kiota.workspace.deleteItem", diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index 7428af4906..15bff27e2f 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -84,7 +84,7 @@ export async function activate( const updateClientsCommand = new UpdateClientsCommand(context); const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context, workspaceTreeProvider); - await loadTreeView(context, workspaceTreeProvider, regenerateCommand); + await loadTreeView(context, workspaceTreeProvider); await checkForLockFileAndPrompt(context); let codeLensProvider = new CodeLensProvider(); context.subscriptions.push( diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 620163b669..4ad22d0506 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -108,19 +108,10 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider { await vscode.window.showTextDocument(resource); } -export async function loadTreeView(context: vscode.ExtensionContext, treeDataProvider: WorkspaceTreeProvider, regenerateCommand: RegenerateCommand): Promise { +export async function loadTreeView(context: vscode.ExtensionContext, treeDataProvider: WorkspaceTreeProvider): Promise { context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(async () => { treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await vscode.commands.executeCommand('kiota.workspace.refresh'); // Refresh the tree view when workspace folders change @@ -160,10 +151,11 @@ export async function loadTreeView(context: vscode.ExtensionContext, treeDataPro await treeDataProvider.refreshView(); })); context.subscriptions.push( - vscode.commands.registerCommand('kiota.workspace.regenerate', async (workspaceTreeItem: WorkspaceTreeItem) => { + vscode.commands.registerCommand('kiota.workspace.selectItem', async (workspaceTreeItem: WorkspaceTreeItem) => { const { label, properties, category } = workspaceTreeItem; - await regenerateCommand.execute({ clientOrPluginKey: label, clientOrPluginObject: properties!, generationType: category! }); + await vscode.commands.executeCommand('kiota.editPaths', label, properties, category); }) ); } +; \ No newline at end of file From cc8b44f5dee4ea6028d3e87d31ff7d3213092c6b Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 11:03:53 +0300 Subject: [PATCH 20/36] add logging dependency --- .../deleteWorkspaceItemCommand.ts | 13 ++++++++----- vscode/microsoft-kiota/src/extension.ts | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index 3bbf73fe44..1e4472ccef 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -1,17 +1,20 @@ +import TelemetryReporter from "@vscode/extension-telemetry"; import * as vscode from "vscode"; -import TelemetryReporter from "@vscode/extension-telemetry"; import { extensionId } from "../../constants"; import { getLogEntriesForLevel, KiotaLogEntry, LogLevel } from "../../kiotaInterop"; import { WorkspaceTreeItem, WorkspaceTreeProvider } from "../../providers/workspaceTreeProvider"; import { isPluginType } from "../../util"; -import { exportLogsAndShowErrors } from "../../utilities/logging"; +import { checkForSuccess, exportLogsAndShowErrors } from "../../utilities/logging"; import { Command } from "../Command"; -import { checkForSuccess } from "../generate/generation-util"; import { removeClient, removePlugin } from "./removeItem"; export class DeleteWorkspaceItemCommand extends Command { - constructor(private _context: vscode.ExtensionContext, private _workspaceTreeProvider: WorkspaceTreeProvider) { + constructor( + private _context: vscode.ExtensionContext, + private _workspaceTreeProvider: WorkspaceTreeProvider, + private _kiotaOutputChannel: vscode.LogOutputChannel + ) { super(); } @@ -27,7 +30,7 @@ export class DeleteWorkspaceItemCommand extends Command { await this._workspaceTreeProvider.refreshView(); void vscode.window.showInformationMessage(vscode.l10n.t(`${workspaceTreeItem.label} removed successfully.`)); } else { - await exportLogsAndShowErrors(result); + await exportLogsAndShowErrors(result, this._kiotaOutputChannel); } } } diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index c4bfbe0c92..9269cdef73 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -81,7 +81,7 @@ export async function activate( const closeDescriptionCommand = new CloseDescriptionCommand(openApiTreeProvider); const statusCommand = new StatusCommand(); const selectLockCommand = new SelectLockCommand(openApiTreeProvider); - const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context, workspaceTreeProvider); + const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context, workspaceTreeProvider, kiotaOutputChannel); const updateClientsCommand = new UpdateClientsCommand(context, kiotaOutputChannel); await loadTreeView(context, workspaceTreeProvider); From 72460cd9228c002ae4ca0e522f0f0e65bd7baa09 Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 12:56:09 +0300 Subject: [PATCH 21/36] refresh view after deleting workspace item --- .../deleteWorkspaceItemCommand.ts | 11 +++++------ .../microsoft-kiota/src/commands/editPathsCommand.ts | 12 ++++-------- vscode/microsoft-kiota/src/extension.ts | 4 ++-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index 1e4472ccef..5bef97918b 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -3,16 +3,15 @@ import * as vscode from "vscode"; import { extensionId } from "../../constants"; import { getLogEntriesForLevel, KiotaLogEntry, LogLevel } from "../../kiotaInterop"; -import { WorkspaceTreeItem, WorkspaceTreeProvider } from "../../providers/workspaceTreeProvider"; +import { WorkspaceTreeItem } from "../../providers/workspaceTreeProvider"; import { isPluginType } from "../../util"; -import { checkForSuccess, exportLogsAndShowErrors } from "../../utilities/logging"; +import { exportLogsAndShowErrors } from "../../utilities/logging"; import { Command } from "../Command"; import { removeClient, removePlugin } from "./removeItem"; export class DeleteWorkspaceItemCommand extends Command { constructor( - private _context: vscode.ExtensionContext, - private _workspaceTreeProvider: WorkspaceTreeProvider, + private _context: vscode.ExtensionContext, private _kiotaOutputChannel: vscode.LogOutputChannel ) { super(); @@ -25,10 +24,10 @@ export class DeleteWorkspaceItemCommand extends Command { public async execute(workspaceTreeItem: WorkspaceTreeItem): Promise { const result = await this.deleteItem(isPluginType(workspaceTreeItem.category!) ? "plugin" : "client", workspaceTreeItem); if (result) { - const isSuccess = await checkForSuccess(result); + const isSuccess = result.some(k => k.message.includes('removed successfully')); if (isSuccess) { - await this._workspaceTreeProvider.refreshView(); void vscode.window.showInformationMessage(vscode.l10n.t(`${workspaceTreeItem.label} removed successfully.`)); + await vscode.commands.executeCommand('kiota.workspace.refresh'); } else { await exportLogsAndShowErrors(result, this._kiotaOutputChannel); } diff --git a/vscode/microsoft-kiota/src/commands/editPathsCommand.ts b/vscode/microsoft-kiota/src/commands/editPathsCommand.ts index 7246478a43..2775d21d86 100644 --- a/vscode/microsoft-kiota/src/commands/editPathsCommand.ts +++ b/vscode/microsoft-kiota/src/commands/editPathsCommand.ts @@ -1,7 +1,8 @@ +import * as vscode from "vscode"; + import { extensionId, treeViewId } from "../constants"; import { ClientOrPluginProperties } from "../kiotaInterop"; import { OpenApiTreeProvider } from "../providers/openApiTreeProvider"; -import { WorkspaceTreeProvider } from "../providers/workspaceTreeProvider"; import { WorkspaceGenerationContext } from "../types/WorkspaceGenerationContext"; import { updateTreeViewIcons } from "../util"; import { openTreeViewWithProgress } from "../utilities/progress"; @@ -9,13 +10,8 @@ import { Command } from "./Command"; export class EditPathsCommand extends Command { - private _openApiTreeProvider: OpenApiTreeProvider; - private _workspaceTreeProvider: WorkspaceTreeProvider; - - public constructor(openApiTreeProvider: OpenApiTreeProvider, workspaceTreeProvider: WorkspaceTreeProvider) { + public constructor(private _openApiTreeProvider: OpenApiTreeProvider) { super(); - this._openApiTreeProvider = openApiTreeProvider; - this._workspaceTreeProvider = workspaceTreeProvider; } public getName(): string { @@ -26,7 +22,7 @@ export class EditPathsCommand extends Command { await this.loadEditPaths(clientOrPluginKey!, clientOrPluginObject!); this._openApiTreeProvider.resetInitialState(); await updateTreeViewIcons(treeViewId, false, true); - await this._workspaceTreeProvider.refreshView(); + await vscode.commands.executeCommand('kiota.workspace.refresh'); } private async loadEditPaths(clientOrPluginKey: string, clientOrPluginObject: ClientOrPluginProperties) { diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index 9269cdef73..afdbd4370e 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -73,7 +73,7 @@ export async function activate( const removeFromSelectedEndpointsCommand = new RemoveFromSelectedEndpointsCommand(openApiTreeProvider); const filterDescriptionCommand = new FilterDescriptionCommand(openApiTreeProvider); const openDocumentationPageCommand = new OpenDocumentationPageCommand(); - const editPathsCommand = new EditPathsCommand(openApiTreeProvider, workspaceTreeProvider); + const editPathsCommand = new EditPathsCommand(openApiTreeProvider); const searchOrOpenApiDescriptionCommand = new SearchOrOpenApiDescriptionCommand(openApiTreeProvider, context); const generateClientCommand = new GenerateClientCommand(openApiTreeProvider, context, dependenciesInfoProvider, setWorkspaceGenerationContext, kiotaOutputChannel); const regenerateCommand = new RegenerateCommand(context, openApiTreeProvider, kiotaOutputChannel); @@ -81,7 +81,7 @@ export async function activate( const closeDescriptionCommand = new CloseDescriptionCommand(openApiTreeProvider); const statusCommand = new StatusCommand(); const selectLockCommand = new SelectLockCommand(openApiTreeProvider); - const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context, workspaceTreeProvider, kiotaOutputChannel); + const deleteWorkspaceItemCommand = new DeleteWorkspaceItemCommand(context, kiotaOutputChannel); const updateClientsCommand = new UpdateClientsCommand(context, kiotaOutputChannel); await loadTreeView(context, workspaceTreeProvider); From 8983f7141b482f5cd58699b19b68b737fd3a337e Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 14:26:26 +0300 Subject: [PATCH 22/36] load works[ace content on refresh --- .../microsoft-kiota/src/providers/workspaceTreeProvider.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 4ad22d0506..0844a8f4ad 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -1,6 +1,5 @@ import * as vscode from 'vscode'; -import { RegenerateCommand } from '../commands/regenerate/regenerateCommand'; import { CLIENTS, KIOTA_WORKSPACE_FILE, PLUGINS } from '../constants'; import { ClientOrPluginProperties } from '../kiotaInterop'; import { getWorkspaceJsonPath, isClientType, isKiotaWorkspaceFilePresent, isPluginType } from '../util'; @@ -36,11 +35,12 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider { - this._onDidChangeTreeData.fire(); + this.loadWorkspaceContent(); + this._onDidChangeTreeData.fire(); } async getChildren(element?: WorkspaceTreeItem): Promise { From 96095f0b689a64db570711374bbe0f02198fdd76 Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 14:26:55 +0300 Subject: [PATCH 23/36] bump version numbrt to match kiota with changes --- vscode/microsoft-kiota/package-lock.json | 4 ++-- vscode/microsoft-kiota/package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vscode/microsoft-kiota/package-lock.json b/vscode/microsoft-kiota/package-lock.json index 84757fb993..89039552fd 100644 --- a/vscode/microsoft-kiota/package-lock.json +++ b/vscode/microsoft-kiota/package-lock.json @@ -1,12 +1,12 @@ { "name": "kiota", - "version": "1.18.100000001", + "version": "1.21.100000001", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kiota", - "version": "1.18.100000001", + "version": "1.21.100000001", "license": "MIT", "dependencies": { "@vscode/extension-telemetry": "^0.9.7", diff --git a/vscode/microsoft-kiota/package.json b/vscode/microsoft-kiota/package.json index 691e62fdf3..271581676e 100644 --- a/vscode/microsoft-kiota/package.json +++ b/vscode/microsoft-kiota/package.json @@ -3,8 +3,8 @@ "displayName": "Microsoft Kiota", "publisher": "ms-graph", "description": "Client generator for HTTP REST APIs described by OpenAPI which helps eliminate the need to take a dependency on a different API client for every API that you need to call, as well as limiting the generation to the exact API surface area you're interested in, thanks to a filtering capability.", - "version": "1.18.100000001", - "kiotaVersion": "1.18.0", + "version": "1.21.100000001", + "kiotaVersion": "1.21.0", "telemetryInstrumentationKey": "4c6357e0-daf9-42b5-bdfb-67878f8957b5", "icon": "images/logo.png", "engines": { From 95f03bcdd38cd4b3422645f626ec9f7ac6f225cc Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 15:07:30 +0300 Subject: [PATCH 24/36] use string formating --- .../commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index 5bef97918b..6aa318c508 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -26,7 +26,7 @@ export class DeleteWorkspaceItemCommand extends Command { if (result) { const isSuccess = result.some(k => k.message.includes('removed successfully')); if (isSuccess) { - void vscode.window.showInformationMessage(vscode.l10n.t(`${workspaceTreeItem.label} removed successfully.`)); + void vscode.window.showInformationMessage(vscode.l10n.t('{0} removed successfully.', workspaceTreeItem.label)); await vscode.commands.executeCommand('kiota.workspace.refresh'); } else { await exportLogsAndShowErrors(result, this._kiotaOutputChannel); From ce5afbe41f982ba5080dcb49ca54058f7bbfe5d3 Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 15:17:42 +0300 Subject: [PATCH 25/36] show no clients or plugins available message --- .../microsoft-kiota/src/providers/workspaceTreeProvider.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 0844a8f4ad..348c6d9ab1 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -15,7 +15,7 @@ export class WorkspaceTreeItem extends vscode.TreeItem { constructor( public readonly label: string, public readonly collapsibleState: vscode.TreeItemCollapsibleState, - public readonly type: 'root' | 'category' | 'item', + public readonly type: 'root' | 'category' | 'item' | 'info', public readonly category?: string, public readonly properties?: ClientOrPluginProperties, public command?: vscode.Command @@ -66,6 +66,9 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider 0) { children.push(new WorkspaceTreeItem(PLUGINS, vscode.TreeItemCollapsibleState.Expanded, 'category')); } + if (children.length === 0) { + children.push(new WorkspaceTreeItem(vscode.l10n.t("No clients or plugins are available"), vscode.TreeItemCollapsibleState.None, 'info')); + } return children; } From 00a381f754abd369e176227e0f6cc076bd3782da Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 15:48:22 +0300 Subject: [PATCH 26/36] use translated button names --- vscode/microsoft-kiota/package.json | 4 ++-- vscode/microsoft-kiota/package.nls.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vscode/microsoft-kiota/package.json b/vscode/microsoft-kiota/package.json index 271581676e..8fba022c74 100644 --- a/vscode/microsoft-kiota/package.json +++ b/vscode/microsoft-kiota/package.json @@ -452,13 +452,13 @@ }, { "command": "kiota.workspace.selectItem", - "title": "Select", + "title": "%kiota.openApiExplorer.editPaths.title%", "category": "Kiota", "icon": "$(bracket)" }, { "command": "kiota.workspace.deleteItem", - "title": "Delete", + "title": "%kiota.openApiExplorer.removeFromSelectedEndpoints.title%", "category": "Kiota", "icon": "$(trash)" } diff --git a/vscode/microsoft-kiota/package.nls.json b/vscode/microsoft-kiota/package.nls.json index 5c7baf619a..d1c0f02166 100644 --- a/vscode/microsoft-kiota/package.nls.json +++ b/vscode/microsoft-kiota/package.nls.json @@ -29,7 +29,7 @@ "kiota.openApiExplorer.openFile.title": "Open file", "kiota.workspace.name": "My Workspace", "kiota.openApiExplorer.regenerateButton.title": "Re-generate", - "kiota.openApiExplorer.editPaths.title": "Edit paths", + "kiota.openApiExplorer.editPaths.title": "Select", "kiota.openApiExplorer.refresh.title": "Refresh", "kiota.migrateClients.title": "Migrate API clients" } From cb9f26b01dbe85187b5cb097c3594acf918bea63 Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 16:03:31 +0300 Subject: [PATCH 27/36] change error message --- src/kiota/Rpc/Server.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kiota/Rpc/Server.cs b/src/kiota/Rpc/Server.cs index 4fd6690283..66cc24c251 100644 --- a/src/kiota/Rpc/Server.cs +++ b/src/kiota/Rpc/Server.cs @@ -312,7 +312,7 @@ public async Task> RemoveClientAsync(string clientName, bool clea } catch (Exception ex) { - logger.LogCritical(ex, "error removing the plugin: {exceptionMessage}", ex.Message); + logger.LogCritical(ex, "error removing the client: {exceptionMessage}", ex.Message); } return logger.LogEntries; } From 084c1aca8129fe000b6b3c1ef039b2026f7f6250 Mon Sep 17 00:00:00 2001 From: thewahome Date: Wed, 20 Nov 2024 16:05:18 +0300 Subject: [PATCH 28/36] remove unnecessary console log --- vscode/microsoft-kiota/src/providers/sharedService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/vscode/microsoft-kiota/src/providers/sharedService.ts b/vscode/microsoft-kiota/src/providers/sharedService.ts index 6ac324b0dc..91e481cd2f 100644 --- a/vscode/microsoft-kiota/src/providers/sharedService.ts +++ b/vscode/microsoft-kiota/src/providers/sharedService.ts @@ -21,7 +21,6 @@ export class SharedService { } public set(key: K, value: SharedState[K]): void { - console.log(`Setting ${key} to ${value}`); this.state.set(key, value); } From c951ffe6c2c14d3c5f91ba1b7f935a814dd9c49b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 21 Nov 2024 07:50:48 -0500 Subject: [PATCH 29/36] chore: removes duplication in server removal implementation Signed-off-by: Vincent Biret --- src/kiota/Rpc/Server.cs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/kiota/Rpc/Server.cs b/src/kiota/Rpc/Server.cs index 66cc24c251..b60155710b 100644 --- a/src/kiota/Rpc/Server.cs +++ b/src/kiota/Rpc/Server.cs @@ -300,37 +300,28 @@ private static string NormalizeSlashesInPath(string path) return path.Replace('\\', '/'); } - public async Task> RemoveClientAsync(string clientName, bool cleanOutput, CancellationToken cancellationToken) + public Task> RemoveClientAsync(string clientName, bool cleanOutput, CancellationToken cancellationToken) + => RemoveClientOrPluginAsync(clientName, cleanOutput, "Client", (workspaceManagementService, clientName, cleanOutput, cancellationToken) => workspaceManagementService.RemoveClientAsync(clientName, cleanOutput, cancellationToken), cancellationToken); + + private static async Task> RemoveClientOrPluginAsync(string clientName, bool cleanOutput, string typeName, Func removal, CancellationToken cancellationToken) { ArgumentException.ThrowIfNullOrEmpty(clientName); + ArgumentException.ThrowIfNullOrEmpty(typeName); + ArgumentNullException.ThrowIfNull(removal); var logger = new ForwardedLogger(); try { var workspaceManagementService = new WorkspaceManagementService(logger, httpClient, IsConfigPreviewEnabled.Value); - await workspaceManagementService.RemoveClientAsync(clientName, cleanOutput, cancellationToken).ConfigureAwait(false); - logger.LogInformation($"Client {clientName} removed successfully!"); + await removal(workspaceManagementService, clientName, cleanOutput, cancellationToken).ConfigureAwait(false); + logger.LogInformation("{TypeName} {ClientName} removed successfully!", typeName, clientName); } catch (Exception ex) { - logger.LogCritical(ex, "error removing the client: {exceptionMessage}", ex.Message); + logger.LogCritical(ex, "error removing the {TypeName}: {ExceptionMessage}", typeName.ToLowerInvariant(), ex.Message); } return logger.LogEntries; } public async Task> RemovePluginAsync(string pluginName, bool cleanOutput, CancellationToken cancellationToken) - { - ArgumentException.ThrowIfNullOrEmpty(pluginName); - var logger = new ForwardedLogger(); - try - { - var workspaceManagementService = new WorkspaceManagementService(logger, httpClient, IsConfigPreviewEnabled.Value); - await workspaceManagementService.RemovePluginAsync(pluginName, cleanOutput, cancellationToken).ConfigureAwait(false); - logger.LogInformation($"Plugin {pluginName} removed successfully!"); - } - catch (Exception ex) - { - logger.LogCritical(ex, "error removing the plugin: {exceptionMessage}", ex.Message); - } - return logger.LogEntries; - } + => await RemoveClientOrPluginAsync(pluginName, cleanOutput, "Plugin", (workspaceManagementService, pluginName, cleanOutput, cancellationToken) => workspaceManagementService.RemovePluginAsync(pluginName, cleanOutput, cancellationToken), cancellationToken); } From ddecb7d37112c989d296e93b994a7cc9b6140949 Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 22 Nov 2024 08:47:46 +0300 Subject: [PATCH 30/36] consolidate plugin and client deletion into a single method --- .../deleteWorkspaceItemCommand.ts | 43 ++++--------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index 6aa318c508..f443b33f86 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -35,55 +35,30 @@ export class DeleteWorkspaceItemCommand extends Command { } private async deleteItem(type: string, workspaceTreeItem: WorkspaceTreeItem): Promise { - if (type === "plugin") { - return await this.deletePlugin(workspaceTreeItem.label); - } else { - return await this.deleteClient(workspaceTreeItem.label); - } + return await this.removeWorkspaceItem(workspaceTreeItem.label, type); } - private async deletePlugin(pluginName: string): Promise { + private async removeWorkspaceItem(itemName: string, type: string): Promise { const result = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, - title: vscode.l10n.t("Removing plugin...") + title: vscode.l10n.t(`Removing ${type}...`) }, async (progress, _) => { const start = performance.now(); - const result = await removePlugin( + const result = type === "plugin" ? await removePlugin( this._context, - pluginName!, + itemName, false, - ); - const duration = performance.now() - start; - const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; - const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); - reporter.sendRawTelemetryEvent(`${extensionId}.removePlugin.completed`, { - "pluginType": pluginName, - "errorsCount": errorsCount.toString(), - }, { - "duration": duration, - }); - return result; - }); - return result; - } - private async deleteClient(clientName: string): Promise { - const result = await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - cancellable: false, - title: vscode.l10n.t("Removing client...") - }, async (progress, _) => { - const start = performance.now(); - const result = await removeClient( + ) : await removeClient( this._context, - clientName, + itemName, false, ); const duration = performance.now() - start; const errorsCount = result ? getLogEntriesForLevel(result, LogLevel.critical, LogLevel.error).length : 0; const reporter = new TelemetryReporter(this._context.extension.packageJSON.telemetryInstrumentationKey); - reporter.sendRawTelemetryEvent(`${extensionId}.removeClient.completed`, { - "client": clientName, + reporter.sendRawTelemetryEvent(`${extensionId}.remove${type}.completed`, { + "pluginType": itemName, "errorsCount": errorsCount.toString(), }, { "duration": duration, From 3217e24dc6236fa3df85807d567a6009f2634a3e Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 22 Nov 2024 09:23:02 +0300 Subject: [PATCH 31/36] introduce WorkspaceContentService to handle workspace file loading --- vscode/microsoft-kiota/src/extension.ts | 5 +- .../src/modules/workspace/index.ts | 9 +++ .../workspace/workspaceContentService.ts | 43 ++++++++++++++ .../src/providers/workspaceTreeProvider.ts | 58 ++++++------------- vscode/microsoft-kiota/src/util.ts | 13 +---- 5 files changed, 74 insertions(+), 54 deletions(-) create mode 100644 vscode/microsoft-kiota/src/modules/workspace/index.ts create mode 100644 vscode/microsoft-kiota/src/modules/workspace/workspaceContentService.ts diff --git a/vscode/microsoft-kiota/src/extension.ts b/vscode/microsoft-kiota/src/extension.ts index afdbd4370e..748f13d760 100644 --- a/vscode/microsoft-kiota/src/extension.ts +++ b/vscode/microsoft-kiota/src/extension.ts @@ -28,6 +28,7 @@ import { UriHandler } from './handlers/uriHandler'; import { ClientOrPluginProperties } from "./kiotaInterop"; +import { WorkspaceContentService } from './modules/workspace'; import { CodeLensProvider } from './providers/codelensProvider'; import { DependenciesViewProvider } from "./providers/dependenciesViewProvider"; import { OpenApiTreeNode, OpenApiTreeProvider } from "./providers/openApiTreeProvider"; @@ -36,7 +37,6 @@ import { loadTreeView, WorkspaceTreeItem, WorkspaceTreeProvider } from './provid import { getExtensionSettings } from "./types/extensionSettings"; import { GeneratedOutputState } from './types/GeneratedOutputState'; import { WorkspaceGenerationContext } from "./types/WorkspaceGenerationContext"; -import { isKiotaWorkspaceFilePresent } from './util'; import { IntegrationParams } from './utilities/deep-linking'; import { loadWorkspaceFile } from './utilities/file'; import { updateStatusBarItem } from './utilities/status'; @@ -54,12 +54,13 @@ export async function activate( log: true, }); const sharedService = SharedService.getInstance(); + const workspaceContentService = new WorkspaceContentService(); const openApiTreeProvider = new OpenApiTreeProvider(context, () => getExtensionSettings(extensionId), sharedService); const dependenciesInfoProvider = new DependenciesViewProvider( context.extensionUri ); const reporter = new TelemetryReporter(context.extension.packageJSON.telemetryInstrumentationKey); - const workspaceTreeProvider = new WorkspaceTreeProvider(await isKiotaWorkspaceFilePresent(), sharedService); + const workspaceTreeProvider = new WorkspaceTreeProvider(workspaceContentService, sharedService); const setWorkspaceGenerationContext = (params: Partial) => { workspaceGenerationContext = { ...workspaceGenerationContext, ...params }; diff --git a/vscode/microsoft-kiota/src/modules/workspace/index.ts b/vscode/microsoft-kiota/src/modules/workspace/index.ts new file mode 100644 index 0000000000..a7c863ab8e --- /dev/null +++ b/vscode/microsoft-kiota/src/modules/workspace/index.ts @@ -0,0 +1,9 @@ +import { ClientOrPluginProperties } from "../../kiotaInterop"; +import WorkspaceContentService from "./workspaceContentService"; + +export interface WorkspaceContent { + version: string; + clients: Record; + plugins: Record; +} +export { WorkspaceContentService }; diff --git a/vscode/microsoft-kiota/src/modules/workspace/workspaceContentService.ts b/vscode/microsoft-kiota/src/modules/workspace/workspaceContentService.ts new file mode 100644 index 0000000000..a7997b2444 --- /dev/null +++ b/vscode/microsoft-kiota/src/modules/workspace/workspaceContentService.ts @@ -0,0 +1,43 @@ +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; + +import { WorkspaceContent } from "."; +import { KIOTA_WORKSPACE_FILE } from "../../constants"; +import { getWorkspaceJsonPath } from '../../util'; + +class WorkspaceContentService { + constructor() { } + + public async load(): Promise { + const isWorkspacePresent = await this.isKiotaWorkspaceFilePresent(); + if (!isWorkspacePresent) { + return; + } + try { + const workspaceJson = vscode.workspace.textDocuments.find(doc => doc.fileName.endsWith(KIOTA_WORKSPACE_FILE)); + if (!workspaceJson) { + throw new Error('Workspace file not found'); + } + const content = workspaceJson.getText(); + return JSON.parse(content); + } catch (error) { + console.error('Error loading workspace.json:', error); + } + } + + async isKiotaWorkspaceFilePresent(): Promise { + if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) { + return false; + } + const workspaceFileDir = path.resolve(getWorkspaceJsonPath()); + try { + await fs.promises.access(workspaceFileDir); + } catch (error) { + return false; + } + return true; + } +} + +export default WorkspaceContentService; \ No newline at end of file diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 348c6d9ab1..982106442d 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -2,15 +2,10 @@ import * as vscode from 'vscode'; import { CLIENTS, KIOTA_WORKSPACE_FILE, PLUGINS } from '../constants'; import { ClientOrPluginProperties } from '../kiotaInterop'; -import { getWorkspaceJsonPath, isClientType, isKiotaWorkspaceFilePresent, isPluginType } from '../util'; +import { WorkspaceContent, WorkspaceContentService } from '../modules/workspace'; +import { getWorkspaceJsonPath, isClientType, isPluginType } from '../util'; import { SharedService } from './sharedService'; -interface WorkspaceContent { - version: string; - clients: Record; - plugins: Record; -} - export class WorkspaceTreeItem extends vscode.TreeItem { constructor( public readonly label: string, @@ -26,25 +21,28 @@ export class WorkspaceTreeItem extends vscode.TreeItem { } export class WorkspaceTreeProvider implements vscode.TreeDataProvider { - public isWorkspacePresent: boolean; private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; - private workspaceContent: WorkspaceContent | null = null; - private sharedService: SharedService; + private workspaceContent: WorkspaceContent | undefined = undefined; - constructor(isWSPresent: boolean, _sharedService: SharedService) { - this.isWorkspacePresent = isWSPresent; - this.sharedService = _sharedService; - this.loadWorkspaceContent(); + constructor( + private workspaceContentService: WorkspaceContentService, + private sharedService: SharedService + ) { + void this.loadContent(); } async refreshView(): Promise { - this.loadWorkspaceContent(); - this._onDidChangeTreeData.fire(); + this.workspaceContent = await this.workspaceContentService.load(); + this._onDidChangeTreeData.fire(); + } + + async loadContent(): Promise { + this.workspaceContent = await this.workspaceContentService.load(); } async getChildren(element?: WorkspaceTreeItem): Promise { - if (!this.isWorkspacePresent) { + if (!this.workspaceContent) { return []; } @@ -89,9 +87,9 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider doc.fileName.endsWith(KIOTA_WORKSPACE_FILE)); - if (!workspaceJson) { - throw new Error('Workspace file not found'); - } - const content = workspaceJson.getText(); - this.workspaceContent = JSON.parse(content); - } catch (error) { - console.error('Error loading workspace.json:', error); - } - } } async function openResource(resource: vscode.Uri): Promise { @@ -144,13 +126,11 @@ async function openResource(resource: vscode.Uri): Promise { export async function loadTreeView(context: vscode.ExtensionContext, treeDataProvider: WorkspaceTreeProvider): Promise { context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(async () => { - treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await vscode.commands.executeCommand('kiota.workspace.refresh'); // Refresh the tree view when workspace folders change })); context.subscriptions.push(vscode.window.createTreeView('kiota.workspace', { treeDataProvider })); context.subscriptions.push(vscode.commands.registerCommand('kiota.workspace.openWorkspaceFile', openResource)); context.subscriptions.push(vscode.commands.registerCommand('kiota.workspace.refresh', async () => { - treeDataProvider.isWorkspacePresent = await isKiotaWorkspaceFilePresent(); await treeDataProvider.refreshView(); })); context.subscriptions.push( @@ -159,6 +139,4 @@ export async function loadTreeView(context: vscode.ExtensionContext, treeDataPro await vscode.commands.executeCommand('kiota.editPaths', label, properties, category); }) ); - -} -; \ No newline at end of file +}; \ No newline at end of file diff --git a/vscode/microsoft-kiota/src/util.ts b/vscode/microsoft-kiota/src/util.ts index ef66cfc201..b07930e64d 100644 --- a/vscode/microsoft-kiota/src/util.ts +++ b/vscode/microsoft-kiota/src/util.ts @@ -172,15 +172,4 @@ export function isValidUrl(url: string): boolean { } } -export async function isKiotaWorkspaceFilePresent(): Promise { - if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) { - return false; - } - const workspaceFileDir = path.resolve(getWorkspaceJsonPath()); - try { - await fs.promises.access(workspaceFileDir); - } catch (error) { - return false; - } - return true; -} + From b512399cb39a1e3a3ee9d8bfda95b49698ca0abb Mon Sep 17 00:00:00 2001 From: thewahome Date: Fri, 22 Nov 2024 09:56:25 +0300 Subject: [PATCH 32/36] call wrapper function instead of service --- vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts index 982106442d..70c9540f13 100644 --- a/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts +++ b/vscode/microsoft-kiota/src/providers/workspaceTreeProvider.ts @@ -33,7 +33,7 @@ export class WorkspaceTreeProvider implements vscode.TreeDataProvider { - this.workspaceContent = await this.workspaceContentService.load(); + await this.loadContent(); this._onDidChangeTreeData.fire(); } From 23da950c7af07023cbb3d6a022dac81c82381c00 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Mon, 25 Nov 2024 11:22:17 +0300 Subject: [PATCH 33/36] test delete workspace command --- .../deleteWorkspaceItemCommand.test.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts diff --git a/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts b/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts new file mode 100644 index 0000000000..93fc1dabba --- /dev/null +++ b/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts @@ -0,0 +1,40 @@ +import assert from "assert"; +import * as sinon from "sinon"; +import * as vscode from 'vscode'; + +import { DeleteWorkspaceItemCommand } from '../../../commands/deleteWorkspaceItem/deleteWorkspaceItemCommand'; +import { WorkspaceTreeItem } from '../../../providers/workspaceTreeProvider'; + +suite('DeleteWorkspaceItemCommand Tests', () => { + let context: vscode.ExtensionContext; + let outputChannel: vscode.LogOutputChannel; + let command: DeleteWorkspaceItemCommand; + let workspaceTreeItem: WorkspaceTreeItem; + + setup(() => { + context = { extension: { packageJSON: { telemetryInstrumentationKey: 'test-key' } } } as any; + outputChannel = { appendLine: sinon.stub() } as any; + command = new DeleteWorkspaceItemCommand(context, outputChannel); + workspaceTreeItem = { label: 'test-item', category: 'plugin' } as any; + }); + + teardown(() => { + sinon.restore(); + }); + + test('getName should return correct command name', () => { + assert.strictEqual("kiota.workspace.deleteItem", command.getName()); + }); + + test('execute should show success message and refresh workspace on success', async () => { + const deleteItemStub = sinon.stub(command as any, 'deleteItem').resolves([{ message: 'removed successfully' }]); + const showInformationMessageStub = sinon.stub(vscode.window, 'showInformationMessage').resolves(); + const executeCommandStub = sinon.stub(vscode.commands, 'executeCommand').resolves(); + + await command.execute(workspaceTreeItem); + + assert.strictEqual(deleteItemStub.calledOnce, true); + assert.strictEqual(showInformationMessageStub.calledOnceWith('test-item removed successfully.'), true); + assert.strictEqual(executeCommandStub.calledOnceWith('kiota.workspace.refresh'), true); + }); +}); \ No newline at end of file From d4a3d9edd0713a41b965e02b94a016172c597eaa Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 26 Nov 2024 10:14:36 +0300 Subject: [PATCH 34/36] add confirmation message before deleting --- .../deleteWorkspaceItemCommand.ts | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index f443b33f86..3136fc3ab2 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -22,23 +22,29 @@ export class DeleteWorkspaceItemCommand extends Command { } public async execute(workspaceTreeItem: WorkspaceTreeItem): Promise { - const result = await this.deleteItem(isPluginType(workspaceTreeItem.category!) ? "plugin" : "client", workspaceTreeItem); - if (result) { - const isSuccess = result.some(k => k.message.includes('removed successfully')); - if (isSuccess) { - void vscode.window.showInformationMessage(vscode.l10n.t('{0} removed successfully.', workspaceTreeItem.label)); - await vscode.commands.executeCommand('kiota.workspace.refresh'); - } else { - await exportLogsAndShowErrors(result, this._kiotaOutputChannel); + const type = workspaceTreeItem.category && isPluginType(workspaceTreeItem.category) ? "plugin" : "client"; + const yesAnswer = vscode.l10n.t("Yes"); + const response = await vscode.window.showInformationMessage( + vscode.l10n.t("Do you want to delete this item?"), + yesAnswer, + vscode.l10n.t("No") + ); + if (response === yesAnswer) { + const result = await this.deleteItem(type, workspaceTreeItem); + if (result) { + const isSuccess = result.some(k => k.message.includes('removed successfully')); + if (isSuccess) { + void vscode.window.showInformationMessage(vscode.l10n.t('{0} removed successfully.', workspaceTreeItem.label)); + await vscode.commands.executeCommand('kiota.workspace.refresh'); + } else { + await exportLogsAndShowErrors(result, this._kiotaOutputChannel); + } } } } private async deleteItem(type: string, workspaceTreeItem: WorkspaceTreeItem): Promise { - return await this.removeWorkspaceItem(workspaceTreeItem.label, type); - } - - private async removeWorkspaceItem(itemName: string, type: string): Promise { + const itemName = workspaceTreeItem.label; const result = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, From bdc2f247ae884556722fb0d9904f50522336337a Mon Sep 17 00:00:00 2001 From: thewahome Date: Tue, 26 Nov 2024 23:26:21 +0300 Subject: [PATCH 35/36] fix failing test due to warning message --- .../commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts | 2 +- .../src/test/suite/commands/deleteWorkspaceItemCommand.test.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index 3136fc3ab2..7a42ac0c74 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -24,7 +24,7 @@ export class DeleteWorkspaceItemCommand extends Command { public async execute(workspaceTreeItem: WorkspaceTreeItem): Promise { const type = workspaceTreeItem.category && isPluginType(workspaceTreeItem.category) ? "plugin" : "client"; const yesAnswer = vscode.l10n.t("Yes"); - const response = await vscode.window.showInformationMessage( + const response = await vscode.window.showWarningMessage( vscode.l10n.t("Do you want to delete this item?"), yesAnswer, vscode.l10n.t("No") diff --git a/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts b/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts index 93fc1dabba..70be3fdca4 100644 --- a/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts +++ b/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts @@ -28,12 +28,14 @@ suite('DeleteWorkspaceItemCommand Tests', () => { test('execute should show success message and refresh workspace on success', async () => { const deleteItemStub = sinon.stub(command as any, 'deleteItem').resolves([{ message: 'removed successfully' }]); + const showWarningMessageStub = sinon.stub(vscode.window, 'showWarningMessage').resolves({ title: "Yes" }); const showInformationMessageStub = sinon.stub(vscode.window, 'showInformationMessage').resolves(); const executeCommandStub = sinon.stub(vscode.commands, 'executeCommand').resolves(); await command.execute(workspaceTreeItem); assert.strictEqual(deleteItemStub.calledOnce, true); + assert.strictEqual(showWarningMessageStub.calledOnceWith("Do you want to delete this item?", sinon.match("Yes"), sinon.match("No")), true); assert.strictEqual(showInformationMessageStub.calledOnceWith('test-item removed successfully.'), true); assert.strictEqual(executeCommandStub.calledOnceWith('kiota.workspace.refresh'), true); }); From 92493e62d227ec1391e3017c132853914b2c1a43 Mon Sep 17 00:00:00 2001 From: Charles Wahome Date: Wed, 27 Nov 2024 12:37:06 +0300 Subject: [PATCH 36/36] refine tests to cater for yes/no dialog --- .../deleteWorkspaceItemCommand.ts | 9 ++++++--- .../commands/deleteWorkspaceItemCommand.test.ts | 12 +++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts index 7a42ac0c74..bc6dd91a41 100644 --- a/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts +++ b/vscode/microsoft-kiota/src/commands/deleteWorkspaceItem/deleteWorkspaceItemCommand.ts @@ -23,13 +23,16 @@ export class DeleteWorkspaceItemCommand extends Command { public async execute(workspaceTreeItem: WorkspaceTreeItem): Promise { const type = workspaceTreeItem.category && isPluginType(workspaceTreeItem.category) ? "plugin" : "client"; - const yesAnswer = vscode.l10n.t("Yes"); + const yesAnswer: vscode.MessageItem = { title: vscode.l10n.t("Yes") }; + const noAnswer: vscode.MessageItem = { title: vscode.l10n.t("No") }; + const response = await vscode.window.showWarningMessage( vscode.l10n.t("Do you want to delete this item?"), yesAnswer, - vscode.l10n.t("No") + noAnswer ); - if (response === yesAnswer) { + + if (response?.title === yesAnswer.title) { const result = await this.deleteItem(type, workspaceTreeItem); if (result) { const isSuccess = result.some(k => k.message.includes('removed successfully')); diff --git a/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts b/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts index 70be3fdca4..cc721a2566 100644 --- a/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts +++ b/vscode/microsoft-kiota/src/test/suite/commands/deleteWorkspaceItemCommand.test.ts @@ -27,16 +27,18 @@ suite('DeleteWorkspaceItemCommand Tests', () => { }); test('execute should show success message and refresh workspace on success', async () => { - const deleteItemStub = sinon.stub(command as any, 'deleteItem').resolves([{ message: 'removed successfully' }]); - const showWarningMessageStub = sinon.stub(vscode.window, 'showWarningMessage').resolves({ title: "Yes" }); + const yesAnswer: vscode.MessageItem = { title: vscode.l10n.t("Yes") }; + + const showWarningMessageStub = sinon.stub(vscode.window, 'showWarningMessage').resolves(yesAnswer); const showInformationMessageStub = sinon.stub(vscode.window, 'showInformationMessage').resolves(); const executeCommandStub = sinon.stub(vscode.commands, 'executeCommand').resolves(); + const deleteItemStub = sinon.stub(command as any, 'deleteItem').resolves([{ message: 'removed successfully' }]); await command.execute(workspaceTreeItem); + assert.strictEqual(showWarningMessageStub.calledOnce, true); + assert.strictEqual(showInformationMessageStub.calledOnce, true); + assert.strictEqual(executeCommandStub.calledWith('kiota.workspace.refresh'), true); assert.strictEqual(deleteItemStub.calledOnce, true); - assert.strictEqual(showWarningMessageStub.calledOnceWith("Do you want to delete this item?", sinon.match("Yes"), sinon.match("No")), true); - assert.strictEqual(showInformationMessageStub.calledOnceWith('test-item removed successfully.'), true); - assert.strictEqual(executeCommandStub.calledOnceWith('kiota.workspace.refresh'), true); }); }); \ No newline at end of file