[Lldb-commits] [lldb] [lldb-dap] Allow providing debug adapter arguments in the extension (PR #129262)

John Harrison via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 14 15:18:00 PDT 2025


================
@@ -0,0 +1,103 @@
+import * as vscode from "vscode";
+import * as child_process from "child_process";
+import * as util from "util";
+import { LLDBDapServer } from "./lldb-dap-server";
+import { createDebugAdapterExecutable } from "./debug-adapter-factory";
+import { ConfigureButton, showErrorMessage } from "./ui/show-error-message";
+import { ErrorWithNotification } from "./ui/error-with-notification";
+
+const exec = util.promisify(child_process.execFile);
+
+/**
+ * Determines whether or not the given lldb-dap executable supports executing
+ * in server mode.
+ *
+ * @param exe the path to the lldb-dap executable
+ * @returns a boolean indicating whether or not lldb-dap supports server mode
+ */
+async function isServerModeSupported(exe: string): Promise<boolean> {
+  const { stdout } = await exec(exe, ["--help"]);
+  return /--connection/.test(stdout);
+}
+
+export class LLDBDapConfigurationProvider
+  implements vscode.DebugConfigurationProvider
+{
+  constructor(private readonly server: LLDBDapServer) {}
+
+  async resolveDebugConfiguration(
+    folder: vscode.WorkspaceFolder | undefined,
+    debugConfiguration: vscode.DebugConfiguration,
----------------
ashgti wrote:

I wonder if we should have our own typed interface + validator to help with writing / validating the debug configurations.

For example,

```
interface LLDBDebugConfiguration extends vscode.DebugConfiguration {
  program: string;
  args?: string[];
  env: Record<string, string>;
  debugAdapterHostname?: string;
  initCommands?: string[];
  stopOnEntry?: boolean;
}

type TypeGuard<in out T> = {
  (val: unknown): val is T;
}

function isBoolean(val: unknown): val is boolean {
  return typeof val === 'boolean';
}

function isString(val: unknown): val is string {
  return typeof val === 'string';
}

function isObject(val: unknown): val is object {
  return typeof val === 'object';
}

function isArrayOf<T>(validator: TypeGuard<T>): TypeGuard<T[]> {
  return (val: unknown): val is T[] => { return Array.isArray(val) && val.every(validator); };
}

function isRecordOf<T>(validator: TypeGuard<T>): TypeGuard<Record<string, T>> {
  return (val: unknown): val is Record<string, T> => {
    return isObject(val) && Object.entries(val).every(([key, value]) => isString(key) && validator(value));
  };
}

function isOptional<T>(validator: TypeGuard<T>): (val: unknown) => val is undefined | T {
  return (val: unknown): val is undefined | T => { return typeof val === 'undefined' ? true : validator(val) };
}

type KeyValidator<T> = { [P in keyof T]: TypeGuard<T[P]>; };

function isStruct<T>(kvValidator: KeyValidator<T>): (val: unknown) => val is T {
  return (val: unknown): val is T => {
    if (typeof val !== 'object' || val === null) return false;
    return Object.entries(kvValidator as Record<string, (arg: unknown) => boolean>).every(([key, validator]) => validator(Reflect.get(val, key)));
  };
}

const isLLDBDebugConfiguration = isStruct<LLDBDebugConfiguration>({
  program: isString,
  env: isRecordOf(isString),
  debugAdapterHostname: isOptional(isString),
  initCommands: isOptional(isArrayOf(isString)),
  ... other validators
});


...

async resolveDebugConfigurationWithSubstitutedVariables(folder, debugConfig) {
  if (!isLLDBDebugConfiguration(debugConfig)) throw new Error("invalid debug configuration");

  // After this you should be able to use `debugConfig.program` etc.
}
```

https://github.com/llvm/llvm-project/pull/129262


More information about the lldb-commits mailing list