Skip to content

Commit

Permalink
Add redundant typed throws rule (#1718)
Browse files Browse the repository at this point in the history
  • Loading branch information
miguel-jimenez-0529 authored and nicklockwood committed Jun 11, 2024
1 parent 173fc58 commit 765d335
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 0 deletions.
23 changes: 23 additions & 0 deletions Rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
* [redundantSelf](#redundantSelf)
* [redundantStaticSelf](#redundantStaticSelf)
* [redundantType](#redundantType)
* [redundantTypedThrows](#redundantTypedThrows)
* [redundantVoidReturnType](#redundantVoidReturnType)
* [semicolons](#semicolons)
* [sortDeclarations](#sortDeclarations)
Expand Down Expand Up @@ -2047,6 +2048,28 @@ Option | Description
</details>
<br/>

## redundantTypedThrows

Converts `throws(any Error)` to `throws`, and converts `throws(Never)` to non-throwing.

<details>
<summary>Examples</summary>

```diff
- func foo() throws(Never) -> Int {
+ func foo() -> Int {
return 0
}

- func foo() throws(any Error) -> Int {
+ func foo() throws -> Int {
throw MyError.foo
}
```

</details>
<br/>

## redundantVoidReturnType

Remove explicit `Void` return type.
Expand Down
14 changes: 14 additions & 0 deletions Sources/Examples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1897,4 +1897,18 @@ private struct Examples {
}
```
"""

let redundantTypedThrows = """
```diff
- func foo() throws(Never) -> Int {
+ func foo() -> Int {
return 0
}
- func foo() throws(any Error) -> Int {
+ func foo() throws -> Int {
throw MyError.foo
}
```
"""
}
29 changes: 29 additions & 0 deletions Sources/Rules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8013,4 +8013,33 @@ public struct _FormatRules {
)
}
}

public let redundantTypedThrows = FormatRule(help: "Converts `throws(any Error)` to `throws`, and converts `throws(Never)` to non-throwing.") { formatter in

formatter.forEach(.keyword("throws")) { throwsIndex, _ in
guard // Typed throws was added in Swift 6.0: https://github.com/apple/swift-evolution/blob/main/proposals/0413-typed-throws.md
formatter.options.swiftVersion >= "6.0",
let startOfScope = formatter.index(of: .nonSpaceOrCommentOrLinebreak, after: throwsIndex),
formatter.tokens[startOfScope] == .startOfScope("("),
let endOfScope = formatter.endOfScope(at: startOfScope)
else { return }

let throwsTypeRange = (startOfScope + 1) ..< endOfScope
let throwsType: String = formatter.tokens[throwsTypeRange].map { $0.string }.joined()

if throwsType == "Never" {
if formatter.tokens[endOfScope + 1].isSpace {
formatter.removeTokens(in: throwsIndex ... endOfScope + 1)
} else {
formatter.removeTokens(in: throwsIndex ... endOfScope)
}
}

// We don't remove `(Error)` because we can't guarantee it will reference the `Swift.Error` protocol
// (it's relatively common to define a custom error like `enum Error: Swift.Error { ... }`).
if throwsType == "any Error" || throwsType == "any Swift.Error" || throwsType == "Swift.Error" {
formatter.removeTokens(in: startOfScope ... endOfScope)
}
}
}
}
51 changes: 51 additions & 0 deletions Tests/RulesTests+Redundancy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10109,4 +10109,55 @@ class RedundancyTests: RulesTests {

testFormatting(for: input, rule: FormatRules.redundantProperty)
}

// MARK: - redundantTypedThrows

func testRemovesRedundantNeverTypeThrows() {
let input = """
func foo() throws(Never) -> Int {
0
}
"""

let output = """
func foo() -> Int {
0
}
"""

let options = FormatOptions(swiftVersion: "6.0")
testFormatting(for: input, output, rule: FormatRules.redundantTypedThrows, options: options)
}

func testRemovesRedundantAnyErrorTypeThrows() {
let input = """
func foo() throws(any Error) -> Int {
throw MyError.foo
}
"""

let output = """
func foo() throws -> Int {
throw MyError.foo
}
"""

let options = FormatOptions(swiftVersion: "6.0")
testFormatting(for: input, output, rule: FormatRules.redundantTypedThrows, options: options)
}

func testDontRemovesNonRedundantErrorTypeThrows() {
let input = """
func bar() throws(BarError) -> Foo {
throw .foo
}
func foo() throws(Error) -> Int {
throw MyError.foo
}
"""

let options = FormatOptions(swiftVersion: "6.0")
testFormatting(for: input, rule: FormatRules.redundantTypedThrows, options: options)
}
}

0 comments on commit 765d335

Please sign in to comment.