Skip to content

Commit

Permalink
Added IBM i Debugger treeview in Debug view
Browse files Browse the repository at this point in the history
Signed-off-by: Seb Julliand <[email protected]>
  • Loading branch information
sebjulliand committed Apr 4, 2024
1 parent 5bb4a36 commit 12f6f86
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 14 deletions.
67 changes: 64 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1620,8 +1620,33 @@
},
{
"command": "code-for-ibmi.openDebugStatus",
"title": "Toggle hidden files",
"category": "IBM i"
"title": "Open debugger dashboard",
"category": "IBM i",
"icon":"$(dashboard)"
},
{
"command": "code-for-ibmi.debug.refresh",
"title": "Refresh",
"category": "IBM i",
"icon": "$(refresh)"
},
{
"command": "code-for-ibmi.debug.job.start",
"title": "Start",
"category": "IBM i",
"icon": "$(debug-start)"
},
{
"command": "code-for-ibmi.debug.job.restart",
"title": "Restart",
"category": "IBM i",
"icon": "$(debug-restart)"
},
{
"command": "code-for-ibmi.debug.job.stop",
"title": "Stop",
"category": "IBM i",
"icon": "$(debug-stop)"
}
],
"keybindings": [
Expand Down Expand Up @@ -1691,7 +1716,7 @@
}
]
},
"views": {
"views": {
"ibmi-explorer": [
{
"id": "helpView",
Expand Down Expand Up @@ -1742,6 +1767,13 @@
"name": "Results",
"when": "code-for-ibmi:searchViewVisible"
}
],
"debug": [
{
"id": "ibmiDebugBrowser",
"name": "IBM i debugger",
"when": "code-for-ibmi:connected && code-for-ibmi:debug"
}
]
},
"submenus": [
Expand Down Expand Up @@ -2159,6 +2191,10 @@
{
"command": "code-for-ibmi.debug.endDebug",
"when": "code-for-ibmi:debug"
},
{
"command": "code-for-ibmi.debug.refresh",
"when": "never"
}
],
"view/title": [
Expand Down Expand Up @@ -2286,6 +2322,16 @@
"command": "code-for-ibmi.collapseSearchView",
"group": "navigation@1",
"when": "view == searchView"
},
{
"command": "code-for-ibmi.openDebugStatus",
"group": "navigation@01",
"when": "view == ibmiDebugBrowser"
},
{
"command": "code-for-ibmi.debug.refresh",
"group": "navigation@99",
"when": "view == ibmiDebugBrowser"
}
],
"editor/title": [
Expand Down Expand Up @@ -2710,6 +2756,21 @@
"command": "code-for-ibmi.runAction",
"when": "view == objectBrowser && (viewItem =~ /^object/ || viewItem == SPF)",
"group": "1_workspace@1"
},
{
"command": "code-for-ibmi.debug.job.start",
"when": "view == ibmiDebugBrowser && viewItem =~ /^debugJob_.*_off$/",
"group": "inline"
},
{
"command": "code-for-ibmi.debug.job.restart",
"when": "view == ibmiDebugBrowser && viewItem =~ /^debugJob_.*_on$/",
"group": "inline"
},
{
"command": "code-for-ibmi.debug.job.stop",
"when": "view == ibmiDebugBrowser && viewItem =~ /^debugJob_.*_on$/",
"group": "inline"
}
]
},
Expand Down
15 changes: 10 additions & 5 deletions src/api/debug/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function debugPTFInstalled() {
return instance.getConnection()?.remoteFeatures[`startDebugService.sh`] !== undefined;
}

