Skip to content

Commit 5d5cf2b

Browse files
authored
Open version specific manifest if applicable (swiftlang#1071)
The language status item has a link to the Package.swift file. If the user has a version specific manifest file in the form `Package@swift-[version].swift` where the version matches their currently installed Swift version, open that Package.swift instead. Issue: swiftlang#1070
1 parent 690fd2a commit 5d5cf2b

File tree

3 files changed

+100
-9
lines changed

3 files changed

+100
-9
lines changed

src/commands.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] {
9191
vscode.commands.registerCommand("swift.switchPlatform", () => switchPlatform()),
9292
vscode.commands.registerCommand("swift.resetPackage", () => resetPackage(ctx)),
9393
vscode.commands.registerCommand("swift.runScript", () => runSwiftScript(ctx)),
94-
vscode.commands.registerCommand("swift.openPackage", () => openPackage(ctx)),
94+
vscode.commands.registerCommand("swift.openPackage", () => {
95+
if (ctx.currentFolder) {
96+
openPackage(ctx.toolchain.swiftVersion, ctx.currentFolder.folder);
97+
}
98+
}),
9599
vscode.commands.registerCommand("swift.runSnippet", () => runSnippet(ctx)),
96100
vscode.commands.registerCommand("swift.debugSnippet", () => debugSnippet(ctx)),
97101
vscode.commands.registerCommand("swift.runPluginTask", () => runPluginTask()),

src/commands/openPackage.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,39 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
import * as vscode from "vscode";
16-
import { WorkspaceContext } from "../WorkspaceContext";
16+
import { Version } from "../utilities/version";
17+
import { fileExists } from "../utilities/filesystem";
1718

1819
/**
19-
* Open Package.swift for in focus project
20+
* Open Package.swift for in focus project. If there is a version specific manifest that
21+
* matches the user's current Swift version that file is opened, otherwise opens Package.swift.
2022
* @param workspaceContext Workspace context, required to get current project
2123
*/
22-
export async function openPackage(workspaceContext: WorkspaceContext) {
23-
if (workspaceContext.currentFolder) {
24-
const packagePath = vscode.Uri.joinPath(
25-
workspaceContext.currentFolder.folder,
26-
"Package.swift"
27-
);
24+
export async function openPackage(swiftVersion: Version, currentFolder: vscode.Uri) {
25+
const packagePath = await packageSwiftFile(currentFolder, swiftVersion);
26+
if (packagePath) {
2827
const document = await vscode.workspace.openTextDocument(packagePath);
2928
vscode.window.showTextDocument(document);
3029
}
3130
}
31+
32+
async function packageSwiftFile(
33+
currentFolder: vscode.Uri,
34+
version: Version
35+
): Promise<vscode.Uri | null> {
36+
// Follow the logic outlined in the SPM documentation on version specific manifest selection
37+
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Usage.md#version-specific-manifest-selection
38+
const files = [
39+
`Package@swift-${version.major}.${version.minor}.${version.patch}.swift`,
40+
`Package@swift-${version.major}.${version.minor}.swift`,
41+
`Package@swift-${version.major}.swift`,
42+
"Package.swift",
43+
].map(file => vscode.Uri.joinPath(currentFolder, file));
44+
45+
for (const file of files) {
46+
if (await fileExists(file.fsPath)) {
47+
return file;
48+
}
49+
}
50+
return null;
51+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2024 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
// import * as assert from "assert";
16+
import * as vscode from "vscode";
17+
import * as path from "path";
18+
import { anything, objectContaining, spy, verify, when } from "ts-mockito";
19+
import { mockNamespace } from "../../unit-tests/MockUtils";
20+
import { openPackage } from "../../../src/commands/openPackage";
21+
import { Version } from "../../../src/utilities/version";
22+
import * as fs from "../../../src/utilities/filesystem";
23+
24+
suite("OpenPackage Command Test Suite", () => {
25+
const workspaceMock = mockNamespace(vscode, "workspace");
26+
const windowMock = mockNamespace(vscode, "window");
27+
const fsSpy = spy(fs);
28+
29+
async function runTestWithMockFs(version: Version, expected: string, paths: string[]) {
30+
const basePath = "/test";
31+
const expectedPath = path.join(basePath, expected);
32+
paths.forEach(p => {
33+
when(fsSpy.fileExists(path.join(basePath, p))).thenResolve(true);
34+
});
35+
when(windowMock.showTextDocument(anything())).thenResolve();
36+
await openPackage(version, vscode.Uri.file(basePath));
37+
38+
verify(workspaceMock.openTextDocument(objectContaining({ fsPath: expectedPath }))).once();
39+
verify(windowMock.showTextDocument(anything())).once();
40+
}
41+
42+
test("Opens nothing when there is no package.swift", async () => {
43+
await openPackage(new Version(6, 0, 0), vscode.Uri.file("/test"));
44+
45+
verify(windowMock.showTextDocument(anything())).never();
46+
});
47+
48+
test("Opens Package.swift file", async () => {
49+
await runTestWithMockFs(new Version(6, 0, 0), "Package.swift", ["Package.swift"]);
50+
});
51+
52+
test("Opens [email protected] file", async () => {
53+
await runTestWithMockFs(new Version(6, 0, 0), "[email protected]", [
54+
"Package.swift",
55+
56+
]);
57+
});
58+
59+
test("Opens [email protected] file", async () => {
60+
await runTestWithMockFs(new Version(6, 1, 2), "[email protected]", [
61+
"Package.swift",
62+
63+
64+
65+
]);
66+
});
67+
});

0 commit comments

Comments
 (0)