From bf704754b7a82bf0f0eb2c2e2b9eb10f4ad2af37 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 25 Sep 2025 11:40:12 -0400 Subject: [PATCH 1/5] Allow using the default `swift` build task for background compilation This is not related to background indexing, but instead the optional background compilation feature that runs a build task on save. Essentially when `swift.backgroundCompilation.useDefaultTask` is enabled, any `swift` task marked as the default "build" group task will be used instead of the Build All task. This way the whole world is not built for large projects. Issue: #1320 --- package.json | 8 +- src/BackgroundCompilation.ts | 14 +++- src/configuration.ts | 6 ++ .../BackgroundCompilation.test.ts | 80 ++++++++++++++++++- 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e9b0cfac0..a05144676 100644 --- a/package.json +++ b/package.json @@ -595,7 +595,13 @@ "swift.backgroundCompilation": { "type": "boolean", "default": false, - "markdownDescription": "**Experimental**: Run `swift build` in the background whenever a file is saved. It is possible the background compilation will already be running when you attempt a compile yourself, so this is disabled by default.", + "markdownDescription": "Run `swift build` in the background whenever a file is saved. It is possible the background compilation will already be running when you attempt a compile yourself, so this is disabled by default.", + "scope": "machine-overridable" + }, + "swift.backgroundCompilation.useDefaultTask": { + "type": "boolean", + "default": false, + "markdownDescription": "Use the default build task configured using the `Tasks: Configure Default Build Task` command when executing the background compilation. `#swift.backgroundCompilation#` must be enabled.", "scope": "machine-overridable" }, "swift.actionAfterBuildError": { diff --git a/src/BackgroundCompilation.ts b/src/BackgroundCompilation.ts index 12c9f57ed..2268644ec 100644 --- a/src/BackgroundCompilation.ts +++ b/src/BackgroundCompilation.ts @@ -86,7 +86,7 @@ export class BackgroundCompilation implements vscode.Disposable { */ async runTask() { // create compile task and execute it - const backgroundTask = await getBuildAllTask(this.folderContext); + const backgroundTask = await this.getTask(); if (!backgroundTask) { return; } @@ -96,4 +96,16 @@ export class BackgroundCompilation implements vscode.Disposable { // can ignore if running task fails } } + + async getTask(): Promise { + if (!configuration.useDefaultTask) { + return await getBuildAllTask(this.folderContext); + } + + const tasks = await vscode.tasks.fetchTasks({ type: "swift" }); + const defaultTask = tasks.find( + t => t.group?.id === vscode.TaskGroup.Build.id && t.group?.isDefault + ); + return defaultTask || (await getBuildAllTask(this.folderContext)); + } } diff --git a/src/configuration.ts b/src/configuration.ts index cd45c60ea..8c8c00fdb 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -419,6 +419,12 @@ const configuration = { .getConfiguration("swift") .get("backgroundCompilation", false); }, + /** use the default `swift` build task when background compilation is enabled */ + get useDefaultTask(): boolean { + return vscode.workspace + .getConfiguration("swift.backgroundCompilation") + .get("useDefaultTask", false); + }, /** background indexing */ get backgroundIndexing(): "on" | "off" | "auto" { const value = vscode.workspace diff --git a/test/integration-tests/BackgroundCompilation.test.ts b/test/integration-tests/BackgroundCompilation.test.ts index 460c895df..3ca040820 100644 --- a/test/integration-tests/BackgroundCompilation.test.ts +++ b/test/integration-tests/BackgroundCompilation.test.ts @@ -11,26 +11,39 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import * as assert from "assert"; +import { expect } from "chai"; +import { match } from "sinon"; import * as vscode from "vscode"; +import { BackgroundCompilation } from "@src/BackgroundCompilation"; +import { FolderContext } from "@src/FolderContext"; import { WorkspaceContext } from "@src/WorkspaceContext"; +import configuration from "@src/configuration"; +import { getBuildAllTask } from "@src/tasks/SwiftTaskProvider"; +import { mockGlobalObject, mockGlobalValue } from "../MockUtils"; import { testAssetUri } from "../fixtures"; import { tag } from "../tags"; import { closeAllEditors } from "../utilities/commands"; import { waitForNoRunningTasks } from "../utilities/tasks"; -import { activateExtensionForTest, updateSettings } from "./utilities/testutilities"; +import { + activateExtensionForTest, + folderInRootWorkspace, + updateSettings, +} from "./utilities/testutilities"; tag("large").suite("BackgroundCompilation Test Suite", () => { let subscriptions: vscode.Disposable[]; let workspaceContext: WorkspaceContext; + let folderContext: FolderContext; + let buildAllTask: vscode.Task; activateExtensionForTest({ async setup(ctx) { subscriptions = []; workspaceContext = ctx; - assert.notEqual(workspaceContext.folders.length, 0); + folderContext = await folderInRootWorkspace("defaultPackage", workspaceContext); + buildAllTask = await getBuildAllTask(folderContext); return await updateSettings({ "swift.backgroundCompilation": true, }); @@ -62,4 +75,65 @@ tag("large").suite("BackgroundCompilation Test Suite", () => { await taskStartPromise; await waitForNoRunningTasks(); }); + + suite("getTask", () => { + const tasksMock = mockGlobalObject(vscode, "tasks"); + let swiftTask: vscode.Task; + let nonSwiftTask: vscode.Task; + let backgroundConfiguration: BackgroundCompilation; + const useDefaultTaskConfig = mockGlobalValue(configuration, "useDefaultTask"); + + setup(async () => { + nonSwiftTask = new vscode.Task( + { + type: "shell", + args: ["./build.sh"], + cwd: "defaultPackage", + group: { + id: "build", + isDefault: true, + }, + label: "Default build", + }, + folderContext.workspaceFolder, + "Default build", + "shell" + ); + swiftTask = new vscode.Task( + { + type: "swift", + args: ["build"], + cwd: "defaultPackage", + group: "build", + label: "swift build", + }, + folderContext.workspaceFolder, + "Swift build", + "swift" + ); + backgroundConfiguration = new BackgroundCompilation(folderContext); + tasksMock.fetchTasks.resolves([nonSwiftTask, swiftTask, buildAllTask]); + tasksMock.fetchTasks.withArgs(match.object).resolves([swiftTask, buildAllTask]); + useDefaultTaskConfig.setValue(true); + }); + + teardown(() => { + backgroundConfiguration.dispose(); + }); + + test("non-swift default task", async () => { + expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); + }); + + test("swift default task", async () => { + swiftTask.group = { id: "build", isDefault: true }; + expect(await backgroundConfiguration.getTask()).to.equal(swiftTask); + }); + + test("don't use default task", async () => { + useDefaultTaskConfig.setValue(false); + swiftTask.group = { id: "build", isDefault: true }; + expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); + }); + }); }); From 9c1693ae92c96bd505b3dc8f24e1caec35fa26a3 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 25 Sep 2025 11:50:24 -0400 Subject: [PATCH 2/5] Add CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9c3ce01..fa83f561d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Prompt to restart `SourceKit-LSP` after changing `.sourcekit-lsp/config.json` files ([#1744](https://github.com/swiftlang/vscode-swift/issues/1744)) - Prompt to cancel and replace the active test run if one is in flight ([#1774](https://github.com/swiftlang/vscode-swift/pull/1774)) - A walkthrough for first time extension users ([#1560](https://github.com/swiftlang/vscode-swift/issues/1560)) +- New `swift.backgroundCompilation.useDefaultTask` setting that will run the default `swift` build task on save ([#1857](https://github.com/swiftlang/vscode-swift/pull/1857)) ### Fixed From c090f85193a024f0bbeb5cf48b50ac819716a5de Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 30 Sep 2025 10:19:25 -0400 Subject: [PATCH 3/5] Move setting from `backgroundCompilation` subsection - Setting `swift.backgroundCompilation` to `true` was causing the value of `swift.backgroundCompilation.useDefaultTask` to be ignored --- CHANGELOG.md | 2 +- package.json | 2 +- src/configuration.ts | 4 +- .../BackgroundCompilation.test.ts | 164 ++++++++++-------- 4 files changed, 94 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa83f561d..dd07559d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ - Prompt to restart `SourceKit-LSP` after changing `.sourcekit-lsp/config.json` files ([#1744](https://github.com/swiftlang/vscode-swift/issues/1744)) - Prompt to cancel and replace the active test run if one is in flight ([#1774](https://github.com/swiftlang/vscode-swift/pull/1774)) - A walkthrough for first time extension users ([#1560](https://github.com/swiftlang/vscode-swift/issues/1560)) -- New `swift.backgroundCompilation.useDefaultTask` setting that will run the default `swift` build task on save ([#1857](https://github.com/swiftlang/vscode-swift/pull/1857)) +- New `swift.backgroundCompilationUsesDefaultTask` setting that will run the default `swift` build task on save ([#1857](https://github.com/swiftlang/vscode-swift/pull/1857)) ### Fixed diff --git a/package.json b/package.json index a05144676..ccf31d343 100644 --- a/package.json +++ b/package.json @@ -598,7 +598,7 @@ "markdownDescription": "Run `swift build` in the background whenever a file is saved. It is possible the background compilation will already be running when you attempt a compile yourself, so this is disabled by default.", "scope": "machine-overridable" }, - "swift.backgroundCompilation.useDefaultTask": { + "swift.backgroundCompilationUsesDefaultTask": { "type": "boolean", "default": false, "markdownDescription": "Use the default build task configured using the `Tasks: Configure Default Build Task` command when executing the background compilation. `#swift.backgroundCompilation#` must be enabled.", diff --git a/src/configuration.ts b/src/configuration.ts index 8c8c00fdb..85c36a58d 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -422,8 +422,8 @@ const configuration = { /** use the default `swift` build task when background compilation is enabled */ get useDefaultTask(): boolean { return vscode.workspace - .getConfiguration("swift.backgroundCompilation") - .get("useDefaultTask", false); + .getConfiguration("swift") + .get("backgroundCompilationUsesDefaultTask", false); }, /** background indexing */ get backgroundIndexing(): "on" | "off" | "auto" { diff --git a/test/integration-tests/BackgroundCompilation.test.ts b/test/integration-tests/BackgroundCompilation.test.ts index 3ca040820..fe4031192 100644 --- a/test/integration-tests/BackgroundCompilation.test.ts +++ b/test/integration-tests/BackgroundCompilation.test.ts @@ -18,62 +18,68 @@ import * as vscode from "vscode"; import { BackgroundCompilation } from "@src/BackgroundCompilation"; import { FolderContext } from "@src/FolderContext"; import { WorkspaceContext } from "@src/WorkspaceContext"; -import configuration from "@src/configuration"; import { getBuildAllTask } from "@src/tasks/SwiftTaskProvider"; -import { mockGlobalObject, mockGlobalValue } from "../MockUtils"; +import { mockGlobalObject } from "../MockUtils"; import { testAssetUri } from "../fixtures"; import { tag } from "../tags"; import { closeAllEditors } from "../utilities/commands"; import { waitForNoRunningTasks } from "../utilities/tasks"; import { - activateExtensionForTest, + activateExtensionForSuite, folderInRootWorkspace, updateSettings, } from "./utilities/testutilities"; tag("large").suite("BackgroundCompilation Test Suite", () => { - let subscriptions: vscode.Disposable[]; let workspaceContext: WorkspaceContext; let folderContext: FolderContext; let buildAllTask: vscode.Task; - activateExtensionForTest({ - async setup(ctx) { - subscriptions = []; - workspaceContext = ctx; - folderContext = await folderInRootWorkspace("defaultPackage", workspaceContext); - buildAllTask = await getBuildAllTask(folderContext); - return await updateSettings({ - "swift.backgroundCompilation": true, - }); - }, - }); + async function setupFolder(ctx: WorkspaceContext) { + workspaceContext = ctx; + folderContext = await folderInRootWorkspace("defaultPackage", workspaceContext); + buildAllTask = await getBuildAllTask(folderContext); + } - suiteTeardown(async () => { - subscriptions.forEach(s => s.dispose()); - await closeAllEditors(); - }); + suite("build all on save", () => { + let subscriptions: vscode.Disposable[]; - test("build all on save", async () => { - const taskStartPromise = new Promise(resolve => { - subscriptions.push( - vscode.tasks.onDidStartTask(e => { - const task = e.execution.task; - if (task.name.includes("Build All")) { - resolve(); - } - }) - ); + activateExtensionForSuite({ + async setup(ctx) { + subscriptions = []; + await setupFolder(ctx); + return await updateSettings({ + "swift.backgroundCompilation": true, + }); + }, }); - const uri = testAssetUri("defaultPackage/Sources/PackageExe/main.swift"); - const doc = await vscode.workspace.openTextDocument(uri.fsPath); - await vscode.window.showTextDocument(doc); - await vscode.workspace.save(uri); + suiteTeardown(async () => { + subscriptions.forEach(s => s.dispose()); + await closeAllEditors(); + }); + + test("runs build task", async () => { + const taskStartPromise = new Promise(resolve => { + subscriptions.push( + vscode.tasks.onDidStartTask(e => { + const task = e.execution.task; + if (task.name.includes("Build All")) { + resolve(); + } + }) + ); + }); - await taskStartPromise; - await waitForNoRunningTasks(); + const uri = testAssetUri("defaultPackage/Sources/PackageExe/main.swift"); + const doc = await vscode.workspace.openTextDocument(uri.fsPath); + await vscode.window.showTextDocument(doc); + await vscode.workspace.save(uri); + + await taskStartPromise; + await waitForNoRunningTasks(); + }); }); suite("getTask", () => { @@ -81,58 +87,68 @@ tag("large").suite("BackgroundCompilation Test Suite", () => { let swiftTask: vscode.Task; let nonSwiftTask: vscode.Task; let backgroundConfiguration: BackgroundCompilation; - const useDefaultTaskConfig = mockGlobalValue(configuration, "useDefaultTask"); - - setup(async () => { - nonSwiftTask = new vscode.Task( - { - type: "shell", - args: ["./build.sh"], - cwd: "defaultPackage", - group: { - id: "build", - isDefault: true, + + activateExtensionForSuite({ + async setup(ctx) { + await setupFolder(ctx); + nonSwiftTask = new vscode.Task( + { + type: "shell", + args: ["./build.sh"], + cwd: "defaultPackage", + group: { + id: "build", + isDefault: true, + }, + label: "Default build", }, - label: "Default build", - }, - folderContext.workspaceFolder, - "Default build", - "shell" - ); - swiftTask = new vscode.Task( - { - type: "swift", - args: ["build"], - cwd: "defaultPackage", - group: "build", - label: "swift build", - }, - folderContext.workspaceFolder, - "Swift build", - "swift" - ); - backgroundConfiguration = new BackgroundCompilation(folderContext); + folderContext.workspaceFolder, + "Default build", + "shell" + ); + nonSwiftTask.group = { id: "build", isDefault: true }; + swiftTask = new vscode.Task( + { + type: "swift", + args: ["build"], + cwd: "defaultPackage", + label: "swift build", + }, + folderContext.workspaceFolder, + "Swift build", + "swift" + ); + swiftTask.group = { id: "build", isDefault: true }; + return await updateSettings({ + "swift.backgroundCompilation": true, + "swift.backgroundCompilationUsesDefaultTask": true, + }); + }, + }); + + setup(() => { tasksMock.fetchTasks.resolves([nonSwiftTask, swiftTask, buildAllTask]); - tasksMock.fetchTasks.withArgs(match.object).resolves([swiftTask, buildAllTask]); - useDefaultTaskConfig.setValue(true); + tasksMock.fetchTasks.withArgs(match.object).resolves([swiftTask, buildAllTask]); // Call for fetchTasks({ type: "swift" }) + backgroundConfiguration = new BackgroundCompilation(folderContext); }); teardown(() => { backgroundConfiguration.dispose(); }); - test("non-swift default task", async () => { - expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); - }); - test("swift default task", async () => { - swiftTask.group = { id: "build", isDefault: true }; expect(await backgroundConfiguration.getTask()).to.equal(swiftTask); }); test("don't use default task", async () => { - useDefaultTaskConfig.setValue(false); - swiftTask.group = { id: "build", isDefault: true }; + await vscode.workspace + .getConfiguration("swift") + .update("backgroundCompilationUsesDefaultTask", false); + expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); + }); + + test("non-swift default task", async () => { + swiftTask.group = { id: "build", isDefault: false }; expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); }); }); From f0c58c9aa226c9c5df261125bfa00aab6d123774 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Wed, 1 Oct 2025 09:57:06 -0400 Subject: [PATCH 4/5] Allow `swift.backgroundCompilation` setting to accept an object Object will accept `enabled`, `release`, and `useDefaultTask` properties --- CHANGELOG.md | 2 +- package.json | 31 +++-- src/BackgroundCompilation.ts | 23 ++-- src/configuration.ts | 32 +++-- src/extension.ts | 4 +- src/tasks/SwiftTaskProvider.ts | 16 ++- .../BackgroundCompilation.test.ts | 118 +++++++++--------- 7 files changed, 131 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd07559d9..2e724fa7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ - Prompt to restart `SourceKit-LSP` after changing `.sourcekit-lsp/config.json` files ([#1744](https://github.com/swiftlang/vscode-swift/issues/1744)) - Prompt to cancel and replace the active test run if one is in flight ([#1774](https://github.com/swiftlang/vscode-swift/pull/1774)) - A walkthrough for first time extension users ([#1560](https://github.com/swiftlang/vscode-swift/issues/1560)) -- New `swift.backgroundCompilationUsesDefaultTask` setting that will run the default `swift` build task on save ([#1857](https://github.com/swiftlang/vscode-swift/pull/1857)) +- Allow `swift.backgroundCompilation` setting to accept an object where enabling the `useDefaultTask` property will run the default build task, and the `release` property will run the `release` variant of the Build All task ([#1857](https://github.com/swiftlang/vscode-swift/pull/1857)) ### Fixed diff --git a/package.json b/package.json index ccf31d343..21af60a52 100644 --- a/package.json +++ b/package.json @@ -593,16 +593,29 @@ "scope": "machine-overridable" }, "swift.backgroundCompilation": { - "type": "boolean", - "default": false, - "markdownDescription": "Run `swift build` in the background whenever a file is saved. It is possible the background compilation will already be running when you attempt a compile yourself, so this is disabled by default.", - "scope": "machine-overridable" - }, - "swift.backgroundCompilationUsesDefaultTask": { - "type": "boolean", + "type": [ + "boolean", + "object" + ], "default": false, - "markdownDescription": "Use the default build task configured using the `Tasks: Configure Default Build Task` command when executing the background compilation. `#swift.backgroundCompilation#` must be enabled.", - "scope": "machine-overridable" + "markdownDescription": "Run `swift build` in the background whenever a file is saved. Setting to `true` enables, or you can use `object` notation for more fine grained control. It is possible the background compilation will already be running when you attempt a compile yourself, so this is disabled by default.", + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "description": "Enable/disable background compilation." + }, + "useDefaultTask": { + "type": "boolean", + "default": true, + "markdownDescription": "Use the default build task configured using the `Tasks: Configure Default Build Task` command when executing the background compilation. `#enabled#` property must be `true`." + }, + "release": { + "type": "boolean", + "default": false, + "markdownDescription": "Use the `release` variant of the `Build All` task when executing the background compilation. `#enabled#` property must be `true`. This is ignored if the `#useDefaultTask#` property is true." + } + } }, "swift.actionAfterBuildError": { "type": "string", diff --git a/src/BackgroundCompilation.ts b/src/BackgroundCompilation.ts index 2268644ec..ad2284d1f 100644 --- a/src/BackgroundCompilation.ts +++ b/src/BackgroundCompilation.ts @@ -30,8 +30,13 @@ export class BackgroundCompilation implements vscode.Disposable { constructor(private folderContext: FolderContext) { // We only want to configure the file watcher if background compilation is enabled. this.configurationEventDisposable = vscode.workspace.onDidChangeConfiguration(event => { - if (event.affectsConfiguration("swift.backgroundCompilation", folderContext.folder)) { - if (configuration.backgroundCompilation) { + if ( + event.affectsConfiguration( + "swift.backgroundCompilation.enabled", + folderContext.folder + ) + ) { + if (configuration.backgroundCompilation.enabled) { this.setupFileWatching(); } else { this.stopFileWatching(); @@ -39,7 +44,7 @@ export class BackgroundCompilation implements vscode.Disposable { } }); - if (configuration.backgroundCompilation) { + if (configuration.backgroundCompilation.enabled) { this.setupFileWatching(); } } @@ -98,14 +103,10 @@ export class BackgroundCompilation implements vscode.Disposable { } async getTask(): Promise { - if (!configuration.useDefaultTask) { - return await getBuildAllTask(this.folderContext); - } - - const tasks = await vscode.tasks.fetchTasks({ type: "swift" }); - const defaultTask = tasks.find( - t => t.group?.id === vscode.TaskGroup.Build.id && t.group?.isDefault + return await getBuildAllTask( + this.folderContext, + configuration.backgroundCompilation.release, + configuration.backgroundCompilation.useDefaultTask ); - return defaultTask || (await getBuildAllTask(this.folderContext)); } } diff --git a/src/configuration.ts b/src/configuration.ts index 85c36a58d..d01a19ee9 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -105,6 +105,15 @@ export interface PluginPermissionConfiguration { allowNetworkConnections?: string; } +export interface BackgroundCompilationConfiguration { + /** enable background compilation task on save */ + enabled: boolean; + /** use the default `swift` build task when background compilation is enabled */ + useDefaultTask: boolean; + /** Use the `release` variant of the build all task */ + release: boolean; +} + /** * Type-safe wrapper around configuration settings. */ @@ -414,16 +423,21 @@ const configuration = { .get("createTasksForLibraryProducts", false); }, /** background compilation */ - get backgroundCompilation(): boolean { - return vscode.workspace - .getConfiguration("swift") - .get("backgroundCompilation", false); - }, - /** use the default `swift` build task when background compilation is enabled */ - get useDefaultTask(): boolean { - return vscode.workspace + get backgroundCompilation(): BackgroundCompilationConfiguration { + const value = vscode.workspace .getConfiguration("swift") - .get("backgroundCompilationUsesDefaultTask", false); + .get("backgroundCompilation", false); + return { + get enabled(): boolean { + return typeof value === "boolean" ? value : value.enabled; + }, + get useDefaultTask(): boolean { + return typeof value === "boolean" ? true : (value.useDefaultTask ?? true); + }, + get release(): boolean { + return typeof value === "boolean" ? false : (value.release ?? false); + }, + }; }, /** background indexing */ get backgroundIndexing(): "on" | "off" | "auto" { diff --git a/src/extension.ts b/src/extension.ts index 93676588a..9ee3c1437 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -189,13 +189,13 @@ function handleFolderEvent(logger: SwiftLogger): (event: FolderEvent) => Promise async function folderAdded(folder: FolderContext, workspace: WorkspaceContext) { if ( !configuration.folder(folder.workspaceFolder).disableAutoResolve || - configuration.backgroundCompilation + configuration.backgroundCompilation.enabled ) { // if background compilation is set then run compile at startup unless // this folder is a sub-folder of the workspace folder. This is to avoid // kicking off compile for multiple projects at the same time if ( - configuration.backgroundCompilation && + configuration.backgroundCompilation.enabled && folder.workspaceFolder.uri === folder.folder ) { await folder.backgroundCompilation.runTask(); diff --git a/src/tasks/SwiftTaskProvider.ts b/src/tasks/SwiftTaskProvider.ts index 95d062f4a..140692bd4 100644 --- a/src/tasks/SwiftTaskProvider.ts +++ b/src/tasks/SwiftTaskProvider.ts @@ -183,7 +183,8 @@ export async function createBuildAllTask( */ export async function getBuildAllTask( folderContext: FolderContext, - release: boolean = false + release: boolean = false, + findDefault: boolean = true ): Promise { const buildTaskName = buildAllTaskName(folderContext, release); const folderWorkingDir = folderContext.workspaceFolder.uri.fsPath; @@ -208,11 +209,14 @@ export async function getBuildAllTask( }); // find default build task - let task = workspaceTasks.find( - task => task.group?.id === vscode.TaskGroup.Build.id && task.group?.isDefault === true - ); - if (task) { - return task; + let task; + if (findDefault) { + task = workspaceTasks.find( + task => task.group?.id === vscode.TaskGroup.Build.id && task.group?.isDefault === true + ); + if (task) { + return task; + } } // find task with name "swift: Build All" task = workspaceTasks.find(task => task.name === `swift: ${buildTaskName}`); diff --git a/test/integration-tests/BackgroundCompilation.test.ts b/test/integration-tests/BackgroundCompilation.test.ts index fe4031192..2f2ccb649 100644 --- a/test/integration-tests/BackgroundCompilation.test.ts +++ b/test/integration-tests/BackgroundCompilation.test.ts @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// import { expect } from "chai"; -import { match } from "sinon"; import * as vscode from "vscode"; import { BackgroundCompilation } from "@src/BackgroundCompilation"; @@ -88,68 +87,73 @@ tag("large").suite("BackgroundCompilation Test Suite", () => { let nonSwiftTask: vscode.Task; let backgroundConfiguration: BackgroundCompilation; - activateExtensionForSuite({ - async setup(ctx) { - await setupFolder(ctx); - nonSwiftTask = new vscode.Task( - { - type: "shell", - args: ["./build.sh"], - cwd: "defaultPackage", - group: { - id: "build", - isDefault: true, + suite("useDefaultTask", () => { + activateExtensionForSuite({ + async setup(ctx) { + await setupFolder(ctx); + nonSwiftTask = new vscode.Task( + { + type: "shell", + args: ["./build.sh"], + cwd: "defaultPackage", + group: { + id: "build", + isDefault: true, + }, + label: "Default build", }, - label: "Default build", - }, - folderContext.workspaceFolder, - "Default build", - "shell" - ); - nonSwiftTask.group = { id: "build", isDefault: true }; - swiftTask = new vscode.Task( - { - type: "swift", - args: ["build"], - cwd: "defaultPackage", - label: "swift build", - }, - folderContext.workspaceFolder, - "Swift build", - "swift" - ); - swiftTask.group = { id: "build", isDefault: true }; - return await updateSettings({ - "swift.backgroundCompilation": true, - "swift.backgroundCompilationUsesDefaultTask": true, - }); - }, - }); + folderContext.workspaceFolder, + "Default build", + "shell" + ); + nonSwiftTask.group = { id: "build", isDefault: true }; + swiftTask = new vscode.Task( + { + type: "swift", + args: ["build"], + cwd: "defaultPackage", + label: "swift build", + }, + folderContext.workspaceFolder, + "Swift build", + "swift" + ); + swiftTask.group = { id: "build", isDefault: true }; + return await updateSettings({ + "swift.backgroundCompilation": { + enabled: true, + useDefaultTask: true, + }, + }); + }, + }); - setup(() => { - tasksMock.fetchTasks.resolves([nonSwiftTask, swiftTask, buildAllTask]); - tasksMock.fetchTasks.withArgs(match.object).resolves([swiftTask, buildAllTask]); // Call for fetchTasks({ type: "swift" }) - backgroundConfiguration = new BackgroundCompilation(folderContext); - }); + setup(() => { + tasksMock.fetchTasks.resolves([swiftTask, buildAllTask]); + backgroundConfiguration = new BackgroundCompilation(folderContext); + }); - teardown(() => { - backgroundConfiguration.dispose(); - }); + teardown(() => { + backgroundConfiguration.dispose(); + }); - test("swift default task", async () => { - expect(await backgroundConfiguration.getTask()).to.equal(swiftTask); - }); + test("swift default task", async () => { + expect(await backgroundConfiguration.getTask()).to.equal(swiftTask); + }); - test("don't use default task", async () => { - await vscode.workspace - .getConfiguration("swift") - .update("backgroundCompilationUsesDefaultTask", false); - expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); - }); + test("don't use default task", async () => { + await vscode.workspace.getConfiguration("swift").update("backgroundCompilation", { + enabled: true, + useDefaultTask: false, + }); + expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); + }); - test("non-swift default task", async () => { - swiftTask.group = { id: "build", isDefault: false }; - expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); + test("non-swift default task", async () => { + tasksMock.fetchTasks.resolves([nonSwiftTask, swiftTask, buildAllTask]); + swiftTask.group = { id: "build", isDefault: false }; + expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); + }); }); }); }); From 55a4d90065a6a8fd2ea0754f47824fa035de7d22 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Wed, 1 Oct 2025 11:39:24 -0400 Subject: [PATCH 5/5] Fix tests --- src/BackgroundCompilation.ts | 7 +-- .../BackgroundCompilation.test.ts | 47 ++++++++++--------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/BackgroundCompilation.ts b/src/BackgroundCompilation.ts index ad2284d1f..8de59e168 100644 --- a/src/BackgroundCompilation.ts +++ b/src/BackgroundCompilation.ts @@ -30,12 +30,7 @@ export class BackgroundCompilation implements vscode.Disposable { constructor(private folderContext: FolderContext) { // We only want to configure the file watcher if background compilation is enabled. this.configurationEventDisposable = vscode.workspace.onDidChangeConfiguration(event => { - if ( - event.affectsConfiguration( - "swift.backgroundCompilation.enabled", - folderContext.folder - ) - ) { + if (event.affectsConfiguration("swift.backgroundCompilation", folderContext.folder)) { if (configuration.backgroundCompilation.enabled) { this.setupFileWatching(); } else { diff --git a/test/integration-tests/BackgroundCompilation.test.ts b/test/integration-tests/BackgroundCompilation.test.ts index 2f2ccb649..3237158cc 100644 --- a/test/integration-tests/BackgroundCompilation.test.ts +++ b/test/integration-tests/BackgroundCompilation.test.ts @@ -17,7 +17,7 @@ import * as vscode from "vscode"; import { BackgroundCompilation } from "@src/BackgroundCompilation"; import { FolderContext } from "@src/FolderContext"; import { WorkspaceContext } from "@src/WorkspaceContext"; -import { getBuildAllTask } from "@src/tasks/SwiftTaskProvider"; +import { createSwiftTask, getBuildAllTask } from "@src/tasks/SwiftTaskProvider"; import { mockGlobalObject } from "../MockUtils"; import { testAssetUri } from "../fixtures"; @@ -94,31 +94,31 @@ tag("large").suite("BackgroundCompilation Test Suite", () => { nonSwiftTask = new vscode.Task( { type: "shell", - args: ["./build.sh"], - cwd: "defaultPackage", + command: ["swift"], + args: ["build"], group: { id: "build", isDefault: true, }, - label: "Default build", + label: "shell build", }, folderContext.workspaceFolder, - "Default build", - "shell" + "shell build", + "Workspace", + new vscode.ShellExecution("", { + cwd: testAssetUri("defaultPackage").fsPath, + }) ); - nonSwiftTask.group = { id: "build", isDefault: true }; - swiftTask = new vscode.Task( + swiftTask = createSwiftTask( + ["build"], + "swift build", { - type: "swift", - args: ["build"], - cwd: "defaultPackage", - label: "swift build", + cwd: testAssetUri("defaultPackage"), + scope: folderContext.workspaceFolder, }, - folderContext.workspaceFolder, - "Swift build", - "swift" + folderContext.toolchain ); - swiftTask.group = { id: "build", isDefault: true }; + swiftTask.source = "Workspace"; return await updateSettings({ "swift.backgroundCompilation": { enabled: true, @@ -129,7 +129,7 @@ tag("large").suite("BackgroundCompilation Test Suite", () => { }); setup(() => { - tasksMock.fetchTasks.resolves([swiftTask, buildAllTask]); + tasksMock.fetchTasks.withArgs().resolves([nonSwiftTask, swiftTask, buildAllTask]); backgroundConfiguration = new BackgroundCompilation(folderContext); }); @@ -138,22 +138,23 @@ tag("large").suite("BackgroundCompilation Test Suite", () => { }); test("swift default task", async () => { + swiftTask.group = { id: "build", isDefault: true }; expect(await backgroundConfiguration.getTask()).to.equal(swiftTask); }); + test("non-swift default task", async () => { + nonSwiftTask.group = { id: "build", isDefault: true }; + expect(await backgroundConfiguration.getTask()).to.equal(nonSwiftTask); + }); + test("don't use default task", async () => { + swiftTask.group = { id: "build", isDefault: true }; await vscode.workspace.getConfiguration("swift").update("backgroundCompilation", { enabled: true, useDefaultTask: false, }); expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); }); - - test("non-swift default task", async () => { - tasksMock.fetchTasks.resolves([nonSwiftTask, swiftTask, buildAllTask]); - swiftTask.group = { id: "build", isDefault: false }; - expect(await backgroundConfiguration.getTask()).to.equal(buildAllTask); - }); }); }); });