Skip to content

Commit 736af54

Browse files
Minor Swiftly cleanup (#1849)
1 parent 3e3dac0 commit 736af54

File tree

9 files changed

+199
-103
lines changed

9 files changed

+199
-103
lines changed

package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,14 @@
11751175
"command": "swift.previewDocumentation",
11761176
"when": "swift.supportsDocumentationLivePreview"
11771177
},
1178+
{
1179+
"command": "swift.installSwiftlyToolchain",
1180+
"when": "swift.supportsSwiftlyInstall"
1181+
},
1182+
{
1183+
"command": "swift.installSwiftlySnapshotToolchain",
1184+
"when": "swift.supportsSwiftlyInstall"
1185+
},
11781186
{
11791187
"command": "swift.createNewProject",
11801188
"when": "!swift.isActivated || swift.createNewProjectAvailable"

src/commands/installSwiftlyToolchain.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export async function installSwiftlyToolchain(ctx: WorkspaceContext): Promise<vo
117117
return;
118118
}
119119

120-
const availableToolchains = await Swiftly.listAvailable(ctx.logger);
120+
const availableToolchains = await Swiftly.listAvailable(undefined, ctx.logger);
121121

122122
if (availableToolchains.length === 0) {
123123
ctx.logger?.debug("No toolchains available for installation via Swiftly.");
@@ -193,7 +193,7 @@ export async function installSwiftlySnapshotToolchain(ctx: WorkspaceContext): Pr
193193
return; // User cancelled input
194194
}
195195

196-
const availableToolchains = await Swiftly.listAvailable(ctx.logger, branch);
196+
const availableToolchains = await Swiftly.listAvailable(branch, ctx.logger);
197197

