diff --git a/package.json b/package.json index 8369697a0..d655b0d6b 100644 --- a/package.json +++ b/package.json @@ -328,6 +328,12 @@ "description": "The path of the SDK to compile against (`--sdk` parameter). The default SDK is determined by the environment on macOS and Windows.", "order": 3 }, + "swift.skipCodeLLDBCheck": { + "type": "boolean", + "default": false, + "description": "Skip check for CodeLLDB being installed.", + "order": 4 + }, "swift.diagnostics": { "type": "boolean", "default": false, @@ -567,9 +573,6 @@ ] } }, - "extensionDependencies": [ - "vadimcn.vscode-lldb" - ], "scripts": { "vscode:prepublish": "npm run esbuild-base -- --minify", "esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=dist/extension.js --external:vscode --format=cjs --platform=node --target=node16", diff --git a/src/WorkspaceContext.ts b/src/WorkspaceContext.ts index 6ab270309..6c5599dc0 100644 --- a/src/WorkspaceContext.ts +++ b/src/WorkspaceContext.ts @@ -23,7 +23,7 @@ import { swiftLibraryPathKey, getErrorDescription, } from "./utilities/utilities"; -import { getLLDBLibPath } from "./debugger/lldb"; +import { checkLLDBInstalled, getLLDBLibPath } from "./debugger/lldb"; import { LanguageClientManager } from "./sourcekit-lsp/LanguageClientManager"; import { TemporaryFolder } from "./utilities/tempFolder"; import { SwiftToolchain } from "./toolchain/toolchain"; @@ -350,6 +350,22 @@ export class WorkspaceContext implements vscode.Disposable { return { dispose: () => this.observers.delete(fn) }; } + async setupLLDB() { + await checkLLDBInstalled().then( + async result => { + if (result) { + this.setLLDBVersion(); + } + }, + error => { + const errorMessage = `Error: ${getErrorDescription(error)}`; + vscode.window.showErrorMessage( + `Failed to setup CodeLLDB for debugging of Swift code. Debugging may produce unexpected results. ${errorMessage}` + ); + } + ); + } + /** find LLDB version and setup path in CodeLLDB */ async setLLDBVersion() { const libPathResult = await getLLDBLibPath(this.toolchain); diff --git a/src/configuration.ts b/src/configuration.ts index 4cddcbab4..d4004d4df 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -141,6 +141,10 @@ const configuration = { .get("backgroundCompilation", false); }, /** output additional diagnostics */ + get skipCodeLLDBCheck(): boolean { + return vscode.workspace.getConfiguration("swift").get("skipCodeLLDBCheck", false); + }, + /** output additional diagnostics */ get diagnostics(): boolean { return vscode.workspace.getConfiguration("swift").get("diagnostics", false); }, diff --git a/src/debugger/lldb.ts b/src/debugger/lldb.ts index 78ac826db..92c579836 100644 --- a/src/debugger/lldb.ts +++ b/src/debugger/lldb.ts @@ -15,11 +15,65 @@ // Based on code taken from CodeLLDB https://github.com/vadimcn/vscode-lldb/ // LICENSED with MIT License +import * as vscode from "vscode"; import * as path from "path"; import * as fs from "fs/promises"; import { execFile } from "../utilities/utilities"; import { Result } from "../utilities/result"; import { SwiftToolchain } from "../toolchain/toolchain"; +import configuration from "../configuration"; + +/** + * Check if CodeLLDB extension is installed and offer to install it if it is not. + * @returns Whether extension was installed + */ +export async function checkLLDBInstalled(): Promise { + const lldbExtension = vscode.extensions.getExtension("vadimcn.vscode-lldb"); + // if extension is in list return true + if (lldbExtension) { + return true; + } + // if workspace is set to ignore LLDB check then return + if (configuration.skipCodeLLDBCheck === true) { + return false; + } + // otherwise display menu asking if user wants to install it + return new Promise((resolve, reject) => { + vscode.window + .showWarningMessage( + "Do you want to install the CodeLLDB extension?", + { + modal: true, + detail: "The Swift extension requires it to enable debugging.", + }, + "Install" + ) + .then(async result => { + switch (result) { + case "Install": + try { + await installCodeLLDB(); + return resolve(true); + } catch (error) { + return reject(error); + } + case undefined: + break; + } + return resolve(false); + }); + }); +} + +/** + * Install CodeLLDB extension + */ +async function installCodeLLDB() { + await vscode.commands.executeCommand( + "workbench.extensions.installExtension", + "vadimcn.vscode-lldb" + ); +} /** * Get LLDB library for given LLDB executable diff --git a/src/extension.ts b/src/extension.ts index 54832cf45..d7352df9a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -46,7 +46,7 @@ export async function activate(context: vscode.ExtensionContext): Promise { context.subscriptions.push(workspaceContext); // setup swift version of LLDB. Don't await on this as it can run in the background - workspaceContext.setLLDBVersion(); + workspaceContext.setupLLDB(); // listen for workspace folder changes and active text editor changes workspaceContext.setupEventListeners(); diff --git a/test/runTest.ts b/test/runTest.ts index a4af7b377..7a7351171 100644 --- a/test/runTest.ts +++ b/test/runTest.ts @@ -12,13 +12,8 @@ // //===----------------------------------------------------------------------===// -import * as cp from "child_process"; import * as path from "path"; -import { - runTests, - downloadAndUnzipVSCode, - resolveCliPathFromVSCodeExecutablePath, -} from "@vscode/test-electron"; +import { runTests } from "@vscode/test-electron"; async function main() { try { @@ -30,22 +25,6 @@ async function main() { // Passed to --extensionTestsPath const extensionTestsPath = path.resolve(__dirname, "./suite/index"); - const vscodeExecutablePath = await downloadAndUnzipVSCode(); - const cliPath = resolveCliPathFromVSCodeExecutablePath(vscodeExecutablePath); - - // Use cp.spawn / cp.exec for custom setup - console.log(`${cliPath} --install-extension vadimcn.vscode-lldb`); - const { stdout, stderr } = cp.spawnSync( - cliPath, - ["--install-extension", "vadimcn.vscode-lldb"], - { - encoding: "utf-8", - stdio: "inherit", - } - ); - console.log(stdout); - console.log(stderr); - // Download VS Code, unzip it and run the integration test await runTests({ extensionDevelopmentPath,