Skip to content

Commit

Permalink
Fix build warning when @CasePathable is applied to enums with no ca…
Browse files Browse the repository at this point in the history
…ses (#164)

* Fix build warning when `@CasePathable` is applied to enums with no cases

Fixes warnings due to unreachable code:

For example:

```swift
@CasePathable enum Foo {}
```

Produces this expansion (compiler warnings added as code comments by me)

```swift
enum Foo: CasePathable {
  public struct AllCasePaths: Sequence {
    public subscript(root: Foo) -> PartialCaseKeyPath<Foo> {
      return \.never // ⚠️ warning: will never be executed
      // 'root' is of type 'Foo' which cannot be constructed because it
      // is an enum with no cases
    }

    public func makeIterator() -> IndexingIterator<[PartialCaseKeyPath<Foo>]> {
      let allCasePaths: [PartialCaseKeyPath<Foo>] = []
      return allCasePaths.makeIterator()
    }
  }
  public static var allCasePaths: AllCasePaths { AllCasePaths() }
}
```

We can fix this warning by simply not producing the subscript definition
when the enum has no cases.

* Omit return statement for enums without cases
  • Loading branch information
jpsim authored Jun 7, 2024
1 parent fe3bfeb commit e4489f5
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
4 changes: 3 additions & 1 deletion Sources/CasePathsMacros/CasePathableMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,13 @@ extension CasePathableMacro: MemberMacro {
"allCasePaths.append(\\.\(raw: $0.name.text))"
}

let subscriptReturn = allCases.isEmpty ? #"\.never"# : #"return \.never"#

return [
"""
public struct AllCasePaths: Sequence {
public subscript(root: \(enumName)) -> PartialCaseKeyPath<\(enumName)> {
\(raw: rootSubscriptCases.map { "\($0.description)\n" }.joined())return \\.never
\(raw: rootSubscriptCases.map { "\($0.description)\n" }.joined())\(raw: subscriptReturn)
}
\(raw: casePaths.map(\.description).joined(separator: "\n"))
public func makeIterator() -> IndexingIterator<[PartialCaseKeyPath<\(enumName)>]> {
Expand Down
31 changes: 29 additions & 2 deletions Tests/CasePathsMacrosTests/CasePathableMacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,33 @@ final class CasePathableMacroTests: XCTestCase {
}
}

func testCasePathable_NoCases() {
assertMacro {
"""
@CasePathable enum EnumWithNoCases {}
"""
} expansion: {
#"""
enum EnumWithNoCases {
public struct AllCasePaths: Sequence {
public subscript(root: EnumWithNoCases) -> PartialCaseKeyPath<EnumWithNoCases> {
\.never
}
public func makeIterator() -> IndexingIterator<[PartialCaseKeyPath<EnumWithNoCases>]> {
let allCasePaths: [PartialCaseKeyPath<EnumWithNoCases>] = []
return allCasePaths.makeIterator()
}
}
public static var allCasePaths: AllCasePaths { AllCasePaths() }}
extension EnumWithNoCases: CasePaths.CasePathable {
}
"""#
}
}

func testCasePathable_ElementList() {
assertMacro {
"""
Expand Down Expand Up @@ -348,7 +375,7 @@ final class CasePathableMacroTests: XCTestCase {
public struct AllCasePaths: Sequence {
public subscript(root: Foo) -> PartialCaseKeyPath<Foo> {
return \.never
\.never
}
public func makeIterator() -> IndexingIterator<[PartialCaseKeyPath<Foo>]> {
Expand All @@ -371,7 +398,7 @@ final class CasePathableMacroTests: XCTestCase {
public struct AllCasePaths: Sequence {
public subscript(root: Foo) -> PartialCaseKeyPath<Foo> {
return \.never
\.never
}
public func makeIterator() -> IndexingIterator<[PartialCaseKeyPath<Foo>]> {
Expand Down

0 comments on commit e4489f5

Please sign in to comment.