Repository: cpisciotta/xcbeautify
Pull request #359 (2025-01-21 20:01:35)

Add SwiftMergeGeneratedHeadersCaptureGroup

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/cpisciotta/xcbeautify/pull/359?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Pisciotta) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 89.95%. Comparing base [(`d5a29fc`)](https://app.codecov.io/gh/cpisciotta/xcbeautify/commit/d5a29fcc952f29ac70537a07d2a7181b052aa870?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Pisciotta) to head [(`44defca`)](https://app.codecov.io/gh/cpisciotta/xcbeautify/commit/44defca1e0cc88d817778e31cf721976456edaa8?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Pisciotta).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #359      +/-   ##
==========================================
+ Coverage   89.89%   89.95%   +0.06%     
==========================================
  Files          17       17              
  Lines        2404     2420      +16     
==========================================
+ Hits         2161     2177      +16     
  Misses        243      243              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/cpisciotta/xcbeautify/pull/359?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Pisciotta).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Pisciotta).


Patch:
diff --git a/Sources/XcbeautifyLib/CaptureGroups.swift b/Sources/XcbeautifyLib/CaptureGroups.swift
index 63fb6cb..84b513a 100644
--- a/Sources/XcbeautifyLib/CaptureGroups.swift
+++ b/Sources/XcbeautifyLib/CaptureGroups.swift
@@ -1947,6 +1947,29 @@ struct SwiftDriverJobDiscoveryCompilingCaptureGroup: CaptureGroup {
     }
 }
 
