diff --git a/Example/HelloWorld/BUILD b/Example/HelloWorld/BUILD index 9b02b194..c3c8db7c 100644 --- a/Example/HelloWorld/BUILD +++ b/Example/HelloWorld/BUILD @@ -1,5 +1,5 @@ load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template_rule") -load("@rules_apple//apple:ios.bzl", "ios_application", "ios_unit_test", "ios_build_test", "ios_ui_test") +load("@rules_apple//apple:ios.bzl", "ios_application", "ios_extension", "ios_unit_test", "ios_build_test", "ios_ui_test") load("@rules_apple//apple:macos.bzl", "macos_application", "macos_command_line_application", "macos_unit_test") load("@rules_apple//apple:watchos.bzl", "watchos_application", "watchos_extension", "watchos_unit_test") load("@rules_cc//cc:defs.bzl", "cc_library") @@ -115,6 +115,7 @@ swift_library( ":TodoModelsAlias", ":TodoObjCSupport", ":ExpandedTemplate", + "@yams//:Yams", # External dep to test bzlmod + version suffix in BSP URIs ] + select({ "//conditions:default": [], ":dbg_mode": [":GeneratedDummy"], @@ -180,6 +181,15 @@ swift_library( srcs = [":ExpandTemplateSwiftFile"], ) +## MARK: iOS extension targets + +swift_library( + name = "NotificationServiceExtensionLib", + module_name = "NotificationServiceExtensionLib", + srcs = glob(["HelloWorldNotificationExtension/Sources/*.swift"]), + deps = [":TodoModels"], +) + ## MARK: WatchOS targets swift_library( @@ -247,9 +257,19 @@ ios_application( infoplists = ["Resources/Info.plist"], minimum_os_version = IOS_MINIMUM_OS_VERSION, watch_application = ":HelloWorldWatchApp", + extensions = [":HelloWorldNotificationServiceExtension"], deps = [":HelloWorldLib"], ) +ios_extension( + name = "HelloWorldNotificationServiceExtension", + bundle_id = "com.example.HelloWorld.NotificationService", + families = ["iphone", "ipad"], + infoplists = ["Resources/IosExt-Info.plist"], + minimum_os_version = IOS_MINIMUM_OS_VERSION, + deps = [":NotificationServiceExtensionLib"], +) + watchos_application( name = "HelloWorldWatchApp", bundle_id = "com.example.HelloWorld.Watch", diff --git a/Example/HelloWorld/HelloWorldLib/Sources/AddTodoView.swift b/Example/HelloWorld/HelloWorldLib/Sources/AddTodoView.swift index 75b5885b..b41b317b 100644 --- a/Example/HelloWorld/HelloWorldLib/Sources/AddTodoView.swift +++ b/Example/HelloWorld/HelloWorldLib/Sources/AddTodoView.swift @@ -19,6 +19,7 @@ import SwiftUI import TodoModels +import Yams struct AddTodoView: View { @@ -113,6 +114,8 @@ struct AddTodoView: View { todoTitle = "" isPresented = false - print("Added task: \(trimmedTitle)") + // Test Yams external dependency + let yaml = try? Yams.dump(object: ["task": trimmedTitle]) + print("Added task: \(trimmedTitle), yaml: \(yaml ?? "nil")") } } diff --git a/Example/HelloWorld/HelloWorldNotificationExtension/Sources/NotificationService.swift b/Example/HelloWorld/HelloWorldNotificationExtension/Sources/NotificationService.swift new file mode 100644 index 00000000..d7b0f7d8 --- /dev/null +++ b/Example/HelloWorld/HelloWorldNotificationExtension/Sources/NotificationService.swift @@ -0,0 +1,27 @@ +import TodoModels +import UserNotifications + +class NotificationService: UNNotificationServiceExtension { + var contentHandler: ((UNNotificationContent) -> Void)? + var bestAttemptContent: UNMutableNotificationContent? + + override func didReceive( + _ request: UNNotificationRequest, + withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void + ) { + self.contentHandler = contentHandler + bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) + + if let bestAttemptContent = bestAttemptContent { + let manager = TodoListManager() + bestAttemptContent.title = "\(bestAttemptContent.title) [\(manager.todoItems.count) todos]" + contentHandler(bestAttemptContent) + } + } + + override func serviceExtensionTimeWillExpire() { + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + contentHandler(bestAttemptContent) + } + } +} diff --git a/Example/HelloWorld/Resources/IosExt-Info.plist b/Example/HelloWorld/Resources/IosExt-Info.plist new file mode 100644 index 00000000..ede40b39 --- /dev/null +++ b/Example/HelloWorld/Resources/IosExt-Info.plist @@ -0,0 +1,27 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + NotificationServiceExtensionLib.NotificationService + + + diff --git a/Example/MODULE.bazel b/Example/MODULE.bazel index 561a6d8e..2e2e5328 100644 --- a/Example/MODULE.bazel +++ b/Example/MODULE.bazel @@ -28,6 +28,10 @@ archive_override( bazel_dep(name = "apple_support", version = "2.2.0") bazel_dep(name = "rules_cc", version = "0.2.16") + +# External Swift library to test the external repo case +bazel_dep(name = "yams", version = "5.0.6") + bazel_dep(name = "aspect_bazel_lib", version = "2.13.0") bazel_dep(name = "rules_multirun", version = "0.13.0") diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerier.swift b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerier.swift index 60de4dbd..0cdc3f31 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerier.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerier.swift @@ -120,7 +120,8 @@ final class BazelTargetQuerier { // We use cquery here because we are interested on what's actually compiled. // Also, this shares more analysis cache compared to the regular query. - let cmd = "cquery '\(topLevelTargetsQuery)' --noinclude_aspects --notool_deps --noimplicit_deps --output proto" + let cmd = + "cquery '\(topLevelTargetsQuery)' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto" let output: Data = try commandRunner.bazelIndexAction( baseConfig: config.baseConfig, outputBase: config.outputBase, @@ -139,7 +140,8 @@ final class BazelTargetQuerier { workspaceName: config.workspaceName, executionRoot: config.executionRoot, toolchainPath: config.devToolchainPath, - outputPath: config.outputPath + outputPath: config.outputPath, + outputBase: config.outputBase ) logger.debug("Cqueried \(processedCqueryResult.buildTargets.count, privacy: .public) targets") @@ -165,6 +167,7 @@ final class BazelTargetQuerier { let baseFlags = [ + "--consistent_labels", "--noinclude_artifacts", "--noinclude_aspects", ] + config.baseConfig.aqueryFlags @@ -265,7 +268,8 @@ final class BazelTargetQuerier { cmd: query, rootUri: config.rootUri, additionalFlags: [ - "--output=proto" + "--consistent_labels", + "--output=proto", ] ) @@ -277,7 +281,8 @@ final class BazelTargetQuerier { rootUri: config.rootUri, workspaceName: config.workspaceName, executionRoot: config.executionRoot, - outputPath: config.outputPath + outputPath: config.outputPath, + outputBase: config.outputBase ) } } diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerierParser.swift b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerierParser.swift index b2ae21ce..399aacfc 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerierParser.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetQuerierParser.swift @@ -81,7 +81,8 @@ protocol BazelTargetQuerierParser: AnyObject { workspaceName: String, executionRoot: String, toolchainPath: String, - outputPath: String + outputPath: String, + outputBase: String ) throws -> ProcessedCqueryResult func processAquery( @@ -95,7 +96,8 @@ protocol BazelTargetQuerierParser: AnyObject { rootUri: String, workspaceName: String, executionRoot: String, - outputPath: String + outputPath: String, + outputBase: String ) throws -> ProcessedCqueryAddedFilesResult } @@ -111,7 +113,8 @@ final class BazelTargetQuerierParserImpl: BazelTargetQuerierParser { workspaceName: String, executionRoot: String, toolchainPath: String, - outputPath: String + outputPath: String, + outputBase: String ) throws -> ProcessedCqueryResult { let cquery = try BazelProtobufBindings.parseCqueryResult(data: data) @@ -255,7 +258,7 @@ final class BazelTargetQuerierParserImpl: BazelTargetQuerierParser { let id = try label.toTargetId( rootUri: rootUri, workspaceName: workspaceName, - executionRoot: executionRoot, + outputBase: outputBase, configMnemonic: configuration ) bspUriToParentConfigMap[id] = configuration @@ -358,7 +361,7 @@ final class BazelTargetQuerierParserImpl: BazelTargetQuerierParser { canDebug: false ) - let isExternal = rule.name.hasPrefix("@") + let isExternal = rule.name.isExternalBazelLabel() let tags: [BuildTargetTag] = { var tags: [BuildTargetTag] = [.library] if isExternal { @@ -866,7 +869,8 @@ extension BazelTargetQuerierParserImpl { rootUri: String, workspaceName: String, executionRoot: String, - outputPath: String + outputPath: String, + outputBase: String ) throws -> ProcessedCqueryAddedFilesResult { let cquery = try BazelProtobufBindings.parseCqueryResult(data: data) @@ -914,7 +918,7 @@ extension BazelTargetQuerierParserImpl { let id = try displayName.toTargetId( rootUri: rootUri, workspaceName: workspaceName, - executionRoot: executionRoot, + outputBase: outputBase, configMnemonic: configMnemonic ) @@ -937,12 +941,12 @@ extension String { /// Converts a Bazel label into a URI and returns a unique target id. /// /// For local labels: bazel:///___ - /// For external labels: bazel:///external//___ + /// For external labels: bazel:///external//___ /// fileprivate func toTargetId( rootUri: String, workspaceName: String, - executionRoot: String, + outputBase: String, configMnemonic: String ) throws -> URI { let (repoName, packageName, targetName) = try splitTargetLabel(workspaceName: workspaceName) @@ -953,7 +957,7 @@ extension String { } else { // External repo: use execution root + external path path = - "bazel://" + executionRoot + "/external/" + repoName + packagePath + "/" + targetName + "_" + "bazel://" + outputBase + "/external/" + repoName + packagePath + "/" + targetName + "_" + configMnemonic } guard let uri = try? URI(string: path) else { @@ -980,17 +984,17 @@ extension String { let repoName: String let packageName: String - if repoAndPackage.hasPrefix("@//") { - // Alias for the main repo. - repoName = workspaceName - packageName = String(repoAndPackage.dropFirst(3)) - } else if repoAndPackage.hasPrefix("//") { - // Also the main repo. + var withoutAt = repoAndPackage + while withoutAt.first == "@" { + withoutAt = withoutAt.dropFirst() + } + + if withoutAt.hasPrefix("//") { + // Main repo label. repoName = workspaceName - packageName = String(repoAndPackage.dropFirst(2)) - } else if repoAndPackage.hasPrefix("@") && repoAndPackage.contains("//") { - // External label - let withoutAt = repoAndPackage.dropFirst() + packageName = String(withoutAt.dropFirst(2)) + } else if !withoutAt.isEmpty { + // External repo label. guard let slashIndex = withoutAt.firstIndex(of: "/") else { throw BazelTargetQuerierParserError.incorrectName(self) } diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetStore.swift b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetStore.swift index a89c218e..af489afc 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetStore.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/BazelTargetStore.swift @@ -395,7 +395,7 @@ extension BazelTargetStoreImpl { }() reportTopLevel.append( .init( - label: label, + label: label.removingLeadingAtForMainRepoBazelLabel(), launchType: launchType, configMnemonic: configMnemonic, testSources: testSources @@ -429,7 +429,7 @@ extension BazelTargetStoreImpl { } reportDependencies.append( .init( - label: label, + label: label.removingLeadingAtForMainRepoBazelLabel(), configMnemonic: configMnemonic, topLevelParent: topLevelParent, extraBuildArgs: extraBuildArgs diff --git a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/IndexOutputPathBuilder.swift b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/IndexOutputPathBuilder.swift index 817c2374..4a0cf670 100644 --- a/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/IndexOutputPathBuilder.swift +++ b/Sources/SourceKitBazelBSP/RequestHandlers/BuildTargets/IndexOutputPathBuilder.swift @@ -46,8 +46,11 @@ enum IndexOutputPathBuilder { // Extract external repo name if present (e.g., "@abseil-cpp" from "@abseil-cpp//absl/base") let externalRepoName: String? - if beforeColon.hasPrefix("@") { - let afterAt = beforeColon.dropFirst() // drop "@" + if beforeColon.isExternalBazelLabel() { + var afterAt = beforeColon.dropFirst() + while afterAt.first == "@" { + afterAt = afterAt.dropFirst() + } if let slashIdx = afterAt.firstIndex(of: "/") { externalRepoName = String(afterAt[.. Analysis_Action { - let bazelTarget: String = { - let base = platformInfo.label - guard base.hasPrefix("@") else { - return base - } - // External labels show up as `@@` in the aquery. - return "@\(base)" - }() - guard let target = aquery.targets[bazelTarget] else { + let bazelTarget: String = platformInfo.label + // The aquery protobuf uses labels without the @ prefix for main repo targets even when + // --consistent_labels is used, but cquery returns labels with @@ or @ prefix. + // External repos keep their @@ prefix in both. Normalize labels for lookup. + // Older Bazel versions may return single @ for external repos, so try both formats. + let normalizedTarget: String + if bazelTarget.hasPrefix("@@//") { + normalizedTarget = String(bazelTarget.dropFirst(2)) + } else if bazelTarget.hasPrefix("@//") { + normalizedTarget = String(bazelTarget.dropFirst(1)) + } else if bazelTarget.hasPrefix("@") && !bazelTarget.hasPrefix("@@") { + // External repo with single @ - convert to @@ for lookup + normalizedTarget = "@" + bazelTarget + } else { + normalizedTarget = bazelTarget + } + // Try normalized target first, then fall back to original for compatibility + let targetToLookup = aquery.targets[normalizedTarget] ?? aquery.targets[bazelTarget] + guard let target = targetToLookup else { throw BazelTargetCompilerArgsExtractorError.targetNotFound(bazelTarget) } guard let actions = aquery.actions[target.id] else { diff --git a/Sources/SourceKitBazelBSP/SharedUtils/BazelLabelSanitizer.swift b/Sources/SourceKitBazelBSP/SharedUtils/BazelLabelSanitizer.swift index 428c446e..8d9a836e 100644 --- a/Sources/SourceKitBazelBSP/SharedUtils/BazelLabelSanitizer.swift +++ b/Sources/SourceKitBazelBSP/SharedUtils/BazelLabelSanitizer.swift @@ -20,11 +20,13 @@ /// Sanitizes Bazel labels into safe identifiers for use as output group names or target names. enum BazelLabelSanitizer { /// Sanitizes a Bazel label with the given prefix. - /// Strips leading `//`, replaces `/`, `:`, `-`, `.` with `_`. + /// Strips all leading `@` and `/` characters, replaces `/`, `:`, `-`, `.`, `+` with `_`. + /// This must match the `_sanitize_label` function in `setup_sourcekit_bsp.sh.tpl`. static func sanitize(_ label: String, prefix: String) -> String { var sanitized = label - if sanitized.hasPrefix("//") { - sanitized = String(sanitized.dropFirst(2)) + // Strip all leading @ and / characters (matches Bazel-side _strip_leading_chars) + while let first = sanitized.first, first == "@" || first == "/" { + sanitized = String(sanitized.dropFirst()) } return prefix + sanitized @@ -32,6 +34,7 @@ enum BazelLabelSanitizer { .replacingOccurrences(of: ":", with: "_") .replacingOccurrences(of: "-", with: "_") .replacingOccurrences(of: ".", with: "_") + .replacingOccurrences(of: "+", with: "_") } /// Converts a Bazel label to a wrapper target name. @@ -40,3 +43,27 @@ enum BazelLabelSanitizer { return sanitize(label, prefix: "wrapper_") } } + +extension String { + func isExternalBazelLabel() -> Bool { + guard hasPrefix("@") else { + return false + } + var rest = self.dropFirst() + while rest.first == "@" { + rest = rest.dropFirst() + } + return !rest.isEmpty && !rest.hasPrefix("//") + } + + func removingLeadingAtForMainRepoBazelLabel() -> String { + guard !isExternalBazelLabel() else { + return self + } + var rest = self.dropFirst() + while rest.first == "@" { + rest = rest.dropFirst() + } + return String(rest) + } +} diff --git a/Sources/SourceKitBazelBSP/SharedUtils/Shell/ShellCommandRunner.swift b/Sources/SourceKitBazelBSP/SharedUtils/Shell/ShellCommandRunner.swift index 81b748e7..283aad4c 100644 --- a/Sources/SourceKitBazelBSP/SharedUtils/Shell/ShellCommandRunner.swift +++ b/Sources/SourceKitBazelBSP/SharedUtils/Shell/ShellCommandRunner.swift @@ -62,7 +62,12 @@ struct ShellCommandRunner: CommandRunner { runningProcess.attachPipes() - logger.logFullObjectInMultipleLogMessages(level: .debug, header: "Running shell", cmd) + logger.logFullObjectInMultipleLogMessages( + level: .debug, + header: "Running shell", + cmd, + splitByCharacterCount: true + ) try process.run() diff --git a/Sources/SourceKitBazelBSP/SharedUtils/SplitLogMessage.swift b/Sources/SourceKitBazelBSP/SharedUtils/SplitLogMessage.swift index a801bef4..56563454 100644 --- a/Sources/SourceKitBazelBSP/SharedUtils/SplitLogMessage.swift +++ b/Sources/SourceKitBazelBSP/SharedUtils/SplitLogMessage.swift @@ -22,16 +22,36 @@ import OSLog -/// Splits `message` on newline characters such that each chunk is at most `maxChunkSize` bytes long. +/// Splits `message` such that each chunk is at most `maxChunkSize` bytes long. /// /// The intended use case for this is to split compiler arguments and a file's contents into multiple chunks so /// that each chunk doesn't exceed the maximum message length of `os_log` and thus won't get truncated. /// -/// - Note: This will only split along newline boundary. If a single line is longer than `maxChunkSize`, it won't be -/// split. This is fine for compiler argument splitting since a single argument is rarely longer than 800 characters. -package func splitLongMultilineMessage(message: String) -> [String] { +/// When `splitByCharacterCount` is true, the message is split purely by character count, ignoring any +/// separator logic. Otherwise, splits along newline boundaries (a single line longer than `maxChunkSize` +/// won't be split in that mode). +package func splitLongMultilineMessage( + message: String, + splitByCharacterCount: Bool = false +) -> [String] { let maxChunkSize = 800 var chunks: [String] = [] + + if splitByCharacterCount { + var remaining = message + while !remaining.isEmpty { + if remaining.utf8.count > maxChunkSize { + let endIndex = remaining.utf8.index(remaining.utf8.startIndex, offsetBy: maxChunkSize) + chunks.append(String(remaining[.. HelloWorldLib -> TodoModelsAlias -> TodoModels // HelloWorldTests -> HelloWorldTestsLib -> HelloWorldLib -> ... + // HelloWorldNotificationServiceExtension -> NotificationServiceExtensionLib -> TodoModels // Note: HelloWorldE2ETests is NOT included because test_host is not a dep // macOS: HelloWorldMacApp -> MacAppLib -> TodoModels // HelloWorldMacTests -> MacAppTestsLib -> MacAppLib -> ... @@ -298,58 +315,59 @@ struct BazelTargetQuerierParserImplTests { // HelloWorldWatchTests -> WatchAppTestsLib -> WatchAppLib -> ... // Note: HelloWorldWatchApp is NOT included because extension is not a dep #expect( - getParentLabels(forLabel: "//HelloWorld:TodoModels") + getParentLabels(forLabel: "@@//HelloWorld:TodoModels") == Set([ - "//HelloWorld:HelloWorldMacTests", - "//HelloWorld:HelloWorldMacCLIApp", - "//HelloWorld:HelloWorldMacApp", - "//HelloWorld:HelloWorldWatchTests", - "//HelloWorld:HelloWorldWatchExtension", - "//HelloWorld:HelloWorldTests", - "//HelloWorld:HelloWorld", + "@@//HelloWorld:HelloWorldMacTests", + "@@//HelloWorld:HelloWorldMacCLIApp", + "@@//HelloWorld:HelloWorldMacApp", + "@@//HelloWorld:HelloWorldWatchTests", + "@@//HelloWorld:HelloWorldWatchExtension", + "@@//HelloWorld:HelloWorldTests", + "@@//HelloWorld:HelloWorld", + "@@//HelloWorld:HelloWorldNotificationServiceExtension", ]) ) // TodoObjCSupport is a dep of HelloWorldLib (iOS only) // Note: HelloWorldE2ETests is NOT included because test_host is not a dep #expect( - getParentLabels(forLabel: "//HelloWorld:TodoObjCSupport") + getParentLabels(forLabel: "@@//HelloWorld:TodoObjCSupport") == Set([ - "//HelloWorld:HelloWorldTests", - "//HelloWorld:HelloWorld", + "@@//HelloWorld:HelloWorldTests", + "@@//HelloWorld:HelloWorld", ]) ) // HelloWorldE2ETestsLib is ONLY a dep of HelloWorldE2ETests #expect( - getParentLabels(forLabel: "//HelloWorld:HelloWorldE2ETestsLib") + getParentLabels(forLabel: "@@//HelloWorld:HelloWorldE2ETestsLib") == Set([ - "//HelloWorld:HelloWorldE2ETests" + "@@//HelloWorld:HelloWorldE2ETests" ]) ) // watchOS targets - WatchAppLib is dep of HelloWorldWatchExtension // HelloWorldWatchTests deps on WatchAppTestsLib which deps on WatchAppLib // Note: HelloWorldWatchApp is NOT included because it uses extension attribute, not deps #expect( - getParentLabels(forLabel: "//HelloWorld:WatchAppLib") + getParentLabels(forLabel: "@@//HelloWorld:WatchAppLib") == Set([ - "//HelloWorld:HelloWorldWatchExtension", - "//HelloWorld:HelloWorldWatchTests", + "@@//HelloWorld:HelloWorldWatchExtension", + "@@//HelloWorld:HelloWorldWatchTests", ]) ) // WatchAppTestsLib is ONLY a dep of HelloWorldWatchTests #expect( - getParentLabels(forLabel: "//HelloWorld:WatchAppTestsLib") + getParentLabels(forLabel: "@@//HelloWorld:WatchAppTestsLib") == Set([ - "//HelloWorld:HelloWorldWatchTests" + "@@//HelloWorld:HelloWorldWatchTests" ]) ) // Verify testTargetToBundleTargetMap - maps test targets to their bundle target URIs // These are the test bundle targets that should have their bundle URIs mapped let expectedTestTargets = Set([ - "//HelloWorld:HelloWorldTests", - "//HelloWorld:HelloWorldE2ETests", - "//HelloWorld:HelloWorldMacTests", - "//HelloWorld:HelloWorldWatchTests", + "@@//HelloWorld:HelloWorldTests", + "@@//HelloWorld:HelloWorldE2ETests", + "@@//HelloWorld:HelloWorldMacTests", + "@@//HelloWorld:HelloWorldWatchTests", ]) let actualTestTargets = Set(result.testTargetToBundleTargetMap.keys) #expect( @@ -372,12 +390,12 @@ struct BazelTargetQuerierParserImplTests { // Verify specific bundle target mappings // HelloWorldTests should map to a bundle target containing test sources - let unitTestBundleUri = try #require(result.testTargetToBundleTargetMap["//HelloWorld:HelloWorldTests"]) + let unitTestBundleUri = try #require(result.testTargetToBundleTargetMap["@@//HelloWorld:HelloWorldTests"]) let unitTestSources = try #require(result.bspURIsToSrcsMap[unitTestBundleUri]) #expect(unitTestSources.sources.contains { $0.uri.stringValue.contains("HelloWorldTests/") }) // HelloWorldE2ETests should map to a bundle target containing E2E test sources - let e2eTestBundleUri = try #require(result.testTargetToBundleTargetMap["//HelloWorld:HelloWorldE2ETests"]) + let e2eTestBundleUri = try #require(result.testTargetToBundleTargetMap["@@//HelloWorld:HelloWorldE2ETests"]) let e2eTestSources = try #require(result.bspURIsToSrcsMap[e2eTestBundleUri]) #expect(e2eTestSources.sources.contains { $0.uri.stringValue.contains("HelloWorldE2ETests/") }) } @@ -392,14 +410,14 @@ struct BazelTargetQuerierParserImplTests { let macOsMnemonic = "darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6" let watchOsMnemonic = "watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed" let topLevelTargets: [(String, TopLevelRuleType, String)] = [ - ("//HelloWorld:HelloWorld", .iosApplication, iosMnemonic), - ("//HelloWorld:HelloWorldMacApp", .macosApplication, macOsMnemonic), - ("//HelloWorld:HelloWorldMacCLIApp", .macosCommandLineApplication, macOsMnemonic), - ("//HelloWorld:HelloWorldMacTests", .macosUnitTest, macOsMnemonic), - ("//HelloWorld:HelloWorldTests", .iosUnitTest, iosMnemonic), - ("//HelloWorld:HelloWorldWatchApp", .watchosApplication, watchOsMnemonic), - ("//HelloWorld:HelloWorldWatchExtension", .watchosExtension, watchOsMnemonic), - ("//HelloWorld:HelloWorldWatchTests", .watchosUnitTest, watchOsMnemonic), + ("@@//HelloWorld:HelloWorld", .iosApplication, iosMnemonic), + ("@@//HelloWorld:HelloWorldMacApp", .macosApplication, macOsMnemonic), + ("@@//HelloWorld:HelloWorldMacCLIApp", .macosCommandLineApplication, macOsMnemonic), + ("@@//HelloWorld:HelloWorldMacTests", .macosUnitTest, macOsMnemonic), + ("@@//HelloWorld:HelloWorldTests", .iosUnitTest, iosMnemonic), + ("@@//HelloWorld:HelloWorldWatchApp", .watchosApplication, watchOsMnemonic), + ("@@//HelloWorld:HelloWorldWatchExtension", .watchosExtension, watchOsMnemonic), + ("@@//HelloWorld:HelloWorldWatchTests", .watchosUnitTest, watchOsMnemonic), ] let result = try parser.processAquery( @@ -457,7 +475,8 @@ struct BazelTargetQuerierParserImplTests { rootUri: Self.mockRootUri, workspaceName: Self.mockWorkspaceName, executionRoot: Self.mockExecutionRoot, - outputPath: Self.mockOutputPath + outputPath: Self.mockOutputPath, + outputBase: Self.mockOutputBase ) let targetUri = try URI( diff --git a/Tests/SourceKitBazelBSPTests/BazelTargetQuerierTests.swift b/Tests/SourceKitBazelBSPTests/BazelTargetQuerierTests.swift index 20a59017..f68cd02f 100644 --- a/Tests/SourceKitBazelBSPTests/BazelTargetQuerierTests.swift +++ b/Tests/SourceKitBazelBSPTests/BazelTargetQuerierTests.swift @@ -103,7 +103,7 @@ struct BazelTargetQuerierTests { let config = Self.makeInitializedConfig() let expectedCommand = - "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)))\' --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" + "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)))\' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleCqueryOutput) _ = try querier.cqueryTargets( @@ -126,7 +126,7 @@ struct BazelTargetQuerierTests { let config = Self.makeInitializedConfig(targets: ["//HelloWorld", "//Tests"]) let expectedCommand = - "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld) union deps(//Tests)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)))\' --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" + "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld) union deps(//Tests)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)))\' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleCqueryOutput) _ = try querier.cqueryTargets( @@ -149,7 +149,7 @@ struct BazelTargetQuerierTests { let config = Self.makeInitializedConfig() let expectedCommand = - "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application|watchos_unit_test\", deps(//HelloWorld)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file|_watchos_internal_unit_test_bundle\", deps($topLevelTargets)))\' --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" + "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application|watchos_unit_test\", deps(//HelloWorld)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file|_watchos_internal_unit_test_bundle\", deps($topLevelTargets)))\' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleCqueryOutput) _ = try querier.cqueryTargets( @@ -174,7 +174,7 @@ struct BazelTargetQuerierTests { ) let expectedCommand = - "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) except set(//HelloWorld:Excluded) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)))\' --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" + "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) except set(//HelloWorld:Excluded) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)))\' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleCqueryOutput) _ = try querier.cqueryTargets( @@ -199,7 +199,7 @@ struct BazelTargetQuerierTests { ) let expectedCommand = - "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)) except set(//Libs/ExcludedLib:ExcludedLib))\' --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" + "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)) except set(//Libs/ExcludedLib:ExcludedLib))\' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleCqueryOutput) _ = try querier.cqueryTargets( @@ -225,7 +225,7 @@ struct BazelTargetQuerierTests { ) let expectedCommand = - "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) except set(//HelloWorld:Excluded //HelloWorld:AlsoExcluded) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)) except set(//Libs/ExcludedLib:ExcludedLib))\' --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" + "bazelisk --output_base=/path/to/output/base cquery \'let topLevelTargets = kind(\"ios_application\", deps(//HelloWorld)) except set(//HelloWorld:Excluded //HelloWorld:AlsoExcluded) in $topLevelTargets union (kind(\"swift_library|objc_library|cc_library|alias|filegroup|source file\", deps($topLevelTargets)) except set(//Libs/ExcludedLib:ExcludedLib))\' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleCqueryOutput) _ = try querier.cqueryTargets( @@ -250,7 +250,7 @@ struct BazelTargetQuerierTests { let config = Self.makeInitializedConfig() let expectedCommand = - "bazelisk --output_base=/path/to/output/base aquery \"mnemonic('SwiftCompile', deps(//HelloWorld:HelloWorld))\" --noinclude_artifacts --noinclude_aspects --output proto --config=test" + "bazelisk --output_base=/path/to/output/base aquery \"mnemonic('SwiftCompile', deps(//HelloWorld:HelloWorld))\" --consistent_labels --noinclude_artifacts --noinclude_aspects --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleAqueryOutput) _ = try querier.aquery( @@ -273,7 +273,7 @@ struct BazelTargetQuerierTests { let config = Self.makeInitializedConfig(targets: ["//HelloWorld", "//Tests"]) let expectedCommand = - "bazelisk --output_base=/path/to/output/base aquery \"mnemonic('SwiftCompile|ObjcCompile', deps(//HelloWorld:HelloWorld) union deps(//Tests:Tests))\" --noinclude_artifacts --noinclude_aspects --output proto --config=test" + "bazelisk --output_base=/path/to/output/base aquery \"mnemonic('SwiftCompile|ObjcCompile', deps(//HelloWorld:HelloWorld) union deps(//Tests:Tests))\" --consistent_labels --noinclude_artifacts --noinclude_aspects --output proto --config=test" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleAqueryOutput) _ = try querier.aquery( @@ -302,7 +302,7 @@ struct BazelTargetQuerierTests { ) let expectedCommand = - "bazelisk --output_base=/path/to/output/base aquery \"mnemonic('SwiftCompile', deps(//HelloWorld:HelloWorld))\" --noinclude_artifacts --noinclude_aspects --features=-compiler_param_file --output proto" + "bazelisk --output_base=/path/to/output/base aquery \"mnemonic('SwiftCompile', deps(//HelloWorld:HelloWorld))\" --consistent_labels --noinclude_artifacts --noinclude_aspects --features=-compiler_param_file --output proto" runnerMock.setResponse(for: expectedCommand, cwd: Self.mockRootUri, response: exampleAqueryOutput) _ = try querier.aquery( @@ -337,7 +337,7 @@ struct BazelTargetQuerierTests { // Second cquery: find owning targets let expectedCquery = - "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/File.swift'))\" --output=proto" + "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/File.swift'))\" --consistent_labels --output=proto" runnerMock.setResponse(for: expectedCquery, cwd: Self.mockRootUri, response: exampleCqueryAddedFilesOutput) parserMock.mockCqueryAddedFilesResult = ProcessedCqueryAddedFilesResult( @@ -379,7 +379,7 @@ struct BazelTargetQuerierTests { ) let expectedCquery = - "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/File.swift'))\" --output=proto" + "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/File.swift'))\" --consistent_labels --output=proto" runnerMock.setResponse(for: expectedCquery, cwd: Self.mockRootUri, response: exampleCqueryAddedFilesOutput) parserMock.mockCqueryAddedFilesResult = ProcessedCqueryAddedFilesResult( @@ -442,7 +442,7 @@ struct BazelTargetQuerierTests { ) let expectedCquery = - "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/File.swift'))\" --output=proto" + "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/File.swift'))\" --consistent_labels --output=proto" runnerMock.setResponse(for: expectedCquery, cwd: Self.mockRootUri, response: exampleCqueryAddedFilesOutput) parserMock.mockCqueryAddedFilesResult = ProcessedCqueryAddedFilesResult( @@ -485,7 +485,7 @@ struct BazelTargetQuerierTests { // Second cquery only includes the valid file let expectedCquery = - "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/Valid.swift'))\" --output=proto" + "bazelisk --output_base=/path/to/output/base cquery \"kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorld, '//HelloWorld:HelloWorld/Sources/Valid.swift'))\" --consistent_labels --output=proto" runnerMock.setResponse(for: expectedCquery, cwd: Self.mockRootUri, response: exampleCqueryAddedFilesOutput) parserMock.mockCqueryAddedFilesResult = ProcessedCqueryAddedFilesResult( @@ -540,7 +540,7 @@ struct BazelTargetQuerierTests { } /// Example aquery output for the example app shipped with this repo. -/// bazelisk aquery "mnemonic('CppCompile|ObjcCompile|SwiftCompile|BundleTreeApp|SignBinary|TestRunner', deps(//HelloWorld:HelloWorldMacTests) union deps(//HelloWorld:HelloWorldTests) union deps(//HelloWorld:HelloWorldLibBuildTest) union deps(//HelloWorld:HelloWorld) union deps(//HelloWorld:HelloWorldWatchExtension) union deps(//HelloWorld:HelloWorldWatchTests) union deps(//HelloWorld:HelloWorldMacCLIApp) union deps(//HelloWorld:HelloWorldMacApp) union deps(//HelloWorld:HelloWorldE2ETests) union deps(//HelloWorld:HelloWorldWatchApp))" --noinclude_artifacts --noinclude_aspects --features=-compiler_param_file --output proto --config=index_build > ../Tests/SourceKitBazelBSPTests/Resources/aquery.pb +/// bazelisk aquery "mnemonic('CppCompile|ObjcCompile|SwiftCompile|BundleTreeApp|SignBinary|TestRunner', deps(//HelloWorld:HelloWorldMacTests) union deps(//HelloWorld:HelloWorldTests) union deps(//HelloWorld:HelloWorldLibBuildTest) union deps(//HelloWorld:HelloWorld) union deps(//HelloWorld:HelloWorldWatchExtension) union deps(//HelloWorld:HelloWorldWatchTests) union deps(//HelloWorld:HelloWorldMacCLIApp) union deps(//HelloWorld:HelloWorldMacApp) union deps(//HelloWorld:HelloWorldE2ETests) union deps(//HelloWorld:HelloWorldWatchApp))" --consistent_labels --noinclude_artifacts --noinclude_aspects --features=-compiler_param_file --output proto --config=index_build > ../Tests/SourceKitBazelBSPTests/Resources/aquery.pb let exampleAqueryOutput: Data = { guard let url = Bundle.module.url(forResource: "aquery", withExtension: "pb"), let data = try? Data.init(contentsOf: url) @@ -549,7 +549,7 @@ let exampleAqueryOutput: Data = { }() /// Example cquery output for the example app shipped with this repo. -/// bazelisk cquery 'let topLevelTargets = kind("ios_application|ios_unit_test|macos_application|ios_ui_test|macos_command_line_application|macos_unit_test|watchos_application|watchos_extension|watchos_unit_test", deps(//HelloWorld/...)) in $topLevelTargets union (kind("swift_library|objc_library|cc_library|alias|filegroup|source file|_ios_internal_unit_test_bundle|_ios_internal_ui_test_bundle|_watchos_internal_unit_test_bundle|_watchos_internal_ui_test_bundle|_macos_internal_unit_test_bundle|_macos_internal_ui_test_bundle|_tvos_internal_unit_test_bundle|_tvos_internal_ui_test_bundle|_visionos_internal_unit_test_bundle|_visionos_internal_ui_test_bundle", deps($topLevelTargets)))' --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=index_build > ../Tests/SourceKitBazelBSPTests/Resources/cquery.pb +/// bazelisk cquery 'let topLevelTargets = kind("ios_application|ios_extension|ios_unit_test|macos_application|ios_ui_test|macos_command_line_application|macos_unit_test|watchos_application|watchos_extension|watchos_unit_test", deps(//HelloWorld/...)) in $topLevelTargets union (kind("swift_library|objc_library|cc_library|alias|filegroup|source file|_ios_internal_unit_test_bundle|_ios_internal_ui_test_bundle|_watchos_internal_unit_test_bundle|_watchos_internal_ui_test_bundle|_macos_internal_unit_test_bundle|_macos_internal_ui_test_bundle|_tvos_internal_unit_test_bundle|_tvos_internal_ui_test_bundle|_visionos_internal_unit_test_bundle|_visionos_internal_ui_test_bundle", deps($topLevelTargets)))' --consistent_labels --noinclude_aspects --notool_deps --noimplicit_deps --output proto --config=index_build > ../Tests/SourceKitBazelBSPTests/Resources/cquery.pb let exampleCqueryOutput: Data = { guard let url = Bundle.module.url(forResource: "cquery", withExtension: "pb"), let data = try? Data.init(contentsOf: url) @@ -558,7 +558,7 @@ let exampleCqueryOutput: Data = { }() /// Example cquery output for an added file event, for the example app shipped with this repo. -/// bazelisk cquery "kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorldLibBuildTest, '//HelloWorld:HelloWorldLib/Sources/TodoItemRow.swift'))" --output=proto --config=index_build > cquery_added_files.pb +/// bazelisk cquery "kind('swift_library|objc_library|cc_library|source file', rdeps(//HelloWorld:HelloWorldLibBuildTest, '//HelloWorld:HelloWorldLib/Sources/TodoItemRow.swift'))" --consistent_labels --output=proto --config=index_build > ../Tests/SourceKitBazelBSPTests/Resources/cquery_added_files.pb let exampleCqueryAddedFilesOutput: Data = { guard let url = Bundle.module.url(forResource: "cquery_added_files", withExtension: "pb"), let data = try? Data.init(contentsOf: url) diff --git a/Tests/SourceKitBazelBSPTests/Fakes/BazelTargetQuerierParserFake.swift b/Tests/SourceKitBazelBSPTests/Fakes/BazelTargetQuerierParserFake.swift index 94b6047b..9308118b 100644 --- a/Tests/SourceKitBazelBSPTests/Fakes/BazelTargetQuerierParserFake.swift +++ b/Tests/SourceKitBazelBSPTests/Fakes/BazelTargetQuerierParserFake.swift @@ -35,7 +35,8 @@ final class BazelTargetQuerierParserFake: BazelTargetQuerierParser { workspaceName: String, executionRoot: String, toolchainPath: String, - outputPath: String + outputPath: String, + outputBase: String ) throws -> ProcessedCqueryResult { guard let mockCqueryResult else { unimplemented() @@ -59,7 +60,8 @@ final class BazelTargetQuerierParserFake: BazelTargetQuerierParser { rootUri: String, workspaceName: String, executionRoot: String, - outputPath: String + outputPath: String, + outputBase: String ) throws -> ProcessedCqueryAddedFilesResult { guard let mockCqueryAddedFilesResult else { unimplemented() diff --git a/Tests/SourceKitBazelBSPTests/IsExternalBazelLabelTests.swift b/Tests/SourceKitBazelBSPTests/IsExternalBazelLabelTests.swift new file mode 100644 index 00000000..44bfa66f --- /dev/null +++ b/Tests/SourceKitBazelBSPTests/IsExternalBazelLabelTests.swift @@ -0,0 +1,81 @@ +// Copyright (c) 2025 Spotify AB. +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import Foundation +import Testing + +@testable import SourceKitBazelBSP + +@Suite +struct IsExternalBazelLabelTests { + @Test + func internalLabelWithoutAtPrefix() { + #expect("//foo/bar:target".isExternalBazelLabel() == false) + } + + @Test + func internalLabelWithSingleAtPrefix() { + #expect("@//foo/bar:target".isExternalBazelLabel() == false) + } + + @Test + func internalLabelWithDoubleAtPrefix() { + #expect("@@//foo/bar:target".isExternalBazelLabel() == false) + } + + @Test + func relativeLabel() { + #expect(":target".isExternalBazelLabel() == false) + } + + @Test + func externalRepoLabel() { + #expect("@external_repo//foo:bar".isExternalBazelLabel() == true) + } + + @Test + func bzlmodExternalRepoLabel() { + #expect("@@external_repo//foo:bar".isExternalBazelLabel() == true) + } + + @Test + func externalRepoWithoutPath() { + #expect("@external_repo".isExternalBazelLabel() == true) + } + + @Test + func emptyString() { + #expect("".isExternalBazelLabel() == false) + } + + @Test + func singleAtOnly() { + #expect("@".isExternalBazelLabel() == false) + } + + @Test + func doubleAtOnly() { + #expect("@@".isExternalBazelLabel() == false) + } + + @Test + func tripleAtExternalLabel() { + #expect("@@@repo//foo:bar".isExternalBazelLabel() == true) + } +} diff --git a/Tests/SourceKitBazelBSPTests/Resources/aquery.pb b/Tests/SourceKitBazelBSPTests/Resources/aquery.pb index 89859257..d38a9861 100644 --- a/Tests/SourceKitBazelBSPTests/Resources/aquery.pb +++ b/Tests/SourceKitBazelBSPTests/Resources/aquery.pb @@ -1,51 +1,34 @@ -:macos_unit_test%//HelloWorld:HelloWorldMacTests*ddarwin_arm64-dbg darwin_arm64"@8ca5719d3aebee816bfbdd62eebb094f9da7c732ea68a510daa94c71b5755dfa@7b0fa2f5f5281dece03101911f9e8c1767cc826c6fc7702a48c93b264fe4a482" +:macos_unit_test%//HelloWorld:HelloWorldMacTests:$ _macos_internal_unit_test_bundle@://HelloWorld:HelloWorldMacTests.__internal__.__test_bundle*ddarwin_arm64-dbg darwin_arm64"@8f8065ccdaf2ad454bef6a50ad79bd342ec9e30167243d1ba692d949137105ce*4darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6 darwin_arm64"@dbb22fcdc944be2a78ad10c439902582f287080907077da05b721220f629e229@7b0fa2f5f5281dece03101911f9e8c1767cc826c6fc7702a48c93b264fe4a482" TestRunner(2-external/bazel_tools/tools/test/test-setup.sh2HelloWorld/HelloWorldMacTestsZ -requires-darwinr@@platforms//host:host: objc_libraryB<@@apple_support+//lib:swizzle_absolute_xcttestsourcelocation: swift_library//HelloWorld:MacAppLib//HelloWorld:TodoModels!//HelloWorld:MacAppTestsLib:  cc_binary60@@bazel_tools//src/tools/launcher:launcher_maker:$ _macos_internal_unit_test_bundle@://HelloWorld:HelloWorldMacTests.__internal__.__test_bundle)#@@rules_swift+//tools/worker:worker*4darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6 darwin_arm64"@621a57d318bdd1dc251eb99951e606d2bb8cc4132aa1df6bd16a0528636c3de8@305881d93402e66176a8b465ebe2619556af3ab1502a9c1e063e4e6352b827d2" SwiftCompile(2]bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/worker2swiftc2-target2arm64-apple-macos15.02-sdk2__BAZEL_XCODE_SDKROOT__2-file-prefix-map28__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2=-Xwrapped-swift=-bazel-target-label=@@//HelloWorld:TodoModels2 -emit-object2-output-file-map2mbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.output_file_map.json2 --Xfrontend2-no-clang-module-breadcrumbs2-emit-module-path2dbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.swiftmodule2-enforce-exclusivity=checked2-emit-const-values-path2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels_objs/TodoModels/Sources/TodoItem.swift.swiftconstvalues2 --Xfrontend2-const-gather-protocols-file2 --Xfrontend2Lexternal/rules_swift+/swift/toolchains/config/const_protocols_to_gather.json2-DDEBUG2-Onone2 --Xfrontend2-internalize-at-link2 --Xfrontend2-no-serialize-debugging-options2-enable-testing2-disable-sandbox2-g2'-Xwrapped-swift=-file-prefix-pwd-is-dot2%-Xwrapped-swift=-emit-swiftsourceinfo2-file-compilation-dir2.2-module-cache-path2Vbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/_swift_module_cache2-Xwrapped-swift=-macro-expansion-dir=bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.macro-expansions2-Xcc2-iquote.2-Xcc2I-iquotebazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin2 --Xfrontend2-color-diagnostics2-enable-batch-mode2 -module-name2 -TodoModels2-index-store-path2cbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.indexstore2-index-ignore-system-modules2-enable-bare-slash-regex2 --Xfrontend2-disable-clang-spi2-enable-experimental-feature2AccessLevelOnImport2-parse-as-library2-static2-Xcc2-O02-Xcc2 -DDEBUG=12-Xcc2-fstack-protector2-Xcc2-fstack-protector-all2 --Xfrontend2-checked-async-objc-bridging=on2,HelloWorld/TodoModels/Sources/TodoItem.swift23HelloWorld/TodoModels/Sources/TodoListManager.swift:' -XCODE_VERSION_OVERRIDE 26.1.1.17B100: -APPLE_SDK_PLATFORMMacOSX:" -APPLE_SDK_VERSION_OVERRIDE26.1Z -requires-darwinZ -requires-worker-protocoljsonZ -supports-workers1Z! -supports-xcode-requirements-setr@@platforms//host:host@3b41d77e3680170ba4ab7e371e7be938acf1e3327abd7fc52966e6e9d3745f90" SwiftCompile(2]bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/worker2swiftc2-target2arm64-apple-macos15.02-sdk2__BAZEL_XCODE_SDKROOT__2-file-prefix-map28__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2<-Xwrapped-swift=-bazel-target-label=@@//HelloWorld:MacAppLib2 -emit-object2-output-file-map2lbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppLib.output_file_map.json2 --Xfrontend2-no-clang-module-breadcrumbs2-emit-module-path2cbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppLib.swiftmodule2-enforce-exclusivity=checked2-emit-const-values-path2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppLib_objs/MacApp/MacAppLib/Sources/MacApp.swift.swiftconstvalues2 --Xfrontend2-const-gather-protocols-file2 --Xfrontend2Lexternal/rules_swift+/swift/toolchains/config/const_protocols_to_gather.json2-DDEBUG2-Onone2 --Xfrontend2-internalize-at-link2 --Xfrontend2-no-serialize-debugging-options2-enable-testing2-disable-sandbox2-g2'-Xwrapped-swift=-file-prefix-pwd-is-dot2%-Xwrapped-swift=-emit-swiftsourceinfo2-file-compilation-dir2.2-module-cache-path2Vbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/_swift_module_cache2O-Ibazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld2-Xwrapped-swift=-macro-expansion-dir=bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppLib.macro-expansions2-Xcc2-iquote.2-Xcc2I-iquotebazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin2 --Xfrontend2-color-diagnostics2-enable-batch-mode2 -module-name2 MacAppLib2-index-store-path2bbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppLib.indexstore2-index-ignore-system-modules2-enable-bare-slash-regex2 --Xfrontend2-disable-clang-spi2-enable-experimental-feature2AccessLevelOnImport2-parse-as-library2-static2-Xcc2-O02-Xcc2 -DDEBUG=12-Xcc2-fstack-protector2-Xcc2-fstack-protector-all2 --Xfrontend2-checked-async-objc-bridging=on20HelloWorld/MacApp/MacAppLib/Sources/MacApp.swift:' -XCODE_VERSION_OVERRIDE 26.1.1.17B100: -APPLE_SDK_PLATFORMMacOSX:" -APPLE_SDK_VERSION_OVERRIDE26.1Z -requires-darwinZ -requires-worker-protocoljsonZ -supports-workers1Z! -supports-xcode-requirements-setr@@platforms//host:host*{%darwin_arm64-opt-exec-ST-d57f47055a04 darwin_arm64"@ce3fb6fae2997484cd84f6aa36507b231b4f702e38f5aed65831c7030dab9c62(@e5a18b0250f4a457e3a3ff2c5319847d32c75100c3585954b62a80f9db9a48c1" BundleTreeApp(2rbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_apple+/tools/bundletool/bundletool_experimental2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/HelloWorldMacTests.__internal__.__test_bundle-intermediates/bundletool_control.json:' +requires-darwinr@@platforms//host:host@e5a18b0250f4a457e3a3ff2c5319847d32c75100c3585954b62a80f9db9a48c1" BundleTreeApp(2rbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_apple+/tools/bundletool/bundletool_experimental2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/HelloWorldMacTests.__internal__.__test_bundle-intermediates/bundletool_control.json:' XCODE_VERSION_OVERRIDE 26.1.1.17B100: APPLE_SDK_PLATFORMMacOSX:" APPLE_SDK_VERSION_OVERRIDE26.1Z no-sandbox1Z requires-darwinZ! -supports-xcode-requirements-setr@@platforms//host:host: -cc_library6 0@@rules_swift+//tools/worker:compile_with_worker@093f80d28e6a1cde5c7bf09519ef45dd303dabd15f27b00ed8f3fe355f03d6c8" SwiftCompile(2]bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/worker2swiftc2-target2arm64-apple-macos15.02-sdk2__BAZEL_XCODE_SDKROOT__2-file-prefix-map28__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2A-Xwrapped-swift=-bazel-target-label=@@//HelloWorld:MacAppTestsLib2 -emit-object2-output-file-map2qbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppTestsLib.output_file_map.json2 +supports-xcode-requirements-setr@@platforms//host:host: objc_libraryB<@@apple_support+//lib:swizzle_absolute_xcttestsourcelocation@d192ff49785fd9c228648fca03ba4dc099d0fa6f9d6e254a7c456afa578647c3" ObjcCompile(2cbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g2--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-Werror=incompatible-sysroot2-Wshorten-64-to-322-Wbool-conversion2-Wconstant-conversion2-Wduplicate-method-match2 -Wempty-body2-Wenum-conversion2-Wint-conversion2-Wunreachable-code2-Wmismatched-return-types2-Wundeclared-selector2-Wuninitialized2-Wunused-function2-Wunused-variable2-iquote2external/apple_support+2-iquote2Zbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/external/apple_support+2-MD2-MF2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/external/apple_support+/lib/_objs/swizzle_absolute_xcttestsourcelocation/arc/swizzle_absolute_xcttestsourcelocation.d2 -DOS_MACOSX2 -fno-autolink2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2 +-fobjc-arc2-no-canonical-prefixes2-target2arm64-apple-macosx15.02-O02 -DDEBUG=12-fstack-protector2-fstack-protector-all2-g2-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c2Dexternal/apple_support+/lib/swizzle_absolute_xcttestsourcelocation.m2-o2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/external/apple_support+/lib/_objs/swizzle_absolute_xcttestsourcelocation/arc/swizzle_absolute_xcttestsourcelocation.o:' +XCODE_VERSION_OVERRIDE 26.1.1.17B100:" +APPLE_SDK_VERSION_OVERRIDE26.1: +APPLE_SDK_PLATFORMMacOSX: + ZERO_AR_DATE1PZ +requires-darwinZ! +supports-xcode-requirements-setr@@platforms//host:host: swift_library!//HelloWorld:MacAppTestsLib//HelloWorld:MacAppLib//HelloWorld:TodoModels:  cc_binary60@@bazel_tools//src/tools/launcher:launcher_maker*{%darwin_arm64-opt-exec-ST-d57f47055a04 darwin_arm64"@ce3fb6fae2997484cd84f6aa36507b231b4f702e38f5aed65831c7030dab9c62( @223c0ee7c56659ba24a7fd11b26f535736284219ce14cbdfa0b1b8106fda2fc6" +CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang_pp2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g02-O22-DNDEBUG2-DNS_BLOCK_ASSERTIONS=12--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-iquote2external/bazel_tools2-iquote2Hbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/bazel_tools2-MD2-MF2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/bazel_tools/src/tools/launcher/_objs/launcher_maker/launcher_maker.d2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2-no-canonical-prefixes2-target2arm64-apple-macosx26.12 +-std=c++172-g02-g02-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c29external/bazel_tools/src/tools/launcher/launcher_maker.cc2-o2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/bazel_tools/src/tools/launcher/_objs/launcher_maker/launcher_maker.o:' +XCODE_VERSION_OVERRIDE 26.1.1.17B100:" +APPLE_SDK_VERSION_OVERRIDE26.1: +APPLE_SDK_PLATFORMMacOSX: + ZERO_AR_DATE1PZ +requires-darwinZ! +supports-xcode-requirements-setr@@platforms//host:host@29934410bfae259701556170fa39d8c7f902013078217587d9fba66b8f00a318" SwiftCompile(2]bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/worker2swiftc2-target2arm64-apple-macos15.02-sdk2__BAZEL_XCODE_SDKROOT__2-file-prefix-map28__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2A-Xwrapped-swift=-bazel-target-label=@@//HelloWorld:MacAppTestsLib2 -emit-object2-output-file-map2qbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppTestsLib.output_file_map.json2 -Xfrontend2-no-clang-module-breadcrumbs2-emit-module-path2hbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppTestsLib.swiftmodule2-enforce-exclusivity=checked2-emit-const-values-path2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppTestsLib_objs/MacApp/MacAppTests/TodoItemMacTests.swift.swiftconstvalues2 -Xfrontend2-const-gather-protocols-file2 -Xfrontend2Lexternal/rules_swift+/swift/toolchains/config/const_protocols_to_gather.json2-DDEBUG2-Onone2 -Xfrontend2-internalize-at-link2 -Xfrontend2-no-serialize-debugging-options2-enable-testing2-disable-sandbox2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2K-I__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/usr/lib2-g2'-Xwrapped-swift=-file-prefix-pwd-is-dot2%-Xwrapped-swift=-emit-swiftsourceinfo2-file-compilation-dir2.2-module-cache-path2Vbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/_swift_module_cache2O-Ibazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld2-Xwrapped-swift=-macro-expansion-dir=bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppTestsLib.macro-expansions2 -plugin-path2A__BAZEL_SWIFT_TOOLCHAIN_PATH__/usr/lib/swift/host/plugins/testing2-Xcc2-iquote.2-Xcc2I-iquotebazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin2 --Xfrontend2-color-diagnostics2-enable-batch-mode2 -module-name2MacAppTestsLib2-index-store-path2gbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppTestsLib.indexstore2-index-ignore-system-modules2-enable-bare-slash-regex2 +-Xfrontend2-color-diagnostics2-enable-batch-mode2 -module-name2MacAppTestsLib2-index-store-path2gbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/MacAppTestsLib.indexstore2-index-ignore-system-modules2M-Xwrapped-swift=-global-index-store-import-path=bazel-out/_global_index_store2-enable-bare-slash-regex2 -Xfrontend2-disable-clang-spi2-enable-experimental-feature2AccessLevelOnImport2-parse-as-library2-static2-Xcc2-O02-Xcc2 -DDEBUG=12-Xcc2-fstack-protector2-Xcc2-fstack-protector-all2 -Xfrontend2-checked-async-objc-bridging=on24HelloWorld/MacApp/MacAppTests/TodoItemMacTests.swift:' XCODE_VERSION_OVERRIDE 26.1.1.17B100: @@ -54,23 +37,8 @@ cc_library6 0@@rules_swift+//tools/worker:compile_with_worker requires-darwinZ requires-worker-protocoljsonZ supports-workers1Z! -supports-xcode-requirements-setr@@platforms//host:host @223c0ee7c56659ba24a7fd11b26f535736284219ce14cbdfa0b1b8106fda2fc6" -CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang_pp2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g02-O22-DNDEBUG2-DNS_BLOCK_ASSERTIONS=12--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-iquote2external/bazel_tools2-iquote2Hbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/bazel_tools2-MD2-MF2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/bazel_tools/src/tools/launcher/_objs/launcher_maker/launcher_maker.d2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2-no-canonical-prefixes2-target2arm64-apple-macosx26.12 --std=c++172-g02-g02-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c29external/bazel_tools/src/tools/launcher/launcher_maker.cc2-o2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/bazel_tools/src/tools/launcher/_objs/launcher_maker/launcher_maker.o:' -XCODE_VERSION_OVERRIDE 26.1.1.17B100:" -APPLE_SDK_VERSION_OVERRIDE26.1: -APPLE_SDK_PLATFORMMacOSX: - ZERO_AR_DATE1PZ -requires-darwinZ! -supports-xcode-requirements-setr@@platforms//host:host@c99269b38bb31b914c97264933ab81f1b783be9579784a83421fa52ae3799e92" -CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang_pp2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g02-O22-DNDEBUG2-DNS_BLOCK_ASSERTIONS=12--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-iquote2external/rules_swift+2-iquote2Ibazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+2-iquote2external/nlohmann_json+2-iquote2Kbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+2-iquote2external/bazel_tools2-iquote2Hbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/bazel_tools2-iquote2external/rules_cc+2-iquote2Fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_cc+2o-Ibazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_cc+/cc/runfiles/_virtual_includes/runfiles2-isystem2external/nlohmann_json+/include2-isystem2Sbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+/include2-MD2-MF2qbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/_objs/worker/worker_main.d2)-DBAZEL_CURRENT_REPOSITORY="rules_swift+"2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2-no-canonical-prefixes2-target2arm64-apple-macosx26.12 --std=c++172-g02-g02-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c21external/rules_swift+/tools/worker/worker_main.cc2-o2qbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/_objs/worker/worker_main.o:' -XCODE_VERSION_OVERRIDE 26.1.1.17B100:" -APPLE_SDK_VERSION_OVERRIDE26.1: -APPLE_SDK_PLATFORMMacOSX: - ZERO_AR_DATE1PZ -requires-darwinZ! -supports-xcode-requirements-setr@@platforms//host:host  @b0645c6f78bb79d8cb3f629ddc265b8b12a30d25f7c558fdeb91ac9e760c7887" +supports-xcode-requirements-setr@@platforms//host:host: +cc_library60@@rules_swift+//tools/worker:compile_with_worker @b0645c6f78bb79d8cb3f629ddc265b8b12a30d25f7c558fdeb91ac9e760c7887" CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang_pp2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g02-O22-DNDEBUG2-DNS_BLOCK_ASSERTIONS=12--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-iquote2external/rules_swift+2-iquote2Ibazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+2-iquote2external/nlohmann_json+2-iquote2Kbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+2-isystem2external/nlohmann_json+/include2-isystem2Sbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+/include2-MD2-MF2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/_objs/compile_with_worker/compile_with_worker.d2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2-no-canonical-prefixes2-target2arm64-apple-macosx26.12 -std=c++172-g02-g02 -std=c++172-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c29external/rules_swift+/tools/worker/compile_with_worker.cc2-o2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/_objs/compile_with_worker/compile_with_worker.o:' @@ -79,8 +47,24 @@ CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple APPLE_SDK_PLATFORMMacOSX: ZERO_AR_DATE1PZ requires-darwinZ! +supports-xcode-requirements-setr@@platforms//host:host) #@@rules_swift+//tools/worker:worker@e832360303b903ecc2faf3fecfd6bbc1a59a17c943bd8b8374d4fe220e63aa8c" SwiftCompile(2]bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/worker2swiftc2-target2arm64-apple-macos15.02-sdk2__BAZEL_XCODE_SDKROOT__2-file-prefix-map28__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2=-Xwrapped-swift=-bazel-target-label=@@//HelloWorld:TodoModels2 -emit-object2-output-file-map2mbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.output_file_map.json2 +-Xfrontend2-no-clang-module-breadcrumbs2-emit-module-path2dbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.swiftmodule2-enforce-exclusivity=checked2-emit-const-values-path2bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels_objs/TodoModels/Sources/TodoItem.swift.swiftconstvalues2 +-Xfrontend2-const-gather-protocols-file2 +-Xfrontend2Lexternal/rules_swift+/swift/toolchains/config/const_protocols_to_gather.json2-DDEBUG2-Onone2 +-Xfrontend2-internalize-at-link2 +-Xfrontend2-no-serialize-debugging-options2-enable-testing2-disable-sandbox2-g2'-Xwrapped-swift=-file-prefix-pwd-is-dot2%-Xwrapped-swift=-emit-swiftsourceinfo2-file-compilation-dir2.2-module-cache-path2Vbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/_swift_module_cache2-Xwrapped-swift=-macro-expansion-dir=bazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.macro-expansions2-Xcc2-iquote.2-Xcc2I-iquotebazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin2 +-Xfrontend2-color-diagnostics2-enable-batch-mode2 -module-name2 +TodoModels2-index-store-path2cbazel-out/darwin_arm64-dbg-macos-arm64-min15.0-ST-3b9f41d61db6/bin/HelloWorld/TodoModels.indexstore2-index-ignore-system-modules2M-Xwrapped-swift=-global-index-store-import-path=bazel-out/_global_index_store2-enable-bare-slash-regex2 +-Xfrontend2-disable-clang-spi2-enable-experimental-feature2AccessLevelOnImport2-parse-as-library2-static2-Xcc2-O02-Xcc2 -DDEBUG=12-Xcc2-fstack-protector2-Xcc2-fstack-protector-all2 +-Xfrontend2-checked-async-objc-bridging=on2,HelloWorld/TodoModels/Sources/TodoItem.swift23HelloWorld/TodoModels/Sources/TodoListManager.swift:' +XCODE_VERSION_OVERRIDE 26.1.1.17B100: +APPLE_SDK_PLATFORMMacOSX:" +APPLE_SDK_VERSION_OVERRIDE26.1Z +requires-darwinZ +requires-worker-protocoljsonZ +supports-workers1Z! supports-xcode-requirements-setr@@platforms//host:host9 -3@@rules_swift+//tools/worker:compile_without_worker  @73359a8c89aa3546b9e6f302910141d4a6726acc9c75cf4e84945d51f4cfb5f4" +3@@rules_swift+//tools/worker:compile_without_worker @73359a8c89aa3546b9e6f302910141d4a6726acc9c75cf4e84945d51f4cfb5f4" CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang_pp2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g02-O22-DNDEBUG2-DNS_BLOCK_ASSERTIONS=12--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-iquote2external/rules_swift+2-iquote2Ibazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+2-iquote2external/nlohmann_json+2-iquote2Kbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+2-isystem2external/nlohmann_json+/include2-isystem2Sbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+/include2-MD2-MF2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/_objs/compile_with_worker/work_processor.d2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2-no-canonical-prefixes2-target2arm64-apple-macosx26.12 -std=c++172-g02-g02 -std=c++172-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c24external/rules_swift+/tools/worker/work_processor.cc2-o2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/_objs/compile_with_worker/work_processor.o:' @@ -89,24 +73,40 @@ CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple APPLE_SDK_PLATFORMMacOSX: ZERO_AR_DATE1PZ requires-darwinZ! -supports-xcode-requirements-setr@@platforms//host:host' !@@rules_cc+//cc/runfiles:runfiles/ )@@rules_swift+//tools/worker:swift_runner2 ,@@rules_swift+//tools/worker:worker_protocol*$@@rules_swift+//tools/common:process  @b50463ed3410f18396872bc907644f6000121937d5ebc87c0938879c7cd5df6d" -CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang_pp2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g02-O22-DNDEBUG2-DNS_BLOCK_ASSERTIONS=12--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-iquote2external/rules_cc+2-iquote2Fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_cc+2o-Ibazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_cc+/cc/runfiles/_virtual_includes/runfiles2-MD2-MF2lbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_cc+/cc/runfiles/_objs/runfiles/runfiles.d2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2-no-canonical-prefixes2-target2arm64-apple-macosx26.12 --std=c++172-g02-g02-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c2*external/rules_cc+/cc/runfiles/runfiles.cc2-o2lbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_cc+/cc/runfiles/_objs/runfiles/runfiles.o:' +supports-xcode-requirements-setr@@platforms//host:host +@38e8c492a631ecdcb5c24e04119d68386981044455cf384a40ce55391c99f043" +CppCompile(2fbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/apple_support+/crosstool/wrapped_clang_pp2-D_FORTIFY_SOURCE=12-fstack-protector2-fcolor-diagnostics2-Wall2-Wthread-safety2 -Wself-assign2-fno-omit-frame-pointer2-g02-O22-DNDEBUG2-DNS_BLOCK_ASSERTIONS=12--fdebug-prefix-map=__BAZEL_EXECUTION_ROOT__=.2K-fdebug-prefix-map=__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2-iquote2external/rules_swift+2-iquote2Ibazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+2-iquote2external/nlohmann_json+2-iquote2Kbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+2-isystem2external/nlohmann_json+/include2-isystem2Sbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/nlohmann_json+/include2-MD2-MF2bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/_objs/compile_without_worker/compile_without_worker.d2 -isysroot2__BAZEL_XCODE_SDKROOT__23-F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks2V-F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks2-no-canonical-prefixes2-target2arm64-apple-macosx26.12 +-std=c++172-g02-g02 +-std=c++172-Wno-builtin-macro-redefined2-D__DATE__="redacted"2-D__TIMESTAMP__="redacted"2-D__TIME__="redacted"2-c2-Xwrapped-swift=-bazel-target-label=@@//HelloWorld:WatchAppLib2 -emit-object2-output-file-map2pbazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld/WatchAppLib.output_file_map.json2 +supports-xcode-requirements-setr@@platforms//host:host @4aa89ea179ff491918b7e5bd9f948c4a96730aad68d4a32e9ac20dff27d54f9c" SwiftCompile(2]bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_swift+/tools/worker/worker2swiftc2-target2 arm64-apple-watchos7.0-simulator2-sdk2__BAZEL_XCODE_SDKROOT__2-file-prefix-map28__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR2>-Xwrapped-swift=-bazel-target-label=@@//HelloWorld:WatchAppLib2 -emit-object2-output-file-map2pbazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld/WatchAppLib.output_file_map.json2 -Xfrontend2-no-clang-module-breadcrumbs2-emit-module-path2gbazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld/WatchAppLib.swiftmodule2-enforce-exclusivity=checked2-emit-const-values-path2bazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld/WatchAppLib_objs/WatchApp/WatchAppLib/Sources/WatchApp.swift.swiftconstvalues2 -Xfrontend2-const-gather-protocols-file2 -Xfrontend2Lexternal/rules_swift+/swift/toolchains/config/const_protocols_to_gather.json2-DDEBUG2-Onone2 -Xfrontend2-internalize-at-link2 -Xfrontend2-no-serialize-debugging-options2-enable-testing2-disable-sandbox2-g2'-Xwrapped-swift=-file-prefix-pwd-is-dot2%-Xwrapped-swift=-emit-swiftsourceinfo2-file-compilation-dir2.2-module-cache-path2Xbazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/_swift_module_cache2Q-Ibazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld2-Xwrapped-swift=-macro-expansion-dir=bazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld/WatchAppLib.macro-expansions2-Xcc2-iquote.2-Xcc2K-iquotebazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin2 --Xfrontend2-color-diagnostics2-enable-batch-mode2 -module-name2 WatchAppLib2-index-store-path2fbazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld/WatchAppLib.indexstore2-index-ignore-system-modules2-enable-bare-slash-regex2 +-Xfrontend2-color-diagnostics2-enable-batch-mode2 -module-name2 WatchAppLib2-index-store-path2fbazel-out/watchos_arm64-dbg-watchos-arm64-min7.0-ST-f4f2bb7e56ed/bin/HelloWorld/WatchAppLib.indexstore2-index-ignore-system-modules2M-Xwrapped-swift=-global-index-store-import-path=bazel-out/_global_index_store2-enable-bare-slash-regex2 -Xfrontend2-disable-clang-spi2-enable-experimental-feature2AccessLevelOnImport2-parse-as-library2-static2-Xcc2-O02-Xcc2 -DDEBUG=12-Xcc2-fstack-protector2-Xcc2-fstack-protector-all2 -Xfrontend2-checked-async-objc-bridging=on26HelloWorld/WatchApp/WatchAppLib/Sources/WatchApp.swift:' XCODE_VERSION_OVERRIDE 26.1.1.17B100:$ @@ -386,20 +336,78 @@ TodoModels2-index-store-path2ebazel-out/watchos_arm64-dbg-watchos-arm64-min7.0- requires-darwinZ requires-worker-protocoljsonZ supports-workers1Z! -supports-xcode-requirements-setr@@platforms//host:host#//HelloWorld:WatchAppTestsLib$@c1996ae5370f8613a7a4f8da98728adf3db32fc5707677e8a7ffe85e162c90ae" BundleTreeApp(2rbazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/rules_apple+/tools/bundletool/bundletool_experimental2bazel-out/ios_sim_arm64-dbg-ios-sim_arm64-min17.0-ST-2842469f5300/bin/HelloWorld/HelloWorldE2ETests.__internal__.__test_bundle-intermediates/bundletool_control.json:' +supports-xcode-requirements-setr@@platforms//host:host:&"_watchos_internal_unit_test_bundleB!