Skip to content

Commit 7b71b1c

Browse files
committed
Don't set swift.path if using swiftly
1 parent 2a98336 commit 7b71b1c

File tree

4 files changed

+79
-45
lines changed

4 files changed

+79
-45
lines changed

src/commands.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,15 @@ import { generateSourcekitConfiguration } from "./commands/generateSourcekitConf
6363
export type WorkspaceContextWithToolchain = WorkspaceContext & { toolchain: SwiftToolchain };
6464

6565
export function registerToolchainCommands(
66-
toolchain: SwiftToolchain | undefined
66+
toolchain: SwiftToolchain | undefined,
67+
cwd?: vscode.Uri
6768
): vscode.Disposable[] {
6869
return [
6970
vscode.commands.registerCommand("swift.createNewProject", () =>
7071
createNewProject(toolchain)
7172
),
7273
vscode.commands.registerCommand("swift.selectToolchain", () =>
73-
showToolchainSelectionQuickPick(toolchain)
74+
showToolchainSelectionQuickPick(toolchain, cwd)
7475
),
7576
vscode.commands.registerCommand("swift.pickProcess", configuration =>
7677
pickProcess(configuration)

src/extension.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<Api> {
8181

8282
context.subscriptions.push(new SwiftEnvironmentVariablesManager(context));
8383
context.subscriptions.push(SwiftTerminalProfileProvider.register());
84-
context.subscriptions.push(...commands.registerToolchainCommands(toolchain));
84+
context.subscriptions.push(
85+
...commands.registerToolchainCommands(toolchain, workspaceContext.currentFolder?.folder)
86+
);
8587

8688
// Watch for configuration changes the trigger a reload of the extension if necessary.
8789
context.subscriptions.push(

src/toolchain/swiftly.ts

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ const ListResult = z.object({
4646
),
4747
});
4848

49+
const InUseVersionResult = z.object({
50+
version: z.string(),
51+
});
52+
4953
export class Swiftly {
5054
/**
5155
* Finds the version of Swiftly installed on the system.
@@ -68,6 +72,27 @@ export class Swiftly {
6872
}
6973
}
7074

75+
/**
76+
* Checks if the installed version of Swiftly supports JSON output.
77+
*
78+
* @returns `true` if JSON output is supported, `false` otherwise.
79+
*/
80+
private static async supportsJsonOutput(
81+
outputChannel?: vscode.OutputChannel
82+
): Promise<boolean> {
83+
if (!Swiftly.isSupported()) {
84+
return false;
85+
}
86+
try {
87+
const { stdout } = await execFile("swiftly", ["--version"]);
88+
const version = Version.fromString(stdout.trim());
89+
return version?.isGreaterThanOrEqual(new Version(1, 1, 0)) ?? false;
90+
} catch (error) {
91+
outputChannel?.appendLine(`Failed to check Swiftly JSON support: ${error}`);
92+
return false;
93+
}
94+
}
95+
7196
/**
7297
* Finds the list of toolchains managed by Swiftly.
7398
*
@@ -85,7 +110,7 @@ export class Swiftly {
85110
return [];
86111
}
87112

88-
if (version.isLessThan(new Version(1, 1, 0))) {
113+
if (!(await Swiftly.supportsJsonOutput(outputChannel))) {
89114
return await Swiftly.getToolchainInstallLegacy(outputChannel);
90115
}
91116

@@ -141,6 +166,25 @@ export class Swiftly {
141166
return inUse.trimEnd();
142167
}
143168

169+
public static async inUseVersion(
170+
swiftlyPath: string = "swiftly",
171+
cwd?: vscode.Uri
172+
): Promise<string | undefined> {
173+
if (!this.isSupported()) {
174+
throw new Error("Swiftly is not supported on this platform");
175+
}
176+
177+
if (!(await Swiftly.supportsJsonOutput())) {
178+
return undefined;
179+
}
180+
181+
const { stdout } = await execFile(swiftlyPath, ["use", "--format=json"], {
182+
cwd: cwd?.fsPath,
183+
});
184+
const result = InUseVersionResult.parse(JSON.parse(stdout));
185+
return result.version;
186+
}
187+
144188
public static async use(version: string): Promise<void> {
145189
if (!this.isSupported()) {
146190
throw new Error("Swiftly is not supported on this platform");
@@ -182,36 +226,6 @@ export class Swiftly {
182226
return undefined;
183227
}
184228

185-
/**
186-
* Returns the home directory for Swiftly.
187-
*
188-
* @returns The path to the Swiftly home directory.
189-
*/
190-
static getHomeDir(): string | undefined {
191-
return process.env["SWIFTLY_HOME_DIR"];
192-
}
193-
194-
/**
195-
* Returns the directory where Swift binaries managed by Swiftly are installed.
196-
* This is a placeholder method and should be implemented based on your environment.
197-
*
198-
* @returns The path to the Swiftly binaries directory.
199-
*/
200-
static getBinDir(): string {
201-
const overriddenBinDir = process.env["SWIFTLY_BIN_DIR"];
202-
if (overriddenBinDir) {
203-
return overriddenBinDir;
204-
}
205-
206-
// If SWIFTLY_BIN_DIR is not set, use the default location based on SWIFTLY_HOME_DIR
207-
// This assumes that the binaries are located in the "bin" subdirectory of SWIFTLY_HOME_DIR
208-
const swiftlyHomeDir = Swiftly.getHomeDir();
209-
if (!swiftlyHomeDir) {
210-
throw new Error("Swiftly is not installed or SWIFTLY_HOME_DIR is not set.");
211-
}
212-
return path.join(swiftlyHomeDir, "bin");
213-
}
214-
215229
/**
216230
* Reads the Swiftly configuration file, if it exists.
217231
*

src/ui/ToolchainSelection.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ type SelectToolchainItem = SwiftToolchainItem | ActionItem | SeparatorItem;
153153
* @returns an array of {@link SelectToolchainItem}
154154
*/
155155
async function getQuickPickItems(
156-
activeToolchain: SwiftToolchain | undefined
156+
activeToolchain: SwiftToolchain | undefined,
157+
cwd?: vscode.Uri
157158
): Promise<SelectToolchainItem[]> {
158159
// Find any Xcode installations on the system
159160
const xcodes = (await SwiftToolchain.findXcodeInstalls())
@@ -206,17 +207,32 @@ async function getQuickPickItems(
206207
label: path.basename(toolchainPath),
207208
category: "swiftly",
208209
version: path.basename(toolchainPath),
210+
onDidSelect: async () => {
211+
try {
212+
await Swiftly.use(toolchainPath);
213+
void showReloadExtensionNotification(
214+
"Changing the Swift path requires Visual Studio Code be reloaded."
215+
);
216+
} catch (error) {
217+
void vscode.window.showErrorMessage(
218+
`Failed to switch Swiftly toolchain: ${error}`
219+
);
220+
}
221+
},
209222
}));
210223
// Mark which toolchain is being actively used
211224
if (activeToolchain) {
225+
const currentSwiftlyVersion = activeToolchain.isSwiftlyManaged
226+
? await Swiftly.inUseVersion("swiftly", cwd)
227+
: undefined;
212228
const toolchainInUse = [...xcodes, ...toolchains, ...swiftlyToolchains].find(toolchain => {
213-
if (activeToolchain.isSwiftlyManaged) {
229+
if (currentSwiftlyVersion) {
214230
if (toolchain.category !== "swiftly") {
215231
return false;
216232
}
217233

218234
// For Swiftly toolchains, check if the label matches the active toolchain version
219-
return toolchain.label === activeToolchain.swiftVersion.toString();
235+
return currentSwiftlyVersion === toolchain.label;
220236
}
221237
// For non-Swiftly toolchains, check if the toolchain path matches
222238
return (
@@ -278,10 +294,13 @@ async function getQuickPickItems(
278294
*
279295
* @param activeToolchain the {@link WorkspaceContext}
280296
*/
281-
export async function showToolchainSelectionQuickPick(activeToolchain: SwiftToolchain | undefined) {
297+
export async function showToolchainSelectionQuickPick(
298+
activeToolchain: SwiftToolchain | undefined,
299+
cwd?: vscode.Uri
300+
) {
282301
let xcodePaths: string[] = [];
283302
const selected = await vscode.window.showQuickPick<SelectToolchainItem>(
284-
getQuickPickItems(activeToolchain).then(result => {
303+
getQuickPickItems(activeToolchain, cwd).then(result => {
285304
xcodePaths = result
286305
.filter((i): i is XcodeToolchainItem => "category" in i && i.category === "xcode")
287306
.map(xcode => xcode.xcodePath);
@@ -319,22 +338,20 @@ export async function showToolchainSelectionQuickPick(activeToolchain: SwiftTool
319338
});
320339
}
321340
}
322-
// Update the toolchain path
323-
let swiftPath: string;
341+
// Update the toolchain path`
342+
let swiftPath: string | undefined;
324343

325344
// Handle Swiftly toolchains specially
326345
if (selected.category === "swiftly") {
327346
try {
328-
// Run swiftly use <version> and get the path to the toolchain
329-
await Swiftly.use(selected.label);
330-
swiftPath = Swiftly.getBinDir();
347+
swiftPath = undefined;
331348
} catch (error) {
332349
void vscode.window.showErrorMessage(`Failed to switch Swiftly toolchain: ${error}`);
333350
return;
334351
}
335352
} else {
336353
// For non-Swiftly toolchains, use the swiftFolderPath
337-
swiftPath = (selected as PublicSwiftToolchainItem | XcodeToolchainItem).swiftFolderPath;
354+
swiftPath = selected.swiftFolderPath;
338355
}
339356

340357
const isUpdated = await setToolchainPath(swiftPath, developerDir);

0 commit comments

Comments
 (0)