Skip to content

Commit 7f5da55

Browse files
committed
WIP: Intergrate debug adapter into python example
1 parent cdd5405 commit 7f5da55

File tree

8 files changed

+248
-5
lines changed

8 files changed

+248
-5
lines changed

package-lock.json

Lines changed: 48 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/examples/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"dependencies": {
7474
"@codingame/monaco-vscode-configuration-service-override": "13.1.3",
7575
"@codingame/monaco-vscode-cpp-default-extension": "13.1.3",
76+
"@codingame/monaco-vscode-debug-service-override": "13.1.3",
7677
"@codingame/monaco-vscode-editor-api": "13.1.3",
7778
"@codingame/monaco-vscode-environment-service-override": "13.1.3",
7879
"@codingame/monaco-vscode-explorer-service-override": "13.1.3",

packages/examples/resources/debugger/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ services:
1111
platform: linux/amd64
1212
volumes:
1313
- ../python:/home/mlc/workspace
14-
- ../../src/debugger:/home/mlc/server/src
14+
- ../../src/debugger/server:/home/mlc/server/src
1515
ports:
1616
- 55555:5555
1717
tty: true

packages/examples/resources/debugger/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@
3939
"tsx": "~4.19.2"
4040
},
4141
"scripts": {
42-
"start": "npm i && vite-node src/debugServer.ts"
42+
"start": "npm i && tsx src/debugServer.ts"
4343
}
4444
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/* --------------------------------------------------------------------------------------------
2+
* Copyright (c) 2024 TypeFox and others.
3+
* Licensed under the MIT License. See LICENSE in the package root for license information.
4+
* ------------------------------------------------------------------------------------------ */
5+
6+
import * as vscode from 'vscode';
7+
import type { ExtensionConfig } from 'monaco-editor-wrapper';
8+
9+
// This is derived from:
10+
// https://github.com/CodinGame/monaco-vscode-api/blob/main/demo/src/features/debugger.ts
11+
12+
export const provideDebuggerExtensionConfig = (): ExtensionConfig => {
13+
const filesOrContents = new Map<string, string | URL>();
14+
filesOrContents.set('./extension.js', '// nothing');
15+
16+
return {
17+
config: {
18+
name: 'debugger-py-client',
19+
publisher: 'TypeFox',
20+
version: '1.0.0',
21+
engines: {
22+
vscode: '*'
23+
},
24+
// A browser field is mandatory for the extension to be flagged as `web`
25+
browser: 'extension.js',
26+
contributes: {
27+
debuggers: [
28+
{
29+
type: 'python',
30+
label: 'Test',
31+
languages: ['python']
32+
}
33+
],
34+
breakpoints: [
35+
{
36+
language: 'python'
37+
}
38+
]
39+
}
40+
},
41+
filesOrContents
42+
};
43+
};
44+
45+
export const confiugureDebugging = async (api: typeof vscode) => {
46+
class WebsocketDebugAdapter implements vscode.DebugAdapter {
47+
private websocket: WebSocket;
48+
49+
constructor(websocket: WebSocket) {
50+
this.websocket = websocket;
51+
this.websocket.onmessage = (message) => {
52+
this._onDidSendMessage.fire(JSON.parse(message.data));
53+
};
54+
}
55+
56+
_onDidSendMessage = new api.EventEmitter<vscode.DebugProtocolMessage>();
57+
onDidSendMessage = this._onDidSendMessage.event;
58+
59+
handleMessage(message: vscode.DebugProtocolMessage): void {
60+
this.websocket.send(JSON.stringify(message));
61+
}
62+
63+
dispose() {
64+
this.websocket.close();
65+
}
66+
}
67+
68+
api.debug.registerDebugConfigurationProvider('javascript', {
69+
resolveDebugConfiguration() {
70+
return {
71+
name: 'Test debugger',
72+
type: 'javascript',
73+
request: 'launch'
74+
};
75+
}
76+
});
77+
78+
api.debug.registerDebugAdapterDescriptorFactory('javascript', {
79+
async createDebugAdapterDescriptor() {
80+
const websocket = new WebSocket('ws://localhost:5555');
81+
82+
await new Promise((resolve, reject) => {
83+
websocket.onopen = resolve;
84+
websocket.onerror = () =>
85+
reject(new Error('Unable to connect to debugger server. Run `npm run start:debugServer`'));
86+
});
87+
88+
websocket.send(
89+
JSON.stringify({
90+
main: '/workspace/test.js',
91+
files: {
92+
'/workspace/test.js': new TextDecoder().decode(
93+
await api.workspace.fs.readFile(
94+
api.Uri.file('/workspace/test.js')
95+
)
96+
)
97+
}
98+
})
99+
);
100+
101+
const adapter = new WebsocketDebugAdapter(websocket);
102+
103+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
104+
adapter.onDidSendMessage((message: any) => {
105+
if (message.type === 'event' && message.event === 'output') {
106+
console.log('OUTPUT', message.body.output);
107+
}
108+
});
109+
return new api.DebugAdapterInlineImplementation(adapter);
110+
}
111+
});
112+
};

