Skip to content

Use LLDB DAP extension to launch debug sessions #1384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,8 @@
]
},
"extensionDependencies": [
"vadimcn.vscode-lldb"
"vadimcn.vscode-lldb",
"llvm-vs-code-extensions.lldb-dap"
],
"scripts": {
"vscode:prepublish": "npm run bundle",
Expand Down
2 changes: 1 addition & 1 deletion src/debugger/debugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const SWIFT_LAUNCH_CONFIG_TYPE = "swift";
* LLDB launch requests.
*/
export const enum LaunchConfigType {
LLDB_DAP = "swift",
LLDB_DAP = "lldb-dap",
CODE_LLDB = "lldb",
}

Expand Down
47 changes: 2 additions & 45 deletions src/debugger/debugAdapterFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,54 +52,10 @@ function registerLLDBDebugAdapter(
toolchain: SwiftToolchain,
outputChannel: SwiftOutputChannel
): vscode.Disposable {
const debugAdpaterFactory = vscode.debug.registerDebugAdapterDescriptorFactory(
SWIFT_LAUNCH_CONFIG_TYPE,
new LLDBDebugAdapterExecutableFactory(toolchain, outputChannel)
);

const debugConfigProvider = vscode.debug.registerDebugConfigurationProvider(
return vscode.debug.registerDebugConfigurationProvider(
SWIFT_LAUNCH_CONFIG_TYPE,
new LLDBDebugConfigurationProvider(process.platform, toolchain, outputChannel)
);

return {
dispose: () => {
debugConfigProvider.dispose();
debugAdpaterFactory.dispose();
},
};
}

/**
* A factory class for creating and providing the executable descriptor for the LLDB Debug Adapter.
* This class implements the vscode.DebugAdapterDescriptorFactory interface and is responsible for
* determining the path to the LLDB Debug Adapter executable and ensuring it exists before launching
* a debug session.
*
* This class uses the workspace context to:
* - Resolve the path to the debug adapter executable.
* - Verify that the debug adapter exists in the toolchain.
*
* The main method of this class, `createDebugAdapterDescriptor`, is invoked by VS Code to supply
* the debug adapter executable when a debug session is started. The executable parameter by default
* will be provided in package.json > contributes > debuggers > program if defined, but since we will
* determine the executable via the toolchain anyway, this is now redundant and will be ignored.
*
* @implements {vscode.DebugAdapterDescriptorFactory}
*/
export class LLDBDebugAdapterExecutableFactory implements vscode.DebugAdapterDescriptorFactory {
private toolchain: SwiftToolchain;
private outputChannel: SwiftOutputChannel;

constructor(toolchain: SwiftToolchain, outputChannel: SwiftOutputChannel) {
this.toolchain = toolchain;
this.outputChannel = outputChannel;
}

async createDebugAdapterDescriptor(): Promise<vscode.DebugAdapterDescriptor> {
const path = await DebugAdapter.getLLDBDebugAdapterPath(this.toolchain);
return new vscode.DebugAdapterExecutable(path, [], {});
}
}

/** Provide configurations for lldb-vscode/lldb-dap
Expand Down Expand Up @@ -150,6 +106,7 @@ export class LLDBDebugConfigurationProvider implements vscode.DebugConfiguration
);
return undefined;
}
launchConfig.debugAdapterExecutable = lldbDapPath;
}

return launchConfig;
Expand Down
44 changes: 6 additions & 38 deletions test/unit-tests/debugger/debugAdapterFactory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@

import * as vscode from "vscode";
import { expect } from "chai";
import {
LLDBDebugAdapterExecutableFactory,
LLDBDebugConfigurationProvider,
} from "../../../src/debugger/debugAdapterFactory";
import { LLDBDebugConfigurationProvider } from "../../../src/debugger/debugAdapterFactory";
import { Version } from "../../../src/utilities/version";
import {
mockGlobalObject,
Expand All @@ -28,46 +25,14 @@ import {
mockFn,
} from "../../MockUtils";
import * as mockFS from "mock-fs";
import {
DebugAdapter,
LaunchConfigType,
SWIFT_LAUNCH_CONFIG_TYPE,
} from "../../../src/debugger/debugAdapter";
import { LaunchConfigType, SWIFT_LAUNCH_CONFIG_TYPE } from "../../../src/debugger/debugAdapter";
import * as lldb from "../../../src/debugger/lldb";
import { SwiftToolchain } from "../../../src/toolchain/toolchain";
import { SwiftOutputChannel } from "../../../src/ui/SwiftOutputChannel";
import * as debugAdapter from "../../../src/debugger/debugAdapter";
import { Result } from "../../../src/utilities/result";
import configuration from "../../../src/configuration";

suite("LLDBDebugAdapterExecutableFactory Tests", () => {
const mockDebugAdapter = mockGlobalModule(DebugAdapter);
let mockToolchain: MockedObject<SwiftToolchain>;
let mockOutputChannel: MockedObject<SwiftOutputChannel>;

setup(() => {
mockToolchain = mockObject<SwiftToolchain>({});
mockOutputChannel = mockObject<SwiftOutputChannel>({
log: mockFn(),
});
});

test("should return a DebugAdapterExecutable with the path to lldb-dap", async () => {
const toolchainPath = "/path/to/debug/adapter";

mockDebugAdapter.getLLDBDebugAdapterPath.resolves(toolchainPath);

const factory = new LLDBDebugAdapterExecutableFactory(
instance(mockToolchain),
instance(mockOutputChannel)
);
const result = await factory.createDebugAdapterDescriptor();

expect(result).to.be.instanceOf(vscode.DebugAdapterExecutable);
expect(result).to.have.property("command").that.equals(toolchainPath);
});
});

suite("LLDBDebugConfigurationProvider Tests", () => {
let mockToolchain: MockedObject<SwiftToolchain>;
let mockOutputChannel: MockedObject<SwiftOutputChannel>;
Expand Down Expand Up @@ -188,7 +153,10 @@ suite("LLDBDebugConfigurationProvider Tests", () => {
request: "launch",
program: "${workspaceFolder}/.build/debug/executable",
});
expect(launchConfig).to.containSubset({ type: LaunchConfigType.LLDB_DAP });
expect(launchConfig).to.containSubset({
type: LaunchConfigType.LLDB_DAP,
debugAdapterExecutable: "/path/to/lldb-dap",
});
});

test("fails if the path to lldb-dap could not be found", async () => {
Expand Down