Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixed

- Fix extension failing to activate when Swiftly was installed via Homebrew ([#1975](https://github.com/swiftlang/vscode-swift/pull/1975))
- Fix running `swift package` commands with `swift.disableSwiftPMIntegration` enabled ([#1969](https://github.com/swiftlang/vscode-swift/pull/1969))
- Fixed an issue where `lldb-dap` could not be found in Command Line Tools toolchains ([#1936](https://github.com/swiftlang/vscode-swift/pull/1936))

## 2.14.1 - 2025-11-20
Expand Down
15 changes: 12 additions & 3 deletions src/FolderContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { TestExplorer } from "./TestExplorer/TestExplorer";
import { TestRunManager } from "./TestExplorer/TestRunManager";
import { TestRunProxy } from "./TestExplorer/TestRunner";
import { FolderOperation, WorkspaceContext } from "./WorkspaceContext";
import configuration from "./configuration";
import { SwiftLogger } from "./logging/SwiftLogger";
import { TaskQueue } from "./tasks/TaskQueue";
import { SwiftToolchain } from "./toolchain/toolchain";
Expand Down Expand Up @@ -135,7 +136,11 @@ export class FolderContext implements vscode.Disposable {
const { linuxMain, swiftPackage } =
await workspaceContext.statusItem.showStatusWhileRunning(statusItemText, async () => {
const linuxMain = await LinuxMain.create(folder);
const swiftPackage = await SwiftPackage.create(folder, toolchain);
const swiftPackage = await SwiftPackage.create(
folder,
toolchain,
configuration.disableSwiftPMIntegration
);
return { linuxMain, swiftPackage };
});
workspaceContext.statusItem.end(statusItemText);
Expand Down Expand Up @@ -193,7 +198,7 @@ export class FolderContext implements vscode.Disposable {

/** reload swift package for this folder */
async reload() {
await this.swiftPackage.reload(this.toolchain);
await this.swiftPackage.reload(this.toolchain, configuration.disableSwiftPMIntegration);
}

/** reload Package.resolved for this folder */
Expand All @@ -208,7 +213,11 @@ export class FolderContext implements vscode.Disposable {

/** Load Swift Plugins and store in Package */
async loadSwiftPlugins(logger: SwiftLogger) {
await this.swiftPackage.loadSwiftPlugins(this.toolchain, logger);
await this.swiftPackage.loadSwiftPlugins(
this.toolchain,
logger,
configuration.disableSwiftPMIntegration
);
}

/**
Expand Down
51 changes: 43 additions & 8 deletions src/SwiftPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,19 +211,22 @@ export class SwiftPackage {
/**
* Create a SwiftPackage from a folder
* @param folder folder package is in
* @param toolchain Swift toolchain to use
* @param disableSwiftPMIntegration Whether to disable SwiftPM integration
* @returns new SwiftPackage
*/
public static async create(
folder: vscode.Uri,
toolchain: SwiftToolchain
toolchain: SwiftToolchain,
disableSwiftPMIntegration: boolean = false
): Promise<SwiftPackage> {
const [resolved, workspaceState] = await Promise.all([
SwiftPackage.loadPackageResolved(folder),
SwiftPackage.loadWorkspaceState(folder),
]);
return new SwiftPackage(
folder,
SwiftPackage.loadPackage(folder, toolchain),
SwiftPackage.loadPackage(folder, toolchain, disableSwiftPMIntegration),
resolved,
workspaceState
);
Expand All @@ -250,12 +253,25 @@ export class SwiftPackage {
/**
* Run `swift package describe` and return results
* @param folder folder package is in
* @param toolchain Swift toolchain to use
* @param disableSwiftPMIntegration Whether to disable SwiftPM integration
* @returns results of `swift package describe`
*/
static async loadPackage(
folder: vscode.Uri,
toolchain: SwiftToolchain
toolchain: SwiftToolchain,
disableSwiftPMIntegration: boolean = false
): Promise<SwiftPackageState> {
// When SwiftPM integration is disabled, return empty package structure
if (disableSwiftPMIntegration) {
return {
name: path.basename(folder.fsPath),
products: [],
dependencies: [],
targets: [],
};
}

try {
// Use swift package describe to describe the package targets, products, and platforms
// Use swift package show-dependencies to get the dependencies in a tree format
Expand Down Expand Up @@ -307,8 +323,14 @@ export class SwiftPackage {
private static async loadPlugins(
folder: vscode.Uri,
toolchain: SwiftToolchain,
logger: SwiftLogger
logger: SwiftLogger,
disableSwiftPMIntegration: boolean = false
): Promise<PackagePlugin[]> {
// When SwiftPM integration is disabled, return empty plugin list
if (disableSwiftPMIntegration) {
return [];
}

try {
const { stdout } = await execSwift(["package", "plugin", "--list"], toolchain, {
cwd: folder.fsPath,
Expand Down Expand Up @@ -355,8 +377,12 @@ export class SwiftPackage {
}

/** Reload swift package */
public async reload(toolchain: SwiftToolchain) {
const loadedContents = await SwiftPackage.loadPackage(this.folder, toolchain);
public async reload(toolchain: SwiftToolchain, disableSwiftPMIntegration: boolean = false) {
const loadedContents = await SwiftPackage.loadPackage(
this.folder,
toolchain,
disableSwiftPMIntegration
);
this._contents = loadedContents;
this.contentsPromise = Promise.resolve(loadedContents);
}
Expand All @@ -370,8 +396,17 @@ export class SwiftPackage {
this.workspaceState = await SwiftPackage.loadWorkspaceState(this.folder);
}

public async loadSwiftPlugins(toolchain: SwiftToolchain, logger: SwiftLogger) {
this.plugins = await SwiftPackage.loadPlugins(this.folder, toolchain, logger);
public async loadSwiftPlugins(
toolchain: SwiftToolchain,
logger: SwiftLogger,
disableSwiftPMIntegration: boolean = false
) {
this.plugins = await SwiftPackage.loadPlugins(
this.folder,
toolchain,
logger,
disableSwiftPMIntegration
);
}

/** Return if has valid contents */
Expand Down
19 changes: 12 additions & 7 deletions src/ui/ProjectPanelProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,8 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
const dependencies = await this.dependencies();
const snippets = await this.snippets();
const commands = await this.commands();
const targets = await this.targets();
const tasks = await this.tasks(folderContext);

// TODO: Control ordering
return [
Expand All @@ -685,13 +687,16 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
),
]
: []),
new HeaderNode("targets", "Targets", "book", this.targets.bind(this)),
new HeaderNode(
"tasks",
"Tasks",
"debug-continue-small",
this.tasks.bind(this, folderContext)
),
...(targets.length > 0
? [new HeaderNode("targets", "Targets", "book", () => Promise.resolve(targets))]
: []),
...(tasks.length > 0
? [
new HeaderNode("tasks", "Tasks", "debug-continue-small", () =>
Promise.resolve(tasks)
),
]
: []),
...(snippets.length > 0
? [
new HeaderNode("snippets", "Snippets", "notebook", () =>
Expand Down
28 changes: 28 additions & 0 deletions test/integration-tests/SwiftPackage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,32 @@ tag("medium").suite("SwiftPackage Test Suite", function () {
assert.strictEqual(spmPackage.resolved.pins.length, 1);
assert.strictEqual(spmPackage.resolved.pins[0].identity, "swift-log");
});

test("Disabled SwiftPM integration returns empty package", async () => {
const spmPackage = await SwiftPackage.create(
testAssetUri("package2"),
toolchain,
true // disableSwiftPMIntegration
);
assert.strictEqual(await spmPackage.isValid, true);
assert.strictEqual(await spmPackage.name, "package2"); // derived from folder name
assert.strictEqual((await spmPackage.executableProducts).length, 0);
assert.strictEqual((await spmPackage.libraryProducts).length, 0);
assert.strictEqual((await spmPackage.dependencies).length, 0);
assert.strictEqual((await spmPackage.targets).length, 0);
});

test("Reload with disabled SwiftPM integration returns empty package", async () => {
const spmPackage = await SwiftPackage.create(testAssetUri("package2"), toolchain, false);
// First verify it loaded normally
assert.strictEqual(await spmPackage.isValid, true);
assert.strictEqual((await spmPackage.libraryProducts).length, 1);

// Now reload with disabled integration
await spmPackage.reload(toolchain, true);
assert.strictEqual(await spmPackage.isValid, true);
assert.strictEqual((await spmPackage.libraryProducts).length, 0);
assert.strictEqual((await spmPackage.dependencies).length, 0);
assert.strictEqual((await spmPackage.targets).length, 0);
});
});