Skip to content

Commit 12f6f86

Browse files
committed
Added IBM i Debugger treeview in Debug view
Signed-off-by: Seb Julliand <[email protected]>
1 parent 5bb4a36 commit 12f6f86

File tree

8 files changed

+194
-14
lines changed

8 files changed

+194
-14
lines changed

package.json

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,8 +1620,33 @@
16201620
},
16211621
{
16221622
"command": "code-for-ibmi.openDebugStatus",
1623-
"title": "Toggle hidden files",
1624-
"category": "IBM i"
1623+
"title": "Open debugger dashboard",
1624+
"category": "IBM i",
1625+
"icon":"$(dashboard)"
1626+
},
1627+
{
1628+
"command": "code-for-ibmi.debug.refresh",
1629+
"title": "Refresh",
1630+
"category": "IBM i",
1631+
"icon": "$(refresh)"
1632+
},
1633+
{
1634+
"command": "code-for-ibmi.debug.job.start",
1635+
"title": "Start",
1636+
"category": "IBM i",
1637+
"icon": "$(debug-start)"
1638+
},
1639+
{
1640+
"command": "code-for-ibmi.debug.job.restart",
1641+
"title": "Restart",
1642+
"category": "IBM i",
1643+
"icon": "$(debug-restart)"
1644+
},
1645+
{
1646+
"command": "code-for-ibmi.debug.job.stop",
1647+
"title": "Stop",
1648+
"category": "IBM i",
1649+
"icon": "$(debug-stop)"
16251650
}
16261651
],
16271652
"keybindings": [
@@ -1691,7 +1716,7 @@
16911716
}
16921717
]
16931718
},
1694-
"views": {
1719+
"views": {
16951720
"ibmi-explorer": [
16961721
{
16971722
"id": "helpView",
@@ -1742,6 +1767,13 @@
17421767
"name": "Results",
17431768
"when": "code-for-ibmi:searchViewVisible"
17441769
}
1770+
],
1771+
"debug": [
1772+
{
1773+
"id": "ibmiDebugBrowser",
1774+
"name": "IBM i debugger",
1775+
"when": "code-for-ibmi:connected && code-for-ibmi:debug"
1776+
}
17451777
]
17461778
},
17471779
"submenus": [
@@ -2159,6 +2191,10 @@
21592191
{
21602192
"command": "code-for-ibmi.debug.endDebug",
21612193
"when": "code-for-ibmi:debug"
2194+
},
2195+
{
2196+
"command": "code-for-ibmi.debug.refresh",
2197+
"when": "never"
21622198
}
21632199
],
21642200
"view/title": [
@@ -2286,6 +2322,16 @@
22862322
"command": "code-for-ibmi.collapseSearchView",
22872323
"group": "navigation@1",
22882324
"when": "view == searchView"
2325+
},
2326+
{
2327+
"command": "code-for-ibmi.openDebugStatus",
2328+
"group": "navigation@01",
2329+
"when": "view == ibmiDebugBrowser"
2330+
},
2331+
{
2332+
"command": "code-for-ibmi.debug.refresh",
2333+
"group": "navigation@99",
2334+
"when": "view == ibmiDebugBrowser"
22892335
}
22902336
],
22912337
"editor/title": [
@@ -2710,6 +2756,21 @@
27102756
"command": "code-for-ibmi.runAction",
27112757
"when": "view == objectBrowser && (viewItem =~ /^object/ || viewItem == SPF)",
27122758
"group": "1_workspace@1"
2759+
},
2760+
{
2761+
"command": "code-for-ibmi.debug.job.start",
2762+
"when": "view == ibmiDebugBrowser && viewItem =~ /^debugJob_.*_off$/",
2763+
"group": "inline"
2764+
},
2765+
{
2766+
"command": "code-for-ibmi.debug.job.restart",
2767+
"when": "view == ibmiDebugBrowser && viewItem =~ /^debugJob_.*_on$/",
2768+
"group": "inline"
2769+
},
2770+
{
2771+
"command": "code-for-ibmi.debug.job.stop",
2772+
"when": "view == ibmiDebugBrowser && viewItem =~ /^debugJob_.*_on$/",
2773+
"group": "inline"
27132774
}
27142775
]
27152776
},

src/api/debug/server.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export function debugPTFInstalled() {
8484
return instance.getConnection()?.remoteFeatures[`startDebugService.sh`] !== undefined;
8585
}
8686

