diff --git a/Package.swift b/Package.swift index d960d73..c768a4f 100644 --- a/Package.swift +++ b/Package.swift @@ -1,6 +1,7 @@ // swift-tools-version: 5.9 import CompilerPluginSupport +import Foundation import PackageDescription let package = Package( @@ -51,8 +52,6 @@ let package = Package( ) #endif -import Foundation - if ProcessInfo.processInfo.environment["OMIT_MACRO_TESTS"] == nil { package.dependencies.append( .package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.2.0") @@ -65,7 +64,7 @@ if ProcessInfo.processInfo.environment["OMIT_MACRO_TESTS"] == nil { .product( name: "MacroTesting", package: "swift-macro-testing" - ) + ), ] ) ) diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index 07ef562..f08645a 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -1,6 +1,7 @@ // swift-tools-version: 6.0 import CompilerPluginSupport +import Foundation import PackageDescription let package = Package( @@ -52,8 +53,6 @@ let package = Package( ) #endif -import Foundation - if ProcessInfo.processInfo.environment["OMIT_MACRO_TESTS"] == nil { package.dependencies.append( .package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.2.0") @@ -66,7 +65,7 @@ if ProcessInfo.processInfo.environment["OMIT_MACRO_TESTS"] == nil { .product( name: "MacroTesting", package: "swift-macro-testing" - ) + ), ] ) ) diff --git a/Sources/CasePaths/EnumReflection.swift b/Sources/CasePaths/EnumReflection.swift index c243e5e..f316608 100644 --- a/Sources/CasePaths/EnumReflection.swift +++ b/Sources/CasePaths/EnumReflection.swift @@ -78,9 +78,11 @@ func extractHelp( return { root in let rootTag = metadata.tag(of: root) - if case let (cachedTag?, (isIndirect: isIndirect, associatedValueType: associatedValueType)?) = cache.withLock({ - ($0.tag, $0.strategy) - }) { + if case let (cachedTag?, (isIndirect: isIndirect, associatedValueType: associatedValueType)?) = + cache.withLock({ + ($0.tag, $0.strategy) + }) + { guard rootTag == cachedTag else { return nil } let value = EnumMetadata diff --git a/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift b/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift index 6a347aa..546f4aa 100644 --- a/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift +++ b/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift @@ -1,1149 +1,1102 @@ #if canImport(MacroTesting) -import CasePathsMacros -import MacroTesting -import SwiftSyntaxMacros -import XCTest - -final class CasePathableMacroTests: XCTestCase { - override func invokeTest() { - withMacroTesting( - // record: .failed, - macros: [CasePathableMacro.self] - ) { - super.invokeTest() + import CasePathsMacros + import MacroTesting + import SwiftSyntaxMacros + import XCTest + + final class CasePathableMacroTests: XCTestCase { + override func invokeTest() { + withMacroTesting( + // record: .failed, + macros: [CasePathableMacro.self] + ) { + super.invokeTest() + } } - } - func testCasePathable() { - assertMacro { - """ - @CasePathable enum Foo { - case bar - case baz(Int) - case fizz(buzz: String) - case fizzier(Int, buzzier: String) - } - """ - } expansion: { - #""" - enum Foo { - case bar - case baz(Int) - case fizz(buzz: String) - case fizzier(Int, buzzier: String) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - if root.is(\.baz) { - return \.baz - } - if root.is(\.fizz) { - return \.fizz - } - if root.is(\.fizzier) { - return \.fizzier - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed({ - Foo.bar - }) { - guard case .bar = $0 else { - return nil + func testCasePathable() { + assertMacro { + """ + @CasePathable enum Foo { + case bar + case baz(Int) + case fizz(buzz: String) + case fizzier(Int, buzzier: String) + } + """ + } expansion: { + #""" + enum Foo { + case bar + case baz(Int) + case fizz(buzz: String) + case fizzier(Int, buzzier: String) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar + } + if root.is(\.baz) { + return \.baz + } + if root.is(\.fizz) { + return \.fizz } - return () + if root.is(\.fizzier) { + return \.fizzier + } + return \.never } - } - public var baz: CasePaths.AnyCasePath { - ._$embed(Foo.baz) { - guard case let .baz(v0) = $0 else { - return nil + public var bar: CasePaths.AnyCasePath { + ._$embed({ + Foo.bar + }) { + guard case .bar = $0 else { + return nil + } + return () } - return v0 } - } - public var fizz: CasePaths.AnyCasePath { - ._$embed(Foo.fizz) { - guard case let .fizz(v0) = $0 else { - return nil + public var baz: CasePaths.AnyCasePath { + ._$embed(Foo.baz) { + guard case let .baz(v0) = $0 else { + return nil + } + return v0 } - return v0 } - } - public var fizzier: CasePaths.AnyCasePath { - ._$embed(Foo.fizzier) { - guard case let .fizzier(v0, v1) = $0 else { - return nil + public var fizz: CasePaths.AnyCasePath { + ._$embed(Foo.fizz) { + guard case let .fizz(v0) = $0 else { + return nil + } + return v0 } - return (v0, v1) + } + public var fizzier: CasePaths.AnyCasePath { + ._$embed(Foo.fizzier) { + guard case let .fizzier(v0, v1) = $0 else { + return nil + } + return (v0, v1) + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + allCasePaths.append(\.baz) + allCasePaths.append(\.fizz) + allCasePaths.append(\.fizzier) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - allCasePaths.append(\.baz) - allCasePaths.append(\.fizz) - allCasePaths.append(\.fizzier) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testCasePathable_NoCases() { - assertMacro { - """ - @CasePathable enum EnumWithNoCases {} - """ - } expansion: { - #""" - enum EnumWithNoCases { - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: EnumWithNoCases) -> CasePaths.PartialCaseKeyPath { - \.never - } + func testCasePathable_NoCases() { + assertMacro { + """ + @CasePathable enum EnumWithNoCases {} + """ + } expansion: { + #""" + enum EnumWithNoCases { + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: EnumWithNoCases) -> CasePaths.PartialCaseKeyPath { + \.never + } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - let allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - return allCasePaths.makeIterator() - } - } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + let allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + return allCasePaths.makeIterator() + } + } + public static var allCasePaths: AllCasePaths { AllCasePaths() } + } - extension EnumWithNoCases: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension EnumWithNoCases: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testCasePathable_NeverCase() { - assertMacro { - """ - @CasePathable enum Foo { - case bar(Never) - } - """ - } expansion: { - #""" - enum Foo { - case bar(Never) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed(Foo.bar) { - guard case let .bar(v0) = $0 else { - return nil + func testCasePathable_NeverCase() { + assertMacro { + """ + @CasePathable enum Foo { + case bar(Never) + } + """ + } expansion: { + #""" + enum Foo { + case bar(Never) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar + } + return \.never + } + public var bar: CasePaths.AnyCasePath { + ._$embed(Foo.bar) { + guard case let .bar(v0) = $0 else { + return nil + } + return v0 } - return v0 + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testCasePathable_ElementList() { - assertMacro { - """ - @CasePathable public enum Foo { - case bar(Int), baz(String) - } - """ - } expansion: { - #""" - public enum Foo { - case bar(Int), baz(String) + func testCasePathable_ElementList() { + assertMacro { + """ + @CasePathable public enum Foo { + case bar(Int), baz(String) + } + """ + } expansion: { + #""" + public enum Foo { + case bar(Int), baz(String) - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - if root.is(\.baz) { - return \.baz + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar + } + if root.is(\.baz) { + return \.baz + } + return \.never } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed(Foo.bar) { - guard case let .bar(v0) = $0 else { - return nil + public var bar: CasePaths.AnyCasePath { + ._$embed(Foo.bar) { + guard case let .bar(v0) = $0 else { + return nil + } + return v0 } - return v0 } - } - public var baz: CasePaths.AnyCasePath { - ._$embed(Foo.baz) { - guard case let .baz(v0) = $0 else { - return nil + public var baz: CasePaths.AnyCasePath { + ._$embed(Foo.baz) { + guard case let .baz(v0) = $0 else { + return nil + } + return v0 } - return v0 + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + allCasePaths.append(\.baz) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - allCasePaths.append(\.baz) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testCasePathable_AccessControl() { - assertMacro { - """ - @CasePathable public enum Foo { - case bar(Int) - } - """ - } expansion: { - #""" - public enum Foo { - case bar(Int) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed(Foo.bar) { - guard case let .bar(v0) = $0 else { - return nil + func testCasePathable_AccessControl() { + assertMacro { + """ + @CasePathable public enum Foo { + case bar(Int) + } + """ + } expansion: { + #""" + public enum Foo { + case bar(Int) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return v0 + return \.never + } + public var bar: CasePaths.AnyCasePath { + ._$embed(Foo.bar) { + guard case let .bar(v0) = $0 else { + return nil + } + return v0 + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { - } - """# - } - assertMacro { - """ - @CasePathable package enum Foo { - case bar(Int) + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """ - } expansion: { - #""" - package enum Foo { - case bar(Int) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed(Foo.bar) { - guard case let .bar(v0) = $0 else { - return nil + assertMacro { + """ + @CasePathable package enum Foo { + case bar(Int) + } + """ + } expansion: { + #""" + package enum Foo { + case bar(Int) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return v0 + return \.never + } + public var bar: CasePaths.AnyCasePath { + ._$embed(Foo.bar) { + guard case let .bar(v0) = $0 else { + return nil + } + return v0 + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { - } - """# - } - assertMacro { - """ - @CasePathable private enum Foo { - case bar(Int) + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """ - } expansion: { - #""" - private enum Foo { - case bar(Int) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed(Foo.bar) { - guard case let .bar(v0) = $0 else { - return nil + assertMacro { + """ + @CasePathable private enum Foo { + case bar(Int) + } + """ + } expansion: { + #""" + private enum Foo { + case bar(Int) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return v0 + return \.never + } + public var bar: CasePaths.AnyCasePath { + ._$embed(Foo.bar) { + guard case let .bar(v0) = $0 else { + return nil + } + return v0 + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testOverloadedCaseName() { - assertMacro { - """ - @CasePathable enum Foo { - case bar(Int) - case bar(int: Int) - } - """ - } diagnostics: { - """ - @CasePathable enum Foo { - case bar(Int) - case bar(int: Int) - ┬── - ╰─ 🛑 '@CasePathable' cannot be applied to overloaded case name 'bar' + func testOverloadedCaseName() { + assertMacro { + """ + @CasePathable enum Foo { + case bar(Int) + case bar(int: Int) + } + """ + } diagnostics: { + """ + @CasePathable enum Foo { + case bar(Int) + case bar(int: Int) + ┬── + ╰─ 🛑 '@CasePathable' cannot be applied to overloaded case name 'bar' + } + """ } - """ } - } - func testRequiresEnum() { - assertMacro { - """ - @CasePathable struct Foo { - } - """ - } diagnostics: { - """ - @CasePathable struct Foo { - ┬───── - ╰─ 🛑 '@CasePathable' cannot be applied to struct type 'Foo' + func testRequiresEnum() { + assertMacro { + """ + @CasePathable struct Foo { + } + """ + } diagnostics: { + """ + @CasePathable struct Foo { + ┬───── + ╰─ 🛑 '@CasePathable' cannot be applied to struct type 'Foo' + } + """ } - """ } - } - func testRedundantConformances() { - assertMacro { - """ - @CasePathable enum Foo: CasePathable { - } - """ - } expansion: { - #""" - enum Foo: CasePathable { + func testRedundantConformances() { + assertMacro { + """ + @CasePathable enum Foo: CasePathable { + } + """ + } expansion: { + #""" + enum Foo: CasePathable { + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + \.never + } - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - \.never - } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + let allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + return allCasePaths.makeIterator() + } + } + public static var allCasePaths: AllCasePaths { AllCasePaths() } + } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - let allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - return allCasePaths.makeIterator() - } - } - public static var allCasePaths: AllCasePaths { AllCasePaths() } + extension Foo: CasePaths.CasePathIterable { + } + """# } + assertMacro { + """ + @CasePathable enum Foo: CasePaths.CasePathable { + } + """ + } expansion: { + #""" + enum Foo: CasePaths.CasePathable { + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + \.never + } - extension Foo: CasePaths.CasePathIterable { + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + let allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + return allCasePaths.makeIterator() + } + } + public static var allCasePaths: AllCasePaths { AllCasePaths() } + } + + extension Foo: CasePaths.CasePathIterable { + } + """# } - """# } - assertMacro { - """ - @CasePathable enum Foo: CasePaths.CasePathable { - } - """ - } expansion: { - #""" - enum Foo: CasePaths.CasePathable { + + func testWildcard() { + assertMacro { + """ + @CasePathable enum Foo { + case bar(_ int: Int, _ bool: Bool) + } + """ + } expansion: { + #""" + enum Foo { + case bar(_ int: Int, _ bool: Bool) public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - \.never + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - let allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - return allCasePaths.makeIterator() + return \.never + } + public var bar: CasePaths.AnyCasePath { + ._$embed(Foo.bar) { + guard case let .bar(v0, v1) = $0 else { + return nil + } + return (v0, v1) } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() + } } public static var allCasePaths: AllCasePaths { AllCasePaths() } - } + } - extension Foo: CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testWildcard() { - assertMacro { - """ - @CasePathable enum Foo { - case bar(_ int: Int, _ bool: Bool) - } - """ - } expansion: { - #""" - enum Foo { - case bar(_ int: Int, _ bool: Bool) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed(Foo.bar) { - guard case let .bar(v0, v1) = $0 else { - return nil + func testSelf() { + assertMacro { + """ + @CasePathable enum Foo { + case bar(Bar) + } + """ + } expansion: { + #""" + enum Foo { + case bar(Bar) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return (v0, v1) + return \.never + } + public var bar: CasePaths.AnyCasePath> { + ._$embed(Foo.bar) { + guard case let .bar(v0) = $0 else { + return nil + } + return v0 + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testSelf() { - assertMacro { - """ - @CasePathable enum Foo { - case bar(Bar) - } - """ - } expansion: { - #""" - enum Foo { - case bar(Bar) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath> { - ._$embed(Foo.bar) { - guard case let .bar(v0) = $0 else { - return nil + func testDefaults() { + assertMacro { + """ + @CasePathable enum Foo { + case bar(int: Int = 42, bool: Bool = true) + } + """ + } expansion: { + #""" + enum Foo { + case bar(int: Int = 42, bool: Bool = true) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return v0 + return \.never + } + public var bar: CasePaths.AnyCasePath { + ._$embed(Foo.bar) { + guard case let .bar(v0, v1) = $0 else { + return nil + } + return (v0, v1) + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testDefaults() { - assertMacro { - """ - @CasePathable enum Foo { - case bar(int: Int = 42, bool: Bool = true) - } - """ - } expansion: { - #""" - enum Foo { - case bar(int: Int = 42, bool: Bool = true) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed(Foo.bar) { - guard case let .bar(v0, v1) = $0 else { - return nil - } - return (v0, v1) - } - } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + func testConditionalCompilation() { + assertMacro { + """ + @CasePathable enum Foo { + case bar + + #if os(macOS) + case macCase + case macSecond(Int) + #elseif os(iOS) + case iosCase + #else + case elseCase(String) + case elseLast + #endif + + #if DEBUG + #if INNER + case twoLevelsDeep + case twoLevels(Double) + #endif + #endif } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } + """ + } expansion: { + #""" + enum Foo { + case bar - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { - } - """# - } - } + #if os(macOS) + case macCase + case macSecond(Int) + #elseif os(iOS) + case iosCase + #else + case elseCase(String) + case elseLast + #endif - func testConditionalCompilation() { - assertMacro { - """ - @CasePathable enum Foo { - case bar - - #if os(macOS) - case macCase - case macSecond(Int) - #elseif os(iOS) - case iosCase - #else - case elseCase(String) - case elseLast - #endif - - #if DEBUG - #if INNER - case twoLevelsDeep - case twoLevels(Double) - #endif - #endif - } - """ - } expansion: { - #""" - enum Foo { - case bar - - #if os(macOS) - case macCase - case macSecond(Int) - #elseif os(iOS) - case iosCase - #else - case elseCase(String) - case elseLast - #endif - - #if DEBUG - #if INNER - case twoLevelsDeep - case twoLevels(Double) - #endif - #endif - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - #if os(macOS) - if root.is(\.macCase) { - return \.macCase - } - if root.is(\.macSecond) { - return \.macSecond - } - #elseif os(iOS) - if root.is(\.iosCase) { - return \.iosCase - } - #else - if root.is(\.elseCase) { - return \.elseCase - } - if root.is(\.elseLast) { - return \.elseLast - } - #endif - #if DEBUG - #if INNER - if root.is(\.twoLevelsDeep) { - return \.twoLevelsDeep - } - if root.is(\.twoLevels) { - return \.twoLevels - } - #endif - #endif - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed({ - Foo.bar - }) { - guard case .bar = $0 else { - return nil + #if DEBUG + #if INNER + case twoLevelsDeep + case twoLevels(Double) + #endif + #endif + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return () - } - } - #if os(macOS) - public var macCase: CasePaths.AnyCasePath { - ._$embed({ - Foo.macCase - }) { - guard case .macCase = $0 else { - return nil + #if os(macOS) + if root.is(\.macCase) { + return \.macCase + } + if root.is(\.macSecond) { + return \.macSecond + } + #elseif os(iOS) + if root.is(\.iosCase) { + return \.iosCase + } + #else + if root.is(\.elseCase) { + return \.elseCase + } + if root.is(\.elseLast) { + return \.elseLast + } + #endif + #if DEBUG + #if INNER + if root.is(\.twoLevelsDeep) { + return \.twoLevelsDeep + } + if root.is(\.twoLevels) { + return \.twoLevels } - return () + #endif + #endif + return \.never } - } - public var macSecond: CasePaths.AnyCasePath { - ._$embed(Foo.macSecond) { - guard case let .macSecond(v0) = $0 else { - return nil + public var bar: CasePaths.AnyCasePath { + ._$embed({ + Foo.bar + }) { + guard case .bar = $0 else { + return nil + } + return () } - return v0 } - } - #elseif os(iOS) - public var iosCase: CasePaths.AnyCasePath { - ._$embed({ - Foo.iosCase - }) { - guard case .iosCase = $0 else { - return nil + #if os(macOS) + public var macCase: CasePaths.AnyCasePath { + ._$embed({ + Foo.macCase + }) { + guard case .macCase = $0 else { + return nil + } + return () } - return () } - } - #else - public var elseCase: CasePaths.AnyCasePath { - ._$embed(Foo.elseCase) { - guard case let .elseCase(v0) = $0 else { - return nil + public var macSecond: CasePaths.AnyCasePath { + ._$embed(Foo.macSecond) { + guard case let .macSecond(v0) = $0 else { + return nil + } + return v0 } - return v0 } - } - public var elseLast: CasePaths.AnyCasePath { - ._$embed({ - Foo.elseLast - }) { - guard case .elseLast = $0 else { - return nil + #elseif os(iOS) + public var iosCase: CasePaths.AnyCasePath { + ._$embed({ + Foo.iosCase + }) { + guard case .iosCase = $0 else { + return nil + } + return () } - return () } - } - #endif - #if DEBUG - #if INNER - public var twoLevelsDeep: CasePaths.AnyCasePath { - ._$embed({ - Foo.twoLevelsDeep - }) { - guard case .twoLevelsDeep = $0 else { - return nil + #else + public var elseCase: CasePaths.AnyCasePath { + ._$embed(Foo.elseCase) { + guard case let .elseCase(v0) = $0 else { + return nil + } + return v0 } - return () } - } - public var twoLevels: CasePaths.AnyCasePath { - ._$embed(Foo.twoLevels) { - guard case let .twoLevels(v0) = $0 else { - return nil + public var elseLast: CasePaths.AnyCasePath { + ._$embed({ + Foo.elseLast + }) { + guard case .elseLast = $0 else { + return nil + } + return () } - return v0 } - } - #endif - #endif - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - #if os(macOS) - allCasePaths.append(\.macCase) - allCasePaths.append(\.macSecond) - #elseif os(iOS) - allCasePaths.append(\.iosCase) - #else - allCasePaths.append(\.elseCase) - allCasePaths.append(\.elseLast) #endif #if DEBUG #if INNER - allCasePaths.append(\.twoLevelsDeep) - allCasePaths.append(\.twoLevels) + public var twoLevelsDeep: CasePaths.AnyCasePath { + ._$embed({ + Foo.twoLevelsDeep + }) { + guard case .twoLevelsDeep = $0 else { + return nil + } + return () + } + } + public var twoLevels: CasePaths.AnyCasePath { + ._$embed(Foo.twoLevels) { + guard case let .twoLevels(v0) = $0 else { + return nil + } + return v0 + } + } #endif #endif - return allCasePaths.makeIterator() + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + #if os(macOS) + allCasePaths.append(\.macCase) + allCasePaths.append(\.macSecond) + #elseif os(iOS) + allCasePaths.append(\.iosCase) + #else + allCasePaths.append(\.elseCase) + allCasePaths.append(\.elseLast) + #endif + #if DEBUG + #if INNER + allCasePaths.append(\.twoLevelsDeep) + allCasePaths.append(\.twoLevels) + #endif + #endif + return allCasePaths.makeIterator() + } } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testAvailability() { - assertMacro { - """ - @available(iOS, unavailable) - @CasePathable - enum Foo { - case bar - } - """ - } expansion: { - #""" - @available(iOS, unavailable) - enum Foo { - case bar - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - public var bar: CasePaths.AnyCasePath { - ._$embed({ - Foo.bar - }) { - guard case .bar = $0 else { - return nil + func testAvailability() { + assertMacro { + """ + @available(iOS, unavailable) + @CasePathable + enum Foo { + case bar + } + """ + } expansion: { + #""" + @available(iOS, unavailable) + enum Foo { + case bar + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar + } + return \.never + } + public var bar: CasePaths.AnyCasePath { + ._$embed({ + Foo.bar + }) { + guard case .bar = $0 else { + return nil + } + return () } - return () + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - @available(iOS, unavailable) extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + @available(iOS, unavailable) extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testDocumentation() { - assertMacro { - """ - @CasePathable - enum Foo { + func testDocumentation() { + assertMacro { + """ + @CasePathable + enum Foo { - /// The bar case. - case bar + /// The bar case. + case bar - /// The baz case. - /// - /// A case for baz. - case baz + /// The baz case. + /// + /// A case for baz. + case baz - /** - The fizz buzz case. + /** + The fizz buzz case. - A case for fizz and buzz. - */ - case fizz, buzz - } - """ - } expansion: { - #""" - enum Foo { + A case for fizz and buzz. + */ + case fizz, buzz + } + """ + } expansion: { + #""" + enum Foo { - /// The bar case. - case bar + /// The bar case. + case bar - /// The baz case. - /// - /// A case for baz. - case baz + /// The baz case. + /// + /// A case for baz. + case baz - /** - The fizz buzz case. + /** + The fizz buzz case. - A case for fizz and buzz. - */ - case fizz, buzz + A case for fizz and buzz. + */ + case fizz, buzz - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - if root.is(\.baz) { - return \.baz - } - if root.is(\.fizz) { - return \.fizz - } - if root.is(\.buzz) { - return \.buzz + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar + } + if root.is(\.baz) { + return \.baz + } + if root.is(\.fizz) { + return \.fizz + } + if root.is(\.buzz) { + return \.buzz + } + return \.never } - return \.never - } - /// The bar case. - public var bar: CasePaths.AnyCasePath { - ._$embed({ - Foo.bar - }) { - guard case .bar = $0 else { - return nil + /// The bar case. + public var bar: CasePaths.AnyCasePath { + ._$embed({ + Foo.bar + }) { + guard case .bar = $0 else { + return nil + } + return () } - return () } - } - /// The baz case. - /// - /// A case for baz. - public var baz: CasePaths.AnyCasePath { - ._$embed({ - Foo.baz - }) { - guard case .baz = $0 else { - return nil + /// The baz case. + /// + /// A case for baz. + public var baz: CasePaths.AnyCasePath { + ._$embed({ + Foo.baz + }) { + guard case .baz = $0 else { + return nil + } + return () } - return () } - } - /** - The fizz buzz case. + /** + The fizz buzz case. - A case for fizz and buzz. - */ - public var fizz: CasePaths.AnyCasePath { - ._$embed({ - Foo.fizz - }) { - guard case .fizz = $0 else { - return nil + A case for fizz and buzz. + */ + public var fizz: CasePaths.AnyCasePath { + ._$embed({ + Foo.fizz + }) { + guard case .fizz = $0 else { + return nil + } + return () } - return () } - } - /** - The fizz buzz case. + /** + The fizz buzz case. - A case for fizz and buzz. - */ - public var buzz: CasePaths.AnyCasePath { - ._$embed({ - Foo.buzz - }) { - guard case .buzz = $0 else { - return nil + A case for fizz and buzz. + */ + public var buzz: CasePaths.AnyCasePath { + ._$embed({ + Foo.buzz + }) { + guard case .buzz = $0 else { + return nil + } + return () } - return () + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + allCasePaths.append(\.baz) + allCasePaths.append(\.fizz) + allCasePaths.append(\.buzz) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - allCasePaths.append(\.baz) - allCasePaths.append(\.fizz) - allCasePaths.append(\.buzz) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testDocumentationIndentationTrimming() { - assertMacro { - """ - @CasePathable - enum Foo { - // baz - // case foo - case bar - } - """ - } expansion: { - #""" - enum Foo { - // baz - // case foo - case bar - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - return \.never - } - // baz - // case foo - public var bar: CasePaths.AnyCasePath { - ._$embed({ - Foo.bar - }) { - guard case .bar = $0 else { - return nil + func testDocumentationIndentationTrimming() { + assertMacro { + """ + @CasePathable + enum Foo { + // baz + // case foo + case bar + } + """ + } expansion: { + #""" + enum Foo { + // baz + // case foo + case bar + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return () + return \.never + } + // baz + // case foo + public var bar: CasePaths.AnyCasePath { + ._$embed({ + Foo.bar + }) { + guard case .bar = $0 else { + return nil + } + return () + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testComments() { - assertMacro { - """ - @CasePathable enum Foo { - // Comment above case - case bar - /*Comment before case*/ case baz(Int) - case fizz(buzz: String) // Comment on case - case fizzier/*Comment in case*/(Int, buzzier: String) - case fizziest // Comment without associated value - } - """ - } expansion: { - #""" - enum Foo { - // Comment above case - case bar - /*Comment before case*/ case baz(Int) - case fizz(buzz: String) // Comment on case - case fizzier/*Comment in case*/(Int, buzzier: String) - case fizziest // Comment without associated value - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { - if root.is(\.bar) { - return \.bar - } - if root.is(\.baz) { - return \.baz - } - if root.is(\.fizz) { - return \.fizz - } - if root.is(\.fizzier) { - return \.fizzier - } - if root.is(\.fizziest) { - return \.fizziest - } - return \.never - } + func testComments() { + assertMacro { + """ + @CasePathable enum Foo { // Comment above case - public var bar: CasePaths.AnyCasePath { - ._$embed({ - Foo.bar - }) { - guard case .bar = $0 else { - return nil + case bar + /*Comment before case*/ case baz(Int) + case fizz(buzz: String) // Comment on case + case fizzier/*Comment in case*/(Int, buzzier: String) + case fizziest // Comment without associated value + } + """ + } expansion: { + #""" + enum Foo { + // Comment above case + case bar + /*Comment before case*/ case baz(Int) + case fizz(buzz: String) // Comment on case + case fizzier/*Comment in case*/(Int, buzzier: String) + case fizziest // Comment without associated value + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar } - return () + if root.is(\.baz) { + return \.baz + } + if root.is(\.fizz) { + return \.fizz + } + if root.is(\.fizzier) { + return \.fizzier + } + if root.is(\.fizziest) { + return \.fizziest + } + return \.never } - } - /*Comment before case*/public var baz: CasePaths.AnyCasePath { - ._$embed(Foo.baz) { - guard case let .baz(v0) = $0 else { - return nil + // Comment above case + public var bar: CasePaths.AnyCasePath { + ._$embed({ + Foo.bar + }) { + guard case .bar = $0 else { + return nil + } + return () } - return v0 } - } - public var fizz: CasePaths.AnyCasePath { - ._$embed(Foo.fizz) { - guard case let .fizz(v0) = $0 else { - return nil + /*Comment before case*/public var baz: CasePaths.AnyCasePath { + ._$embed(Foo.baz) { + guard case let .baz(v0) = $0 else { + return nil + } + return v0 } - return v0 } - } - public var fizzier: CasePaths.AnyCasePath { - ._$embed(Foo.fizzier) { - guard case let .fizzier(v0, v1) = $0 else { - return nil + public var fizz: CasePaths.AnyCasePath { + ._$embed(Foo.fizz) { + guard case let .fizz(v0) = $0 else { + return nil + } + return v0 } - return (v0, v1) } - } - public var fizziest: CasePaths.AnyCasePath { - ._$embed({ - Foo.fizziest - }) { - guard case .fizziest = $0 else { - return nil + public var fizzier: CasePaths.AnyCasePath { + ._$embed(Foo.fizzier) { + guard case let .fizzier(v0, v1) = $0 else { + return nil + } + return (v0, v1) } - return () } - } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.bar) - allCasePaths.append(\.baz) - allCasePaths.append(\.fizz) - allCasePaths.append(\.fizzier) - allCasePaths.append(\.fizziest) - return allCasePaths.makeIterator() - } - } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - } - - extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { - } - """# - } - } - - func testElementGeneric() { - assertMacro { - """ - @CasePathable enum Action { - case element(Element) - } - """ - } expansion: { - #""" - enum Action { - case element(Element) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Action) -> CasePaths.PartialCaseKeyPath { - if root.is(\.element) { - return \.element - } - return \.never - } - public var element: CasePaths.AnyCasePath { - ._$embed(Action.element) { - guard case let .element(v0) = $0 else { - return nil + public var fizziest: CasePaths.AnyCasePath { + ._$embed({ + Foo.fizziest + }) { + guard case .fizziest = $0 else { + return nil + } + return () } - return v0 + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + allCasePaths.append(\.baz) + allCasePaths.append(\.fizz) + allCasePaths.append(\.fizzier) + allCasePaths.append(\.fizziest) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.element) - return allCasePaths.makeIterator() - } + public static var allCasePaths: AllCasePaths { AllCasePaths() } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - public typealias _$Element = Element - } - - extension Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testParentElementGeneric() { - assertMacro { - """ - struct Reducer { - @CasePathable enum Action { + func testElementGeneric() { + assertMacro { + """ + @CasePathable enum Action { case element(Element) } - } - """ - } expansion: { - #""" - struct Reducer { - enum Action { + """ + } expansion: { + #""" + enum Action { case element(Element) public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { @@ -1171,128 +1124,175 @@ final class CasePathableMacroTests: XCTestCase { public typealias _$Element = Element } - } - extension Reducer.Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testAssociatedValueElementArray() { - assertMacro { - """ - @CasePathable enum Action { - case element(Array) - } - """ - } expansion: { - #""" - enum Action { - case element(Array) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Action) -> CasePaths.PartialCaseKeyPath { - if root.is(\.element) { - return \.element - } - return \.never + func testParentElementGeneric() { + assertMacro { + """ + struct Reducer { + @CasePathable enum Action { + case element(Element) } - public var element: CasePaths.AnyCasePath> { - ._$embed(Action.element) { - guard case let .element(v0) = $0 else { - return nil + } + """ + } expansion: { + #""" + struct Reducer { + enum Action { + case element(Element) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Action) -> CasePaths.PartialCaseKeyPath { + if root.is(\.element) { + return \.element + } + return \.never + } + public var element: CasePaths.AnyCasePath { + ._$embed(Action.element) { + guard case let .element(v0) = $0 else { + return nil + } + return v0 + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.element) + return allCasePaths.makeIterator() } - return v0 } - } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.element) - return allCasePaths.makeIterator() + public static var allCasePaths: AllCasePaths { AllCasePaths() } + + public typealias _$Element = Element } } - public static var allCasePaths: AllCasePaths { AllCasePaths() } - public typealias _$Element = Element + extension Reducer.Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } + } + + func testAssociatedValueElementArray() { + assertMacro { + """ + @CasePathable enum Action { + case element(Array) + } + """ + } expansion: { + #""" + enum Action { + case element(Array) - extension Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Action) -> CasePaths.PartialCaseKeyPath { + if root.is(\.element) { + return \.element + } + return \.never + } + public var element: CasePaths.AnyCasePath> { + ._$embed(Action.element) { + guard case let .element(v0) = $0 else { + return nil + } + return v0 + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.element) + return allCasePaths.makeIterator() + } + } + public static var allCasePaths: AllCasePaths { AllCasePaths() } + + public typealias _$Element = Element + } + + extension Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } - } - func testMultipleAssociatedValueElement() { - assertMacro { - """ - @CasePathable enum Action { - case element(Array) - case secondElement(Element) - case thirdElement(Element, Element, Int) - } - """ - } expansion: { - #""" - enum Action { - case element(Array) - case secondElement(Element) - case thirdElement(Element, Element, Int) - - public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { - public subscript(root: Action) -> CasePaths.PartialCaseKeyPath { - if root.is(\.element) { - return \.element - } - if root.is(\.secondElement) { - return \.secondElement - } - if root.is(\.thirdElement) { - return \.thirdElement - } - return \.never - } - public var element: CasePaths.AnyCasePath> { - ._$embed(Action.element) { - guard case let .element(v0) = $0 else { - return nil + func testMultipleAssociatedValueElement() { + assertMacro { + """ + @CasePathable enum Action { + case element(Array) + case secondElement(Element) + case thirdElement(Element, Element, Int) + } + """ + } expansion: { + #""" + enum Action { + case element(Array) + case secondElement(Element) + case thirdElement(Element, Element, Int) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Action) -> CasePaths.PartialCaseKeyPath { + if root.is(\.element) { + return \.element + } + if root.is(\.secondElement) { + return \.secondElement } - return v0 + if root.is(\.thirdElement) { + return \.thirdElement + } + return \.never } - } - public var secondElement: CasePaths.AnyCasePath { - ._$embed(Action.secondElement) { - guard case let .secondElement(v0) = $0 else { - return nil + public var element: CasePaths.AnyCasePath> { + ._$embed(Action.element) { + guard case let .element(v0) = $0 else { + return nil + } + return v0 } - return v0 } - } - public var thirdElement: CasePaths.AnyCasePath { - ._$embed(Action.thirdElement) { - guard case let .thirdElement(v0, v1, v2) = $0 else { - return nil + public var secondElement: CasePaths.AnyCasePath { + ._$embed(Action.secondElement) { + guard case let .secondElement(v0) = $0 else { + return nil + } + return v0 } - return (v0, v1, v2) + } + public var thirdElement: CasePaths.AnyCasePath { + ._$embed(Action.thirdElement) { + guard case let .thirdElement(v0, v1, v2) = $0 else { + return nil + } + return (v0, v1, v2) + } + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.element) + allCasePaths.append(\.secondElement) + allCasePaths.append(\.thirdElement) + return allCasePaths.makeIterator() } } - public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { - var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] - allCasePaths.append(\.element) - allCasePaths.append(\.secondElement) - allCasePaths.append(\.thirdElement) - return allCasePaths.makeIterator() - } - } - public static var allCasePaths: AllCasePaths { AllCasePaths() } + public static var allCasePaths: AllCasePaths { AllCasePaths() } - public typealias _$Element = Element - } + public typealias _$Element = Element + } - extension Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Action: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# } - """# } } -} #endif