From ddf203a9984824116b3c5c1d95f40c63f412c77e Mon Sep 17 00:00:00 2001 From: Wang Lun Date: Tue, 19 Aug 2025 16:08:06 +0900 Subject: [PATCH] fixed bsp config file location issue --- src/WorkspaceContext.ts | 5 +- src/utilities/workspace.ts | 71 ++++++++++++++++--- .../utilities/workspace.test.ts | 6 +- test/unit-tests/utilities/workspace.test.ts | 6 +- 4 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/WorkspaceContext.ts b/src/WorkspaceContext.ts index 252f67f65..8a0e809a4 100644 --- a/src/WorkspaceContext.ts +++ b/src/WorkspaceContext.ts @@ -421,7 +421,8 @@ export class WorkspaceContext implements vscode.Disposable { const folders = await searchForPackages( workspaceFolder.uri, configuration.disableSwiftPMIntegration, - configuration.folder(workspaceFolder).searchSubfoldersForPackages + configuration.folder(workspaceFolder).searchSubfoldersForPackages, + this.globalToolchainSwiftVersion ); for (const folder of folders) { @@ -605,7 +606,7 @@ export class WorkspaceContext implements vscode.Disposable { * Package.swift or a CMake compile_commands.json, compile_flags.txt, or a BSP buildServer.json. */ async isValidWorkspaceFolder(folder: string): Promise { - return await isValidWorkspaceFolder(folder, configuration.disableSwiftPMIntegration); + return await isValidWorkspaceFolder(folder, configuration.disableSwiftPMIntegration, this.globalToolchainSwiftVersion); } /** send unfocus event to current focussed folder and clear current folder */ diff --git a/src/utilities/workspace.ts b/src/utilities/workspace.ts index 97d6b8c4d..c9228ff95 100644 --- a/src/utilities/workspace.ts +++ b/src/utilities/workspace.ts @@ -13,19 +13,23 @@ //===----------------------------------------------------------------------===// import * as vscode from "vscode"; +import * as path from "path"; +import * as fs from "fs/promises"; import { globDirectory, pathExists } from "./filesystem"; import { basename } from "path"; +import { Version } from "./version"; export async function searchForPackages( folder: vscode.Uri, disableSwiftPMIntegration: boolean, - searchSubfoldersForPackages: boolean + searchSubfoldersForPackages: boolean, + swiftVersion: Version ): Promise> { const folders: Array = []; async function search(folder: vscode.Uri) { // add folder if Package.swift/compile_commands.json/compile_flags.txt/buildServer.json exists - if (await isValidWorkspaceFolder(folder.fsPath, disableSwiftPMIntegration)) { + if (await isValidWorkspaceFolder(folder.fsPath, disableSwiftPMIntegration, swiftVersion)) { folders.push(folder); } // should I search sub-folders for more Swift Packages @@ -47,16 +51,61 @@ export async function searchForPackages( return folders; } +export async function hasBuildServerConfigurationFile( + folder: string, + swiftVersion: Version +): Promise { + // buildServer.json + const buildServerPath = path.join(folder, "buildServer.json"); + const buildServerStat = await fs.stat(buildServerPath).catch(() => undefined); + if (buildServerStat && buildServerStat.isFile()) { + return true; + } + // .bsp/*.json for Swift >= 6.1.0 + if (swiftVersion.isGreaterThanOrEqual(new Version(6, 1, 0))) { + const bspDir = path.join(folder, '.bsp'); + const bspStat = await fs.stat(bspDir).catch(() => undefined); + if (bspStat && bspStat.isDirectory()) { + const files = await fs.readdir(bspDir).catch(() => []); + if (files.some((f: string) => f.endsWith('.json'))) { + return true; + } + } + } + return false; +} + export async function isValidWorkspaceFolder( folder: string, - disableSwiftPMIntegration: boolean + disableSwiftPMIntegration: boolean, + swiftVersion: Version ): Promise { - return ( - (!disableSwiftPMIntegration && (await pathExists(folder, "Package.swift"))) || - (await pathExists(folder, "compile_commands.json")) || - (await pathExists(folder, "compile_flags.txt")) || - (await pathExists(folder, "buildServer.json")) || - (await pathExists(folder, "build")) || - (await pathExists(folder, "out")) - ); + // Check Package.swift first (most common case) + if (!disableSwiftPMIntegration && (await pathExists(folder, "Package.swift"))) { + return true; + } + + // Check other common build files + if (await pathExists(folder, "compile_commands.json")) { + return true; + } + + if (await pathExists(folder, "compile_flags.txt")) { + return true; + } + + if (await pathExists(folder, "build")) { + return true; + } + + if (await pathExists(folder, "out")) { + return true; + } + + // Check build server configuration last (potentially more expensive) + if (await hasBuildServerConfigurationFile(folder, swiftVersion)) { + return true; + } + + return false; } diff --git a/test/integration-tests/utilities/workspace.test.ts b/test/integration-tests/utilities/workspace.test.ts index 8093186e0..ef7df60c8 100644 --- a/test/integration-tests/utilities/workspace.test.ts +++ b/test/integration-tests/utilities/workspace.test.ts @@ -15,14 +15,18 @@ import * as vscode from "vscode"; import { searchForPackages } from "../../../src/utilities/workspace"; import { expect } from "chai"; +import { Version } from "../../../src/utilities/version"; suite("Workspace Utilities Test Suite", () => { suite("searchForPackages", () => { + const testSwiftVersion = new Version(5, 9, 0); + test("ignores excluded file", async () => { const folders = await searchForPackages( (vscode.workspace.workspaceFolders ?? [])[0]!.uri, false, - true + true, + testSwiftVersion ); expect(folders.find(f => f.fsPath.includes("defaultPackage"))).to.not.be.undefined; diff --git a/test/unit-tests/utilities/workspace.test.ts b/test/unit-tests/utilities/workspace.test.ts index 7ca500fc0..71cfc4f17 100644 --- a/test/unit-tests/utilities/workspace.test.ts +++ b/test/unit-tests/utilities/workspace.test.ts @@ -16,21 +16,23 @@ import * as vscode from "vscode"; import { searchForPackages } from "../../../src/utilities/workspace"; import { testAssetUri } from "../../fixtures"; import { expect } from "chai"; +import { Version } from "../../../src/utilities/version"; suite("Workspace Utilities Unit Test Suite", () => { suite("searchForPackages", () => { const packageFolder = testAssetUri("ModularPackage"); const firstModuleFolder = vscode.Uri.joinPath(packageFolder, "Module1"); const secondModuleFolder = vscode.Uri.joinPath(packageFolder, "Module2"); + const testSwiftVersion = new Version(5, 9, 0); test("returns only root package when search for subpackages disabled", async () => { - const folders = await searchForPackages(packageFolder, false, false); + const folders = await searchForPackages(packageFolder, false, false, testSwiftVersion); expect(folders.map(folder => folder.fsPath)).eql([packageFolder.fsPath]); }); test("returns subpackages when search for subpackages enabled", async () => { - const folders = await searchForPackages(packageFolder, false, true); + const folders = await searchForPackages(packageFolder, false, true, testSwiftVersion); expect(folders.map(folder => folder.fsPath).sort()).deep.equal([ packageFolder.fsPath,