103 lines · typescript
1import * as vscode from "vscode";2 3export class LaunchUriHandler implements vscode.UriHandler {4 async handleUri(uri: vscode.Uri) {5 try {6 const params = new URLSearchParams(uri.query);7 if (uri.path == "/start") {8 // Some properties have default values9 let debugConfig: vscode.DebugConfiguration = {10 type: "lldb-dap",11 request: "launch",12 name: "",13 };14 // The `config` parameter allows providing a complete JSON-encoded configuration15 const configJson = params.get("config");16 if (configJson !== null) {17 Object.assign(debugConfig, JSON.parse(configJson));18 }19 // Furthermore, some frequently used parameters can also be provided as separate parameters20 const stringKeys = [21 "name",22 "request",23 "program",24 "cwd",25 "debuggerRoot",26 ];27 const numberKeys = ["pid"];28 const arrayKeys = [29 "args",30 "initCommands",31 "preRunCommands",32 "stopCommands",33 "exitCommands",34 "terminateCommands",35 "launchCommands",36 "attachCommands",37 ];38 for (const key of stringKeys) {39 const value = params.get(key);40 if (value) {41 debugConfig[key] = value;42 }43 }44 for (const key of numberKeys) {45 const value = params.get(key);46 if (value) {47 debugConfig[key] = Number(value);48 }49 }50 for (const key of arrayKeys) {51 // `getAll()` returns an array of strings.52 const value = params.getAll(key);53 if (value) {54 debugConfig[key] = value;55 }56 }57 // Report an error if we received any unknown parameters58 const supportedKeys = new Set<string>(59 ["config"].concat(stringKeys).concat(numberKeys).concat(arrayKeys),60 );61 const presentKeys = new Set<string>(params.keys());62 // FIXME: Use `Set.difference` as soon as ES2024 is widely available63 const unknownKeys = new Set<string>();64 for (const k of presentKeys.keys()) {65 if (!supportedKeys.has(k)) {66 unknownKeys.add(k);67 }68 }69 if (unknownKeys.size > 0) {70 throw new Error(71 `Unsupported URL parameters: ${Array.from(unknownKeys.keys()).join(", ")}`,72 );73 }74 // Prodide a default for the config name75 const defaultName =76 debugConfig.request == "launch"77 ? "URL-based Launch"78 : "URL-based Attach";79 debugConfig.name =80 debugConfig.name || debugConfig.program || defaultName;81 // Force the type to `lldb-dap`. We don't want to allow launching any other82 // Debug Adapters using this URI scheme.83 if (debugConfig.type != "lldb-dap") {84 throw new Error(`Unsupported debugger type: ${debugConfig.type}`);85 }86 await vscode.debug.startDebugging(undefined, debugConfig);87 } else {88 throw new Error(`Unsupported Uri path: ${uri.path}`);89 }90 } catch (err) {91 if (err instanceof Error) {92 await vscode.window.showErrorMessage(93 `Failed to handle lldb-dap URI request: ${err.message}`,94 );95 } else {96 await vscode.window.showErrorMessage(97 `Failed to handle lldb-dap URI request: ${JSON.stringify(err)}`,98 );99 }100 }101 }102}103