| import * as vscode from "vscode"; |
| |
| export class LaunchUriHandler implements vscode.UriHandler { |
| async handleUri(uri: vscode.Uri) { |
| try { |
| const params = new URLSearchParams(uri.query); |
| if (uri.path == '/start') { |
| // Some properties have default values |
| let debugConfig: vscode.DebugConfiguration = { |
| type: 'lldb-dap', |
| request: 'launch', |
| name: '', |
| }; |
| // The `config` parameter allows providing a complete JSON-encoded configuration |
| const configJson = params.get("config"); |
| if (configJson !== null) { |
| Object.assign(debugConfig, JSON.parse(configJson)); |
| } |
| // Furthermore, some frequently used parameters can also be provided as separate parameters |
| const stringKeys = ["name", "request", "program", "cwd", "debuggerRoot"]; |
| const numberKeys = ["pid"]; |
| const arrayKeys = [ |
| "args", "initCommands", "preRunCommands", "stopCommands", "exitCommands", |
| "terminateCommands", "launchCommands", "attachCommands" |
| ]; |
| for (const key of stringKeys) { |
| const value = params.get(key); |
| if (value) { |
| debugConfig[key] = value; |
| } |
| } |
| for (const key of numberKeys) { |
| const value = params.get(key); |
| if (value) { |
| debugConfig[key] = Number(value); |
| } |
| } |
| for (const key of arrayKeys) { |
| // `getAll()` returns an array of strings. |
| const value = params.getAll(key); |
| if (value) { |
| debugConfig[key] = value; |
| } |
| } |
| // Report an error if we received any unknown parameters |
| const supportedKeys = new Set<string>(["config"].concat(stringKeys).concat(numberKeys).concat(arrayKeys)); |
| const presentKeys = new Set<string>(params.keys()); |
| // FIXME: Use `Set.difference` as soon as ES2024 is widely available |
| const unknownKeys = new Set<string>(); |
| for (const k of presentKeys.keys()) { |
| if (!supportedKeys.has(k)) { |
| unknownKeys.add(k); |
| } |
| } |
| if (unknownKeys.size > 0) { |
| throw new Error(`Unsupported URL parameters: ${Array.from(unknownKeys.keys()).join(", ")}`); |
| } |
| // Prodide a default for the config name |
| const defaultName = debugConfig.request == 'launch' ? "URL-based Launch" : "URL-based Attach"; |
| debugConfig.name = debugConfig.name || debugConfig.program || defaultName; |
| // Force the type to `lldb-dap`. We don't want to allow launching any other |
| // Debug Adapters using this URI scheme. |
| if (debugConfig.type != "lldb-dap") { |
| throw new Error(`Unsupported debugger type: ${debugConfig.type}`); |
| } |
| await vscode.debug.startDebugging(undefined, debugConfig); |
| } else { |
| throw new Error(`Unsupported Uri path: ${uri.path}`); |
| } |
| } catch (err) { |
| if (err instanceof Error) { |
| await vscode.window.showErrorMessage(`Failed to handle lldb-dap URI request: ${err.message}`); |
| } else { |
| await vscode.window.showErrorMessage(`Failed to handle lldb-dap URI request: ${JSON.stringify(err)}`); |
| } |
| } |
| } |
| } |