From 7259488657ebaeb5d69a0795b93d539d6251f48c Mon Sep 17 00:00:00 2001 From: Brett-Best Date: Wed, 10 Jun 2026 13:32:29 +1000 Subject: [PATCH 1/5] chore: Xcode 27b1 workaround --- .../FlagControl/FlagTextField+FloatingPoint.swift | 8 ++++---- .../FlagControl/FlagTextField+Integer.swift | 8 ++++---- Sources/Vexillographer/FlagControl/FlagTextField.swift | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Sources/Vexillographer/FlagControl/FlagTextField+FloatingPoint.swift b/Sources/Vexillographer/FlagControl/FlagTextField+FloatingPoint.swift index 80529bd..97dfb1d 100644 --- a/Sources/Vexillographer/FlagControl/FlagTextField+FloatingPoint.swift +++ b/Sources/Vexillographer/FlagControl/FlagTextField+FloatingPoint.swift @@ -18,13 +18,13 @@ import Vexil extension FlagTextField where Value.BoxedValueType: BinaryFloatingPoint { init(configuration: FlagControlConfiguration) { - self = Self( + self.init( configuration: configuration, formatted: \.asString, editingFormat: { $0 }, ) #if os(iOS) || os(tvOS) - .keyboardType(.decimalPad) + keyboardType = .decimalPad #endif } @@ -56,13 +56,13 @@ extension FlagControlConfiguration: FloatingPointTextFieldRepresentable where Va extension FlagTextField { init(configuration: FlagControlConfiguration) where Value == Wrapped?, Wrapped.BoxedValueType: BinaryFloatingPoint { - self = Self( + self.init( configuration: configuration, formatted: \.asStringOrEmpty, editingFormat: { $0 }, ) #if os(iOS) || os(tvOS) - .keyboardType(.decimalPad) + keyboardType = .decimalPad #endif } diff --git a/Sources/Vexillographer/FlagControl/FlagTextField+Integer.swift b/Sources/Vexillographer/FlagControl/FlagTextField+Integer.swift index befd298..5cd9294 100644 --- a/Sources/Vexillographer/FlagControl/FlagTextField+Integer.swift +++ b/Sources/Vexillographer/FlagControl/FlagTextField+Integer.swift @@ -18,13 +18,13 @@ import Vexil extension FlagTextField where Value.BoxedValueType: BinaryInteger { init(configuration: FlagControlConfiguration) { - self = Self( + self.init( configuration: configuration, formatted: \.asString, editingFormat: { $0.filter(\.isNumber) }, ) #if os(iOS) || os(tvOS) - .keyboardType(.numberPad) + keyboardType = .numberPad #endif } @@ -56,13 +56,13 @@ extension FlagControlConfiguration: IntegerFlagTextFieldRepresentable where Valu extension FlagTextField { init(configuration: FlagControlConfiguration) where Value == Wrapped?, Wrapped.BoxedValueType: BinaryInteger { - self = Self( + self.init( configuration: configuration, formatted: \.asStringOrEmpty, editingFormat: { $0.filter(\.isNumber) }, ) #if os(iOS) || os(tvOS) - .keyboardType(.numberPad) + keyboardType = .numberPad #endif } diff --git a/Sources/Vexillographer/FlagControl/FlagTextField.swift b/Sources/Vexillographer/FlagControl/FlagTextField.swift index 4f95764..bf85a6b 100644 --- a/Sources/Vexillographer/FlagControl/FlagTextField.swift +++ b/Sources/Vexillographer/FlagControl/FlagTextField.swift @@ -27,7 +27,7 @@ struct FlagTextField: View { private var format: (String) -> String private var editingFormat: (String) -> String #if os(iOS) || os(tvOS) - private var keyboardType = UIKeyboardType.default + var keyboardType = UIKeyboardType.default #endif @State From 82266d5079793a19e7bb5b62ad3b90bc0bb2c14d Mon Sep 17 00:00:00 2001 From: Brett-Best Date: Thu, 5 Nov 2026 15:57:52 +1100 Subject: [PATCH 2/5] Allow and upgrade to swift-syntax 604.0.0 Co-Authored-By: Claude Opus 5.5 --- Package.resolved | 6 +++--- Package.swift | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Package.resolved b/Package.resolved index 044bf93..ae8f713 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "7724a377457178ce875fe18adc9a76467dd42003b108c81973a2c98f158d4aef", + "originHash" : "28f3aa4d47ce18babb59fc2624554f373236e7d4bde940ac380abb401af9e84a", "pins" : [ { "identity" : "swift-async-algorithms", @@ -24,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swiftlang/swift-syntax.git", "state" : { - "revision" : "0687f71944021d616d34d922343dcef086855920", - "version" : "600.0.1" + "revision" : "050f1a346fbbac0ca2cfb15a95274f7bd1cf0ccf", + "version" : "604.0.0" } }, { diff --git a/Package.swift b/Package.swift index 57a9a60..4f73ee4 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-async-algorithms.git", from: "1.0.0"), .package(url: "https://github.com/nicklockwood/SwiftFormat.git", from: "0.60.1"), - .package(url: "https://github.com/swiftlang/swift-syntax.git", "600.0.0" ..< "604.0.0"), + .package(url: "https://github.com/swiftlang/swift-syntax.git", "600.0.0" ..< "605.0.0"), ], targets: [ From 9a22b0d19976feb363e8a340e56be706fa9ea404 Mon Sep 17 00:00:00 2001 From: Brett-Best Date: Thu, 5 Nov 2026 16:38:05 +1100 Subject: [PATCH 3/5] Use MacroSpec conformances in macro tests instead of env-var workaround swift test on Swift 6.4 no longer sets XCTestConfigurationFilePath, so the workaround for swiftlang/swift-syntax#2031 never triggered and extension macros generated no conformances in tests. Pass conformances explicitly via MacroSpec (available since swift-syntax 600.0.0, the package minimum) and drop the workaround. Co-Authored-By: Claude Opus 5.5 --- Sources/VexilMacros/FlagContainerMacro.swift | 19 +--------- .../EquatableFlagContainerMacroTests.swift | 37 ++++++++++--------- .../FlagContainerMacroTests.swift | 17 +++++---- 3 files changed, 30 insertions(+), 43 deletions(-) diff --git a/Sources/VexilMacros/FlagContainerMacro.swift b/Sources/VexilMacros/FlagContainerMacro.swift index de4c779..74e0c41 100644 --- a/Sources/VexilMacros/FlagContainerMacro.swift +++ b/Sources/VexilMacros/FlagContainerMacro.swift @@ -67,9 +67,7 @@ extension FlagContainerMacro: ExtensionMacro { conformingTo protocols: [TypeSyntax], in context: some MacroExpansionContext, ) throws -> [ExtensionDeclSyntax] { - var shouldGenerateConformance = protocols.isEmpty && ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil - ? node.shouldGenerateConformance - : protocols.shouldGenerateConformance + var shouldGenerateConformance = protocols.shouldGenerateConformance // Check if the user has disabled Equatable conformance manually if @@ -79,8 +77,7 @@ extension FlagContainerMacro: ExtensionMacro { shouldGenerateConformance.equatable = false } - // Check that conformance doesn't already exist, or that we are inside a unit test. - // The latter is a workaround for https://github.com/apple/swift-syntax/issues/2031 + // Check that conformance doesn't already exist guard shouldGenerateConformance.flagContainer else { return [] } @@ -239,15 +236,3 @@ private extension [TypeSyntax] { } } - -private extension AttributeSyntax { - - var shouldGenerateConformance: (flagContainer: Bool, equatable: Bool, sendable: Bool) { - if attributeName.identifier == "FlagContainer" { - (true, true, true) - } else { - (false, false, false) - } - } - -} diff --git a/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift b/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift index 005feb9..098fd6b 100644 --- a/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift +++ b/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift @@ -14,6 +14,7 @@ #if canImport(VexilMacros) import SwiftSyntaxMacros +import SwiftSyntaxMacroExpansion import SwiftSyntaxMacrosTestSupport import VexilMacros import XCTest @@ -60,8 +61,8 @@ final class EquatableFlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), ], ) } @@ -163,9 +164,9 @@ final class EquatableFlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, - "Flag": FlagMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), + "Flag": MacroSpec(type: FlagMacro.self), ], ) } @@ -241,9 +242,9 @@ final class EquatableFlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, - "Flag": FlagMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), + "Flag": MacroSpec(type: FlagMacro.self), ], ) } @@ -322,9 +323,9 @@ final class EquatableFlagContainerMacroTests: XCTestCase { extension SomeContainer.TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, - "Flag": FlagMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), + "Flag": MacroSpec(type: FlagMacro.self), ], ) } @@ -399,9 +400,9 @@ final class EquatableFlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, - "Flag": FlagMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), + "Flag": MacroSpec(type: FlagMacro.self), ], ) } @@ -497,8 +498,8 @@ final class EquatableFlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), ], ) } @@ -594,8 +595,8 @@ final class EquatableFlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), ], ) } diff --git a/Tests/VexilMacroTests/FlagContainerMacroTests.swift b/Tests/VexilMacroTests/FlagContainerMacroTests.swift index 6cbadb3..dd47828 100644 --- a/Tests/VexilMacroTests/FlagContainerMacroTests.swift +++ b/Tests/VexilMacroTests/FlagContainerMacroTests.swift @@ -14,6 +14,7 @@ #if canImport(VexilMacros) import SwiftSyntaxMacros +import SwiftSyntaxMacroExpansion import SwiftSyntaxMacrosTestSupport import VexilMacros import XCTest @@ -60,8 +61,8 @@ final class FlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), ], ) } @@ -106,8 +107,8 @@ final class FlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), ], ) } @@ -152,8 +153,8 @@ final class FlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), ], ) } @@ -251,8 +252,8 @@ final class FlagContainerMacroTests: XCTestCase { extension TestFlags: Sendable { } """, - macros: [ - "FlagContainer": FlagContainerMacro.self, + macroSpecs: [ + "FlagContainer": MacroSpec(type: FlagContainerMacro.self, conformances: ["FlagContainer", "Equatable", "Sendable"]), ], ) } From 49209068df834893a1ac21a44a786375641565c9 Mon Sep 17 00:00:00 2001 From: Brett-Best Date: Thu, 5 Nov 2026 16:43:09 +1100 Subject: [PATCH 4/5] Fix import ordering in macro tests for SwiftFormat lint Co-Authored-By: Claude Opus 5.5 --- Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift | 2 +- Tests/VexilMacroTests/FlagContainerMacroTests.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift b/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift index 098fd6b..5285969 100644 --- a/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift +++ b/Tests/VexilMacroTests/EquatableFlagContainerMacroTests.swift @@ -13,8 +13,8 @@ #if canImport(VexilMacros) -import SwiftSyntaxMacros import SwiftSyntaxMacroExpansion +import SwiftSyntaxMacros import SwiftSyntaxMacrosTestSupport import VexilMacros import XCTest diff --git a/Tests/VexilMacroTests/FlagContainerMacroTests.swift b/Tests/VexilMacroTests/FlagContainerMacroTests.swift index dd47828..6a3f34c 100644 --- a/Tests/VexilMacroTests/FlagContainerMacroTests.swift +++ b/Tests/VexilMacroTests/FlagContainerMacroTests.swift @@ -13,8 +13,8 @@ #if canImport(VexilMacros) -import SwiftSyntaxMacros import SwiftSyntaxMacroExpansion +import SwiftSyntaxMacros import SwiftSyntaxMacrosTestSupport import VexilMacros import XCTest From 84e959f1637ff726a12d9c32a60ef50a8a097529 Mon Sep 17 00:00:00 2001 From: Brett-Best Date: Thu, 5 Nov 2026 16:56:32 +1100 Subject: [PATCH 5/5] Build tvOS against a generic simulator destination The tvOS job only builds, but it asked for a named Apple TV simulator, which fails with exit 70 on runner images that lack the tvOS simulator runtime. Use generic/platform=tvOS Simulator, as the visionOS workflow already does. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/tvos-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tvos-tests.yml b/.github/workflows/tvos-tests.yml index 401a874..c08e77c 100644 --- a/.github/workflows/tvos-tests.yml +++ b/.github/workflows/tvos-tests.yml @@ -42,7 +42,7 @@ jobs: run: | set -o pipefail && \ NSUnbufferedIO=YES \ - xcrun xcodebuild build -workspace . -scheme Vexil-Package -skipMacroValidation -destination "platform=tvOS Simulator,name=Apple TV 4K (3rd generation)" \ + xcrun xcodebuild build -workspace . -scheme Vexil-Package -skipMacroValidation -destination "generic/platform=tvOS Simulator" \ | xcbeautify --renderer github-actions build-tvos: