diff --git a/Example/.bazelrc b/Example/.bazelrc index 1175ecb4..1b9426e0 100644 --- a/Example/.bazelrc +++ b/Example/.bazelrc @@ -1,7 +1,7 @@ common --ios_simulator_device="iPhone 16 Pro" common --ios_simulator_version="18.4" -# All of the following are Debug/Index setup configs inspired by the recommended rules_xcodeproj templates +# All of the following are Debug/Index setup configs inspired by the default rules_xcodeproj template common --verbose_failures common --cache_computed_file_digests=500000 @@ -17,11 +17,11 @@ common --features=swift.index_while_building common --features=swift.use_global_index_store common --features=swift.use_global_module_cache common --features=swift.emit_swiftsourceinfo +common --nolegacy_important_outputs build --noworker_sandboxing build --spawn_strategy=remote,worker,local # Only for BSP builds common:index_build --experimental_convenience_symlinks=ignore common:index_build --bes_backend= --bes_results_url= -common:index_build --nolegacy_important_outputs common:index_build --show_result=0 \ No newline at end of file diff --git a/Example/HelloWorld/BUILD b/Example/HelloWorld/BUILD index 1cdd8883..88b753cc 100644 --- a/Example/HelloWorld/BUILD +++ b/Example/HelloWorld/BUILD @@ -220,38 +220,8 @@ setup_sourcekit_bsp( index_flags = [ "config=index_build", ], - targets = [ - "//HelloWorld:HelloWorld", - "//HelloWorld:HelloWorldTests", - "//HelloWorld:HelloWorldWatchApp", - "//HelloWorld:HelloWorldWatchTests", - "//HelloWorld:HelloWorldMacApp", - "//HelloWorld:HelloWorldMacTests", - "//HelloWorld:HelloWorldMacCLIApp", - ], -) - -# Variant that uses build_test targets directly, for test reasons - -setup_sourcekit_bsp( - name = "setup_sourcekit_bsp_example_project_build_tests", - bazel_wrapper = "bazelisk", - files_to_watch = [ - "HelloWorld/**/*.swift", - "HelloWorld/**/*.h", - "HelloWorld/**/*.m" - ], - index_flags = [ - "config=index_build", - ], compile_top_level = True, targets = [ - "//HelloWorld:HelloWorldLib_ios_skbsp", - "//HelloWorld:HelloWorldTestsLib_ios_skbsp", - "//HelloWorld:WatchAppLib_watchos_skbsp", - "//HelloWorld:WatchAppTestsLib_watchos_skbsp", - "//HelloWorld:MacAppLib_macos_skbsp", - "//HelloWorld:MacAppTestsLib_macos_skbsp", - "//HelloWorld:MacCLIAppLib_macos_skbsp", + "//HelloWorld/...", ], ) diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetDiscoverer.swift b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetDiscoverer.swift index bcbf2d09..a2e67359 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetDiscoverer.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetDiscoverer.swift @@ -22,12 +22,14 @@ public enum BazelTargetDiscoverer { /// - Parameters: /// - rules: The rule types to search for (e.g. ios_application, ios_unit_test) /// - bazelWrapper: The Bazel executable to use (defaults to "bazel") + /// - additionalFlags: Additional flags to pass to the Bazel command /// - Returns: An array of discovered target labels /// - Throws: DiscoverTargetsError.noTargetsDiscovered if no matching targets are found public static func discoverTargets( for rules: [TopLevelRuleType] = TopLevelRuleType.allCases, bazelWrapper: String = "bazel", locations: [String] = [], + additionalFlags: [String] = [], commandRunner: CommandRunner? = nil ) throws -> [String] { guard !rules.isEmpty else { @@ -40,11 +42,19 @@ public enum BazelTargetDiscoverer { let commandRunner = commandRunner ?? ShellCommandRunner() + // FIXME: This has a lot of overlap with the Bazel utilities in CommandRunner, but we cannot + // use them because this logic runs before the actual initialize code that builds all necessary info. + // So we're duplicating a bunch of this logic here as a result. let kindsQuery = "\"" + rules.map { $0.rawValue }.joined(separator: "|") + "\"" let locationsQuery = locations.joined(separator: " union ") let query = "kind(\(kindsQuery), \(locationsQuery))" - - let cmd = "\(bazelWrapper) query '\(query)' --output label" + let additionalFlagsString: String = { + if additionalFlags.isEmpty { + return "" + } + return " " + additionalFlags.joined(separator: " ") + }() + let cmd = "\(bazelWrapper) cquery '\(query)'\(additionalFlagsString) --output label" let output: String = try commandRunner.run(cmd) @@ -54,6 +64,7 @@ public enum BazelTargetDiscoverer { .components(separatedBy: .newlines) .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } .filter { !$0.isEmpty } + .map { $0.components(separatedBy: " (")[0] } if discoveredTargets.isEmpty { throw BazelTargetDiscovererError.noTargetsDiscovered diff --git a/Sources/sourcekit-bazel-bsp/Commands/Serve.swift b/Sources/sourcekit-bazel-bsp/Commands/Serve.swift index ae84c2cf..c4ab3340 100644 --- a/Sources/sourcekit-bazel-bsp/Commands/Serve.swift +++ b/Sources/sourcekit-bazel-bsp/Commands/Serve.swift @@ -67,6 +67,7 @@ struct Serve: ParsableCommand { func run() throws { logger.info("`serve` invoked, initializing BSP server...") + let indexFlags = indexFlag.map { "--" + $0 } let targets: [String] if !target.isEmpty { var expandedTargets = [String]() @@ -83,7 +84,8 @@ struct Serve: ParsableCommand { contentsOf: try expandWildcardTargets( bazelWrapper: bazelWrapper, targets: targetsToExpand, - topLevelRuleToDiscover: topLevelRuleToDiscover + topLevelRuleToDiscover: topLevelRuleToDiscover, + indexFlags: indexFlags ) ) } @@ -94,14 +96,15 @@ struct Serve: ParsableCommand { targets = try expandWildcardTargets( bazelWrapper: bazelWrapper, targets: ["..."], - topLevelRuleToDiscover: topLevelRuleToDiscover + topLevelRuleToDiscover: topLevelRuleToDiscover, + indexFlags: indexFlags ) } let config = BaseServerConfig( bazelWrapper: bazelWrapper, targets: targets, - indexFlags: indexFlag.map { "--" + $0 }, + indexFlags: indexFlags, filesToWatch: filesToWatch, compileTopLevel: compileTopLevel, indexBuildBatchSize: indexBuildBatchSize @@ -116,7 +119,8 @@ struct Serve: ParsableCommand { private func expandWildcardTargets( bazelWrapper: String, targets: [String], - topLevelRuleToDiscover: [TopLevelRuleType] + topLevelRuleToDiscover: [TopLevelRuleType], + indexFlags: [String] ) throws -> [String] { let targetsString = targets.joined(separator: ", ") logger.warning( @@ -132,7 +136,8 @@ struct Serve: ParsableCommand { return try BazelTargetDiscoverer.discoverTargets( for: rulesToUse, bazelWrapper: bazelWrapper, - locations: targets + locations: targets, + additionalFlags: indexFlags ) } catch { logger.error( diff --git a/Tests/SourceKitBazelBSPTests/BazelTargetDiscovererTests.swift b/Tests/SourceKitBazelBSPTests/BazelTargetDiscovererTests.swift index 51842213..07becc02 100644 --- a/Tests/SourceKitBazelBSPTests/BazelTargetDiscovererTests.swift +++ b/Tests/SourceKitBazelBSPTests/BazelTargetDiscovererTests.swift @@ -27,8 +27,8 @@ struct BazelTargetDiscovererTests { func discoverSingleRuleTypeWithMultipleTargets() throws { let commandRunner = CommandRunnerFake() commandRunner.setResponse( - for: "fakeBazel query 'kind(\"ios_application\", ...)' --output label", - response: "//Example/HelloWorld:HelloWorld\n//Example/AnotherApp:AnotherApp\n" + for: "fakeBazel cquery 'kind(\"ios_application\", ...)' --output label", + response: "//Example/HelloWorld:HelloWorld\n//Example/AnotherApp:AnotherApp (abc)\n" ) let targets = try BazelTargetDiscoverer.discoverTargets( @@ -40,15 +40,15 @@ struct BazelTargetDiscovererTests { #expect(targets == ["//Example/HelloWorld:HelloWorld", "//Example/AnotherApp:AnotherApp"]) #expect(commandRunner.commands.count == 1) - #expect(commandRunner.commands[0].command == "fakeBazel query 'kind(\"ios_application\", ...)' --output label") + #expect(commandRunner.commands[0].command == "fakeBazel cquery 'kind(\"ios_application\", ...)' --output label") } @Test func discoverMultipleRuleTypes() throws { let commandRunner = CommandRunnerFake() commandRunner.setResponse( - for: "fakeBazel query 'kind(\"ios_application|ios_unit_test\", ...)' --output label", - response: "//Example/HelloWorld:HelloWorld\n//Example/HelloWorldTests:HelloWorldTests\n" + for: "fakeBazel cquery 'kind(\"ios_application|ios_unit_test\", ...)' --output label", + response: "//Example/HelloWorld:HelloWorld\n//Example/HelloWorldTests:HelloWorldTests (abc)\n" ) let targets = try BazelTargetDiscoverer.discoverTargets( @@ -62,7 +62,7 @@ struct BazelTargetDiscovererTests { #expect(commandRunner.commands.count == 1) #expect( commandRunner.commands[0].command - == "fakeBazel query 'kind(\"ios_application|ios_unit_test\", ...)' --output label" + == "fakeBazel cquery 'kind(\"ios_application|ios_unit_test\", ...)' --output label" ) } @@ -70,8 +70,8 @@ struct BazelTargetDiscovererTests { func discoverAtMultipleLocations() throws { let commandRunner = CommandRunnerFake() commandRunner.setResponse( - for: "fakeBazel query 'kind(\"ios_application\", //A/... union //B/...)' --output label", - response: "//Example/HelloWorld:HelloWorld\n//Example/AnotherApp:AnotherApp\n" + for: "fakeBazel cquery 'kind(\"ios_application\", //A/... union //B/...)' --output label", + response: "//Example/HelloWorld:HelloWorld\n//Example/AnotherApp:AnotherApp (abc)\n" ) let targets = try BazelTargetDiscoverer.discoverTargets( @@ -85,7 +85,31 @@ struct BazelTargetDiscovererTests { #expect(commandRunner.commands.count == 1) #expect( commandRunner.commands[0].command - == "fakeBazel query 'kind(\"ios_application\", //A/... union //B/...)' --output label" + == "fakeBazel cquery 'kind(\"ios_application\", //A/... union //B/...)' --output label" + ) + } + + @Test + func handlesAdditionalFlags() throws { + let commandRunner = CommandRunnerFake() + commandRunner.setResponse( + for: "fakeBazel cquery 'kind(\"ios_application\", //A/... union //B/...)' --config=test --output label", + response: "//Example/HelloWorld:HelloWorld\n//Example/AnotherApp:AnotherApp (abc)\n" + ) + + let targets = try BazelTargetDiscoverer.discoverTargets( + for: [.iosApplication], + bazelWrapper: "fakeBazel", + locations: ["//A/...", "//B/..."], + additionalFlags: ["--config=test"], + commandRunner: commandRunner, + ) + + #expect(targets == ["//Example/HelloWorld:HelloWorld", "//Example/AnotherApp:AnotherApp"]) + #expect(commandRunner.commands.count == 1) + #expect( + commandRunner.commands[0].command + == "fakeBazel cquery 'kind(\"ios_application\", //A/... union //B/...)' --config=test --output label" ) } @@ -93,7 +117,7 @@ struct BazelTargetDiscovererTests { func throwsErrorWhenNoTargetsFound() throws { let commandRunner = CommandRunnerFake() commandRunner.setResponse( - for: "fakeBazel query 'kind(\"ios_application\", ...)' --output label", + for: "fakeBazel cquery 'kind(\"ios_application\", ...)' --output label", response: "\n \n" )