Skip to content

Commit f600ed0

Browse files
authored
Add rule to prefer opaque generic parameter syntax (#193)
1 parent f7f2ff9 commit f600ed0

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ let package = Package(
3838

3939
.binaryTarget(
4040
name: "SwiftFormat",
41-
url: "https://github.com/calda/SwiftFormat/releases/download/0.50-beta-4/SwiftFormat.artifactbundle.zip",
42-
checksum: "b7dfc4e623c1a6686d51904f74f7898194b950cd1db65f831bd3c0e0e6e70749"),
41+
url: "https://github.com/calda/SwiftFormat/releases/download/0.51-beta-2/SwiftFormat.artifactbundle.zip",
42+
checksum: "77066735bb56a2f2f37d8bfbd7606612b206d99c15ec3250e712c6a842c823a2"),
4343

4444
.binaryTarget(
4545
name: "SwiftLintBinary",

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,6 +2221,72 @@ _You can enable the following settings in Xcode by running [this script](resourc
22212221

22222222
</details>
22232223

2224+
* <a id='prefer-opaque-generic-parameters'></a>(<a href='#prefer-opaque-generic-parameters'>link</a>) **Prefer using opaque generic parameters (with `some`) over verbose named generic parameter syntax where possible.** [![SwiftFormat: opaqueGenericParameters](https://img.shields.io/badge/SwiftFormat-opaqueGenericParameters-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#opaqueGenericParameters)
2225+
2226+
<details>
2227+
2228+
#### Why?
2229+
2230+
Opaque generic parameter syntax is significantly less verbose and thus more legible than the full named generic parameter syntax.
2231+
2232+
```swift
2233+
// WRONG
2234+
func spaceshipDashboard<WarpDriveView: View, CaptainsLogView: View>(
2235+
warpDrive: WarpDriveView,
2236+
captainsLog: CaptainsLogView)
2237+
-> some View
2238+
{ }
2239+
2240+
func generate<Planets>(_ planets: Planets) where Planets: Collection, Planets.Element == Planet {
2241+
2242+
}
2243+
2244+
// RIGHT
2245+
func spaceshipDashboard(
2246+
warpDrive: some View,
2247+
captainsLog: some View)
2248+
-> some View
2249+
{ }
2250+
2251+
func generate(_ planets: some Collection<Planet>) {
2252+
2253+
}
2254+
2255+
// Also fine, since there isn't an equivalent opaque parameter syntax for expressing
2256+
// that two parameters in the type signature are of the same type:
2257+
func terraform<Body: PlanetaryBody>(_ planetaryBody: Body, into terraformedBody: Body) {
2258+
2259+
}
2260+
2261+
// Also fine, since the generic patameter name is referenced in the function body so can't be removed:
2262+
func terraform<Body: PlanetaryBody>(_ planetaryBody: Body) {
2263+
plataryBody.generateAtmosphere(Body.idealAtmosphere)
2264+
}
2265+
```
2266+
2267+
#### `some Any`
2268+
2269+
Fully-unconstrained generic parameters are somewhat uncommon, but are equivalent to `some Any`. For example:
2270+
2271+
```swift
2272+
func assertFailure<Value>(_ result: Result<Value, Error>) {
2273+
if case .failure(let error) = result {
2274+
XCTFail(error.localizedDescription)
2275+
}
2276+
}
2277+
2278+
// is equivalent to:
2279+
func assertFailure(_ result: Result<some Any, Error>) {
2280+
if case .failure(let error) = result {
2281+
XCTFail(error.localizedDescription)
2282+
}
2283+
}
2284+
```
2285+
2286+
`some Any` is somewhat unintuitive, and the named generic parameter is useful in this situation to compensate for the weak type information. Because of this, prefer using named generic parameters instead of `some Any`.
2287+
2288+
</details>
2289+
22242290
**[ back to top](#table-of-contents)**
22252291

22262292
## File Organization

Sources/AirbnbSwiftFormatTool/airbnb.swiftformat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
--redundanttype inferred # redundantType
2626
--typeblanklines preserve # blankLinesAtStartOfScope, blankLinesAtEndOfScope
2727
--emptybraces spaced # emptyBraces
28+
--someAny disabled # opaqueGenericParameters
2829

2930
# We recommend a max width of 100 but _strictly enforce_ a max width of 130
3031
--maxwidth 130 # wrap
@@ -76,5 +77,6 @@
7677
--rules blankLinesAtEndOfScope
7778
--rules emptyBraces
7879
--rules andOperator
80+
--rules opaqueGenericParameters
7981
--rules genericExtensions
8082
--rules trailingClosures

0 commit comments

Comments
 (0)