Skip to content

Commit 1ba88bf

Browse files
ask where to use newly installed Swiftly toolchain (#1873)
1 parent 9a73e0c commit 1ba88bf

File tree

5 files changed

+61
-144
lines changed

5 files changed

+61
-144
lines changed

src/commands.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,7 @@ import { useLocalDependency } from "./commands/dependencies/useLocal";
3030
import { generateLaunchConfigurations } from "./commands/generateLaunchConfigurations";
3131
import { generateSourcekitConfiguration } from "./commands/generateSourcekitConfiguration";
3232
import { insertFunctionComment } from "./commands/insertFunctionComment";
33-
import {
34-
installSwiftlySnapshotToolchain,
35-
installSwiftlyToolchain,
36-
} from "./commands/installSwiftlyToolchain";
33+
import { promptToInstallSwiftlyToolchain } from "./commands/installSwiftlyToolchain";
3734
import { newSwiftFile } from "./commands/newFile";
3835
import { openDocumentation } from "./commands/openDocumentation";
3936
import { openEducationalNote } from "./commands/openEducationalNote";
@@ -356,11 +353,11 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] {
356353
),
357354
vscode.commands.registerCommand(
358355
Commands.INSTALL_SWIFTLY_TOOLCHAIN,
359-
async () => await installSwiftlyToolchain(ctx)
356+
async () => await promptToInstallSwiftlyToolchain(ctx, "stable")
360357
),
361358
vscode.commands.registerCommand(
362359
Commands.INSTALL_SWIFTLY_SNAPSHOT_TOOLCHAIN,
363-
async () => await installSwiftlySnapshotToolchain(ctx)
360+
async () => await promptToInstallSwiftlyToolchain(ctx, "snapshot")
364361
),
365362
];
366363
}

src/commands/installSwiftlyToolchain.ts

Lines changed: 41 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,22 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414
import * as vscode from "vscode";
15-
import { QuickPickItem } from "vscode";
1615

1716
import { WorkspaceContext } from "../WorkspaceContext";
1817
import { SwiftLogger } from "../logging/SwiftLogger";
19-
import { AvailableToolchain, Swiftly, SwiftlyProgressData } from "../toolchain/swiftly";
20-
import { showReloadExtensionNotification } from "../ui/ReloadExtension";
21-
22-
interface SwiftlyToolchainItem extends QuickPickItem {
23-
toolchain: AvailableToolchain;
24-
}
25-
26-
async function downloadAndInstallToolchain(selected: SwiftlyToolchainItem, ctx: WorkspaceContext) {
27-
return await installSwiftlyToolchainVersion(selected.toolchain.version.name, ctx.logger, true);
28-
}
18+
import { Swiftly, SwiftlyProgressData } from "../toolchain/swiftly";
19+
import { askWhereToSetToolchain } from "../ui/ToolchainSelection";
2920

