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
4 changes: 2 additions & 2 deletions Example/.bazelrc
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
32 changes: 1 addition & 31 deletions Example/HelloWorld/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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/...",
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)

Expand All @@ -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
Expand Down
15 changes: 10 additions & 5 deletions Sources/sourcekit-bazel-bsp/Commands/Serve.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]()
Expand All @@ -83,7 +84,8 @@ struct Serve: ParsableCommand {
contentsOf: try expandWildcardTargets(
bazelWrapper: bazelWrapper,
targets: targetsToExpand,
topLevelRuleToDiscover: topLevelRuleToDiscover
topLevelRuleToDiscover: topLevelRuleToDiscover,
indexFlags: indexFlags
)
)
}
Expand All @@ -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
Expand All @@ -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(
Expand All @@ -132,7 +136,8 @@ struct Serve: ParsableCommand {
return try BazelTargetDiscoverer.discoverTargets(
for: rulesToUse,
bazelWrapper: bazelWrapper,
locations: targets
locations: targets,
additionalFlags: indexFlags
)
} catch {
logger.error(
Expand Down
44 changes: 34 additions & 10 deletions Tests/SourceKitBazelBSPTests/BazelTargetDiscovererTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -62,16 +62,16 @@ 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"
)
}

@Test
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(
Expand All @@ -85,15 +85,39 @@ 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"
)
}

@Test
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"
)

Expand Down