From 6aca05f67440d269a41d7000ade60eb2020f6e6d Mon Sep 17 00:00:00 2001 From: Priyambada Roul Date: Wed, 23 Jul 2025 20:24:53 +0530 Subject: [PATCH 1/4] Fixed JSON parsing error --- src/toolchain/swiftly.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/toolchain/swiftly.ts b/src/toolchain/swiftly.ts index 139170691..c39d6ec10 100644 --- a/src/toolchain/swiftly.ts +++ b/src/toolchain/swiftly.ts @@ -20,18 +20,17 @@ import * as vscode from "vscode"; import { Version } from "../utilities/version"; import { z } from "zod"; -const ListAvailableResult = z.object({ +const ListResult = z.object({ toolchains: z.array( z.object({ inUse: z.boolean(), - installed: z.boolean(), isDefault: z.boolean(), - name: z.string(), version: z.discriminatedUnion("type", [ z.object({ major: z.number(), minor: z.number(), patch: z.number().optional(), + name: z.string(), type: z.literal("stable"), }), z.object({ @@ -39,7 +38,7 @@ const ListAvailableResult = z.object({ minor: z.number(), branch: z.string(), date: z.string(), - + name: z.string(), type: z.literal("snapshot"), }), ]), @@ -97,9 +96,9 @@ export class Swiftly { outputChannel?: vscode.OutputChannel ): Promise { try { - const { stdout } = await execFile("swiftly", ["list-available", "--format=json"]); - const response = ListAvailableResult.parse(JSON.parse(stdout)); - return response.toolchains.map(t => t.name); + const { stdout } = await execFile("swiftly", ["list", "--format=json"]); + const response = ListResult.parse(JSON.parse(stdout)); + return response.toolchains.map(t => t.version.name); } catch (error) { outputChannel?.appendLine(`Failed to retrieve Swiftly installations: ${error}`); throw new Error( From 506762c294b09df5265134e941aa5b63be797d37 Mon Sep 17 00:00:00 2001 From: Priyambada Roul Date: Thu, 24 Jul 2025 22:33:16 +0530 Subject: [PATCH 2/4] Fix Swiftly toolchain selection --- src/toolchain/swiftly.ts | 11 ++++++++--- src/ui/ToolchainSelection.ts | 17 ++++++++++++++++- test/unit-tests/toolchain/swiftly.test.ts | 21 ++++++++------------- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/toolchain/swiftly.ts b/src/toolchain/swiftly.ts index c39d6ec10..4501ad5f9 100644 --- a/src/toolchain/swiftly.ts +++ b/src/toolchain/swiftly.ts @@ -101,9 +101,7 @@ export class Swiftly { return response.toolchains.map(t => t.version.name); } catch (error) { outputChannel?.appendLine(`Failed to retrieve Swiftly installations: ${error}`); - throw new Error( - `Failed to retrieve Swiftly installations from disk: ${(error as Error).message}` - ); + return []; } } @@ -143,6 +141,13 @@ export class Swiftly { return inUse.trimEnd(); } + public static async use(version: string): Promise { + if (!this.isSupported()) { + throw new Error("Swiftly is not supported on this platform"); + } + await execFile("swiftly", ["use", version]); + } + /** * Determine if Swiftly is being used to manage the active toolchain and if so, return * the path to the active toolchain. diff --git a/src/ui/ToolchainSelection.ts b/src/ui/ToolchainSelection.ts index 2cdb2a9bb..16df88ca4 100644 --- a/src/ui/ToolchainSelection.ts +++ b/src/ui/ToolchainSelection.ts @@ -304,7 +304,22 @@ export async function showToolchainSelectionQuickPick(activeToolchain: SwiftTool } } // Update the toolchain path - const isUpdated = await setToolchainPath(selected.swiftFolderPath, developerDir); + let swiftPath = selected.swiftFolderPath; + + // Handle Swiftly toolchains specially + if (selected.category === "swiftly") { + try { + // Run swiftly use and get the path to the toolchain + await Swiftly.use(selected.label); + const inUseLocation = await Swiftly.inUseLocation("swiftly"); + swiftPath = path.join(inUseLocation, "usr", "bin"); + } catch (error) { + void vscode.window.showErrorMessage(`Failed to switch Swiftly toolchain: ${error}`); + return; + } + } + + const isUpdated = await setToolchainPath(swiftPath, developerDir); if (isUpdated && selected.onDidSelect) { await selected.onDidSelect(); } diff --git a/test/unit-tests/toolchain/swiftly.test.ts b/test/unit-tests/toolchain/swiftly.test.ts index 71cd193ac..fa48bea81 100644 --- a/test/unit-tests/toolchain/swiftly.test.ts +++ b/test/unit-tests/toolchain/swiftly.test.ts @@ -38,50 +38,45 @@ suite("Swiftly Unit Tests", () => { toolchains: [ { inUse: true, - installed: true, isDefault: true, - name: "swift-5.9.0-RELEASE", version: { major: 5, minor: 9, patch: 0, + name: "swift-5.9.0-RELEASE", type: "stable", }, }, { inUse: false, - installed: true, isDefault: false, - name: "swift-5.8.0-RELEASE", version: { major: 5, minor: 8, patch: 0, + name: "swift-5.8.0-RELEASE", type: "stable", }, }, { inUse: false, - installed: false, isDefault: false, - name: "swift-DEVELOPMENT-SNAPSHOT-2023-10-15-a", version: { major: 5, minor: 10, branch: "development", date: "2023-10-15", + name: "swift-DEVELOPMENT-SNAPSHOT-2023-10-15-a", type: "snapshot", }, }, ], }; - mockUtilities.execFile - .withArgs("swiftly", ["list-available", "--format=json"]) - .resolves({ - stdout: JSON.stringify(jsonOutput), - stderr: "", - }); + mockUtilities.execFile.withArgs("swiftly", ["list", "--format=json"]).resolves({ + stdout: JSON.stringify(jsonOutput), + stderr: "", + }); const result = await Swiftly.listAvailableToolchains(); @@ -93,7 +88,7 @@ suite("Swiftly Unit Tests", () => { expect(mockUtilities.execFile).to.have.been.calledWith("swiftly", ["--version"]); expect(mockUtilities.execFile).to.have.been.calledWith("swiftly", [ - "list-available", + "list", "--format=json", ]); }); From 2a983368fce56bb305b07db89c0d7f79312fdbb9 Mon Sep 17 00:00:00 2001 From: Priyambada Roul Date: Fri, 25 Jul 2025 10:01:57 +0530 Subject: [PATCH 3/4] Fix Swiftly toolchain management and selection support --- src/toolchain/swiftly.ts | 40 +++++++++++++++++++++++++++---- src/toolchain/toolchain.ts | 21 ++++++++++++---- src/ui/ToolchainSelection.ts | 46 +++++++++++++++++++++++++----------- 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/src/toolchain/swiftly.ts b/src/toolchain/swiftly.ts index 4501ad5f9..6a8207d58 100644 --- a/src/toolchain/swiftly.ts +++ b/src/toolchain/swiftly.ts @@ -27,15 +27,15 @@ const ListResult = z.object({ isDefault: z.boolean(), version: z.discriminatedUnion("type", [ z.object({ - major: z.number(), - minor: z.number(), + major: z.number().optional(), + minor: z.number().optional(), patch: z.number().optional(), name: z.string(), type: z.literal("stable"), }), z.object({ - major: z.number(), - minor: z.number(), + major: z.number().optional(), + minor: z.number().optional(), branch: z.string(), date: z.string(), name: z.string(), @@ -134,7 +134,7 @@ export class Swiftly { return process.platform === "linux" || process.platform === "darwin"; } - public static async inUseLocation(swiftlyPath: string, cwd?: vscode.Uri) { + public static async inUseLocation(swiftlyPath: string = "swiftly", cwd?: vscode.Uri) { const { stdout: inUse } = await execFile(swiftlyPath, ["use", "--print-location"], { cwd: cwd?.fsPath, }); @@ -182,6 +182,36 @@ export class Swiftly { return undefined; } + /** + * Returns the home directory for Swiftly. + * + * @returns The path to the Swiftly home directory. + */ + static getHomeDir(): string | undefined { + return process.env["SWIFTLY_HOME_DIR"]; + } + + /** + * Returns the directory where Swift binaries managed by Swiftly are installed. + * This is a placeholder method and should be implemented based on your environment. + * + * @returns The path to the Swiftly binaries directory. + */ + static getBinDir(): string { + const overriddenBinDir = process.env["SWIFTLY_BIN_DIR"]; + if (overriddenBinDir) { + return overriddenBinDir; + } + + // If SWIFTLY_BIN_DIR is not set, use the default location based on SWIFTLY_HOME_DIR + // This assumes that the binaries are located in the "bin" subdirectory of SWIFTLY_HOME_DIR + const swiftlyHomeDir = Swiftly.getHomeDir(); + if (!swiftlyHomeDir) { + throw new Error("Swiftly is not installed or SWIFTLY_HOME_DIR is not set."); + } + return path.join(swiftlyHomeDir, "bin"); + } + /** * Reads the Swiftly configuration file, if it exists. * diff --git a/src/toolchain/toolchain.ts b/src/toolchain/toolchain.ts index 96321590f..6914d037e 100644 --- a/src/toolchain/toolchain.ts +++ b/src/toolchain/toolchain.ts @@ -112,7 +112,8 @@ export class SwiftToolchain { public customSDK?: string, public xcTestPath?: string, public swiftTestingPath?: string, - public swiftPMTestingHelperPath?: string + public swiftPMTestingHelperPath?: string, + public isSwiftlyManaged: boolean = false // true if this toolchain is managed by Swiftly ) { this.swiftVersionString = targetInfo.compilerVersion; } @@ -121,7 +122,10 @@ export class SwiftToolchain { folder?: vscode.Uri, outputChannel?: vscode.OutputChannel ): Promise { - const swiftFolderPath = await this.getSwiftFolderPath(folder, outputChannel); + const { path: swiftFolderPath, isSwiftlyManaged } = await this.getSwiftFolderPath( + folder, + outputChannel + ); const toolchainPath = await this.getToolchainPath(swiftFolderPath, folder, outputChannel); const targetInfo = await this.getSwiftTargetInfo( this._getToolchainExecutable(toolchainPath, "swift") @@ -159,7 +163,8 @@ export class SwiftToolchain { customSDK, xcTestPath, swiftTestingPath, - swiftPMTestingHelperPath + swiftPMTestingHelperPath, + isSwiftlyManaged ); } @@ -518,7 +523,7 @@ export class SwiftToolchain { private static async getSwiftFolderPath( cwd?: vscode.Uri, outputChannel?: vscode.OutputChannel - ): Promise { + ): Promise<{ path: string; isSwiftlyManaged: boolean }> { try { let swift: string; if (configuration.path !== "") { @@ -564,18 +569,24 @@ export class SwiftToolchain { } // swift may be a symbolic link let realSwift = await fs.realpath(swift); + let isSwiftlyManaged = false; + if (path.basename(realSwift) === "swiftly") { try { const inUse = await Swiftly.inUseLocation(realSwift, cwd); if (inUse) { realSwift = path.join(inUse, "usr", "bin", "swift"); + isSwiftlyManaged = true; } } catch { // Ignore, will fall back to original path } } const swiftPath = expandFilePathTilde(path.dirname(realSwift)); - return await this.getSwiftEnvPath(swiftPath); + return { + path: await this.getSwiftEnvPath(swiftPath), + isSwiftlyManaged, + }; } catch (error) { outputChannel?.appendLine(`Failed to find swift executable: ${error}`); throw Error("Failed to find swift executable"); diff --git a/src/ui/ToolchainSelection.ts b/src/ui/ToolchainSelection.ts index 16df88ca4..e747f536e 100644 --- a/src/ui/ToolchainSelection.ts +++ b/src/ui/ToolchainSelection.ts @@ -98,25 +98,27 @@ export async function selectToolchain() { } /** A {@link vscode.QuickPickItem} that contains the path to an installed Swift toolchain */ -type SwiftToolchainItem = PublicSwiftToolchainItem | XcodeToolchainItem; +type SwiftToolchainItem = PublicSwiftToolchainItem | XcodeToolchainItem | SwiftlyToolchainItem; /** Common properties for a {@link vscode.QuickPickItem} that represents a Swift toolchain */ interface BaseSwiftToolchainItem extends vscode.QuickPickItem { type: "toolchain"; - toolchainPath: string; - swiftFolderPath: string; onDidSelect?(): Promise; } /** A {@link vscode.QuickPickItem} for a Swift toolchain that has been installed manually */ interface PublicSwiftToolchainItem extends BaseSwiftToolchainItem { - category: "public" | "swiftly"; + category: "public"; + toolchainPath: string; + swiftFolderPath: string; } /** A {@link vscode.QuickPickItem} for a Swift toolchain provided by an installed Xcode application */ interface XcodeToolchainItem extends BaseSwiftToolchainItem { category: "xcode"; xcodePath: string; + toolchainPath: string; + swiftFolderPath: string; } /** A {@link vscode.QuickPickItem} that performs an action for the user */ @@ -125,6 +127,11 @@ interface ActionItem extends vscode.QuickPickItem { run(): Promise; } +interface SwiftlyToolchainItem extends BaseSwiftToolchainItem { + category: "swiftly"; + version: string; +} + /** A {@link vscode.QuickPickItem} that separates items in the UI */ class SeparatorItem implements vscode.QuickPickItem { readonly type = "separator"; @@ -178,7 +185,6 @@ async function getQuickPickItems( type: "toolchain", category: "public", label: path.basename(toolchainPath, ".xctoolchain"), - detail: toolchainPath, toolchainPath: path.join(toolchainPath, "usr"), swiftFolderPath: path.join(toolchainPath, "usr", "bin"), }; @@ -195,18 +201,28 @@ async function getQuickPickItems( // Find any Swift toolchains installed via Swiftly const swiftlyToolchains = (await Swiftly.listAvailableToolchains()) .reverse() - .map(toolchainPath => ({ + .map(toolchainPath => ({ type: "toolchain", - category: "swiftly", label: path.basename(toolchainPath), - detail: toolchainPath, - toolchainPath: path.join(toolchainPath, "usr"), - swiftFolderPath: path.join(toolchainPath, "usr", "bin"), + category: "swiftly", + version: path.basename(toolchainPath), })); // Mark which toolchain is being actively used if (activeToolchain) { const toolchainInUse = [...xcodes, ...toolchains, ...swiftlyToolchains].find(toolchain => { - return toolchain.toolchainPath === activeToolchain.toolchainPath; + if (activeToolchain.isSwiftlyManaged) { + if (toolchain.category !== "swiftly") { + return false; + } + + // For Swiftly toolchains, check if the label matches the active toolchain version + return toolchain.label === activeToolchain.swiftVersion.toString(); + } + // For non-Swiftly toolchains, check if the toolchain path matches + return ( + (toolchain as PublicSwiftToolchainItem | XcodeToolchainItem).toolchainPath === + activeToolchain.toolchainPath + ); }); if (toolchainInUse) { toolchainInUse.description = "$(check) in use"; @@ -304,19 +320,21 @@ export async function showToolchainSelectionQuickPick(activeToolchain: SwiftTool } } // Update the toolchain path - let swiftPath = selected.swiftFolderPath; + let swiftPath: string; // Handle Swiftly toolchains specially if (selected.category === "swiftly") { try { // Run swiftly use and get the path to the toolchain await Swiftly.use(selected.label); - const inUseLocation = await Swiftly.inUseLocation("swiftly"); - swiftPath = path.join(inUseLocation, "usr", "bin"); + swiftPath = Swiftly.getBinDir(); } catch (error) { void vscode.window.showErrorMessage(`Failed to switch Swiftly toolchain: ${error}`); return; } + } else { + // For non-Swiftly toolchains, use the swiftFolderPath + swiftPath = (selected as PublicSwiftToolchainItem | XcodeToolchainItem).swiftFolderPath; } const isUpdated = await setToolchainPath(swiftPath, developerDir); From ce6c83f00c6c298fee5f75fe9a1d4df2edfec186 Mon Sep 17 00:00:00 2001 From: Priyambada Roul Date: Fri, 25 Jul 2025 23:31:53 +0530 Subject: [PATCH 4/4] Don't set swift.path if using swiftly --- src/commands.ts | 5 ++- src/extension.ts | 4 +- src/toolchain/swiftly.ts | 76 +++++++++++++++++++++--------------- src/ui/ToolchainSelection.ts | 40 +++++++++++++------ 4 files changed, 80 insertions(+), 45 deletions(-) diff --git a/src/commands.ts b/src/commands.ts index 772725020..5866ecce2 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -63,14 +63,15 @@ import { generateSourcekitConfiguration } from "./commands/generateSourcekitConf export type WorkspaceContextWithToolchain = WorkspaceContext & { toolchain: SwiftToolchain }; export function registerToolchainCommands( - toolchain: SwiftToolchain | undefined + toolchain: SwiftToolchain | undefined, + cwd?: vscode.Uri ): vscode.Disposable[] { return [ vscode.commands.registerCommand("swift.createNewProject", () => createNewProject(toolchain) ), vscode.commands.registerCommand("swift.selectToolchain", () => - showToolchainSelectionQuickPick(toolchain) + showToolchainSelectionQuickPick(toolchain, cwd) ), vscode.commands.registerCommand("swift.pickProcess", configuration => pickProcess(configuration) diff --git a/src/extension.ts b/src/extension.ts index 33ef8a0b3..d05e1efd3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -81,7 +81,9 @@ export async function activate(context: vscode.ExtensionContext): Promise { context.subscriptions.push(new SwiftEnvironmentVariablesManager(context)); context.subscriptions.push(SwiftTerminalProfileProvider.register()); - context.subscriptions.push(...commands.registerToolchainCommands(toolchain)); + context.subscriptions.push( + ...commands.registerToolchainCommands(toolchain, workspaceContext.currentFolder?.folder) + ); // Watch for configuration changes the trigger a reload of the extension if necessary. context.subscriptions.push( diff --git a/src/toolchain/swiftly.ts b/src/toolchain/swiftly.ts index 6a8207d58..1e2843cd8 100644 --- a/src/toolchain/swiftly.ts +++ b/src/toolchain/swiftly.ts @@ -46,6 +46,10 @@ const ListResult = z.object({ ), }); +const InUseVersionResult = z.object({ + version: z.string(), +}); + export class Swiftly { /** * Finds the version of Swiftly installed on the system. @@ -68,6 +72,27 @@ export class Swiftly { } } + /** + * Checks if the installed version of Swiftly supports JSON output. + * + * @returns `true` if JSON output is supported, `false` otherwise. + */ + private static async supportsJsonOutput( + outputChannel?: vscode.OutputChannel + ): Promise { + if (!Swiftly.isSupported()) { + return false; + } + try { + const { stdout } = await execFile("swiftly", ["--version"]); + const version = Version.fromString(stdout.trim()); + return version?.isGreaterThanOrEqual(new Version(1, 1, 0)) ?? false; + } catch (error) { + outputChannel?.appendLine(`Failed to check Swiftly JSON support: ${error}`); + return false; + } + } + /** * Finds the list of toolchains managed by Swiftly. * @@ -85,7 +110,7 @@ export class Swiftly { return []; } - if (version.isLessThan(new Version(1, 1, 0))) { + if (!(await Swiftly.supportsJsonOutput(outputChannel))) { return await Swiftly.getToolchainInstallLegacy(outputChannel); } @@ -141,6 +166,25 @@ export class Swiftly { return inUse.trimEnd(); } + public static async inUseVersion( + swiftlyPath: string = "swiftly", + cwd?: vscode.Uri + ): Promise { + if (!this.isSupported()) { + throw new Error("Swiftly is not supported on this platform"); + } + + if (!(await Swiftly.supportsJsonOutput())) { + return undefined; + } + + const { stdout } = await execFile(swiftlyPath, ["use", "--format=json"], { + cwd: cwd?.fsPath, + }); + const result = InUseVersionResult.parse(JSON.parse(stdout)); + return result.version; + } + public static async use(version: string): Promise { if (!this.isSupported()) { throw new Error("Swiftly is not supported on this platform"); @@ -182,36 +226,6 @@ export class Swiftly { return undefined; } - /** - * Returns the home directory for Swiftly. - * - * @returns The path to the Swiftly home directory. - */ - static getHomeDir(): string | undefined { - return process.env["SWIFTLY_HOME_DIR"]; - } - - /** - * Returns the directory where Swift binaries managed by Swiftly are installed. - * This is a placeholder method and should be implemented based on your environment. - * - * @returns The path to the Swiftly binaries directory. - */ - static getBinDir(): string { - const overriddenBinDir = process.env["SWIFTLY_BIN_DIR"]; - if (overriddenBinDir) { - return overriddenBinDir; - } - - // If SWIFTLY_BIN_DIR is not set, use the default location based on SWIFTLY_HOME_DIR - // This assumes that the binaries are located in the "bin" subdirectory of SWIFTLY_HOME_DIR - const swiftlyHomeDir = Swiftly.getHomeDir(); - if (!swiftlyHomeDir) { - throw new Error("Swiftly is not installed or SWIFTLY_HOME_DIR is not set."); - } - return path.join(swiftlyHomeDir, "bin"); - } - /** * Reads the Swiftly configuration file, if it exists. * diff --git a/src/ui/ToolchainSelection.ts b/src/ui/ToolchainSelection.ts index e747f536e..9cff98ebb 100644 --- a/src/ui/ToolchainSelection.ts +++ b/src/ui/ToolchainSelection.ts @@ -153,7 +153,8 @@ type SelectToolchainItem = SwiftToolchainItem | ActionItem | SeparatorItem; * @returns an array of {@link SelectToolchainItem} */ async function getQuickPickItems( - activeToolchain: SwiftToolchain | undefined + activeToolchain: SwiftToolchain | undefined, + cwd?: vscode.Uri ): Promise { // Find any Xcode installations on the system const xcodes = (await SwiftToolchain.findXcodeInstalls()) @@ -185,6 +186,7 @@ async function getQuickPickItems( type: "toolchain", category: "public", label: path.basename(toolchainPath, ".xctoolchain"), + detail: toolchainPath, toolchainPath: path.join(toolchainPath, "usr"), swiftFolderPath: path.join(toolchainPath, "usr", "bin"), }; @@ -206,17 +208,32 @@ async function getQuickPickItems( label: path.basename(toolchainPath), category: "swiftly", version: path.basename(toolchainPath), + onDidSelect: async () => { + try { + await Swiftly.use(toolchainPath); + void showReloadExtensionNotification( + "Changing the Swift path requires Visual Studio Code be reloaded." + ); + } catch (error) { + void vscode.window.showErrorMessage( + `Failed to switch Swiftly toolchain: ${error}` + ); + } + }, })); // Mark which toolchain is being actively used if (activeToolchain) { + const currentSwiftlyVersion = activeToolchain.isSwiftlyManaged + ? await Swiftly.inUseVersion("swiftly", cwd) + : undefined; const toolchainInUse = [...xcodes, ...toolchains, ...swiftlyToolchains].find(toolchain => { - if (activeToolchain.isSwiftlyManaged) { + if (currentSwiftlyVersion) { if (toolchain.category !== "swiftly") { return false; } // For Swiftly toolchains, check if the label matches the active toolchain version - return toolchain.label === activeToolchain.swiftVersion.toString(); + return currentSwiftlyVersion === toolchain.label; } // For non-Swiftly toolchains, check if the toolchain path matches return ( @@ -278,10 +295,13 @@ async function getQuickPickItems( * * @param activeToolchain the {@link WorkspaceContext} */ -export async function showToolchainSelectionQuickPick(activeToolchain: SwiftToolchain | undefined) { +export async function showToolchainSelectionQuickPick( + activeToolchain: SwiftToolchain | undefined, + cwd?: vscode.Uri +) { let xcodePaths: string[] = []; const selected = await vscode.window.showQuickPick( - getQuickPickItems(activeToolchain).then(result => { + getQuickPickItems(activeToolchain, cwd).then(result => { xcodePaths = result .filter((i): i is XcodeToolchainItem => "category" in i && i.category === "xcode") .map(xcode => xcode.xcodePath); @@ -319,22 +339,20 @@ export async function showToolchainSelectionQuickPick(activeToolchain: SwiftTool }); } } - // Update the toolchain path - let swiftPath: string; + // Update the toolchain path` + let swiftPath: string | undefined; // Handle Swiftly toolchains specially if (selected.category === "swiftly") { try { - // Run swiftly use and get the path to the toolchain - await Swiftly.use(selected.label); - swiftPath = Swiftly.getBinDir(); + swiftPath = undefined; } catch (error) { void vscode.window.showErrorMessage(`Failed to switch Swiftly toolchain: ${error}`); return; } } else { // For non-Swiftly toolchains, use the swiftFolderPath - swiftPath = (selected as PublicSwiftToolchainItem | XcodeToolchainItem).swiftFolderPath; + swiftPath = selected.swiftFolderPath; } const isUpdated = await setToolchainPath(swiftPath, developerDir);