3021
/**
31-
* Installs a Swiftly toolchain by version string
22+
* Installs a Swiftly toolchain and shows a progress notification to the user.
23+
*
3224
* @param version The toolchain version to install
3325
* @param logger Optional logger for error reporting
34-
* @param showReloadNotification Whether to show reload notification after installation
3526
* @returns Promise<boolean> true if installation succeeded, false otherwise
3627
*/
37-
export async function installSwiftlyToolchainVersion(
28+
export async function installSwiftlyToolchainWithProgress(
3829
version: string,
39-
logger?: SwiftLogger,
40-
showReloadNotification: boolean = true,
41-
token?: vscode.CancellationToken
30+
logger?: SwiftLogger
4231
): Promise<boolean> {
4332
try {
4433
await vscode.window.withProgress(
@@ -47,8 +36,7 @@ export async function installSwiftlyToolchainVersion(
4736
title: `Installing Swift ${version}`,
4837
cancellable: true,
4938
},
50-
async (progress, progressToken) => {
51-
const effectiveToken = token || progressToken;
39+
async (progress, token) => {
5240
progress.report({ message: "Starting installation..." });
5341

5442
let lastProgress = 0;
@@ -71,7 +59,7 @@ export async function installSwiftlyToolchainVersion(
7159
}
7260
},
7361
logger,
74-
effectiveToken
62+
token
7563
);
7664

7765
progress.report({
@@ -81,11 +69,6 @@ export async function installSwiftlyToolchainVersion(
8169
}
8270
);
8371

84-
if (showReloadNotification) {
85-
void showReloadExtensionNotification(
86-
`Swift ${version} has been installed and activated. Visual Studio Code needs to be reloaded.`
87-
);
88-
}
8972
return true;
9073
} catch (error) {
9174
const errorMessage = (error as Error).message;
@@ -104,7 +87,10 @@ export async function installSwiftlyToolchainVersion(
10487
/**
10588
* Shows a quick pick dialog to install available Swiftly toolchains
10689
*/
107-
export async function installSwiftlyToolchain(ctx: WorkspaceContext): Promise<void> {
90+
export async function promptToInstallSwiftlyToolchain(
91+
ctx: WorkspaceContext,
92+
type: "stable" | "snapshot"
93+
): Promise<void> {
10894
if (!Swiftly.isSupported()) {
10995
ctx.logger?.warn("Swiftly is not supported on this platform.");
11096
void vscode.window.showErrorMessage(
@@ -121,7 +107,21 @@ export async function installSwiftlyToolchain(ctx: WorkspaceContext): Promise<vo
121107
return;
122108
}
123109

124-
const availableToolchains = await Swiftly.listAvailable(undefined, ctx.logger);
110+
let branch: string | undefined = undefined;
111+
if (type === "snapshot") {
112+
// Prompt user to enter the branch for snapshot toolchains
113+
branch = await vscode.window.showInputBox({
114+
title: "Enter Swift Snapshot Branch",
115+
prompt: "Enter the branch name to list snapshot toolchains (e.g., 'main-snapshot', '6.1-snapshot')",
116+
placeHolder: "main-snapshot",
117+
value: "main-snapshot",
118+
});
119+
if (!branch) {
120+
return; // User cancelled input
121+
}
122+
}
123+
124+
const availableToolchains = await Swiftly.listAvailable(branch, ctx.logger);
125125

126126
if (availableToolchains.length === 0) {
127127
ctx.logger?.debug("No toolchains available for installation via Swiftly.");
@@ -131,7 +131,9 @@ export async function installSwiftlyToolchain(ctx: WorkspaceContext): Promise<vo
131131
return;
132132
}
133133

134-
const uninstalledToolchains = availableToolchains.filter(toolchain => !toolchain.installed);
134+
const uninstalledToolchains = availableToolchains
135+
.filter(toolchain => !toolchain.installed)
136+
.filter(toolchain => toolchain.version.type === type);
135137

136138
if (uninstalledToolchains.length === 0) {
137139
ctx.logger?.debug("All available toolchains are already installed.");
@@ -154,85 +156,27 @@ export async function installSwiftlyToolchain(ctx: WorkspaceContext): Promise<vo
154156
placeHolder: "Pick a Swift toolchain to install",
155157
canPickMany: false,
156158
});
157-
158159
if (!selected) {
159160
return;
160161
}
161162

162-
await downloadAndInstallToolchain(selected, ctx);
163-
}
164-
165-
/**
166-
* Shows a quick pick dialog to install available Swiftly snapshot toolchains
167-
*/
168-
export async function installSwiftlySnapshotToolchain(ctx: WorkspaceContext): Promise<void> {
169-
if (!Swiftly.isSupported()) {
170-
void vscode.window.showErrorMessage(
171-
"Swiftly is not supported on this platform. Only macOS and Linux are supported."
172-
);
163+
const target = await askWhereToSetToolchain();
164+
if (!target) {
173165
return;
174166
}
175167

176-
if (!(await Swiftly.isInstalled())) {
177-
void vscode.window.showErrorMessage(
178-
"Swiftly is not installed. Please install Swiftly first from https://www.swift.org/install/"
179-
);
168+
// Install the toolchain via Swiftly
169+
if (!(await installSwiftlyToolchainWithProgress(selected.toolchain.version.name, ctx.logger))) {
180170
return;
181171
}
182-
183-
// Prompt user to enter the branch for snapshot toolchains
184-
const branch = await vscode.window.showInputBox({
185-
title: "Enter Swift Snapshot Branch",
186-
prompt: "Enter the branch name to list snapshot toolchains (e.g., 'main-snapshot', '6.1-snapshot')",
187-
placeHolder: "main-snapshot",
188-
value: "main-snapshot",
189-
});
190-
191-
if (!branch) {
192-
return; // User cancelled input
193-
}
194-
195-
const availableToolchains = await Swiftly.listAvailable(branch, ctx.logger);
196-
197-
if (availableToolchains.length === 0) {
198-
ctx.logger?.debug("No toolchains available for installation via Swiftly.");
199-
void vscode.window.showInformationMessage(
200-
"No toolchains are available for installation via Swiftly."
201-
);
202-
return;
203-
}
204-
205-
// Filter for only uninstalled snapshot toolchains
206-
const uninstalledSnapshotToolchains = availableToolchains.filter(
207-
toolchain => !toolchain.installed && toolchain.version.type === "snapshot"
208-
);
209-
210-
if (uninstalledSnapshotToolchains.length === 0) {
211-
ctx.logger?.debug("All available snapshot toolchains are already installed.");
212-
void vscode.window.showInformationMessage(
213-
"All available snapshot toolchains are already installed."
172+
// Tell Swiftly to use the newly installed toolchain
173+
if (target === vscode.ConfigurationTarget.Workspace) {
174+
await Promise.all(
175+
vscode.workspace.workspaceFolders?.map(folder =>
176+
Swiftly.use(selected.toolchain.version.name, folder.uri.fsPath)
177+
) ?? []
214178
);
215179
return;
216180
}
217-
218-
const quickPickItems = uninstalledSnapshotToolchains.map(toolchain => ({
219-
label: `$(cloud-download) ${toolchain.version.name}`,
220-
description: "snapshot",
221-
detail: `Date: ${
222-
toolchain.version.type === "snapshot" ? toolchain.version.date || "Unknown" : "Unknown"
223-
} • Branch: ${toolchain.version.type === "snapshot" ? toolchain.version.branch || "Unknown" : "Unknown"}`,
224-
toolchain: toolchain,
225-
}));
226-
227-
const selected = await vscode.window.showQuickPick(quickPickItems, {
228-
title: "Install Swift Snapshot Toolchain via Swiftly",
229-
placeHolder: "Pick a Swift snapshot toolchain to install",
230-
canPickMany: false,
231-
});
232-
233-
if (!selected) {
234-
return;
235-
}
236-
237-
await downloadAndInstallToolchain(selected, ctx);
181+
await Swiftly.use(selected.toolchain.version.name);
238182
}

src/toolchain/swiftly.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ import * as Stream from "stream";
2121
import * as vscode from "vscode";
2222
import { z } from "zod/v4/mini";
2323

24-
// Import the reusable installation function
25-
import { installSwiftlyToolchainVersion } from "../commands/installSwiftlyToolchain";
24+
import { installSwiftlyToolchainWithProgress } from "../commands/installSwiftlyToolchain";
2625
import { ContextKeys } from "../contextKeys";
2726
import { SwiftLogger } from "../logging/SwiftLogger";
2827
import { showMissingToolchainDialog } from "../ui/ToolchainSelection";
@@ -153,8 +152,7 @@ export function parseSwiftlyMissingToolchainError(
153152
export async function handleMissingSwiftlyToolchain(
154153
version: string,
155154
logger?: SwiftLogger,
156-
folder?: vscode.Uri,
157-
token?: vscode.CancellationToken
155+
folder?: vscode.Uri
158156
): Promise<boolean> {
159157
logger?.info(`Attempting to handle missing toolchain: ${version}`);
160158

@@ -167,7 +165,7 @@ export async function handleMissingSwiftlyToolchain(
167165

168166
// Use the existing installation function without showing reload notification
169167
// (since we want to continue the current operation)
170-
return await installSwiftlyToolchainVersion(version, logger, false, token);
168+
return await installSwiftlyToolchainWithProgress(version, logger);
171169
}
172170

173171
export class Swiftly {
@@ -532,7 +530,6 @@ export class Swiftly {
532530
const installArgs = [
533531
"install",
534532
version,
535-
"--use",
536533
"--assume-yes",
537534
"--post-install-file",
538535
postInstallFilePath,

src/ui/ToolchainSelection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ export async function removeToolchainPath() {
505505
await swiftSettings.update("path", undefined, vscode.ConfigurationTarget.Workspace);
506506
}
507507

508-
async function askWhereToSetToolchain(): Promise<vscode.ConfigurationTarget | undefined> {
508+
export async function askWhereToSetToolchain(): Promise<vscode.ConfigurationTarget | undefined> {
509509
if (!vscode.workspace.workspaceFolders) {
510510
return vscode.ConfigurationTarget.Global;
511511
}

0 commit comments

Comments
 (0)