87-
export async function isSEPSupported(){
87+
export async function isSEPSupported() {
8888
return (await getDebugServiceDetails()).semanticVersion().major > 1;
8989
}
9090

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

148148
if (!endResult.code) {
149149
window.showInformationMessage(t("stop.debug.service.succeeded"));
150-
commands.executeCommand("code-for-ibmi.updateConnectedBar");
150+
refreshDebugSensitiveItems();
151151
return true;
152152
} else {
153153
window.showErrorMessage(t("stop.debug.service.failed", endResult.stdout || endResult.stderr));
@@ -215,7 +215,7 @@ export async function startServer() {
215215
return false;
216216
}
217217
else {
218-
commands.executeCommand("code-for-ibmi.updateConnectedBar");
218+
refreshDebugSensitiveItems();
219219
window.showInformationMessage(t("strdbgsvr.succeeded"));
220220
}
221221
}
@@ -230,7 +230,7 @@ export async function stopServer() {
230230
return false;
231231
}
232232
else {
233-
commands.executeCommand("code-for-ibmi.updateConnectedBar");
233+
refreshDebugSensitiveItems();
234234
window.showInformationMessage(t("enddbgsvr.succeeded"));
235235
}
236236
}
@@ -239,4 +239,9 @@ export async function stopServer() {
239239

240240
export function getServiceConfigurationFile() {
241241
return path.posix.join(binDirectory, "DebugService.env");
242+
}
243+
244+
function refreshDebugSensitiveItems() {
245+
commands.executeCommand("code-for-ibmi.updateConnectedBar");
246+
commands.executeCommand("code-for-ibmi.debug.refresh");
242247
}

src/extension.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { CodeForIBMi, ConnectionData } from "./typings";
2424
import { initializeConnectionBrowser } from "./views/ConnectionBrowser";
2525
import { LibraryListProvider } from "./views/LibraryListView";
2626
import { ProfilesView } from "./views/ProfilesView";
27+
import { initializeDebugBrowser } from "./views/debugView";
2728
import { HelpView } from "./views/helpView";
2829
import { initializeIFSBrowser } from "./views/ifsBrowser";
2930
import { initializeObjectBrowser } from "./views/objectBrowser";
@@ -46,7 +47,8 @@ export async function activate(context: ExtensionContext): Promise<CodeForIBMi>
4647
initializeConnectionBrowser(context);
4748
initializeObjectBrowser(context)
4849
initializeIFSBrowser(context);
49-
50+
initializeDebugBrowser(context);
51+
5052
context.subscriptions.push(
5153
window.registerTreeDataProvider(
5254
`helpView`,

src/locale/ids/da.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,5 +385,7 @@ export const da: Locale = {
385385
'stop.debug.service.succeeded': 'Debug service stopped.',
386386
'stop.debug.service.failed': 'Failed to stop debug service: {0}',
387387
'open.service.configuration': 'Open configuration',
388-
'detail.reading.error':'Failed to read debug service detail file {0}: {1}'
388+
'detail.reading.error': 'Failed to read debug service detail file {0}: {1}',
389+
'start.debug.server.task': 'Starting debug server...',
390+
'stop.debug.server.task': 'Stopping debug server...'
389391
};

src/locale/ids/en.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,5 +385,7 @@ export const en: Locale = {
385385
'stop.debug.service.succeeded': 'Debug service stopped.',
386386
'stop.debug.service.failed': 'Failed to stop debug service: {0}',
387387
'open.service.configuration': 'Open configuration',
388-
'detail.reading.error':'Failed to read debug service detail file {0}: {1}'
388+
'detail.reading.error': 'Failed to read debug service detail file {0}: {1}',
389+
'start.debug.server.task': 'Starting debug server...',
390+
'stop.debug.server.task': 'Stopping debug server...'
389391
};

src/locale/ids/fr.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,5 +385,7 @@ export const fr: Locale = {
385385
'stop.debug.service.succeeded': 'Service de débogage arrêté.',
386386
'stop.debug.service.failed': 'Échec de l\'arrêt du service de débogage: {0}',
387387
'open.service.configuration': 'Ouvrir la configuration',
388-
'detail.reading.error':'Erreur de lecture du fichier détail du service de débogage {0}: {1}'
388+
'detail.reading.error': 'Erreur de lecture du fichier détail du service de débogage {0}: {1}',
389+
'start.debug.server.task': 'Démarrage du serveur de débogage...',
390+
'stop.debug.server.task': 'Arrêt du serveur de débogage...'
389391
};

src/typings.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Ignore } from 'ignore';
2-
import { ProviderResult, Range, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
2+
import { ProviderResult, Range, ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
33
import { ConnectionConfiguration } from './api/Configuration';
44
import { CustomUI } from "./api/CustomUI";
55
import Instance from "./api/Instance";
@@ -165,14 +165,15 @@ export type FocusOptions = { select?: boolean; focus?: boolean; expand?: boolean
165165

166166
export type BrowserItemParameters = {
167167
icon?: string
168+
color?: string
168169
state?: TreeItemCollapsibleState
169170
parent?: BrowserItem
170171
}
171172

172173
export class BrowserItem extends TreeItem {
173174
constructor(label: string, readonly params?: BrowserItemParameters) {
174175
super(label, params?.state);
175-
this.iconPath = params?.icon ? new ThemeIcon(params.icon) : undefined;
176+
this.iconPath = params?.icon ? new ThemeIcon(params.icon, params.color ? new ThemeColor(params.color) : undefined) : undefined;
176177
}
177178

178179
get parent() {

src/views/debugView.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import vscode from "vscode";
2+
import { DebugJob, getDebugServerJob, getDebugServiceDetails, getDebugServiceJob, isDebugEngineRunning, startServer, startService, stopServer, stopService } from "../api/debug/server";
3+
import { instance } from "../instantiate";
4+
import { t } from "../locale";
5+
import { BrowserItem } from "../typings";
6+
7+
const title = "IBM i debugger";
8+
9+
export function initializeDebugBrowser(context: vscode.ExtensionContext) {
10+
const debugBrowser = new DebugBrowser();
11+
const debugTreeViewer = vscode.window.createTreeView(
12+
`ibmiDebugBrowser`, {
13+
treeDataProvider: debugBrowser,
14+
showCollapseAll: true
15+
});
16+
17+
const updateDebugBrowser = async () => {
18+
if (instance.getConnection()) {
19+
debugTreeViewer.title = `${title} ${(await getDebugServiceDetails()).version}`
20+
debugTreeViewer.description = await isDebugEngineRunning() ? t("online") : t("offline");
21+
}
22+
else {
23+
debugTreeViewer.title = title;
24+
debugTreeViewer.description = "";
25+
}
26+
27+
debugBrowser.refresh();
28+
}
29+
30+
instance.onEvent("connected", updateDebugBrowser);
31+
instance.onEvent("disconnected", updateDebugBrowser);
32+
33+
context.subscriptions.push(
34+
debugTreeViewer,
35+
vscode.commands.registerCommand("code-for-ibmi.debug.refresh", updateDebugBrowser),
36+
vscode.commands.registerCommand("code-for-ibmi.debug.refresh.item", (item: DebugItem) => debugBrowser.refresh(item)),
37+
vscode.commands.registerCommand("code-for-ibmi.debug.job.start", (item: DebugJobItem) => item.start()),
38+
vscode.commands.registerCommand("code-for-ibmi.debug.job.stop", (item: DebugJobItem) => item.stop()),
39+
vscode.commands.registerCommand("code-for-ibmi.debug.job.restart", async (item: DebugJobItem) => await item.start() && item.stop()),
40+
);
41+
}
42+
43+
class DebugBrowser implements vscode.TreeDataProvider<DebugItem> {
44+
private readonly _emitter: vscode.EventEmitter<DebugItem | undefined | null | void> = new vscode.EventEmitter();
45+
readonly onDidChangeTreeData: vscode.Event<DebugItem | undefined | null | void> = this._emitter.event;
46+
47+
refresh(item?: DebugItem) {
48+
this._emitter.fire(item);
49+
}
50+
51+
getTreeItem(element: DebugItem) {
52+
return element;
53+
}
54+
55+
async getChildren(): Promise<DebugItem[]> {
56+
const connection = instance.getConnection();
57+
if (connection) {
58+
return [
59+
new DebugJobItem("server",
60+
t("debug.server"),
61+
startServer,
62+
stopServer,
63+
await getDebugServerJob()
64+
),
65+
new DebugJobItem("service",
66+
t("debug.service"),
67+
() => startService(connection),
68+
() => stopService(connection),
69+
await getDebugServiceJob()
70+
)
71+
];
72+
}
73+
else {
74+
return [];
75+
}
76+
}
77+
}
78+
79+
class DebugItem extends BrowserItem {
80+
refresh() {
81+
vscode.commands.executeCommand("code-for-ibmi.debug.refresh.item", this);
82+
}
83+
}
84+
85+
class DebugJobItem extends DebugItem {
86+
constructor(readonly type: "server" | "service", label: string, readonly startFunction: () => Promise<boolean>, readonly stopFunction: () => Promise<boolean>, readonly debugJob?: DebugJob) {
87+
const running = debugJob !== undefined;
88+
super(label, {
89+
state: vscode.TreeItemCollapsibleState.None,
90+
icon: running ? "pass" : "error",
91+
color: running ? "testing.iconPassed" : "testing.iconFailed"
92+
});
93+
this.contextValue = `debugJob_${type}_${running ? "on" : "off"}`;
94+
this.description = running ? debugJob.name : t("offline");
95+
this.tooltip = `${t(`listening.on.port${debugJob?.ports.length === 1 ? '' : 's'}`)} ${debugJob?.ports.join(", ")}`;
96+
}
97+
98+
async start() {
99+
return vscode.window.withProgress({ title: t(`start.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.startFunction);
100+
}
101+
102+
async stop() {
103+
return vscode.window.withProgress({ title: t(`stop.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.stopFunction);
104+
}
105+
}

0 commit comments

Comments
 (0)