aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-vscode/src/features/debug.ts
diff options
context:
space:
mode:
authorGravatar Ashcon Partovi <ashcon@partovi.net> 2023-08-24 22:53:34 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-24 22:53:34 -0700
commit1480889205d49cf7221a36608a8896b452967cea (patch)
treee1427e4041cf19ef1e8e8e0f58cfbbceb4cbbf74 /packages/bun-vscode/src/features/debug.ts
parentf269432d90826ad3e5b66c7685a6e826e0fb05e2 (diff)
downloadbun-1480889205d49cf7221a36608a8896b452967cea.tar.gz
bun-1480889205d49cf7221a36608a8896b452967cea.tar.zst
bun-1480889205d49cf7221a36608a8896b452967cea.zip
Improved support for `debug-adapter-protocol` (#4186)
* Improve support for \`debug-adapter-protocol\` * More improvements, fix formatting in debug console * Fix attaching * Prepare for source maps * Start of source map support, breakpoints work * Source map support * add some package.jsons * wip * Update package.json * More fixes * Make source maps safer if exception occurs * Check bun version if it fails * Fix console.log formatting * Fix source maps partly * More source map fixes * Prepare for extension * watch mode with dap * Improve preview code * Prepare for extension 2 --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'packages/bun-vscode/src/features/debug.ts')
-rw-r--r--packages/bun-vscode/src/features/debug.ts153
1 files changed, 153 insertions, 0 deletions
diff --git a/packages/bun-vscode/src/features/debug.ts b/packages/bun-vscode/src/features/debug.ts
new file mode 100644
index 000000000..3b841ea66
--- /dev/null
+++ b/packages/bun-vscode/src/features/debug.ts
@@ -0,0 +1,153 @@
+import * as vscode from "vscode";
+import type { CancellationToken, DebugConfiguration, ProviderResult, WorkspaceFolder } from "vscode";
+import type { DAP } from "../../../bun-debug-adapter-protocol";
+import { DebugAdapter } from "../../../bun-debug-adapter-protocol";
+import { DebugSession } from "@vscode/debugadapter";
+
+const debugConfiguration: vscode.DebugConfiguration = {
+ type: "bun",
+ request: "launch",
+ name: "Debug Bun",
+ program: "${file}",
+ watch: true,
+};
+
+const runConfiguration: vscode.DebugConfiguration = {
+ type: "bun",
+ request: "launch",
+ name: "Run Bun",
+ program: "${file}",
+ watch: true,
+};
+
+const attachConfiguration: vscode.DebugConfiguration = {
+ type: "bun",
+ request: "attach",
+ name: "Attach to Bun",
+ url: "ws://localhost:6499/",
+};
+
+const debugConfigurations: vscode.DebugConfiguration[] = [debugConfiguration, attachConfiguration];
+
+export default function (context: vscode.ExtensionContext, factory?: vscode.DebugAdapterDescriptorFactory) {
+ context.subscriptions.push(
+ vscode.commands.registerCommand("extension.bun.runFile", (resource: vscode.Uri) => {
+ let targetResource = resource;
+ if (!targetResource && vscode.window.activeTextEditor) {
+ targetResource = vscode.window.activeTextEditor.document.uri;
+ }
+ if (targetResource) {
+ vscode.debug.startDebugging(undefined, runConfiguration, {
+ noDebug: true,
+ });
+ }
+ }),
+ vscode.commands.registerCommand("extension.bun.debugFile", (resource: vscode.Uri) => {
+ let targetResource = resource;
+ if (!targetResource && vscode.window.activeTextEditor) {
+ targetResource = vscode.window.activeTextEditor.document.uri;
+ }
+ if (targetResource) {
+ vscode.debug.startDebugging(undefined, {
+ ...debugConfiguration,
+ program: targetResource.fsPath,
+ });
+ }
+ }),
+ );
+
+ const provider = new BunConfigurationProvider();
+ context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider("bun", provider));
+
+ context.subscriptions.push(
+ vscode.debug.registerDebugConfigurationProvider(
+ "bun",
+ {
+ provideDebugConfigurations(folder: WorkspaceFolder | undefined): ProviderResult<DebugConfiguration[]> {
+ return debugConfigurations;
+ },
+ },
+ vscode.DebugConfigurationProviderTriggerKind.Dynamic,
+ ),
+ );
+
+ if (!factory) {
+ factory = new InlineDebugAdapterFactory();
+ }
+ context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory("bun", factory));
+ if ("dispose" in factory && typeof factory.dispose === "function") {
+ // @ts-ignore
+ context.subscriptions.push(factory);
+ }
+}
+
+class BunConfigurationProvider implements vscode.DebugConfigurationProvider {
+ resolveDebugConfiguration(
+ folder: WorkspaceFolder | undefined,
+ config: DebugConfiguration,
+ token?: CancellationToken,
+ ): ProviderResult<DebugConfiguration> {
+ if (!config.type && !config.request && !config.name) {
+ const editor = vscode.window.activeTextEditor;
+ if (editor && isJavaScript(editor.document.languageId)) {
+ Object.assign(config, debugConfiguration);
+ }
+ }
+ return config;
+ }
+}
+
+class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory {
+ createDebugAdapterDescriptor(_session: vscode.DebugSession): ProviderResult<vscode.DebugAdapterDescriptor> {
+ const adapter = new VSCodeAdapter(_session);
+ return new vscode.DebugAdapterInlineImplementation(adapter);
+ }
+}
+
+function isJavaScript(languageId: string): boolean {
+ return (
+ languageId === "javascript" ||
+ languageId === "javascriptreact" ||
+ languageId === "typescript" ||
+ languageId === "typescriptreact"
+ );
+}
+
+export class VSCodeAdapter extends DebugSession {
+ #adapter: DebugAdapter;
+ #dap: vscode.OutputChannel;
+
+ constructor(session: vscode.DebugSession) {
+ super();
+ this.#dap = vscode.window.createOutputChannel("Debug Adapter Protocol");
+ this.#adapter = new DebugAdapter({
+ sendToAdapter: this.sendMessage.bind(this),
+ });
+ }
+
+ sendMessage(message: DAP.Request | DAP.Response | DAP.Event): void {
+ console.log("[dap] -->", message);
+ this.#dap.appendLine("--> " + JSON.stringify(message));
+
+ const { type } = message;
+ if (type === "response") {
+ this.sendResponse(message);
+ } else if (type === "event") {
+ this.sendEvent(message);
+ } else {
+ throw new Error(`Not supported: ${type}`);
+ }
+ }
+
+ handleMessage(message: DAP.Event | DAP.Request | DAP.Response): void {
+ console.log("[dap] <--", message);
+ this.#dap.appendLine("<-- " + JSON.stringify(message));
+
+ this.#adapter.accept(message);
+ }
+
+ dispose() {
+ this.#adapter.close();
+ this.#dap.dispose();
+ }
+}