From 9613f10a01a25074b9fb01837438cb032d908951 Mon Sep 17 00:00:00 2001 From: Bruno Henrique da Rocha e Silva Date: Sat, 6 Dec 2025 12:37:29 +0100 Subject: [PATCH 1/3] Index batching: Use upstream version --- Example/.gitignore | 4 ++- Example/.sourcekit-lsp/config.json | 9 ------ Example/.vscode/settings.json | 13 -------- Example/HelloWorld/BUILD | 1 + .../RequestHandlers/InitializeHandler.swift | 17 ---------- .../RequestHandlers/PrepareHandler.swift | 8 ++--- .../Server/BaseServerConfig.swift | 3 -- .../sourcekit-bazel-bsp/Commands/Serve.swift | 9 +----- rules/setup_sourcekit_bsp.bzl | 31 ++++++++++++++++--- rules/setup_sourcekit_bsp.sh.tpl | 6 ++++ 10 files changed, 41 insertions(+), 60 deletions(-) delete mode 100644 Example/.sourcekit-lsp/config.json delete mode 100644 Example/.vscode/settings.json diff --git a/Example/.gitignore b/Example/.gitignore index 77621548..7f227c2c 100644 --- a/Example/.gitignore +++ b/Example/.gitignore @@ -17,4 +17,6 @@ /.sass-cache user.bazelrc /.bsp/skbsp.json -/.bsp/sourcekit-bazel-bsp \ No newline at end of file +/.bsp/sourcekit-bazel-bsp +/.sourcekit-lsp/config.json +/.vscode/settings.json \ No newline at end of file diff --git a/Example/.sourcekit-lsp/config.json b/Example/.sourcekit-lsp/config.json deleted file mode 100644 index 7715da74..00000000 --- a/Example/.sourcekit-lsp/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "backgroundIndexing": true, - "backgroundPreparationMode": "build", - "defaultWorkspaceType": "buildServer", - "logging": { - "level": "error", - "privacyLevel": "sensitive" - } -} diff --git a/Example/.vscode/settings.json b/Example/.vscode/settings.json deleted file mode 100644 index 8c68a20b..00000000 --- a/Example/.vscode/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "swift.sourcekit-lsp.backgroundIndexing": "on", - "swift.sourcekit-lsp.trace.server": "messages", - "terminal.integrated.profiles.osx": { - "zsh": { - "path": "/bin/zsh", - "args": [ - "-l", - "-i" - ] - } - } -} diff --git a/Example/HelloWorld/BUILD b/Example/HelloWorld/BUILD index 88b753cc..108133eb 100644 --- a/Example/HelloWorld/BUILD +++ b/Example/HelloWorld/BUILD @@ -221,6 +221,7 @@ setup_sourcekit_bsp( "config=index_build", ], compile_top_level = True, + index_build_batch_size = 10, targets = [ "//HelloWorld/...", ], diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/InitializeHandler.swift b/Sources/SourceKitBazelBSP/RequestHandlers/InitializeHandler.swift index f7972161..86c6f127 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/InitializeHandler.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/InitializeHandler.swift @@ -172,18 +172,6 @@ final class InitializeHandler { } else { watchers = nil } - let batchSize: Int? = { - let compileTopLevel = initializedConfig.baseConfig.compileTopLevel - let indexBuildBatchSize = initializedConfig.baseConfig.indexBuildBatchSize - if compileTopLevel == false && indexBuildBatchSize != nil { - // FIXME: It's possible to support this, just doing one thing at a time for simplicity. - logger.warning("Ignoring indexBuildBatchSize: Currently only supported for --compile-top-level.") - } - guard compileTopLevel == false else { - return indexBuildBatchSize - } - return 1 - }() return InitializeBuildResponse( displayName: "sourcekit-bazel-bsp", version: sourcekitBazelBSPVersion, @@ -204,11 +192,6 @@ final class InitializeHandler { data: SourceKitInitializeBuildResponseData( indexDatabasePath: initializedConfig.indexDatabasePath, indexStorePath: initializedConfig.indexStorePath, - // Commented out on purpose while we get batching working upstream - // multiTargetPreparation: MultiTargetPreparationSupport( - // supported: true, - // batchSize: batchSize - // ), outputPathsProvider: nil, prepareProvider: true, sourceKitOptionsProvider: true, diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift b/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift index d03a9eed..e5ba38a8 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift @@ -26,11 +26,11 @@ import struct os.OSAllocatedUnfairLock private let logger = makeFileLevelBSPLogger() enum PrepareHandlerError: Error, LocalizedError { - case unexpectedBatching([String]) + case unexpectedBatching var errorDescription: String? { switch self { - case .unexpectedBatching(let labels): return "Unexpected batching of targets: \(labels.joined(separator: ", "))" + case .unexpectedBatching: return "Your sourcekit-lsp instance appears to be configured for batching, but the BSP currently only supports this when passing --compile-top-level. To fix this, either disable batching or enable --compile-top-level for the BSP." } } } @@ -108,9 +108,7 @@ final class PrepareHandler { extraArgs = [] // Not applicable in this case } else { guard platformInfo.count == 1 else { - // Should not happen as we force the batch size to 1 in this case, - // but catching it just in case. - throw PrepareHandlerError.unexpectedBatching(platformInfo.map { $0.label }) + throw PrepareHandlerError.unexpectedBatching } let infoToBuild = platformInfo[0] labelsToBuild = [infoToBuild.label] diff --git a/Sources/SourceKitBazelBSP/Server/BaseServerConfig.swift b/Sources/SourceKitBazelBSP/Server/BaseServerConfig.swift index da3cbc89..c48bd9d1 100644 --- a/Sources/SourceKitBazelBSP/Server/BaseServerConfig.swift +++ b/Sources/SourceKitBazelBSP/Server/BaseServerConfig.swift @@ -29,7 +29,6 @@ package struct BaseServerConfig: Equatable { let targets: [String] let indexFlags: [String] let filesToWatch: String? - let indexBuildBatchSize: Int? let compileTopLevel: Bool package init( @@ -38,13 +37,11 @@ package struct BaseServerConfig: Equatable { indexFlags: [String], filesToWatch: String?, compileTopLevel: Bool, - indexBuildBatchSize: Int? = nil ) { self.bazelWrapper = bazelWrapper self.indexFlags = indexFlags self.filesToWatch = filesToWatch self.compileTopLevel = compileTopLevel - self.indexBuildBatchSize = indexBuildBatchSize // We need to post-process the target list provided by the user // because the queries will always return the "full" label. diff --git a/Sources/sourcekit-bazel-bsp/Commands/Serve.swift b/Sources/sourcekit-bazel-bsp/Commands/Serve.swift index c4ab3340..0902d8a5 100644 --- a/Sources/sourcekit-bazel-bsp/Commands/Serve.swift +++ b/Sources/sourcekit-bazel-bsp/Commands/Serve.swift @@ -52,12 +52,6 @@ struct Serve: ParsableCommand { ) var topLevelRuleToDiscover: [TopLevelRuleType] = [] - @Option( - help: - "The number of targets to prepare in parallel. If not specified, SourceKit-LSP will calculate an appropriate value based on the environment. Requires --compile-top-level and using the pre-built SourceKit-LSP binary from the release archive.", - ) - var indexBuildBatchSize: Int? = nil - @Flag( help: "Instead of attempting to build targets individually, build the top-level parent. If your project contains build_test targets for your individual libraries and you're passing them as the top-level targets for the BSP, you can use this flag to build those targets directly for better predictability and caching." @@ -106,8 +100,7 @@ struct Serve: ParsableCommand { targets: targets, indexFlags: indexFlags, filesToWatch: filesToWatch, - compileTopLevel: compileTopLevel, - indexBuildBatchSize: indexBuildBatchSize + compileTopLevel: compileTopLevel ) logger.debug("Initializing BSP with targets: \(targets)") diff --git a/rules/setup_sourcekit_bsp.bzl b/rules/setup_sourcekit_bsp.bzl index b0ae8ecb..12b8c1df 100644 --- a/rules/setup_sourcekit_bsp.bzl +++ b/rules/setup_sourcekit_bsp.bzl @@ -1,5 +1,10 @@ def _setup_sourcekit_bsp_impl(ctx): + # Config of the BSP itself, a.k.a .bsp/skbsp.json rendered_bsp_config = ctx.actions.declare_file("skbsp.json") + # Configs for sourcekit-lsp, a.k.a .sourcekit-lsp/config.json + rendered_lsp_config = ctx.actions.declare_file("config.json") + + # BSP setup bits bsp_config_argv = [ ".bsp/sourcekit-bazel-bsp", "serve", @@ -9,9 +14,6 @@ def _setup_sourcekit_bsp_impl(ctx): bsp_config_argv.append(target) bsp_config_argv.append("--bazel-wrapper") bsp_config_argv.append(ctx.attr.bazel_wrapper) - if ctx.attr.index_build_batch_size: - bsp_config_argv.append("--index-build-batch-size") - bsp_config_argv.append(ctx.attr.index_build_batch_size) if ctx.attr.compile_top_level: bsp_config_argv.append("--compile-top-level") for index_flag in ctx.attr.index_flags: @@ -31,6 +33,25 @@ def _setup_sourcekit_bsp_impl(ctx): "%argv%": ",\n ".join(["\"%s\"" % arg for arg in bsp_config_argv]), }, ) + + # sourcekit-lsp setup bits + lsp_config_json = { + "backgroundIndexing": "true", + "backgroundPreparationMode": "build", + "defaultWorkspaceType": "buildServer", + "buildServerWorkspaceRequestsTimeout": 999, # Temporary while we don't follow the recommendation of returning from buildTargets as fast as possible + use notifications + "buildSettingsTimeout": 999, # Temporary while we don't follow the recommendation of returning from buildTargets as fast as possible + use notifications + } + if ctx.attr.index_build_batch_size: + if not ctx.attr.compile_top_level: + fail("index_build_batch_size is currently only supported when compile_top_level is true.") + lsp_config_json["preparationBatchingStrategy"] = { + "strategy": "fixedTargetBatchSize", + "batchSize": ctx.attr.index_build_batch_size + } + ctx.actions.write(rendered_lsp_config, json.encode(lsp_config_json)) + + # Generating the script that ties everything together executable = ctx.actions.declare_file("setup_sourcekit_bsp.sh") ctx.actions.expand_template( template = ctx.file._setup_sourcekit_bsp_script, @@ -38,6 +59,7 @@ def _setup_sourcekit_bsp_impl(ctx): output = executable, substitutions = { "%bsp_config_path%": rendered_bsp_config.short_path, + "%lsp_config_path%": rendered_lsp_config.short_path, "%sourcekit_bazel_bsp_path%": ctx.executable.sourcekit_bazel_bsp.short_path, }, ) @@ -45,6 +67,7 @@ def _setup_sourcekit_bsp_impl(ctx): files = [ ctx.executable.sourcekit_bazel_bsp, rendered_bsp_config, + rendered_lsp_config, ], ) return DefaultInfo( @@ -97,7 +120,7 @@ setup_sourcekit_bsp = rule( default = [], ), "index_build_batch_size": attr.int( - doc = "The number of targets to prepare in parallel. If not specified, SourceKit-LSP will calculate an appropriate value based on the environment. Requires compile_top_level and using the pre-built SourceKit-LSP binary from the release archive.", + doc = "The number of targets to prepare in parallel. Requires compile_top_level and using the pre-built SourceKit-LSP binary from the release archive.", mandatory = False, ), "compile_top_level": attr.bool( diff --git a/rules/setup_sourcekit_bsp.sh.tpl b/rules/setup_sourcekit_bsp.sh.tpl index cf4ddfce..9179b09f 100644 --- a/rules/setup_sourcekit_bsp.sh.tpl +++ b/rules/setup_sourcekit_bsp.sh.tpl @@ -4,15 +4,20 @@ set -euo pipefail sourcekit_bazel_bsp_path="%sourcekit_bazel_bsp_path%" bsp_config_path="%bsp_config_path%" +lsp_config_path="%lsp_config_path%" bsp_folder_path="$BUILD_WORKSPACE_DIRECTORY/.bsp" +lsp_folder_path="$BUILD_WORKSPACE_DIRECTORY/.sourcekit-lsp" mkdir -p "$bsp_folder_path" +mkdir -p "$lsp_folder_path" target_bsp_config_path="$bsp_folder_path/skbsp.json" target_sourcekit_bazel_bsp_path="$bsp_folder_path/sourcekit-bazel-bsp" +target_lsp_config_path="$lsp_folder_path/config.json" cp "$bsp_config_path" "$target_bsp_config_path" +cp "$lsp_config_path" "$target_lsp_config_path" # Delete the existing binary first to avoid issues when running this while a server is running. rm -f "$target_sourcekit_bazel_bsp_path" || true @@ -20,3 +25,4 @@ cp "$sourcekit_bazel_bsp_path" "$target_sourcekit_bazel_bsp_path" chmod +w "$target_bsp_config_path" chmod +w "$target_sourcekit_bazel_bsp_path" +chmod +w "$target_lsp_config_path" From 459e94d79421fa471b258a1d9e0645aae766ad6b Mon Sep 17 00:00:00 2001 From: Bruno Henrique da Rocha e Silva Date: Sat, 6 Dec 2025 13:37:13 +0100 Subject: [PATCH 2/3] Lint sources --- .../SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift b/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift index e5ba38a8..47eeea19 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/PrepareHandler.swift @@ -30,7 +30,9 @@ enum PrepareHandlerError: Error, LocalizedError { var errorDescription: String? { switch self { - case .unexpectedBatching: return "Your sourcekit-lsp instance appears to be configured for batching, but the BSP currently only supports this when passing --compile-top-level. To fix this, either disable batching or enable --compile-top-level for the BSP." + case .unexpectedBatching: + return + "Your sourcekit-lsp instance appears to be configured for batching, but the BSP currently only supports this when passing --compile-top-level. To fix this, either disable batching or enable --compile-top-level for the BSP." } } } From dc00a42a2cea2b2d9fb9955343e7e10afe438c63 Mon Sep 17 00:00:00 2001 From: Bruno Henrique da Rocha e Silva Date: Sat, 6 Dec 2025 18:41:11 +0100 Subject: [PATCH 3/3] Fix boolean key in the lsp json --- rules/setup_sourcekit_bsp.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/setup_sourcekit_bsp.bzl b/rules/setup_sourcekit_bsp.bzl index 12b8c1df..bd1f304c 100644 --- a/rules/setup_sourcekit_bsp.bzl +++ b/rules/setup_sourcekit_bsp.bzl @@ -36,7 +36,7 @@ def _setup_sourcekit_bsp_impl(ctx): # sourcekit-lsp setup bits lsp_config_json = { - "backgroundIndexing": "true", + "backgroundIndexing": True, "backgroundPreparationMode": "build", "defaultWorkspaceType": "buildServer", "buildServerWorkspaceRequestsTimeout": 999, # Temporary while we don't follow the recommendation of returning from buildTargets as fast as possible + use notifications