From 328c61a8cc8ee65972656cc887abe9dc18254f79 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Fri, 19 Jul 2024 14:02:36 +0200 Subject: [PATCH 01/12] Cleaned up onConnected function call Signed-off-by: Seb Julliand --- src/instantiate.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/instantiate.ts b/src/instantiate.ts index c635ea346..cf71ae991 100644 --- a/src/instantiate.ts +++ b/src/instantiate.ts @@ -779,7 +779,7 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { ActionsUI.initialize(context); VariablesUI.initialize(context); - instance.onEvent("connected", () => onConnected(context)); + instance.onEvent("connected", onConnected); instance.onEvent("disconnected", onDisconnected); context.subscriptions.push( @@ -818,7 +818,7 @@ async function updateConnectedBar() { connectedBarItem.tooltip.isTrusted = true; } -async function onConnected(context: vscode.ExtensionContext) { +async function onConnected() { const config = instance.getConfig(); [ From acadceb513b4982ffc3a1ddf3dc051b7feecd7b1 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Fri, 19 Jul 2024 14:03:15 +0200 Subject: [PATCH 02/12] Surround event function calls with try/catch Signed-off-by: Seb Julliand --- src/api/Instance.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/Instance.ts b/src/api/Instance.ts index 97b219ceb..49126b959 100644 --- a/src/api/Instance.ts +++ b/src/api/Instance.ts @@ -66,7 +66,13 @@ export default class Instance { async processEvent(event: IBMiEvent) { for (const subscriber of this.subscribers.filter(s => s.event === event)) { - await subscriber.func(); + try{ + await subscriber.func(); + } + catch(error){ + const name = subscriber.func.name ? `Event function ${subscriber.func.name}` : `Anonymous event function`; + vscode.window.showWarningMessage(`${name} failed: ${error}`) + } } } } \ No newline at end of file From 5591e33de61c6aa98d6f55759d576a24b7c6bc91 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Fri, 19 Jul 2024 14:04:06 +0200 Subject: [PATCH 03/12] Updated version Signed-off-by: Seb Julliand --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 897d31a20..35ad8408f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "code-for-ibmi", - "version": "2.12.0", + "version": "2.12.1-dev.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "code-for-ibmi", - "version": "2.12.0", + "version": "2.12.1-dev.0", "license": "MIT", "dependencies": { "@bendera/vscode-webview-elements": "^0.12.0", diff --git a/package.json b/package.json index 43c14d4e4..ecc5e5857 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "icon": "icon.png", "displayName": "Code for IBM i", "description": "Maintain your RPGLE, CL, COBOL, C/CPP on IBM i right from Visual Studio Code.", - "version": "2.12.0", + "version": "2.12.1-dev.0", "keywords": [ "ibmi", "rpgle", From 13985aa0c8fd13ab9b1ecb1ffd50c17e63dee7e8 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 22 Jul 2024 11:15:32 +0200 Subject: [PATCH 04/12] Log function error to console Signed-off-by: Seb Julliand --- src/api/Instance.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/Instance.ts b/src/api/Instance.ts index 49126b959..c53c62fbb 100644 --- a/src/api/Instance.ts +++ b/src/api/Instance.ts @@ -70,8 +70,8 @@ export default class Instance { await subscriber.func(); } catch(error){ - const name = subscriber.func.name ? `Event function ${subscriber.func.name}` : `Anonymous event function`; - vscode.window.showWarningMessage(`${name} failed: ${error}`) + const name = subscriber.func.name ? `Event function ${subscriber.func.name}` : `Anonymous event function`; + console.log(`${name} failed`, error); } } } From f00134a719b6e924842083dddf1f8315801c50ea Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 22 Jul 2024 23:18:18 +0200 Subject: [PATCH 05/12] Removed redundant views' refresh on connect event Signed-off-by: Seb Julliand --- src/views/LibraryListView.ts | 1 - src/views/ifsBrowser.ts | 2 -- src/views/objectBrowser.ts | 2 -- 3 files changed, 5 deletions(-) diff --git a/src/views/LibraryListView.ts b/src/views/LibraryListView.ts index 9297a5698..34dfccc7b 100644 --- a/src/views/LibraryListView.ts +++ b/src/views/LibraryListView.ts @@ -254,7 +254,6 @@ export class LibraryListProvider implements vscode.TreeDataProvider this.refresh()); } private async updateConfig(config: ConnectionConfiguration.Parameters) { diff --git a/src/views/ifsBrowser.ts b/src/views/ifsBrowser.ts index a99a83526..a1fa21561 100644 --- a/src/views/ifsBrowser.ts +++ b/src/views/ifsBrowser.ts @@ -307,8 +307,6 @@ export function initializeIFSBrowser(context: vscode.ExtensionContext) { dragAndDropController: new IFSBrowserDragAndDrop() }); - instance.onEvent(`connected`, () => ifsBrowser.refresh()); - context.subscriptions.push( ifsTreeViewer, vscode.commands.registerCommand(`code-for-ibmi.refreshIFSBrowser`, () => ifsBrowser.refresh()), diff --git a/src/views/objectBrowser.ts b/src/views/objectBrowser.ts index 1aaf2fda1..cff7dd610 100644 --- a/src/views/objectBrowser.ts +++ b/src/views/objectBrowser.ts @@ -442,8 +442,6 @@ export function initializeObjectBrowser(context: vscode.ExtensionContext) { dragAndDropController: new ObjectBrowserMemberItemDragAndDrop() }); - instance.onEvent(`connected`, () => objectBrowser.refresh()); - context.subscriptions.push( objectTreeViewer, From 83740ed39ca07a97bae89b1e09bbdc8a16ce08e5 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 22 Jul 2024 23:22:50 +0200 Subject: [PATCH 06/12] Added subscribe function that supersedes deprecated onEvent function Signed-off-by: Seb Julliand --- src/api/Instance.ts | 55 ++++++++++++++++----- src/api/Terminal.ts | 21 +++++--- src/api/debug/index.ts | 56 ++++++++++++--------- src/api/local/deployment.ts | 90 ++++++++++++++++++---------------- src/extension.ts | 20 ++++---- src/filesystems/qsys/QSysFs.ts | 13 ++++- src/instantiate.ts | 29 ++++++----- src/testing/index.ts | 4 +- src/views/ConnectionBrowser.ts | 6 +-- src/views/debugView.ts | 4 +- src/views/helpView.ts | 18 +++---- 11 files changed, 188 insertions(+), 128 deletions(-) diff --git a/src/api/Instance.ts b/src/api/Instance.ts index c53c62fbb..02193b853 100644 --- a/src/api/Instance.ts +++ b/src/api/Instance.ts @@ -5,18 +5,21 @@ import IBMi from "./IBMi"; import { ConnectionStorage, GlobalStorage } from "./Storage"; type IBMiEventSubscription = { - event: IBMiEvent, - func: Function + func: Function, + transient?: boolean }; +type SubscriptionMap = Map + export default class Instance { private connection: IBMi | undefined; private storage: ConnectionStorage; private emitter: vscode.EventEmitter = new vscode.EventEmitter(); - private subscribers: IBMiEventSubscription[] = []; + private subscribers: Map = new Map; + + private deprecationCount = 0; //TODO: remove in v3.0.0 constructor(context: vscode.ExtensionContext) { - this.subscribers = []; this.storage = new ConnectionStorage(context); this.emitter.event(e => this.processEvent(e)); } @@ -56,8 +59,33 @@ export default class Instance { return this.storage.ready ? this.storage : undefined; } + /** + * Subscribe to an {@link IBMiEvent}. When the event is triggerred, the `func` function gets executed. + * + * Each `context`/`name` couple must be unique. + * @param context the extension subscribing to the event + * @param event the {@link IBMiEvent} to subscribe to + * @param name a human-readable name summarizing the function + * @param func the function to execute when the {@link IBMiEvent} is triggerred + * @param transient if `true`, the function will only be executed once during the lifetime of a connection + */ + subscribe(context: vscode.ExtensionContext, event: IBMiEvent, name: string, func: Function, transient?: boolean) { + this.getSubscribers(event).set(`${context.extension.id} - ${name}`, { func, transient }); + } + + private getSubscribers(event: IBMiEvent) { + let eventSubscribers: SubscriptionMap = this.subscribers.get(event) || new Map; + if (!this.subscribers.has(event)) { + this.subscribers.set(event, eventSubscribers); + } + return eventSubscribers; + } + + /** + * @deprecated Will be removed in `v3.0.0`; use {@link subscribe} instead + */ onEvent(event: IBMiEvent, func: Function): void { - this.subscribers.push({ event, func }); + this.getSubscribers(event).set(`deprecated - ${func.name || "unknown"}_${this.deprecationCount++}`, { func }); } fire(event: IBMiEvent) { @@ -65,13 +93,18 @@ export default class Instance { } async processEvent(event: IBMiEvent) { - for (const subscriber of this.subscribers.filter(s => s.event === event)) { - try{ - await subscriber.func(); + const eventSubscribers = this.getSubscribers(event) + for (const [identity, callable] of eventSubscribers.entries()) { + try { + await callable.func(); + } + catch (error) { + console.log(`Event function ${identity} failed`, error); } - catch(error){ - const name = subscriber.func.name ? `Event function ${subscriber.func.name}` : `Anonymous event function`; - console.log(`${name} failed`, error); + finally { + if (callable.transient) { + eventSubscribers.delete(identity); + } } } } diff --git a/src/api/Terminal.ts b/src/api/Terminal.ts index fb4842ca6..9c017a82c 100644 --- a/src/api/Terminal.ts +++ b/src/api/Terminal.ts @@ -34,6 +34,8 @@ export namespace Terminal { connectionString?: string } + let terminalCount = 0; + function setHalted(state: boolean) { commands.executeCommand(`setContext`, `code-for-ibmi:term5250Halted`, state); } @@ -43,17 +45,17 @@ export namespace Terminal { const ATTENTION = 1; const TAB = 9; - export function registerTerminalCommands() { + export function registerTerminalCommands(context: vscode.ExtensionContext) { return [ vscode.commands.registerCommand(`code-for-ibmi.launchTerminalPicker`, () => { - return selectAndOpen(instance); + return selectAndOpen(context, instance); }), vscode.commands.registerCommand(`code-for-ibmi.openTerminalHere`, async (ifsNode) => { const content = instance.getContent(); if (content) { const ifsPath = (await content.isDirectory(ifsNode.path)) ? ifsNode.path : path.dirname(ifsNode.path); - const terminal = await selectAndOpen(instance, TerminalType.PASE); + const terminal = await selectAndOpen(context, instance, TerminalType.PASE); terminal?.sendText(`cd ${ifsPath}`); } }), @@ -68,7 +70,7 @@ export namespace Terminal { ]; } - export async function selectAndOpen(instance: Instance, openType?: TerminalType) { + async function selectAndOpen(context: vscode.ExtensionContext, instance: Instance, openType?: TerminalType) { const connection = instance.getConnection(); const configuration = instance.getConfig(); if (connection && configuration) { @@ -104,14 +106,14 @@ export namespace Terminal { vscode.workspace.getConfiguration().update(`terminal.integrated.sendKeybindingsToShell`, true, true); } - return createTerminal(connection, terminalSettings); + return createTerminal(context, connection, terminalSettings); } } } const HALTED = ` II`; - async function createTerminal(connection: IBMi, terminalSettings: TerminalSettings) { + async function createTerminal(context: vscode.ExtensionContext, connection: IBMi, terminalSettings: TerminalSettings) { const writeEmitter = new vscode.EventEmitter(); const paseWelcomeMessage = 'echo "Terminal started. Thanks for using Code for IBM i"'; @@ -201,7 +203,12 @@ export namespace Terminal { channel.stdin.write(`${paseWelcomeMessage}\n`); } - instance.onEvent('disconnected', () => emulatorTerminal.dispose()); + instance.subscribe( + context, + 'disconnected', + `Dispose Terminal ${terminalCount++}`, + () => emulatorTerminal.dispose(), + true); return emulatorTerminal; } diff --git a/src/api/debug/index.ts b/src/api/debug/index.ts index 2517cea33..3e78e2885 100644 --- a/src/api/debug/index.ts +++ b/src/api/debug/index.ts @@ -371,36 +371,44 @@ export async function initialize(context: ExtensionContext) { ); // Run during startup: - instance.onEvent("connected", async () => { - activateDebugExtension(); - const connection = instance.getConnection(); - const content = instance.getContent(); - if (connection && content && server.debugPTFInstalled()) { - vscode.commands.executeCommand(`setContext`, ptfContext, true); + instance.subscribe( + context, + 'connected', + `Load debugger status`, + async () => { + activateDebugExtension(); + const connection = instance.getConnection(); + const content = instance.getContent(); + if (connection && content && server.debugPTFInstalled()) { + vscode.commands.executeCommand(`setContext`, ptfContext, true); - //Enable debug related commands - vscode.commands.executeCommand(`setContext`, debugContext, true); + //Enable debug related commands + vscode.commands.executeCommand(`setContext`, debugContext, true); - //Enable service entry points related commands - vscode.commands.executeCommand(`setContext`, debugSEPContext, await server.isSEPSupported()); + //Enable service entry points related commands + vscode.commands.executeCommand(`setContext`, debugSEPContext, await server.isSEPSupported()); - const isDebugManaged = isManaged(); - vscode.commands.executeCommand(`setContext`, `code-for-ibmi:debugManaged`, isDebugManaged); - if (!isDebugManaged) { - if (validateIPv4address(connection.currentHost)) { - vscode.window.showWarningMessage(`You are using an IPv4 address to connect to this system. This may cause issues with debugging. Please use a hostname in the Login Settings instead.`); - } + const isDebugManaged = isManaged(); + vscode.commands.executeCommand(`setContext`, `code-for-ibmi:debugManaged`, isDebugManaged); + if (!isDebugManaged) { + if (validateIPv4address(connection.currentHost)) { + vscode.window.showWarningMessage(`You are using an IPv4 address to connect to this system. This may cause issues with debugging. Please use a hostname in the Login Settings instead.`); + } - certificates.sanityCheck(connection, content); + certificates.sanityCheck(connection, content); + } } - } - }); + }); - instance.onEvent("disconnected", () => { - resetDebugServiceDetails(); - vscode.commands.executeCommand(`setContext`, debugContext, false); - vscode.commands.executeCommand(`setContext`, debugSEPContext, false); - }); + instance.subscribe( + context, + 'disconnected', + `Clear debugger status`, + () => { + resetDebugServiceDetails(); + vscode.commands.executeCommand(`setContext`, debugContext, false); + vscode.commands.executeCommand(`setContext`, debugSEPContext, false); + }); } function validateIPv4address(ipaddress: string) { diff --git a/src/api/local/deployment.ts b/src/api/local/deployment.ts index 851556543..dbeeb9de2 100644 --- a/src/api/local/deployment.ts +++ b/src/api/local/deployment.ts @@ -45,55 +45,63 @@ export namespace Deployment { buildWatcher().then(bw => context.subscriptions.push(bw)); } - instance.onEvent("connected", () => { - const workspaces = vscode.workspace.workspaceFolders; - const connection = instance.getConnection(); - const config = instance.getConfig(); - const storage = instance.getStorage(); - - if (workspaces && connection && storage && config) { - if (workspaces.length > 0) { - buildWatcher().then(bw => context.subscriptions.push(bw)); - button.show(); - } + instance.subscribe( + context, + 'connected', + `Initialize deployment`, + () => { + const workspaces = vscode.workspace.workspaceFolders; + const connection = instance.getConnection(); + const config = instance.getConfig(); + const storage = instance.getStorage(); + + if (workspaces && connection && storage && config) { + if (workspaces.length > 0) { + buildWatcher().then(bw => context.subscriptions.push(bw)); + button.show(); + } - const existingPaths = storage.getDeployment(); + const existingPaths = storage.getDeployment(); - if (workspaces.length === 1) { - const workspace = workspaces[0]; - - if (existingPaths && !existingPaths[workspace.uri.fsPath]) { - const possibleDeployDir = DeployTools.buildPossibleDeploymentDirectory(workspace); - vscode.window.showInformationMessage( - `Deploy directory for Workspace not setup. Would you like to default to '${possibleDeployDir}'?`, - `Yes`, - `Ignore` - ).then(async result => { - if (result === `Yes`) { - DeployTools.setDeployLocation({ path: possibleDeployDir }, workspace); - } - }); - } + if (workspaces.length === 1) { + const workspace = workspaces[0]; - getLocalActions(workspace).then(result => { - if (result.length === 0) { + if (existingPaths && !existingPaths[workspace.uri.fsPath]) { + const possibleDeployDir = DeployTools.buildPossibleDeploymentDirectory(workspace); vscode.window.showInformationMessage( - `There are no local Actions defined for this project.`, - `Run Setup` - ).then(result => { - if (result === `Run Setup`) - vscode.commands.executeCommand(`code-for-ibmi.launchActionsSetup`); + `Deploy directory for Workspace not setup. Would you like to default to '${possibleDeployDir}'?`, + `Yes`, + `Ignore` + ).then(async result => { + if (result === `Yes`) { + DeployTools.setDeployLocation({ path: possibleDeployDir }, workspace); + } }); } - }) + + getLocalActions(workspace).then(result => { + if (result.length === 0) { + vscode.window.showInformationMessage( + `There are no local Actions defined for this project.`, + `Run Setup` + ).then(result => { + if (result === `Run Setup`) + vscode.commands.executeCommand(`code-for-ibmi.launchActionsSetup`); + }); + } + }) + } } - } - }); + }); - instance.onEvent("disconnected", () => { - fixCCSID = undefined; - button.hide(); - }) + instance.subscribe( + context, + 'disconnected', + `Clear deployment`, + () => { + fixCCSID = undefined; + button.hide(); + }) } export function getConnection(): IBMi { diff --git a/src/extension.ts b/src/extension.ts index 51234655f..a2b4c97bc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -57,7 +57,7 @@ export async function activate(context: ExtensionContext): Promise context.subscriptions.push( window.registerTreeDataProvider( `helpView`, - new HelpView() + new HelpView(context) ), window.registerTreeDataProvider( `libraryListView`, @@ -114,14 +114,16 @@ export async function activate(context: ExtensionContext): Promise initialise(context); } - instance.onEvent(`connected`, () => { - Promise.all([ - commands.executeCommand("code-for-ibmi.refreshObjectBrowser"), - commands.executeCommand("code-for-ibmi.refreshLibraryListView"), - commands.executeCommand("code-for-ibmi.refreshIFSBrowser"), - commands.executeCommand("code-for-ibmi.refreshProfileView") - ]); - }); + instance.subscribe( + context, + 'connected', + `Refresh views`, + () => { + commands.executeCommand("code-for-ibmi.refreshObjectBrowser"); + commands.executeCommand("code-for-ibmi.refreshLibraryListView"); + commands.executeCommand("code-for-ibmi.refreshIFSBrowser"); + commands.executeCommand("code-for-ibmi.refreshProfileView"); + }); return { instance, customUI: () => new CustomUI(), deployTools: DeployTools, evfeventParser: parseErrors, tools: Tools }; } diff --git a/src/filesystems/qsys/QSysFs.ts b/src/filesystems/qsys/QSysFs.ts index 1fe3a10d9..efa702375 100644 --- a/src/filesystems/qsys/QSysFs.ts +++ b/src/filesystems/qsys/QSysFs.ts @@ -52,8 +52,17 @@ export class QSysFS implements vscode.FileSystemProvider { context.subscriptions.push(onCodeForIBMiConfigurationChange(["connectionSettings", "showDateSearchButton"], () => this.updateMemberSupport())); - instance.onEvent("connected", () => this.updateMemberSupport()); - instance.onEvent("disconnected", () => this.updateMemberSupport()); + instance.subscribe( + context, + 'connected', + `Update member support`, + () => this.updateMemberSupport()); + + instance.subscribe( + context, + 'disconnected', + `Update member support`, + () => this.updateMemberSupport()); } private updateMemberSupport() { diff --git a/src/instantiate.ts b/src/instantiate.ts index cf71ae991..dd90c0c62 100644 --- a/src/instantiate.ts +++ b/src/instantiate.ts @@ -204,9 +204,9 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { } else { vscode.window.showInformationMessage(t(`compare.no.file`)); } - } else { - vscode.window.showInformationMessage(t(`compare.no.file`)); - } + } else { + vscode.window.showInformationMessage(t(`compare.no.file`)); + } }), vscode.commands.registerCommand(`code-for-ibmi.goToFileReadOnly`, async () => vscode.commands.executeCommand(`code-for-ibmi.goToFile`, true)), @@ -245,11 +245,11 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { }); }); - const recentItems: vscode.QuickPickItem[] = recent.map(item => ({ + const recentItems: vscode.QuickPickItem[] = recent.map(item => ({ label: item, buttons: [compareButton] })); - const listItems: vscode.QuickPickItem[] = list.map(item => ({ + const listItems: vscode.QuickPickItem[] = list.map(item => ({ label: item, buttons: [compareButton] })); @@ -299,7 +299,7 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { filteredItems = []; } else { if (!starRemoved && !list.includes(connection!.upperCaseName(quickPick.value))) { - quickPick.items = [connection!.upperCaseName(quickPick.value), ...list].map(label => ({ + quickPick.items = [connection!.upperCaseName(quickPick.value), ...list].map(label => ({ label: label, buttons: [compareButton] })); @@ -517,9 +517,9 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { const editor = vscode.window.activeTextEditor; if (editor) { - currentFile = editor.document.uri; - vscode.commands.executeCommand(`vscode.diff`, currentFile, path); - quickPick.hide(); + currentFile = editor.document.uri; + vscode.commands.executeCommand(`vscode.diff`, currentFile, path); + quickPick.hide(); } } }); @@ -657,7 +657,7 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { } }), - ...Terminal.registerTerminalCommands(), + ...Terminal.registerTerminalCommands(context), vscode.commands.registerCommand(`code-for-ibmi.getPassword`, async (extensionId: string, reason?: string) => { if (extensionId) { @@ -778,9 +778,8 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) { ActionsUI.initialize(context); VariablesUI.initialize(context); - - instance.onEvent("connected", onConnected); - instance.onEvent("disconnected", onDisconnected); + instance.subscribe(context, 'connected', 'Load status bars', onConnected); + instance.subscribe(context, 'disconnected', 'Unload status bars', onDisconnected); context.subscriptions.push( vscode.workspace.registerFileSystemProvider(`member`, new QSysFS(context), { @@ -895,10 +894,10 @@ async function compareCurrentFile(node: any, scheme: `streamfile` | `file` | `me if (currentFile) { let compareWith = await vscode.window.showInputBox({ prompt: t(`compare.prompt`), - title: t(`compare.title`), + title: t(`compare.title`), value: currentFile.path }); - + if (compareWith) { if (scheme == 'member' && !compareWith.startsWith('/')) { compareWith = `/${compareWith}`; diff --git a/src/testing/index.ts b/src/testing/index.ts index ac6abdd49..14940a5d7 100644 --- a/src/testing/index.ts +++ b/src/testing/index.ts @@ -52,10 +52,10 @@ export function initialise(context: vscode.ExtensionContext) { vscode.commands.executeCommand(`setContext`, `code-for-ibmi:testing`, true); if (!testIndividually) { - instance.onEvent(`connected`, runTests); + instance.subscribe(context, 'connected', 'Run tests', runTests); } - instance.onEvent(`disconnected`, resetTests); + instance.subscribe(context, 'disconnected', 'Reset tests', resetTests); testSuitesTreeProvider = new TestSuitesTreeProvider(suites); context.subscriptions.push( vscode.window.createTreeView("testingView", { treeDataProvider: testSuitesTreeProvider, showCollapseAll: true }), diff --git a/src/views/ConnectionBrowser.ts b/src/views/ConnectionBrowser.ts index 5edacc8f9..41d3ea0c8 100644 --- a/src/views/ConnectionBrowser.ts +++ b/src/views/ConnectionBrowser.ts @@ -14,7 +14,7 @@ type CopyOperationItem = { } export function initializeConnectionBrowser(context: vscode.ExtensionContext) { - const connectionBrowser = new ConnectionBrowser(); + const connectionBrowser = new ConnectionBrowser(context); const connectionTreeViewer = vscode.window.createTreeView( `connectionBrowser`, { treeDataProvider: connectionBrowser, @@ -246,8 +246,8 @@ class ConnectionBrowser implements vscode.TreeDataProvider { private readonly _emitter: vscode.EventEmitter = new vscode.EventEmitter(); readonly onDidChangeTreeData: vscode.Event = this._emitter.event; - constructor() { - instance.onEvent("disconnected", () => this.refresh()) + constructor(context: vscode.ExtensionContext) { + instance.subscribe(context, 'disconnected', 'Refresh Connection Browser', () => this.refresh()); } refresh() { diff --git a/src/views/debugView.ts b/src/views/debugView.ts index ced100c23..6dcc9803a 100644 --- a/src/views/debugView.ts +++ b/src/views/debugView.ts @@ -41,8 +41,8 @@ export function initializeDebugBrowser(context: vscode.ExtensionContext) { debugBrowser.refresh(); } - instance.onEvent("connected", updateDebugBrowser); - instance.onEvent("disconnected", updateDebugBrowser); + instance.subscribe(context, "connected", "Update Debug Browser", updateDebugBrowser); + instance.subscribe(context, "disconnected", "Update Debug Browser", updateDebugBrowser); context.subscriptions.push( debugTreeViewer, diff --git a/src/views/helpView.ts b/src/views/helpView.ts index d173b4384..6786b4421 100644 --- a/src/views/helpView.ts +++ b/src/views/helpView.ts @@ -1,28 +1,22 @@ -import { parse } from 'path'; +import AdmZip from 'adm-zip'; +import path, { parse } from 'path'; import vscode from 'vscode'; +import { DebugConfiguration } from '../api/debug/config'; import IBMi from '../api/IBMi'; import { instance } from '../instantiate'; -import path from 'path'; import { t } from "../locale"; -import AdmZip from 'adm-zip'; -import { DebugConfiguration } from '../api/debug/config'; export class HelpView implements vscode.TreeDataProvider { private _onDidChangeTreeData = new vscode.EventEmitter(); readonly onDidChangeTreeData = this._onDidChangeTreeData.event; - constructor() { + constructor(context: vscode.ExtensionContext) { vscode.commands.registerCommand("code-for-ibmi.openNewIssue", openNewIssue) vscode.commands.registerCommand("code-for-ibmi.downloadLogs", downloadLogs) - instance.onEvent(`connected`, () => { - this.refresh(); - }); - - instance.onEvent(`disconnected`, () => { - this.refresh(); - }); + instance.subscribe(context, `connected`, 'Refresh Help View', () => this.refresh()); + instance.subscribe(context, `disconnected`, 'Refresh Help View', () => this.refresh()); } refresh(element?: vscode.TreeItem) { From c8856caad136c7c28ba65eb51e9016a929e44bca Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 22 Jul 2024 23:33:38 +0200 Subject: [PATCH 07/12] Added event functions time tracing Signed-off-by: Seb Julliand --- src/api/Instance.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/api/Instance.ts b/src/api/Instance.ts index 02193b853..8d5c49134 100644 --- a/src/api/Instance.ts +++ b/src/api/Instance.ts @@ -96,7 +96,9 @@ export default class Instance { const eventSubscribers = this.getSubscribers(event) for (const [identity, callable] of eventSubscribers.entries()) { try { + console.time(identity); await callable.func(); + console.timeEnd(identity); } catch (error) { console.log(`Event function ${identity} failed`, error); From 8d42b73128f1da6c383e3837f53be4effeafe8dc Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 22 Jul 2024 23:41:05 +0200 Subject: [PATCH 08/12] Better error log and global event timer trace Signed-off-by: Seb Julliand --- src/api/Instance.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api/Instance.ts b/src/api/Instance.ts index 8d5c49134..270af9954 100644 --- a/src/api/Instance.ts +++ b/src/api/Instance.ts @@ -94,6 +94,7 @@ export default class Instance { async processEvent(event: IBMiEvent) { const eventSubscribers = this.getSubscribers(event) + console.time(event); for (const [identity, callable] of eventSubscribers.entries()) { try { console.time(identity); @@ -101,7 +102,7 @@ export default class Instance { console.timeEnd(identity); } catch (error) { - console.log(`Event function ${identity} failed`, error); + console.log(`${event} event function ${identity} failed`, error); } finally { if (callable.transient) { @@ -109,5 +110,6 @@ export default class Instance { } } } + console.timeEnd(event); } } \ No newline at end of file From 8f8f40713b66694bf0997953960d0e44ccd91047 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 22 Jul 2024 23:43:05 +0200 Subject: [PATCH 09/12] Restored use of promise.all Signed-off-by: Seb Julliand --- src/extension.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index a2b4c97bc..d52d644f2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -118,12 +118,12 @@ export async function activate(context: ExtensionContext): Promise context, 'connected', `Refresh views`, - () => { - commands.executeCommand("code-for-ibmi.refreshObjectBrowser"); - commands.executeCommand("code-for-ibmi.refreshLibraryListView"); - commands.executeCommand("code-for-ibmi.refreshIFSBrowser"); - commands.executeCommand("code-for-ibmi.refreshProfileView"); - }); + () => Promise.all([ + commands.executeCommand("code-for-ibmi.refreshObjectBrowser"), + commands.executeCommand("code-for-ibmi.refreshLibraryListView"), + commands.executeCommand("code-for-ibmi.refreshIFSBrowser"), + commands.executeCommand("code-for-ibmi.refreshProfileView") + ])); return { instance, customUI: () => new CustomUI(), deployTools: DeployTools, evfeventParser: parseErrors, tools: Tools }; } From 268f18ba6876e990fd083ee7ad0e9d5ca7972d01 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 22 Jul 2024 23:45:01 +0200 Subject: [PATCH 10/12] Revert "Restored use of promise.all" This reverts commit 8f8f40713b66694bf0997953960d0e44ccd91047. --- src/extension.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index d52d644f2..a2b4c97bc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -118,12 +118,12 @@ export async function activate(context: ExtensionContext): Promise context, 'connected', `Refresh views`, - () => Promise.all([ - commands.executeCommand("code-for-ibmi.refreshObjectBrowser"), - commands.executeCommand("code-for-ibmi.refreshLibraryListView"), - commands.executeCommand("code-for-ibmi.refreshIFSBrowser"), - commands.executeCommand("code-for-ibmi.refreshProfileView") - ])); + () => { + commands.executeCommand("code-for-ibmi.refreshObjectBrowser"); + commands.executeCommand("code-for-ibmi.refreshLibraryListView"); + commands.executeCommand("code-for-ibmi.refreshIFSBrowser"); + commands.executeCommand("code-for-ibmi.refreshProfileView"); + }); return { instance, customUI: () => new CustomUI(), deployTools: DeployTools, evfeventParser: parseErrors, tools: Tools }; } From 464e41a84348fa96949969c9ce0ef449fc80cbdb Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Tue, 23 Jul 2024 09:05:43 +0200 Subject: [PATCH 11/12] Log error instead of info Signed-off-by: Seb Julliand --- src/api/Instance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/Instance.ts b/src/api/Instance.ts index 270af9954..0417d08cd 100644 --- a/src/api/Instance.ts +++ b/src/api/Instance.ts @@ -102,7 +102,7 @@ export default class Instance { console.timeEnd(identity); } catch (error) { - console.log(`${event} event function ${identity} failed`, error); + console.error(`${event} event function ${identity} failed`, error); } finally { if (callable.transient) { From 53edeff15d6e19f9e81d0905d968bc319a303610 Mon Sep 17 00:00:00 2001 From: Seb Julliand Date: Mon, 29 Jul 2024 22:26:44 +0200 Subject: [PATCH 12/12] Log a deprecation warning to warn about uses of Instance::onEvent Signed-off-by: Seb Julliand --- src/api/Instance.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/Instance.ts b/src/api/Instance.ts index 0417d08cd..bc9b76c81 100644 --- a/src/api/Instance.ts +++ b/src/api/Instance.ts @@ -86,6 +86,7 @@ export default class Instance { */ onEvent(event: IBMiEvent, func: Function): void { this.getSubscribers(event).set(`deprecated - ${func.name || "unknown"}_${this.deprecationCount++}`, { func }); + console.warn("[Code for IBM i] Deprecation warning: you are using Instance::onEvent which is deprecated and will be removed in v3.0.0. Please use Instance::subscribe instead."); } fire(event: IBMiEvent) {