+struct SwiftMergeGeneratedHeadersCaptureGroup: CaptureGroup {
+    static let outputType: OutputType = .task
+
+    static let regex = XCRegex(pattern: #"^SwiftMergeGeneratedHeaders (.+) \(in target '(.+)' from project '(.+)'\)$"#)
+
+    // TODO: Split this into String array after requiring macOS 13+
+    // Requires: https://github.com/cpisciotta/xcbeautify/issues/358
+    let headerFilePaths: String
+    let target: String
+    let project: String
+
+    init?(groups: [String]) {
+        assert(groups.count == 3)
+        guard let headerFilePaths = groups[safe: 0], let target = groups[safe: 1], let project = groups[safe: 2] else { return nil }
+        // TODO: Split headerFilePaths by non-escaped whitespace
+        // Requires: https://github.com/cpisciotta/xcbeautify/issues/358
+        // assert(headerFilePaths.allSatisfy { $0.hasSuffix(".h") })
+        self.headerFilePaths = headerFilePaths
+        self.target = target
+        self.project = project
+    }
+}
+
 struct SwiftTestingRunStartedCaptureGroup: CaptureGroup {
     static let outputType: OutputType = .result
 
diff --git a/Sources/XcbeautifyLib/Formatter.swift b/Sources/XcbeautifyLib/Formatter.swift
index 1db1386..f22bf45 100644
--- a/Sources/XcbeautifyLib/Formatter.swift
+++ b/Sources/XcbeautifyLib/Formatter.swift
@@ -226,6 +226,8 @@ package struct Formatter {
             return renderer.formatSwiftDriverJobDiscoveryCompiling(group: group)
         case let group as SwiftEmitModuleCaptureGroup:
             return renderer.formatSwiftEmitModule(group: group)
+        case let group as SwiftMergeGeneratedHeadersCaptureGroup:
+            return renderer.formatSwiftMergeGeneratedHeaders(group: group)
         case let group as TestingStartedCaptureGroup:
             return renderer.formatTestingStarted(group: group)
         case let group as SwiftTestingRunStartedCaptureGroup:
diff --git a/Sources/XcbeautifyLib/Parser.swift b/Sources/XcbeautifyLib/Parser.swift
index 46141d5..b3ad3c9 100644
--- a/Sources/XcbeautifyLib/Parser.swift
+++ b/Sources/XcbeautifyLib/Parser.swift
@@ -108,6 +108,7 @@ package final class Parser {
         TestSuiteAllTestsFailedCaptureGroup.self,
         TestingStartedCaptureGroup.self,
         SwiftEmitModuleCaptureGroup.self,
+        SwiftMergeGeneratedHeadersCaptureGroup.self,
         SwiftTestingRunStartedCaptureGroup.self,
         SwiftTestingRunCompletionCaptureGroup.self,
         SwiftTestingRunFailedCaptureGroup.self,
diff --git a/Sources/XcbeautifyLib/Renderers/OutputRendering.swift b/Sources/XcbeautifyLib/Renderers/OutputRendering.swift
index 80ff9c6..305d6ef 100644
--- a/Sources/XcbeautifyLib/Renderers/OutputRendering.swift
+++ b/Sources/XcbeautifyLib/Renderers/OutputRendering.swift
@@ -92,6 +92,7 @@ protocol OutputRendering {
     func formatTestingStarted(group: TestingStartedCaptureGroup) -> String
     func formatSwiftDriverJobDiscoveryCompiling(group: SwiftDriverJobDiscoveryCompilingCaptureGroup) -> String?
     func formatSwiftEmitModule(group: SwiftEmitModuleCaptureGroup) -> String?
+    func formatSwiftMergeGeneratedHeaders(group: SwiftMergeGeneratedHeadersCaptureGroup) -> String?
     func formatSwiftTestingRunStarted(group: SwiftTestingRunStartedCaptureGroup) -> String
     func formatSwiftTestingRunCompletion(group: SwiftTestingRunCompletionCaptureGroup) -> String
     func formatSwiftTestingRunFailed(group: SwiftTestingRunFailedCaptureGroup) -> String
@@ -621,6 +622,10 @@ extension OutputRendering {
         nil
     }
 
+    func formatSwiftMergeGeneratedHeaders(group: SwiftMergeGeneratedHeadersCaptureGroup) -> String? {
+        nil
+    }
+
     func formatSwiftTestingRunStarted(group: SwiftTestingRunStartedCaptureGroup) -> String {
         colored ? group.message.s.Bold : group.message
     }


Test patch:
diff --git a/Tests/XcbeautifyLibTests/CaptureGroupTests.swift b/Tests/XcbeautifyLibTests/CaptureGroupTests.swift
index 47f769b..716db69 100644
--- a/Tests/XcbeautifyLibTests/CaptureGroupTests.swift
+++ b/Tests/XcbeautifyLibTests/CaptureGroupTests.swift
@@ -71,6 +71,15 @@ final class CaptureGroupTests: XCTestCase {
         XCTAssertEqual(groups[2], "Project")
     }
 
+    func testSwiftMergeGeneratedHeadersCaptureGroupCaptureGroup() throws {
+        let input = #"SwiftMergeGeneratedHeaders /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/DerivedSources/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/arm64/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/x86_64/Backyard_Birds-Swift.h (in target 'Backyard Birds Target' from project 'Backyard Birds Project')"#
+        let groups = try XCTUnwrap(SwiftMergeGeneratedHeadersCaptureGroup.regex.captureGroups(for: input))
+        XCTAssertEqual(groups.count, 3)
+        XCTAssertEqual(groups[0], #"/Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/DerivedSources/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/arm64/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/x86_64/Backyard_Birds-Swift.h"#)
+        XCTAssertEqual(groups[1], "Backyard Birds Target")
+        XCTAssertEqual(groups[2], "Backyard Birds Project")
+    }
+
     func testUnindentedShellCommand() throws {
         let input = #"/Applications/Xcode-16.0.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -Xlinker -reproducible -target arm64-apple-macos14.0 -dynamiclib -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk -O0 -L/Backyard-Birds/Build/Intermediates.noindex/EagerLinkingTBDs/Debug -L/Backyard-Birds/Build/Products/Debug -L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -F/Backyard-Birds/Build/Intermediates.noindex/EagerLinkingTBDs/Debug -F/Backyard-Birds/Build/Products/Debug/PackageFrameworks -F/Backyard-Birds/Build/Products/Debug -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -filelist /Backyard-Birds/Build/Intermediates.noindex/BackyardBirdsData.build/Debug/BackyardBirdsData\ product.build/Objects-normal/arm64/BackyardBirdsData.LinkFileList -install_name @rpath/BackyardBirdsData.framework/Versions/A/BackyardBirdsData -Xlinker -rpath -Xlinker /Backyard-Birds/Build/Products/Debug/PackageFrameworks -Xlinker -object_path_lto -Xlinker /Backyard-Birds/Build/Intermediates.noindex/BackyardBirdsData.build/Debug/BackyardBirdsData\ product.build/Objects-normal/arm64/BackyardBirdsData_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -fobjc-link-runtime -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -L/usr/lib/swift -Wl,-no_warn_duplicate_libraries -Xlinker -dependency_info -Xlinker /Backyard-Birds/Build/Intermediates.noindex/BackyardBirdsData.build/Debug/BackyardBirdsData\ product.build/Objects-normal/arm64/BackyardBirdsData_dependency_info.dat -o /Backyard-Birds/Build/Intermediates.noindex/BackyardBirdsData.build/Debug/BackyardBirdsData\ product.build/Objects-normal/arm64/Binary/BackyardBirdsData -Xlinker -add_ast_path -Xlinker /Backyard-Birds/Build/Intermediates.noindex/BackyardBirdsData.build/Debug/BackyardBirdsData.build/Objects-normal/arm64/BackyardBirdsData.swiftmodule"#
         let groups = try XCTUnwrap(NonPCHClangCommandCaptureGroup.regex.captureGroups(for: input))
diff --git a/Tests/XcbeautifyLibTests/ParserTests.swift b/Tests/XcbeautifyLibTests/ParserTests.swift
index cdfe79e..603cb9b 100644
--- a/Tests/XcbeautifyLibTests/ParserTests.swift
+++ b/Tests/XcbeautifyLibTests/ParserTests.swift
@@ -106,6 +106,14 @@ final class ParserTests: XCTestCase {
         XCTAssertEqual(captureGroup.target, "BackyardBirdsData")
     }
 
+    func testMatchSwiftDriverJobDiscoveryCompilingCaptureGroup() throws {
+        let input = #"SwiftMergeGeneratedHeaders /Backyard-Birds/Build/Intermediates.noindex/GeneratedModuleMaps/LayeredArtworkLibrary-Swift.h /Backyard-Birds/Build/Intermediates.noindex/LayeredArtworkLibrary.build/Debug/LayeredArtworkLibrary.build/Objects-normal/arm64/LayeredArtworkLibrary-Swift.h /Backyard-Birds/Build/Intermediates.noindex/LayeredArtworkLibrary.build/Debug/LayeredArtworkLibrary.build/Objects-normal/x86_64/LayeredArtworkLibrary-Swift.h (in target 'LayeredArtworkLibraryTarget' from project 'LayeredArtworkLibraryProject')"#
+        let captureGroup = try XCTUnwrap(parser.parse(line: input) as? SwiftMergeGeneratedHeadersCaptureGroup)
+        XCTAssertEqual(captureGroup.headerFilePaths, "/Backyard-Birds/Build/Intermediates.noindex/GeneratedModuleMaps/LayeredArtworkLibrary-Swift.h /Backyard-Birds/Build/Intermediates.noindex/LayeredArtworkLibrary.build/Debug/LayeredArtworkLibrary.build/Objects-normal/arm64/LayeredArtworkLibrary-Swift.h /Backyard-Birds/Build/Intermediates.noindex/LayeredArtworkLibrary.build/Debug/LayeredArtworkLibrary.build/Objects-normal/x86_64/LayeredArtworkLibrary-Swift.h")
+        XCTAssertEqual(captureGroup.target, "LayeredArtworkLibraryTarget")
+        XCTAssertEqual(captureGroup.project, "LayeredArtworkLibraryProject")
+    }
+
     func testMatchExplicitDependency() throws {
         let input = #"        ➜ Explicit dependency on target 'BackyardBirdsData_BackyardBirdsData' in project 'Backyard Birds Data'"#
         let captureGroup = try XCTUnwrap(parser.parse(line: input) as? ExplicitDependencyCaptureGroup)
diff --git a/Tests/XcbeautifyLibTests/ParsingTests/ParsingTests.swift b/Tests/XcbeautifyLibTests/ParsingTests/ParsingTests.swift
index a8136af..9165eb5 100644
--- a/Tests/XcbeautifyLibTests/ParsingTests/ParsingTests.swift
+++ b/Tests/XcbeautifyLibTests/ParsingTests/ParsingTests.swift
@@ -26,9 +26,9 @@ final class ParsingTests: XCTestCase {
         // Update this magic number whenever `uncapturedOutput` is less than the current magic number.
         // There's a regression whenever `uncapturedOutput` is greater than the current magic number.
         #if os(macOS)
-        XCTAssertEqual(uncapturedOutput, 172)
+        XCTAssertEqual(uncapturedOutput, 167)
         #else
-        XCTAssertEqual(uncapturedOutput, 188)
+        XCTAssertEqual(uncapturedOutput, 183)
         #endif
     }
 
@@ -56,9 +56,9 @@ final class ParsingTests: XCTestCase {
         // Update this magic number whenever `uncapturedOutput` is less than the current magic number.
         // There's a regression whenever `uncapturedOutput` is greater than the current magic number.
         #if os(macOS)
-        XCTAssertEqual(uncapturedOutput, 5700)
+        XCTAssertEqual(uncapturedOutput, 5520)
         #else
-        XCTAssertEqual(uncapturedOutput, 6268)
+        XCTAssertEqual(uncapturedOutput, 6088)
         #endif
     }
 
diff --git a/Tests/XcbeautifyLibTests/RendererTests/AzureDevOpsPipelinesRendererTests.swift b/Tests/XcbeautifyLibTests/RendererTests/AzureDevOpsPipelinesRendererTests.swift
index 66a04b6..d6d4928 100644
--- a/Tests/XcbeautifyLibTests/RendererTests/AzureDevOpsPipelinesRendererTests.swift
+++ b/Tests/XcbeautifyLibTests/RendererTests/AzureDevOpsPipelinesRendererTests.swift
@@ -648,6 +648,11 @@ final class AzureDevOpsPipelinesRendererTests: XCTestCase {
         XCTAssertEqual(formatted, #"[Target] Signing Some+File.o"#)
     }
 
+    func testSwiftMergeGeneratedHeaders() {
+        let formatted = logFormatted(#"SwiftMergeGeneratedHeaders /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/DerivedSources/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/arm64/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/x86_64/Backyard_Birds-Swift.h (in target 'Backyard Birds' from project 'Backyard Birds')"#)
+        XCTAssertNil(formatted)
+    }
+
     func testSwiftTestingRunCompletion() {
         let input = #"􁁛 Test run with 5 tests passed after 12.345 seconds."#
         let formatted = logFormatted(input)
diff --git a/Tests/XcbeautifyLibTests/RendererTests/GitHubActionsRendererTests.swift b/Tests/XcbeautifyLibTests/RendererTests/GitHubActionsRendererTests.swift
index a086be4..c49036b 100644
--- a/Tests/XcbeautifyLibTests/RendererTests/GitHubActionsRendererTests.swift
+++ b/Tests/XcbeautifyLibTests/RendererTests/GitHubActionsRendererTests.swift
@@ -645,6 +645,11 @@ final class GitHubActionsRendererTests: XCTestCase {
         XCTAssertEqual(formatted, #"[Target] Signing Some+File.o"#)
     }
 
+    func testSwiftMergeGeneratedHeaders() {
+        let formatted = logFormatted(#"SwiftMergeGeneratedHeaders /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/DerivedSources/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/arm64/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/x86_64/Backyard_Birds-Swift.h (in target 'Backyard Birds' from project 'Backyard Birds')"#)
+        XCTAssertNil(formatted)
+    }
+
     func testSwiftTestingRunCompletion() {
         let input = #"􁁛 Test run with 5 tests passed after 12.345 seconds."#
         let formatted = logFormatted(input)
diff --git a/Tests/XcbeautifyLibTests/RendererTests/TeamCityRendererTests.swift b/Tests/XcbeautifyLibTests/RendererTests/TeamCityRendererTests.swift
index 9e55765..fe46bce 100644
--- a/Tests/XcbeautifyLibTests/RendererTests/TeamCityRendererTests.swift
+++ b/Tests/XcbeautifyLibTests/RendererTests/TeamCityRendererTests.swift
@@ -460,6 +460,11 @@ final class TeamCityRendererTests: XCTestCase {
         XCTAssertEqual(formatted, #"[Target] Signing Some+File.o"#)
     }
 
+    func testSwiftMergeGeneratedHeaders() {
+        let formatted = noColoredFormatted(#"SwiftMergeGeneratedHeaders /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/DerivedSources/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/arm64/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/x86_64/Backyard_Birds-Swift.h (in target 'Backyard Birds' from project 'Backyard Birds')"#)
+        XCTAssertNil(formatted)
+    }
+
     func testSymbolReferencedFrom() {
         let formatted = noColoredFormatted("  \"NetworkBusiness.ImageDownloadManager.saveImage(image: __C.UIImage, needWatermark: Swift.Bool, params: [Swift.String : Any], downloadHandler: (Swift.Bool) -> ()?) -> ()\", referenced from:")
         XCTAssertEqual(formatted, "[x]   \"NetworkBusiness.ImageDownloadManager.saveImage(image: __C.UIImage, needWatermark: Swift.Bool, params: [Swift.String : Any], downloadHandler: (Swift.Bool) -> ()?) -> ()\", referenced from:")
diff --git a/Tests/XcbeautifyLibTests/RendererTests/TerminalRendererTests.swift b/Tests/XcbeautifyLibTests/RendererTests/TerminalRendererTests.swift
index 44d0a73..d9bb231 100644
--- a/Tests/XcbeautifyLibTests/RendererTests/TerminalRendererTests.swift
+++ b/Tests/XcbeautifyLibTests/RendererTests/TerminalRendererTests.swift
@@ -653,6 +653,11 @@ final class TerminalRendererTests: XCTestCase {
         XCTAssertEqual(formatted, #"[Target] Signing Some+File.o"#)
     }
 
+    func testSwiftMergeGeneratedHeaders() {
+        let formatted = noColoredFormatted(#"SwiftMergeGeneratedHeaders /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/DerivedSources/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/arm64/Backyard_Birds-Swift.h /Backyard-Birds/Build/Intermediates.noindex/Backyard\ Birds.build/Debug/Backyard\ Birds.build/Objects-normal/x86_64/Backyard_Birds-Swift.h (in target 'Backyard Birds' from project 'Backyard Birds')"#)
+        XCTAssertNil(formatted)
+    }
+
     func testSwiftTestingRunStarted() {
         let input = #"􀟈 Test run started."#
         let output = "Test run started."