198198
if (availableToolchains.length === 0) {
199199
ctx.logger?.debug("No toolchains available for installation via Swiftly.");

src/contextKeys.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ export interface ContextKeys {
8484
*/
8585
supportsDocumentationLivePreview: boolean;
8686

87+
/**
88+
* Whether the installed version of Swiftly can be used to install toolchains from within VS Code.
89+
*/
90+
supportsSwiftlyInstall: boolean;
91+
8792
/**
8893
* Whether the swift.switchPlatform command is available.
8994
*/
@@ -109,6 +114,7 @@ export function createContextKeys(): ContextKeys {
109114
let createNewProjectAvailable: boolean = false;
110115
let supportsReindexing: boolean = false;
111116
let supportsDocumentationLivePreview: boolean = false;
117+
let supportsSwiftlyInstall: boolean = false;
112118
let switchPlatformAvailable: boolean = false;
113119

114120
return {
@@ -278,6 +284,19 @@ export function createContextKeys(): ContextKeys {
278284
});
279285
},
280286

287+
get supportsSwiftlyInstall() {
288+
return supportsSwiftlyInstall;
289+
},
290+
291+
set supportsSwiftlyInstall(value: boolean) {
292+
supportsSwiftlyInstall = value;
293+
void vscode.commands
294+
.executeCommand("setContext", "swift.supportsSwiftlyInstall", value)
295+
.then(() => {
296+
/* Put in worker queue */
297+
});
298+
},
299+
281300
get switchPlatformAvailable() {
282301
return switchPlatformAvailable;
283302
},

src/extension.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { SwiftLogger } from "./logging/SwiftLogger";
3030
import { SwiftLoggerFactory } from "./logging/SwiftLoggerFactory";
3131
import { SwiftEnvironmentVariablesManager, SwiftTerminalProfileProvider } from "./terminal";
3232
import { SelectedXcodeWatcher } from "./toolchain/SelectedXcodeWatcher";
33+
import { checkForSwiftlyInstallation } from "./toolchain/swiftly";
3334
import { SwiftToolchain } from "./toolchain/toolchain";
3435
import { LanguageStatusItems } from "./ui/LanguageStatusItems";
3536
import { ProjectPanelProvider } from "./ui/ProjectPanelProvider";
@@ -69,6 +70,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<Api> {
6970

7071
const contextKeys = createContextKeys();
7172
const toolchain = await createActiveToolchain(contextKeys, logger);
73+
checkForSwiftlyInstallation(contextKeys, logger);
7274

7375
// If we don't have a toolchain, show an error and stop initializing the extension.
7476
// This can happen if the user has not installed Swift or if the toolchain is not

src/toolchain/swiftly.ts

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { z } from "zod/v4/mini";
2222

2323
// Import the reusable installation function
2424
import { installSwiftlyToolchainVersion } from "../commands/installSwiftlyToolchain";
25+
import { ContextKeys } from "../contextKeys";
2526
import { SwiftLogger } from "../logging/SwiftLogger";
2627
import { showMissingToolchainDialog } from "../ui/ToolchainSelection";
2728
import { findBinaryPath } from "../utilities/shell";
@@ -220,11 +221,11 @@ export class Swiftly {
220221
}
221222

222223
/**
223-
* Finds the list of toolchains managed by Swiftly.
224+
* Finds the list of toolchains installed via Swiftly.
224225
*
225-
* @returns an array of toolchain paths
226+
* @returns an array of toolchain version names.
226227
*/
227-
public static async listAvailableToolchains(logger?: SwiftLogger): Promise<string[]> {
228+
public static async list(logger?: SwiftLogger): Promise<string[]> {
228229
if (!this.isSupported()) {
229230
return [];
230231
}
@@ -235,13 +236,13 @@ export class Swiftly {
235236
}
236237

237238
if (!(await Swiftly.supportsJsonOutput(logger))) {
238-
return await Swiftly.getToolchainInstallLegacy(logger);
239+
return await Swiftly.listFromSwiftlyConfig(logger);
239240
}
240241

241-
return await Swiftly.getListAvailableToolchains(logger);
242+
return await Swiftly.listUsingJSONFormat(logger);
242243
}
243244

244-
private static async getListAvailableToolchains(logger?: SwiftLogger): Promise<string[]> {
245+
private static async listUsingJSONFormat(logger?: SwiftLogger): Promise<string[]> {
245246
try {
246247
const { stdout } = await execFile("swiftly", ["list", "--format=json"]);
247248
const response = ListResult.parse(JSON.parse(stdout));
@@ -254,7 +255,7 @@ export class Swiftly {
254255
}
255256
}
256257

257-
private static async getToolchainInstallLegacy(logger?: SwiftLogger) {
258+
private static async listFromSwiftlyConfig(logger?: SwiftLogger) {
258259
try {
259260
const swiftlyHomeDir: string | undefined = process.env["SWIFTLY_HOME_DIR"];
260261
if (!swiftlyHomeDir) {
@@ -279,17 +280,32 @@ export class Swiftly {
279280
}
280281
}
281282

283+
/**
284+
* Checks whether or not the current operating system supports Swiftly.
285+
*/
282286
public static isSupported() {
283287
return process.platform === "linux" || process.platform === "darwin";
284288
}
285289

290+
/**
291+
* Retrieves the location of the toolchain that is currently in use by Swiftly.
292+
*
293+
* @param swiftlyPath Optional path to the Swiftly binary.
294+
* @param cwd Optional current working directory to check within.
295+
*/
286296
public static async inUseLocation(swiftlyPath: string = "swiftly", cwd?: vscode.Uri) {
287297
const { stdout: inUse } = await execFile(swiftlyPath, ["use", "--print-location"], {
288298
cwd: cwd?.fsPath,
289299
});
290300
return inUse.trimEnd();
291301
}
292302

303+
/**
304+
* Retrieves the version name of the toolchain that is currently in use by Swiftly.
305+
*
306+
* @param swiftlyPath Optional path to the Swiftly binary.
307+
* @param cwd Optional current working directory to check within.
308+
*/
293309
public static async inUseVersion(
294310
swiftlyPath: string = "swiftly",
295311
cwd?: vscode.Uri
@@ -309,6 +325,11 @@ export class Swiftly {
309325
return result.version;
310326
}
311327

328+
/**
329+
* Instructs Swiftly to use a specific version of the Swift toolchain.
330+
*
331+
* @param version The version name to use. Obtainable via {@link Swiftly.list}.
332+
*/
312333
public static async use(version: string): Promise<void> {
313334
if (!this.isSupported()) {
314335
throw new Error("Swiftly is not supported on this platform");
@@ -319,6 +340,7 @@ export class Swiftly {
319340
/**
320341
* Determine if Swiftly is being used to manage the active toolchain and if so, return
321342
* the path to the active toolchain.
343+
*
322344
* @returns The location of the active toolchain if swiftly is being used to manage it.
323345
*/
324346
public static async toolchain(
@@ -383,15 +405,15 @@ export class Swiftly {
383405
}
384406

385407
/**
386-
* Lists all toolchains available for installation from swiftly
408+
* Lists all toolchains available for installation from swiftly.
387409
*
388-
* @param branch Optional branch to filter available toolchains (e.g., "main" for snapshots)
389-
* @param logger Optional logger for error reporting
390-
* @returns Array of available toolchains
410+
* @param branch Optional branch to filter available toolchains (e.g., "main" for snapshots).
411+
* @param logger Optional logger for error reporting.
412+
* @returns Array of available toolchains.
391413
*/
392414
public static async listAvailable(
393-
logger?: SwiftLogger,
394-
branch?: string
415+
branch?: string,
416+
logger?: SwiftLogger
395417
): Promise<SwiftlyToolchain[]> {
396418
if (!this.isSupported()) {
397419
return [];
@@ -425,11 +447,11 @@ export class Swiftly {
425447
}
426448

427449
/**
428-
* Installs a toolchain via swiftly with optional progress tracking
450+
* Installs a toolchain via swiftly with optional progress tracking.
429451
*
430-
* @param version The toolchain version to install
431-
* @param progressCallback Optional callback that receives progress data as JSON objects
432-
* @param logger Optional logger for error reporting
452+
* @param version The toolchain version to install.
453+
* @param progressCallback Optional callback that receives progress data as JSON objects.
454+
* @param logger Optional logger for error reporting.
433455
*/
434456
public static async installToolchain(
435457
version: string,
@@ -742,6 +764,9 @@ export class Swiftly {
742764
return JSON.parse(swiftlyConfigRaw);
743765
}
744766

767+
/**
768+
* Checks whether or not Swiftly is installed on the current system.
769+
*/
745770
public static async isInstalled(): Promise<boolean> {
746771
if (!this.isSupported()) {
747772
return false;
@@ -754,3 +779,32 @@ export class Swiftly {
754779
}
755780
}
756781
}
782+
783+
/**
784+
* Checks whether or not Swiftly is installed and updates context keys appropriately.
785+
*/
786+
export function checkForSwiftlyInstallation(contextKeys: ContextKeys, logger: SwiftLogger): void {
787+
contextKeys.supportsSwiftlyInstall = false;
788+
if (!Swiftly.isSupported()) {
789+
logger.debug(`Swiftly is not available on ${process.platform}`);
790+
return;
791+
}
792+
// Don't block while checking the Swiftly insallation.
793+
void Swiftly.isInstalled().then(async isInstalled => {
794+
if (!isInstalled) {
795+
logger.debug("Swiftly is not installed on this system.");
796+
return;
797+
}
798+
const version = await Swiftly.version(logger);
799+
if (!version) {
800+
logger.warn("Unable to determine Swiftly version.");
801+
return;
802+
}
803+
logger.debug(`Detected Swiftly version ${version}.`);
804+
contextKeys.supportsSwiftlyInstall = version.isGreaterThanOrEqual({
805+
major: 1,
806+
minor: 1,
807+
patch: 0,
808+
});
809+
});
810+
}

0 commit comments

Comments
 (0)