export async function isSEPSupported(){
export async function isSEPSupported() {
return (await getDebugServiceDetails()).semanticVersion().major > 1;
}

Expand Down Expand Up @@ -126,7 +126,7 @@ export async function startService(connection: IBMi) {
while (!didNotStart && tries < 20) {
if (await getDebugServiceJob()) {
window.showInformationMessage(t("start.debug.service.succeeded"));
commands.executeCommand("code-for-ibmi.updateConnectedBar");
refreshDebugSensitiveItems();
return true;
}
else {
Expand All @@ -147,7 +147,7 @@ export async function stopService(connection: IBMi) {

if (!endResult.code) {
window.showInformationMessage(t("stop.debug.service.succeeded"));
commands.executeCommand("code-for-ibmi.updateConnectedBar");
refreshDebugSensitiveItems();
return true;
} else {
window.showErrorMessage(t("stop.debug.service.failed", endResult.stdout || endResult.stderr));
Expand Down Expand Up @@ -215,7 +215,7 @@ export async function startServer() {
return false;
}
else {
commands.executeCommand("code-for-ibmi.updateConnectedBar");
refreshDebugSensitiveItems();
window.showInformationMessage(t("strdbgsvr.succeeded"));
}
}
Expand All @@ -230,7 +230,7 @@ export async function stopServer() {
return false;
}
else {
commands.executeCommand("code-for-ibmi.updateConnectedBar");
refreshDebugSensitiveItems();
window.showInformationMessage(t("enddbgsvr.succeeded"));
}
}
Expand All @@ -239,4 +239,9 @@ export async function stopServer() {

export function getServiceConfigurationFile() {
return path.posix.join(binDirectory, "DebugService.env");
}

function refreshDebugSensitiveItems() {
commands.executeCommand("code-for-ibmi.updateConnectedBar");
commands.executeCommand("code-for-ibmi.debug.refresh");
}
4 changes: 3 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { CodeForIBMi, ConnectionData } from "./typings";
import { initializeConnectionBrowser } from "./views/ConnectionBrowser";
import { LibraryListProvider } from "./views/LibraryListView";
import { ProfilesView } from "./views/ProfilesView";
import { initializeDebugBrowser } from "./views/debugView";
import { HelpView } from "./views/helpView";
import { initializeIFSBrowser } from "./views/ifsBrowser";
import { initializeObjectBrowser } from "./views/objectBrowser";
Expand All @@ -46,7 +47,8 @@ export async function activate(context: ExtensionContext): Promise<CodeForIBMi>
initializeConnectionBrowser(context);
initializeObjectBrowser(context)
initializeIFSBrowser(context);

initializeDebugBrowser(context);

context.subscriptions.push(
window.registerTreeDataProvider(
`helpView`,
Expand Down
4 changes: 3 additions & 1 deletion src/locale/ids/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,5 +385,7 @@ export const da: Locale = {
'stop.debug.service.succeeded': 'Debug service stopped.',
'stop.debug.service.failed': 'Failed to stop debug service: {0}',
'open.service.configuration': 'Open configuration',
'detail.reading.error':'Failed to read debug service detail file {0}: {1}'
'detail.reading.error': 'Failed to read debug service detail file {0}: {1}',
'start.debug.server.task': 'Starting debug server...',
'stop.debug.server.task': 'Stopping debug server...'
};
4 changes: 3 additions & 1 deletion src/locale/ids/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,5 +385,7 @@ export const en: Locale = {
'stop.debug.service.succeeded': 'Debug service stopped.',
'stop.debug.service.failed': 'Failed to stop debug service: {0}',
'open.service.configuration': 'Open configuration',
'detail.reading.error':'Failed to read debug service detail file {0}: {1}'
'detail.reading.error': 'Failed to read debug service detail file {0}: {1}',
'start.debug.server.task': 'Starting debug server...',
'stop.debug.server.task': 'Stopping debug server...'
};
4 changes: 3 additions & 1 deletion src/locale/ids/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,5 +385,7 @@ export const fr: Locale = {
'stop.debug.service.succeeded': 'Service de débogage arrêté.',
'stop.debug.service.failed': 'Échec de l\'arrêt du service de débogage: {0}',
'open.service.configuration': 'Ouvrir la configuration',
'detail.reading.error':'Erreur de lecture du fichier détail du service de débogage {0}: {1}'
'detail.reading.error': 'Erreur de lecture du fichier détail du service de débogage {0}: {1}',
'start.debug.server.task': 'Démarrage du serveur de débogage...',
'stop.debug.server.task': 'Arrêt du serveur de débogage...'
};
5 changes: 3 additions & 2 deletions src/typings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Ignore } from 'ignore';
import { ProviderResult, Range, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { ProviderResult, Range, ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { ConnectionConfiguration } from './api/Configuration';
import { CustomUI } from "./api/CustomUI";
import Instance from "./api/Instance";
Expand Down Expand Up @@ -165,14 +165,15 @@ export type FocusOptions = { select?: boolean; focus?: boolean; expand?: boolean

export type BrowserItemParameters = {
icon?: string
color?: string
state?: TreeItemCollapsibleState
parent?: BrowserItem
}

export class BrowserItem extends TreeItem {
constructor(label: string, readonly params?: BrowserItemParameters) {
super(label, params?.state);
this.iconPath = params?.icon ? new ThemeIcon(params.icon) : undefined;
this.iconPath = params?.icon ? new ThemeIcon(params.icon, params.color ? new ThemeColor(params.color) : undefined) : undefined;
}

get parent() {
Expand Down
105 changes: 105 additions & 0 deletions src/views/debugView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import vscode from "vscode";
import { DebugJob, getDebugServerJob, getDebugServiceDetails, getDebugServiceJob, isDebugEngineRunning, startServer, startService, stopServer, stopService } from "../api/debug/server";
import { instance } from "../instantiate";
import { t } from "../locale";
import { BrowserItem } from "../typings";

const title = "IBM i debugger";

export function initializeDebugBrowser(context: vscode.ExtensionContext) {
const debugBrowser = new DebugBrowser();
const debugTreeViewer = vscode.window.createTreeView(
`ibmiDebugBrowser`, {
treeDataProvider: debugBrowser,
showCollapseAll: true
});

const updateDebugBrowser = async () => {
if (instance.getConnection()) {
debugTreeViewer.title = `${title} ${(await getDebugServiceDetails()).version}`
debugTreeViewer.description = await isDebugEngineRunning() ? t("online") : t("offline");
}
else {
debugTreeViewer.title = title;
debugTreeViewer.description = "";
}

debugBrowser.refresh();
}

instance.onEvent("connected", updateDebugBrowser);
instance.onEvent("disconnected", updateDebugBrowser);

context.subscriptions.push(
debugTreeViewer,
vscode.commands.registerCommand("code-for-ibmi.debug.refresh", updateDebugBrowser),
vscode.commands.registerCommand("code-for-ibmi.debug.refresh.item", (item: DebugItem) => debugBrowser.refresh(item)),
vscode.commands.registerCommand("code-for-ibmi.debug.job.start", (item: DebugJobItem) => item.start()),
vscode.commands.registerCommand("code-for-ibmi.debug.job.stop", (item: DebugJobItem) => item.stop()),
vscode.commands.registerCommand("code-for-ibmi.debug.job.restart", async (item: DebugJobItem) => await item.start() && item.stop()),
);
}

class DebugBrowser implements vscode.TreeDataProvider<DebugItem> {
private readonly _emitter: vscode.EventEmitter<DebugItem | undefined | null | void> = new vscode.EventEmitter();
readonly onDidChangeTreeData: vscode.Event<DebugItem | undefined | null | void> = this._emitter.event;

refresh(item?: DebugItem) {
this._emitter.fire(item);
}

getTreeItem(element: DebugItem) {
return element;
}

async getChildren(): Promise<DebugItem[]> {
const connection = instance.getConnection();
if (connection) {
return [
new DebugJobItem("server",
t("debug.server"),
startServer,
stopServer,
await getDebugServerJob()
),
new DebugJobItem("service",
t("debug.service"),
() => startService(connection),
() => stopService(connection),
await getDebugServiceJob()
)
];
}
else {
return [];
}
}
}

class DebugItem extends BrowserItem {
refresh() {
vscode.commands.executeCommand("code-for-ibmi.debug.refresh.item", this);
}
}

class DebugJobItem extends DebugItem {
constructor(readonly type: "server" | "service", label: string, readonly startFunction: () => Promise<boolean>, readonly stopFunction: () => Promise<boolean>, readonly debugJob?: DebugJob) {
const running = debugJob !== undefined;
super(label, {
state: vscode.TreeItemCollapsibleState.None,
icon: running ? "pass" : "error",
color: running ? "testing.iconPassed" : "testing.iconFailed"
});
this.contextValue = `debugJob_${type}_${running ? "on" : "off"}`;
this.description = running ? debugJob.name : t("offline");
this.tooltip = `${t(`listening.on.port${debugJob?.ports.length === 1 ? '' : 's'}`)} ${debugJob?.ports.join(", ")}`;
}

async start() {
return vscode.window.withProgress({ title: t(`start.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.startFunction);
}

async stop() {
return vscode.window.withProgress({ title: t(`stop.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.stopFunction);
}
}

0 comments on commit 12f6f86

Please sign in to comment.