packages/examples/src/debugger/debugServer.ts renamed to packages/examples/src/debugger/server/debugServer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See LICENSE in the package root for license information.
44
* ------------------------------------------------------------------------------------------ */
55

6-
// this is derived from:
6+
// This is derived from:
77
// https://github.com/CodinGame/monaco-vscode-api/blob/main/demo/src/debugServer.ts
88
// the major difference is that the debug server runs already inside the container
99

@@ -125,6 +125,7 @@ wss.on('connection', (ws) => {
125125
ws.on(
126126
'message',
127127
sequential(async (message: string) => {
128+
console.log('Received message', message);
128129
if (!initialized) {
129130
try {
130131
initialized = true;

packages/examples/src/python/client/config.ts

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,30 @@
44
* ------------------------------------------------------------------------------------------ */
55

66
import * as vscode from 'vscode';
7+
import getConfigurationServiceOverride from '@codingame/monaco-vscode-configuration-service-override';
8+
import getDebugServiceOverride from '@codingame/monaco-vscode-debug-service-override';
79
import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override';
10+
import getLifecycleServiceOverride from '@codingame/monaco-vscode-lifecycle-service-override';
11+
import getLocalizationServiceOverride from '@codingame/monaco-vscode-localization-service-override';
12+
import getBannerServiceOverride from '@codingame/monaco-vscode-view-banner-service-override';
13+
import getStatusBarServiceOverride from '@codingame/monaco-vscode-view-status-bar-service-override';
14+
import getTitleBarServiceOverride from '@codingame/monaco-vscode-view-title-bar-service-override';
15+
import getExplorerServiceOverride from '@codingame/monaco-vscode-explorer-service-override';
16+
import getRemoteAgentServiceOverride from '@codingame/monaco-vscode-remote-agent-service-override';
17+
import getEnvironmentServiceOverride from '@codingame/monaco-vscode-environment-service-override';
18+
import getSecretStorageServiceOverride from '@codingame/monaco-vscode-secret-storage-service-override';
19+
import getStorageServiceOverride from '@codingame/monaco-vscode-storage-service-override';
20+
import getSearchServiceOverride from '@codingame/monaco-vscode-search-service-override';
821
import '@codingame/monaco-vscode-python-default-extension';
922
import { LogLevel } from '@codingame/monaco-vscode-api';
1023
import { MonacoLanguageClient } from 'monaco-languageclient';
1124
import { createUrl } from 'monaco-languageclient/tools';
1225
import type { WrapperConfig } from 'monaco-editor-wrapper';
1326
import { toSocket, WebSocketMessageReader, WebSocketMessageWriter } from 'vscode-ws-jsonrpc';
1427
import { configureMonacoWorkers } from '../../common/client/utils.js';
28+
import { defaultHtmlAugmentationInstructions, defaultViewsInit } from 'monaco-editor-wrapper/vscode/services';
29+
import { createDefaultLocaleConfiguration } from 'monaco-languageclient/vscode/services';
30+
import { provideDebuggerExtensionConfig } from '../../debugger/client/debugger.js';
1531

1632
export const createWrapperConfig = (workspaceRoot: string, code: string, codeUri: string): WrapperConfig => {
1733
const url = createUrl({
@@ -28,6 +44,8 @@ export const createWrapperConfig = (workspaceRoot: string, code: string, codeUri
2844
const reader = new WebSocketMessageReader(iWebSocket);
2945
const writer = new WebSocketMessageWriter(iWebSocket);
3046

47+
const workspaceFile = vscode.Uri.file('/home/mlc/workspace/.vscode/workspace.code-workspace');
48+
3149
return {
3250
$type: 'extended',
3351
htmlContainer: document.getElementById('monaco-editor-root')!,
@@ -66,7 +84,25 @@ export const createWrapperConfig = (workspaceRoot: string, code: string, codeUri
6684
},
6785
vscodeApiConfig: {
6886
serviceOverrides: {
69-
...getKeybindingsServiceOverride()
87+
...getConfigurationServiceOverride(),
88+
...getKeybindingsServiceOverride(),
89+
...getLifecycleServiceOverride(),
90+
...getLocalizationServiceOverride(createDefaultLocaleConfiguration()),
91+
...getBannerServiceOverride(),
92+
...getStatusBarServiceOverride(),
93+
...getTitleBarServiceOverride(),
94+
...getExplorerServiceOverride(),
95+
...getRemoteAgentServiceOverride(),
96+
...getEnvironmentServiceOverride(),
97+
...getSecretStorageServiceOverride(),
98+
...getStorageServiceOverride(),
99+
...getSearchServiceOverride(),
100+
...getDebugServiceOverride()
101+
},
102+
viewsConfig: {
103+
viewServiceType: 'ViewsService',
104+
htmlAugmentationInstructions: defaultHtmlAugmentationInstructions,
105+
viewsInitFunc: defaultViewsInit
70106
},
71107
userConfiguration: {
72108
json: JSON.stringify({
@@ -75,8 +111,46 @@ export const createWrapperConfig = (workspaceRoot: string, code: string, codeUri
75111
'editor.wordBasedSuggestions': 'off',
76112
'editor.experimental.asyncTokenization': true
77113
})
78-
}
114+
},
115+
workspaceConfig: {
116+
enableWorkspaceTrust: true,
117+
windowIndicator: {
118+
label: 'mlc-python-example',
119+
tooltip: '',
120+
command: ''
121+
},
122+
workspaceProvider: {
123+
trusted: true,
124+
async open() {
125+
window.open(window.location.href);
126+
return true;
127+
},
128+
workspace: {
129+
workspaceUri: workspaceFile
130+
}
131+
},
132+
configurationDefaults: {
133+
'window.title': 'mlc-python-example${separator}${dirty}${activeEditorShort}'
134+
},
135+
productConfiguration: {
136+
nameShort: 'mlc-python-example',
137+
nameLong: 'mlc-python-example'
138+
}
139+
},
79140
},
141+
extensions: [
142+
{
143+
config: {
144+
name: 'mlc-app-playground',
145+
publisher: 'TypeFox',
146+
version: '1.0.0',
147+
engines: {
148+
vscode: '*'
149+
}
150+
}
151+
},
152+
provideDebuggerExtensionConfig()
153+
],
80154
editorAppConfig: {
81155
codeResources: {
82156
modified: {

packages/examples/src/python/client/main.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import * as vscode from 'vscode';
77
// this is required syntax highlighting
88
import '@codingame/monaco-vscode-python-default-extension';
99
import { RegisteredFileSystemProvider, registerFileSystemOverlay, RegisteredMemoryFile } from '@codingame/monaco-vscode-files-service-override';
10+
import { type RegisterLocalProcessExtensionResult } from '@codingame/monaco-vscode-api/extensions';
1011
import { MonacoEditorLanguageClientWrapper } from 'monaco-editor-wrapper';
1112
import { createWrapperConfig } from './config.js';
13+
import '../../debugger/client/debugger.js';
1214
import helloPyCode from '../../../resources/python/hello.py?raw';
1315
import hello2PyCode from '../../../resources/python/hello2.py?raw';
16+
import { confiugureDebugging } from '../../debugger/client/debugger.js';
1417

1518
export const runPythonWrapper = async () => {
1619
const helloPyUri = vscode.Uri.file('/workspace/hello.py');
@@ -30,6 +33,10 @@ export const runPythonWrapper = async () => {
3033
console.warn('Editor was already started!');
3134
} else {
3235
await wrapper.init(wrapperConfig);
36+
const initResult = wrapper.getExtensionRegisterResult('debugger-py-client') as RegisterLocalProcessExtensionResult | undefined;
37+
if (initResult !== undefined) {
38+
confiugureDebugging(await initResult.getApi());
39+
}
3340

3441
// open files, so the LS can pick it up
3542
await vscode.workspace.openTextDocument(hello2PyUri);

0 commit comments

Comments
 (0)