Skip to content

Commit

Permalink
Add rule to prefer a generated Equatable implementation when possible (
Browse files Browse the repository at this point in the history
  • Loading branch information
calda authored Oct 4, 2024
1 parent 0b853e3 commit b879ec6
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ let package = Package(

.binaryTarget(
name: "swiftformat",
url: "https://github.com/calda/SwiftFormat/releases/download/0.55-beta-12/SwiftFormat.artifactbundle.zip",
checksum: "8783cefc0837416759f81064df7907cc60ddca6d3f8c3b301b123a2193a8585b"),
url: "https://github.com/calda/SwiftFormat/releases/download/0.55-beta-15/SwiftFormat.artifactbundle.zip",
checksum: "5da82a61d4a29e77acc5a2e8668c40168970e1d6b2078bdfcb377b6f6ef35039"),

.binaryTarget(
name: "SwiftLintBinary",
Expand Down
68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3677,6 +3677,74 @@ _You can enable the following settings in Xcode by running [this script](resourc

</details>

* <a id='redundant-equatable-implementation'></a>(<a href='#redundant-equatable-implementation'>link</a>) **Prefer using a generated Equatable implementation when comparing all properties of a type.** For structs, prefer using the compiler-synthesized Equatable implementation when possible. [![SwiftFormat: redundantEquatable](https://img.shields.io/badge/SwiftFormat-redundantEquatable-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#redundantEquatable)

<details>

### Why?

Manually-implemented Equatable implementations are verbose, and keeping them up-to-date is error-prone. For example, when adding a new property, it's possible to forget to update the Equatable implementation to compare it.

```swift
/// WRONG: The `static func ==` implementation is redundant and error-prone.
struct Planet: Equatable {
let mass: Double
let orbit: OrbitalElements
let rotation: Double

static func ==(lhs: Planet, rhs: Planet) -> Bool {
lhs.mass == rhs.mass
&& lhs.orbit == rhs.orbit
&& lhs.rotation == rhs.rotation
}
}

/// RIGHT: The `static func ==` implementation is synthesized by the compiler.
struct Planet: Equatable {
let mass: Double
let orbit: OrbitalElements
let rotation: Double
}

/// ALSO RIGHT: The `static func ==` implementation differs from the implementation that
/// would be synthesized by the compiler and compared all properties, so is not redundant.
struct CelestialBody: Equatable {
let id: UUID
let orbit: OrbitalElements

static func ==(lhs: Planet, rhs: Planet) -> Bool {
lhs.id == rhs.id
}
}
```

In projects that provide an `@Equatable` macro, prefer using that macro to generate the `static func ==` for classes rather than implementing it manually.

```swift
/// WRONG: The `static func ==` implementation is verbose and error-prone.
final class Planet: Equatable {
let mass: Double
let orbit: OrbitalElements
let rotation: Double

static func ==(lhs: Planet, rhs: Planet) -> Bool {
lhs.mass == rhs.mass
&& lhs.orbit == rhs.orbit
&& lhs.rotation == rhs.rotation
}
}

/// RIGHT: The `static func ==` implementation is generated by the `@Equatable` macro.
@Equatable
final class struct Planet: Equatable {
let mass: Double
let orbit: OrbitalElements
let rotation: Double
}
```

</details>

* <a id='void-type'></a>(<a href='#void-type'>link</a>) **Avoid using `()` as a type**. Prefer `Void`.

<details>
Expand Down
1 change: 1 addition & 0 deletions Sources/AirbnbSwiftFormatTool/airbnb.swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
--rules redundantGet
--rules redundantFileprivate
--rules redundantRawValues
--rules redundantEquatable
--rules sortImports
--rules sortDeclarations
--rules strongifiedSelf
Expand Down

0 comments on commit b879ec6

Please sign in to comment.