Skip to content

Commit

Permalink
Add —nilinit for redundantNilInit rule (#1680)
Browse files Browse the repository at this point in the history
  • Loading branch information
rakuyoMo authored and nicklockwood committed Jun 9, 2024
1 parent b135d17 commit 1a1c749
Show file tree
Hide file tree
Showing 6 changed files with 331 additions and 31 deletions.
15 changes: 14 additions & 1 deletion Rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -1686,11 +1686,17 @@ Remove redundant `let error` from `catch` clause.

## redundantNilInit

Remove redundant `nil` default value (Optional vars are nil by default).
Remove/insert redundant `nil` default value (Optional vars are nil by default).

Option | Description
--- | ---
`--nilinit` | "remove" (default) redundant nil or "insert" missing nil

<details>
<summary>Examples</summary>

`--nilinit remove`

```diff
- var foo: Int? = nil
+ var foo: Int?
Expand All @@ -1706,6 +1712,13 @@ let foo: Int? = nil
var foo: Int? = 0
```

`--nilinit insert`

```diff
- var foo: Int?
+ var foo: Int? = nil
```

</details>
<br/>

Expand Down
9 changes: 9 additions & 0 deletions Sources/Examples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,8 @@ private struct Examples {
"""

let redundantNilInit = """
`--nilinit remove`
```diff
- var foo: Int? = nil
+ var foo: Int?
Expand All @@ -566,6 +568,13 @@ private struct Examples {
// doesn't affect non-nil initialization
var foo: Int? = 0
```
`--nilinit insert`
```diff
- var foo: Int?
+ var foo: Int? = nil
```
"""

let redundantObjc = """
Expand Down
6 changes: 6 additions & 0 deletions Sources/OptionDescriptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,12 @@ struct _Descriptors {
fromArgument: { FormatTimeZone(rawValue: $0) },
toArgument: { $0.rawValue }
)
let nilInit = OptionDescriptor(
argumentName: "nilinit",
displayName: "Nil init type",
help: "\"remove\" (default) redundant nil or \"insert\" missing nil",
keyPath: \.nilInit
)

// MARK: - Internal

Expand Down
13 changes: 13 additions & 0 deletions Sources/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,16 @@ public enum FormatTimeZone: Equatable, RawRepresentable, CustomStringConvertible
}
}

/// When initializing an optional value type,
/// is it necessary to explicitly declare a default value
public enum NilInitType: String, CaseIterable {
/// Remove redundant `nil` if it is added as default value
case remove

/// Add `nil` as default if not explicitly declared
case insert
}

/// Configuration options for formatting. These aren't actually used by the
/// Formatter class itself, but it makes them available to the format rules.
public struct FormatOptions: CustomStringConvertible {
Expand Down Expand Up @@ -640,6 +650,7 @@ public struct FormatOptions: CustomStringConvertible {
public var initCoderNil: Bool
public var dateFormat: DateFormat
public var timeZone: FormatTimeZone
public var nilInit: NilInitType

/// Deprecated
public var indentComments: Bool
Expand Down Expand Up @@ -753,6 +764,7 @@ public struct FormatOptions: CustomStringConvertible {
initCoderNil: Bool = false,
dateFormat: DateFormat = .system,
timeZone: FormatTimeZone = .system,
nilInit: NilInitType = .remove,
// Doesn't really belong here, but hard to put elsewhere
fragment: Bool = false,
ignoreConflictMarkers: Bool = false,
Expand Down Expand Up @@ -856,6 +868,7 @@ public struct FormatOptions: CustomStringConvertible {
self.initCoderNil = initCoderNil
self.dateFormat = dateFormat
self.timeZone = timeZone
self.nilInit = nilInit
// Doesn't really belong here, but hard to put elsewhere
self.fragment = fragment
self.ignoreConflictMarkers = ignoreConflictMarkers
Expand Down
30 changes: 20 additions & 10 deletions Sources/Rules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2944,23 +2944,33 @@ public struct _FormatRules {
}
}
/// Remove redundant `= nil` initialization for Optional properties
/// Remove or insert redundant `= nil` initialization for Optional properties
public let redundantNilInit = FormatRule(
help: "Remove redundant `nil` default value (Optional vars are nil by default)."
help: "Remove/insert redundant `nil` default value (Optional vars are nil by default).",
options: ["nilinit"]
) { formatter in
func search(from index: Int) {
if let optionalIndex = formatter.index(of: .unwrapOperator, after: index) {
if formatter.index(of: .endOfStatement, in: index + 1 ..< optionalIndex) != nil {
return
}
if !formatter.tokens[optionalIndex - 1].isSpaceOrCommentOrLinebreak,
let equalsIndex = formatter.index(of: .nonSpaceOrLinebreak, after: optionalIndex, if: {
$0 == .operator("=", .infix)
}), let nilIndex = formatter.index(of: .nonSpaceOrLinebreak, after: equalsIndex, if: {
$0 == .identifier("nil")
})
{
formatter.removeTokens(in: optionalIndex + 1 ... nilIndex)
if !formatter.tokens[optionalIndex - 1].isSpaceOrCommentOrLinebreak {
let equalsIndex = formatter.index(of: .nonSpaceOrLinebreak, after: optionalIndex, if: {
$0 == .operator("=", .infix)
})
switch formatter.options.nilInit {
case .remove:
if let equalsIndex = equalsIndex, let nilIndex = formatter.index(of: .nonSpaceOrLinebreak, after: equalsIndex, if: {
$0 == .identifier("nil")
}) {
formatter.removeTokens(in: optionalIndex + 1 ... nilIndex)
}
case .insert:
if equalsIndex == nil {
let tokens: [Token] = [.space(" "), .operator("=", .infix), .space(" "), .identifier("nil")]
formatter.insert(tokens, at: optionalIndex + 1)
}
}
}
search(from: optionalIndex)
}
Expand Down
Loading

0 comments on commit 1a1c749

Please sign in to comment.