mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-05-17 10:30:35 +00:00
4655 lines
87 KiB
Markdown
4655 lines
87 KiB
Markdown
# Default Rules (enabled by default)
|
|
|
|
* [andOperator](#andOperator)
|
|
* [anyObjectProtocol](#anyObjectProtocol)
|
|
* [applicationMain](#applicationMain)
|
|
* [assertionFailures](#assertionFailures)
|
|
* [blankLineAfterImports](#blankLineAfterImports)
|
|
* [blankLinesAroundMark](#blankLinesAroundMark)
|
|
* [blankLinesAtEndOfScope](#blankLinesAtEndOfScope)
|
|
* [blankLinesAtStartOfScope](#blankLinesAtStartOfScope)
|
|
* [blankLinesBetweenChainedFunctions](#blankLinesBetweenChainedFunctions)
|
|
* [blankLinesBetweenImports](#blankLinesBetweenImports)
|
|
* [blankLinesBetweenScopes](#blankLinesBetweenScopes)
|
|
* [braces](#braces)
|
|
* [conditionalAssignment](#conditionalAssignment)
|
|
* [consecutiveBlankLines](#consecutiveBlankLines)
|
|
* [consecutiveSpaces](#consecutiveSpaces)
|
|
* [consistentSwitchCaseSpacing](#consistentSwitchCaseSpacing)
|
|
* [docComments](#docComments)
|
|
* [docCommentsBeforeModifiers](#docCommentsBeforeModifiers)
|
|
* [duplicateImports](#duplicateImports)
|
|
* [elseOnSameLine](#elseOnSameLine)
|
|
* [emptyBraces](#emptyBraces)
|
|
* [emptyExtensions](#emptyExtensions)
|
|
* [enumNamespaces](#enumNamespaces)
|
|
* [environmentEntry](#environmentEntry)
|
|
* [extensionAccessControl](#extensionAccessControl)
|
|
* [fileHeader](#fileHeader)
|
|
* [fileMacro](#fileMacro)
|
|
* [genericExtensions](#genericExtensions)
|
|
* [headerFileName](#headerFileName)
|
|
* [hoistAwait](#hoistAwait)
|
|
* [hoistPatternLet](#hoistPatternLet)
|
|
* [hoistTry](#hoistTry)
|
|
* [indent](#indent)
|
|
* [initCoderUnavailable](#initCoderUnavailable)
|
|
* [leadingDelimiters](#leadingDelimiters)
|
|
* [linebreakAtEndOfFile](#linebreakAtEndOfFile)
|
|
* [linebreaks](#linebreaks)
|
|
* [modifierOrder](#modifierOrder)
|
|
* [modifiersOnSameLine](#modifiersOnSameLine)
|
|
* [noForceTryInTests](#noForceTryInTests)
|
|
* [noForceUnwrapInTests](#noForceUnwrapInTests)
|
|
* [numberFormatting](#numberFormatting)
|
|
* [opaqueGenericParameters](#opaqueGenericParameters)
|
|
* [preferCountWhere](#preferCountWhere)
|
|
* [preferForLoop](#preferForLoop)
|
|
* [preferKeyPath](#preferKeyPath)
|
|
* [redundantAsync](#redundantAsync)
|
|
* [redundantBackticks](#redundantBackticks)
|
|
* [redundantBreak](#redundantBreak)
|
|
* [redundantClosure](#redundantClosure)
|
|
* [redundantEmptyView](#redundantEmptyView)
|
|
* [redundantEquatable](#redundantEquatable)
|
|
* [redundantExtensionACL](#redundantExtensionACL)
|
|
* [redundantFileprivate](#redundantFileprivate)
|
|
* [redundantGet](#redundantGet)
|
|
* [redundantInit](#redundantInit)
|
|
* [redundantInternal](#redundantInternal)
|
|
* [redundantLet](#redundantLet)
|
|
* [redundantLetError](#redundantLetError)
|
|
* [redundantMemberwiseInit](#redundantMemberwiseInit)
|
|
* [redundantNilInit](#redundantNilInit)
|
|
* [redundantObjc](#redundantObjc)
|
|
* [redundantOptionalBinding](#redundantOptionalBinding)
|
|
* [redundantParens](#redundantParens)
|
|
* [redundantPattern](#redundantPattern)
|
|
* [redundantPublic](#redundantPublic)
|
|
* [redundantRawValues](#redundantRawValues)
|
|
* [redundantReturn](#redundantReturn)
|
|
* [redundantSelf](#redundantSelf)
|
|
* [redundantSendable](#redundantSendable)
|
|
* [redundantStaticSelf](#redundantStaticSelf)
|
|
* [redundantSwiftTestingSuite](#redundantSwiftTestingSuite)
|
|
* [redundantThrows](#redundantThrows)
|
|
* [redundantType](#redundantType)
|
|
* [redundantTypedThrows](#redundantTypedThrows)
|
|
* [redundantVariable](#redundantVariable)
|
|
* [redundantViewBuilder](#redundantViewBuilder)
|
|
* [redundantVoidReturnType](#redundantVoidReturnType)
|
|
* [semicolons](#semicolons)
|
|
* [simplifyGenericConstraints](#simplifyGenericConstraints)
|
|
* [sortDeclarations](#sortDeclarations)
|
|
* [sortImports](#sortImports)
|
|
* [sortTypealiases](#sortTypealiases)
|
|
* [spaceAroundBraces](#spaceAroundBraces)
|
|
* [spaceAroundBrackets](#spaceAroundBrackets)
|
|
* [spaceAroundComments](#spaceAroundComments)
|
|
* [spaceAroundGenerics](#spaceAroundGenerics)
|
|
* [spaceAroundOperators](#spaceAroundOperators)
|
|
* [spaceAroundParens](#spaceAroundParens)
|
|
* [spaceInsideBraces](#spaceInsideBraces)
|
|
* [spaceInsideBrackets](#spaceInsideBrackets)
|
|
* [spaceInsideComments](#spaceInsideComments)
|
|
* [spaceInsideGenerics](#spaceInsideGenerics)
|
|
* [spaceInsideParens](#spaceInsideParens)
|
|
* [strongOutlets](#strongOutlets)
|
|
* [strongifiedSelf](#strongifiedSelf)
|
|
* [swiftTestingTestCaseNames](#swiftTestingTestCaseNames)
|
|
* [todos](#todos)
|
|
* [trailingClosures](#trailingClosures)
|
|
* [trailingCommas](#trailingCommas)
|
|
* [trailingSpace](#trailingSpace)
|
|
* [typeSugar](#typeSugar)
|
|
* [unusedArguments](#unusedArguments)
|
|
* [void](#void)
|
|
* [wrap](#wrap)
|
|
* [wrapArguments](#wrapArguments)
|
|
* [wrapAttributes](#wrapAttributes)
|
|
* [wrapFunctionBodies](#wrapFunctionBodies)
|
|
* [wrapLoopBodies](#wrapLoopBodies)
|
|
* [wrapMultilineStatementBraces](#wrapMultilineStatementBraces)
|
|
* [wrapPropertyBodies](#wrapPropertyBodies)
|
|
* [wrapSingleLineComments](#wrapSingleLineComments)
|
|
* [yodaConditions](#yodaConditions)
|
|
|
|
# Opt-in Rules (disabled by default)
|
|
|
|
* [acronyms](#acronyms)
|
|
* [blankLineAfterSwitchCase](#blankLineAfterSwitchCase)
|
|
* [blankLinesAfterGuardStatements](#blankLinesAfterGuardStatements)
|
|
* [blockComments](#blockComments)
|
|
* [isEmpty](#isEmpty)
|
|
* [markTypes](#markTypes)
|
|
* [noExplicitOwnership](#noExplicitOwnership)
|
|
* [noGuardInTests](#noGuardInTests)
|
|
* [organizeDeclarations](#organizeDeclarations)
|
|
* [preferExplicitFalse](#preferExplicitFalse)
|
|
* [preferFinalClasses](#preferFinalClasses)
|
|
* [preferSwiftStringAPI](#preferSwiftStringAPI)
|
|
* [preferSwiftTesting](#preferSwiftTesting)
|
|
* [privateStateVariables](#privateStateVariables)
|
|
* [propertyTypes](#propertyTypes)
|
|
* [singlePropertyPerLine](#singlePropertyPerLine)
|
|
* [sortSwitchCases](#sortSwitchCases)
|
|
* [testSuiteAccessControl](#testSuiteAccessControl)
|
|
* [unusedPrivateDeclarations](#unusedPrivateDeclarations)
|
|
* [urlMacro](#urlMacro)
|
|
* [validateTestCases](#validateTestCases)
|
|
* [wrapCaseBodies](#wrapCaseBodies)
|
|
* [wrapConditionalBodies](#wrapConditionalBodies)
|
|
* [wrapEnumCases](#wrapEnumCases)
|
|
* [wrapMultilineConditionalAssignment](#wrapMultilineConditionalAssignment)
|
|
* [wrapMultilineFunctionChains](#wrapMultilineFunctionChains)
|
|
* [wrapSwitchCases](#wrapSwitchCases)
|
|
|
|
# Deprecated Rules (do not use)
|
|
|
|
* [redundantProperty](#redundantProperty)
|
|
* [sortedImports](#sortedImports)
|
|
* [sortedSwitchCases](#sortedSwitchCases)
|
|
* [specifiers](#specifiers)
|
|
* [throwingTests](#throwingTests)
|
|
|
|
----------
|
|
|
|
## acronyms
|
|
|
|
Capitalize acronyms when the first character is capitalized.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--acronyms` | Acronyms to auto-capitalize. Defaults to "ID,URL,UUID"
|
|
`--preserve-acronyms` | List of symbols to be ignored by the acronyms rule
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let destinationUrl: URL
|
|
- let urlRouter: UrlRouter
|
|
- let screenIds: [String]
|
|
- let entityUuid: UUID
|
|
|
|
+ let destinationURL: URL
|
|
+ let urlRouter: URLRouter
|
|
+ let screenIDs: [String]
|
|
+ let entityUUID: UUID
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## andOperator
|
|
|
|
Prefer comma over `&&` in `if`, `guard` or `while` conditions.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if true && true {
|
|
+ if true, true {
|
|
```
|
|
|
|
```diff
|
|
- guard true && true else {
|
|
+ guard true, true else {
|
|
```
|
|
|
|
```diff
|
|
- if functionReturnsBool() && true {
|
|
+ if functionReturnsBool(), true {
|
|
```
|
|
|
|
```diff
|
|
- if functionReturnsBool() && variable {
|
|
+ if functionReturnsBool(), variable {
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## anyObjectProtocol
|
|
|
|
Prefer `AnyObject` over `class` in protocol definitions.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- protocol Foo: class {}
|
|
+ protocol Foo: AnyObject {}
|
|
```
|
|
|
|
**NOTE:** The guideline to use `AnyObject` instead of `class` was only
|
|
introduced in Swift 4.1, so the `anyObjectProtocol` rule is disabled unless the
|
|
swift version is set to 4.1 or above.
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## applicationMain
|
|
|
|
Replace obsolete @UIApplicationMain and @NSApplicationMain attributes
|
|
with @main for Swift 5.3 and above.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- @UIApplicationMain
|
|
+ @main
|
|
class AppDelegate: UIResponder, UIApplicationDelegate {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## assertionFailures
|
|
|
|
Changes all instances of assert(false, ...) to assertionFailure(...)
|
|
and precondition(false, ...) to preconditionFailure(...).
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- assert(false)
|
|
+ assertionFailure()
|
|
```
|
|
|
|
```diff
|
|
- assert(false, "message", 2, 1)
|
|
+ assertionFailure("message", 2, 1)
|
|
```
|
|
|
|
```diff
|
|
- precondition(false, "message", 2, 1)
|
|
+ preconditionFailure("message", 2, 1)
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLineAfterImports
|
|
|
|
Insert blank line after import statements.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import A
|
|
import B
|
|
@testable import D
|
|
+
|
|
class Foo {
|
|
// foo
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLineAfterSwitchCase
|
|
|
|
Insert a blank line after switch cases (excluding the last case,
|
|
which is followed by a closing brace).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--blank-line-after-switch-case` | Insert line After switch cases: "always" or "multiline-only" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
`--blank-line-after-switch-case multiline-only` (default)
|
|
|
|
```diff
|
|
func handle(_ action: SpaceshipAction) {
|
|
switch action {
|
|
case .engageWarpDrive:
|
|
navigationComputer.destination = targetedDestination
|
|
await warpDrive.spinUp()
|
|
warpDrive.activate()
|
|
+
|
|
case let .scanPlanet(planet):
|
|
scanner.target = planet
|
|
scanner.scanAtmosphere()
|
|
scanner.scanBiosphere()
|
|
scanner.scanForArticialLife()
|
|
+
|
|
case .handleIncomingEnergyBlast:
|
|
await energyShields.prepare()
|
|
energyShields.engage()
|
|
}
|
|
}
|
|
```
|
|
|
|
```diff
|
|
func handle(_ action: SpaceshipAction) {
|
|
switch action {
|
|
case .engageWarpDrive:
|
|
warpDrive.activate()
|
|
|
|
case let .scanPlanet(planet):
|
|
scanner.scanForArticialLife()
|
|
|
|
case .handleIncomingEnergyBlast:
|
|
energyShields.engage()
|
|
}
|
|
}
|
|
```
|
|
`--blank-line-after-switch-case always`
|
|
|
|
```diff
|
|
func handle(_ action: SpaceshipAction) {
|
|
switch action {
|
|
case .engageWarpDrive:
|
|
navigationComputer.destination = targetedDestination
|
|
await warpDrive.spinUp()
|
|
warpDrive.activate()
|
|
+
|
|
case let .scanPlanet(planet):
|
|
scanner.target = planet
|
|
scanner.scanAtmosphere()
|
|
scanner.scanBiosphere()
|
|
scanner.scanForArticialLife()
|
|
+
|
|
case .handleIncomingEnergyBlast:
|
|
await energyShields.prepare()
|
|
energyShields.engage()
|
|
}
|
|
}
|
|
```
|
|
|
|
```diff
|
|
func handle(_ action: SpaceshipAction) {
|
|
switch action {
|
|
case .engageWarpDrive:
|
|
warpDrive.activate()
|
|
+
|
|
case let .scanPlanet(planet):
|
|
scanner.scanForArticialLife()
|
|
+
|
|
case .handleIncomingEnergyBlast:
|
|
energyShields.engage()
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLinesAfterGuardStatements
|
|
|
|
Remove blank lines between consecutive guard statements, and insert a blank after the last guard statement.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--line-between-guards` | Insert line between guards: "true" or "false" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
`--line-between-guards false` (default)
|
|
|
|
```diff
|
|
// Multiline guard
|
|
guard let spicy = self.makeSpicy() else {
|
|
return
|
|
}
|
|
-
|
|
guard let yummy = self.makeYummy() else {
|
|
return
|
|
}
|
|
guard let soap = self.clean() else {
|
|
return
|
|
}
|
|
+
|
|
let doTheJob = nikekov()
|
|
```
|
|
```diff
|
|
// Single-line guard
|
|
guard let spicy = self.makeSpicy() else { return }
|
|
-
|
|
guard let yummy = self.makeYummy() else { return }
|
|
guard let soap = self.clean() else { return }
|
|
+
|
|
let doTheJob = nikekov()
|
|
```
|
|
|
|
`--line-between-guards true`
|
|
|
|
```diff
|
|
// Multiline guard
|
|
guard let spicy = self.makeSpicy() else {
|
|
return
|
|
}
|
|
|
|
guard let yummy = self.makeYummy() else {
|
|
return
|
|
}
|
|
+
|
|
guard let soap = self.clean() else {
|
|
return
|
|
}
|
|
+
|
|
let doTheJob = nikekov()
|
|
```
|
|
```diff
|
|
// Single-line guard
|
|
guard let spicy = self.makeSpicy() else { return }
|
|
|
|
guard let yummy = self.makeYummy() else { return }
|
|
+
|
|
guard let soap = self.clean() else { return }
|
|
+
|
|
let doTheJob = nikekov()
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLinesAroundMark
|
|
|
|
Insert blank line before and after `MARK:` comments.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--line-after-marks` | Insert blank line after "MARK:": "true" (default) or "false"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func foo() {
|
|
// foo
|
|
}
|
|
// MARK: bar
|
|
func bar() {
|
|
// bar
|
|
}
|
|
|
|
func foo() {
|
|
// foo
|
|
}
|
|
+
|
|
// MARK: bar
|
|
+
|
|
func bar() {
|
|
// bar
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLinesAtEndOfScope
|
|
|
|
Remove or insert trailing blank line at the end of a scope.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--type-blank-lines` | Blank lines in type declarations: "remove" (default), "insert" or "preserve"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func foo() {
|
|
// foo
|
|
-
|
|
}
|
|
|
|
func foo() {
|
|
// foo
|
|
}
|
|
```
|
|
|
|
```diff
|
|
array = [
|
|
foo,
|
|
bar,
|
|
baz,
|
|
-
|
|
]
|
|
|
|
array = [
|
|
foo,
|
|
bar,
|
|
baz,
|
|
]
|
|
```
|
|
|
|
With `--type-blank-lines insert`:
|
|
|
|
```diff
|
|
struct Foo {
|
|
let bar: Bar
|
|
+
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLinesAtStartOfScope
|
|
|
|
Remove leading blank line at the start of a scope.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--type-blank-lines` | Blank lines in type declarations: "remove" (default), "insert" or "preserve"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func foo() {
|
|
-
|
|
// foo
|
|
}
|
|
|
|
func foo() {
|
|
// foo
|
|
}
|
|
```
|
|
|
|
```diff
|
|
array = [
|
|
-
|
|
foo,
|
|
bar,
|
|
baz,
|
|
]
|
|
|
|
array = [
|
|
foo,
|
|
bar,
|
|
baz,
|
|
]
|
|
```
|
|
|
|
With `--type-blank-lines insert`:
|
|
|
|
```diff
|
|
struct Foo {
|
|
+
|
|
let bar: Bar
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLinesBetweenChainedFunctions
|
|
|
|
Remove blank lines between chained functions but keep the linebreaks.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
[0, 1, 2]
|
|
.map { $0 * 2 }
|
|
-
|
|
-
|
|
-
|
|
.map { $0 * 3 }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLinesBetweenImports
|
|
|
|
Remove blank lines between import statements.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import A
|
|
-
|
|
import B
|
|
import C
|
|
-
|
|
-
|
|
@testable import D
|
|
import E
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blankLinesBetweenScopes
|
|
|
|
Insert blank line before class, struct, enum, extension, protocol or function
|
|
declarations.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func foo() {
|
|
// foo
|
|
}
|
|
func bar() {
|
|
// bar
|
|
}
|
|
var baz: Bool
|
|
var quux: Int
|
|
|
|
func foo() {
|
|
// foo
|
|
}
|
|
+
|
|
func bar() {
|
|
// bar
|
|
}
|
|
+
|
|
var baz: Bool
|
|
var quux: Int
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## blockComments
|
|
|
|
Convert block comments to consecutive single line comments.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- /*
|
|
- * foo
|
|
- * bar
|
|
- */
|
|
|
|
+ // foo
|
|
+ // bar
|
|
```
|
|
|
|
```diff
|
|
- /**
|
|
- * foo
|
|
- * bar
|
|
- */
|
|
|
|
+ /// foo
|
|
+ /// bar
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## braces
|
|
|
|
Wrap braces in accordance with selected style (K&R or Allman).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--allman` | Use Allman indentation style: "true" or "false" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if x
|
|
- {
|
|
// foo
|
|
}
|
|
- else
|
|
- {
|
|
// bar
|
|
}
|
|
|
|
+ if x {
|
|
// foo
|
|
}
|
|
+ else {
|
|
// bar
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## conditionalAssignment
|
|
|
|
Assign properties using if / switch expressions.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--conditional-assignment` | Use if/switch expressions for conditional assignment: "after-property" (default) or "always"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let foo: String
|
|
- if condition {
|
|
+ let foo = if condition {
|
|
- foo = "foo"
|
|
+ "foo"
|
|
} else {
|
|
- foo = "bar"
|
|
+ "bar"
|
|
}
|
|
|
|
- let foo: String
|
|
- switch condition {
|
|
+ let foo = switch condition {
|
|
case true:
|
|
- foo = "foo"
|
|
+ "foo"
|
|
case false:
|
|
- foo = "bar"
|
|
+ "bar"
|
|
}
|
|
|
|
// With --condassignment always (disabled by default)
|
|
- switch condition {
|
|
+ foo.bar = switch condition {
|
|
case true:
|
|
- foo.bar = "baaz"
|
|
+ "baaz"
|
|
case false:
|
|
- foo.bar = "quux"
|
|
+ "quux"
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## consecutiveBlankLines
|
|
|
|
Replace consecutive blank lines with a single blank line.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func foo() {
|
|
let x = "bar"
|
|
-
|
|
|
|
print(x)
|
|
}
|
|
|
|
func foo() {
|
|
let x = "bar"
|
|
|
|
print(x)
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## consecutiveSpaces
|
|
|
|
Replace consecutive spaces with a single space.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let foo = 5
|
|
+ let foo = 5
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## consistentSwitchCaseSpacing
|
|
|
|
Ensures consistent spacing among all of the cases in a switch statement.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func handle(_ action: SpaceshipAction) {
|
|
switch action {
|
|
case .engageWarpDrive:
|
|
navigationComputer.destination = targetedDestination
|
|
await warpDrive.spinUp()
|
|
warpDrive.activate()
|
|
|
|
case .enableArtificialGravity:
|
|
artificialGravityEngine.enable(strength: .oneG)
|
|
+
|
|
case let .scanPlanet(planet):
|
|
scanner.target = planet
|
|
scanner.scanAtmosphere()
|
|
scanner.scanBiosphere()
|
|
scanner.scanForArtificialLife()
|
|
|
|
case .handleIncomingEnergyBlast:
|
|
energyShields.engage()
|
|
}
|
|
}
|
|
```
|
|
|
|
```diff
|
|
var name: PlanetType {
|
|
switch self {
|
|
case .mercury:
|
|
"Mercury"
|
|
-
|
|
case .venus:
|
|
"Venus"
|
|
case .earth:
|
|
"Earth"
|
|
case .mars:
|
|
"Mars"
|
|
-
|
|
case .jupiter:
|
|
"Jupiter"
|
|
case .saturn:
|
|
"Saturn"
|
|
case .uranus:
|
|
"Uranus"
|
|
case .neptune:
|
|
"Neptune"
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## docComments
|
|
|
|
Use doc comments for API declarations, otherwise use regular comments.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--doc-comments` | Preserve doc comments: "preserve" or "before-declarations" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- // A placeholder type used to demonstrate syntax rules
|
|
+ /// A placeholder type used to demonstrate syntax rules
|
|
class Foo {
|
|
- // This function doesn't really do anything
|
|
+ /// This function doesn't really do anything
|
|
func bar() {
|
|
- /// TODO: implement Foo.bar() algorithm
|
|
+ // TODO: implement Foo.bar() algorithm
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## docCommentsBeforeModifiers
|
|
|
|
Place doc comments before any declaration modifiers or attributes.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
+ /// Doc comment on this function declaration
|
|
@MainActor
|
|
- /// Doc comment on this function declaration
|
|
func foo() {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## duplicateImports
|
|
|
|
Remove duplicate import statements.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import Foo
|
|
import Bar
|
|
- import Foo
|
|
```
|
|
|
|
```diff
|
|
import B
|
|
#if os(iOS)
|
|
import A
|
|
- import B
|
|
#endif
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## elseOnSameLine
|
|
|
|
Place `else`, `catch` or `while` keyword in accordance with current style (same or
|
|
next line).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--else-position` | Placement of else/catch: "same-line" (default) or "next-line"
|
|
`--guard-else` | Placement of else in guard statements: "same-line", "next-line" or "auto" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
if x {
|
|
// foo
|
|
- }
|
|
- else {
|
|
// bar
|
|
}
|
|
|
|
if x {
|
|
// foo
|
|
+ } else {
|
|
// bar
|
|
}
|
|
```
|
|
|
|
```diff
|
|
do {
|
|
// try foo
|
|
- }
|
|
- catch {
|
|
// bar
|
|
}
|
|
|
|
do {
|
|
// try foo
|
|
+ } catch {
|
|
// bar
|
|
}
|
|
```
|
|
|
|
```diff
|
|
repeat {
|
|
// foo
|
|
- }
|
|
- while {
|
|
// bar
|
|
}
|
|
|
|
repeat {
|
|
// foo
|
|
+ } while {
|
|
// bar
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## emptyBraces
|
|
|
|
Remove whitespace inside empty braces.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--empty-braces` | Empty brace spacing: "spaced", "no-space" (default) or "linebreak"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- func foo() {
|
|
-
|
|
- }
|
|
|
|
+ func foo() {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## emptyExtensions
|
|
|
|
Remove empty, non-protocol-conforming extensions.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- extension String {}
|
|
-
|
|
extension String: Equatable {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## enumNamespaces
|
|
|
|
Convert types used for hosting only static members into enums (an empty enum is
|
|
the canonical way to create a namespace in Swift as it can't be instantiated).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--enum-namespaces` | Change types used as namespaces to enums: "always" (default) or "structs-only"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- class FeatureConstants {
|
|
+ enum FeatureConstants {
|
|
static let foo = "foo"
|
|
static let bar = "bar"
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## environmentEntry
|
|
|
|
Updates SwiftUI `EnvironmentValues` definitions to use the @Entry macro.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- struct ScreenNameEnvironmentKey: EnvironmentKey {
|
|
- static var defaultValue: Identifier? {
|
|
- .init("undefined")
|
|
- }
|
|
- }
|
|
|
|
extension EnvironmentValues {
|
|
- var screenName: Identifier? {
|
|
- get { self[ScreenNameEnvironmentKey.self] }
|
|
- set { self[ScreenNameEnvironmentKey.self] = newValue }
|
|
- }
|
|
+ @Entry var screenName: Identifier? = .init("undefined")
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## extensionAccessControl
|
|
|
|
Configure the placement of an extension's access control keyword.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--extension-acl` | Access control keyword placement: "on-extension" (default) or "on-declarations"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
`--extension-acl on-extension` (default)
|
|
|
|
```diff
|
|
- extension Foo {
|
|
- public func bar() {}
|
|
- public func baz() {}
|
|
}
|
|
|
|
+ public extension Foo {
|
|
+ func bar() {}
|
|
+ func baz() {}
|
|
}
|
|
```
|
|
|
|
`--extension-acl on-declarations`
|
|
|
|
```diff
|
|
- public extension Foo {
|
|
- func bar() {}
|
|
- func baz() {}
|
|
- internal func quux() {}
|
|
}
|
|
|
|
+ extension Foo {
|
|
+ public func bar() {}
|
|
+ public func baz() {}
|
|
+ func quux() {}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## fileHeader
|
|
|
|
Use specified source file header template for all files.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--header` | Header comments: "strip", "ignore", or the text you wish use
|
|
`--date-format` | File header date format: "system" (default), "iso", "dmy", "mdy" or custom
|
|
`--timezone` | File header date timezone: "system" (default) or a valid identifier/abbreviation
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
You can use the following tokens in the text:
|
|
|
|
Token | Description
|
|
--- | ---
|
|
`{file}` | File name
|
|
`{year}` | Current year
|
|
`{created}` | File creation date
|
|
`{created.year}` | File creation year
|
|
`{author}` | Name and email of the user who first committed the file
|
|
`{author.name}` | Name of the user who first committed the file
|
|
`{author.email}` | Email of the user who first committed the file
|
|
|
|
**Example**:
|
|
|
|
`--header \n {file}\n\n Copyright © {created.year} {author.name}.\n`
|
|
|
|
```diff
|
|
- // SomeFile.swift
|
|
|
|
+ //
|
|
+ // SomeFile.swift
|
|
+ // Copyright © 2023 Tim Apple.
|
|
+ //
|
|
```
|
|
|
|
You can use the following built-in formats for `--date-format`:
|
|
|
|
Token | Description
|
|
--- | ---
|
|
system | Use the local system locale
|
|
iso | ISO 8601 (yyyy-MM-dd)
|
|
dmy | Date/Month/Year (dd/MM/yyyy)
|
|
mdy | Month/Day/Year (MM/dd/yyyy)
|
|
|
|
Custom formats are defined using
|
|
[Unicode symbols](https://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Field_Symbol_Table).
|
|
|
|
`--date-format iso`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 2023-08-10
|
|
```
|
|
|
|
`--date-format dmy`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 10/08/2023
|
|
```
|
|
|
|
`--date-format mdy`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 08/10/2023
|
|
```
|
|
|
|
`--date-format 'yyyy.MM.dd.HH.mm'`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 2023.08.10.11.00
|
|
```
|
|
|
|
Setting a time zone enforces consistent date formatting across environments
|
|
around the world. By default the local system locale is used and for convenience
|
|
`gmt` and `utc` can be used. The time zone can be further customized by
|
|
setting it to a abbreviation/time zone identifier supported by the Swift
|
|
standard library.
|
|
|
|
`--date-format 'yyyy-MM-dd HH:mm ZZZZ' --timezone utc`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 2023-08-10 11:00 GMT
|
|
```
|
|
|
|
`--date-format 'yyyy-MM-dd HH:mm ZZZZ' --timezone Pacific/Fiji`
|
|
|
|
```diff
|
|
- // Created 2023-08-10 11:00 GMT
|
|
+ // Created 2023-08-10 23:00 GMT+12:00
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## fileMacro
|
|
|
|
Prefer either #file or #fileID, which have the same behavior in Swift 6 and later.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--file-macro` | File macro to prefer: "#file" (default) or "#fileID"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
// --filemacro #file
|
|
- func foo(file: StaticString = #fileID) { ... }
|
|
+ func foo(file: StaticString = #file) { ... }
|
|
|
|
// --filemacro #fileID
|
|
- func foo(file: StaticString = #file) { ... }
|
|
+ func foo(file: StaticString = #fileID) { ... }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## genericExtensions
|
|
|
|
Use angle brackets (`extension Array<Foo>`) for generic type extensions
|
|
instead of type constraints (`extension Array where Element == Foo`).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--generic-types` | Semicolon-delimited list of generic types and type parameters. For example: "LinkedList<Element>;StateStore<State, Action>"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- extension Array where Element == Foo {}
|
|
- extension Optional where Wrapped == Foo {}
|
|
- extension Dictionary where Key == Foo, Value == Bar {}
|
|
- extension Collection where Element == Foo {}
|
|
+ extension Array<Foo> {}
|
|
+ extension Optional<Foo> {}
|
|
+ extension Dictionary<Key, Value> {}
|
|
+ extension Collection<Foo> {}
|
|
|
|
// With `typeSugar` also enabled:
|
|
- extension Array where Element == Foo {}
|
|
- extension Optional where Wrapped == Foo {}
|
|
- extension Dictionary where Key == Foo, Value == Bar {}
|
|
+ extension [Foo] {}
|
|
+ extension Foo? {}
|
|
+ extension [Key: Value] {}
|
|
|
|
// Also supports user-defined types!
|
|
- extension LinkedList where Element == Foo {}
|
|
- extension Reducer where
|
|
- State == FooState,
|
|
- Action == FooAction,
|
|
- Environment == FooEnvironment {}
|
|
+ extension LinkedList<Foo> {}
|
|
+ extension Reducer<FooState, FooAction, FooEnvironment> {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## headerFileName
|
|
|
|
Ensure file name in header comment matches the actual file name.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
For a file named `Bar.swift`:
|
|
|
|
```diff
|
|
- // Foo.swift
|
|
+ // Bar.swift
|
|
// SwiftFormat
|
|
//
|
|
// Created by Nick Lockwood on 5/3/23.
|
|
|
|
struct Bar {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## hoistAwait
|
|
|
|
Move inline `await` keyword(s) to start of expression.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--async-capturing` | List of functions with async @autoclosure arguments
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- greet(await forename, await surname)
|
|
+ await greet(forename, surname)
|
|
```
|
|
|
|
```diff
|
|
- let foo = String(try await getFoo())
|
|
+ let foo = await String(try getFoo())
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## hoistPatternLet
|
|
|
|
Reposition `let` or `var` bindings within pattern.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--pattern-let` | Placement of let/var in patterns: "hoist" (default) or "inline"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- (let foo, let bar) = baz()
|
|
+ let (foo, bar) = baz()
|
|
```
|
|
|
|
```diff
|
|
- if case .foo(let bar, let baz) = quux {
|
|
// inner foo
|
|
}
|
|
|
|
+ if case let .foo(bar, baz) = quux {
|
|
// inner foo
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## hoistTry
|
|
|
|
Move inline `try` keyword(s) to start of expression.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--throw-capturing` | List of functions with throwing @autoclosure arguments
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- foo(try bar(), try baz())
|
|
+ try foo(bar(), baz())
|
|
```
|
|
|
|
```diff
|
|
- let foo = String(try await getFoo())
|
|
+ let foo = try String(await getFoo())
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## indent
|
|
|
|
Indent code in accordance with the scope level.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--indent` | Number of spaces to indent, or "tab" to use tabs
|
|
`--tab-width` | The width of a tab character. Defaults to "unspecified"
|
|
`--smart-tabs` | Align code independently of tab-width: "enabled" (default) or "disabled"
|
|
`--indent-case` | Indent cases inside a switch statement: "true" or "false" (default)
|
|
`--ifdef` | #if statement indenting: "indent" (default), "no-indent", "preserve" or "outdent"
|
|
`--xcode-indentation` | Match Xcode indenting: "enabled" or "disabled" (default)
|
|
`--indent-strings` | Indent multiline strings: "true" or "false" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
if x {
|
|
- // foo
|
|
} else {
|
|
- // bar
|
|
- }
|
|
|
|
if x {
|
|
+ // foo
|
|
} else {
|
|
+ // bar
|
|
+ }
|
|
```
|
|
|
|
```diff
|
|
let array = [
|
|
foo,
|
|
- bar,
|
|
- baz
|
|
- ]
|
|
|
|
let array = [
|
|
foo,
|
|
+ bar,
|
|
+ baz
|
|
+ ]
|
|
```
|
|
|
|
```diff
|
|
switch foo {
|
|
- case bar: break
|
|
- case baz: break
|
|
}
|
|
|
|
switch foo {
|
|
+ case bar: break
|
|
+ case baz: break
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## initCoderUnavailable
|
|
|
|
Add `@available(*, unavailable)` attribute to required `init(coder:)` when
|
|
it hasn't been implemented.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--init-coder-nil` | Replace fatalError with nil in unavailable init?(coder:): "true" or "false" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
+ @available(*, unavailable)
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## isEmpty
|
|
|
|
Prefer `isEmpty` over comparing `count` against zero.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if foo.count == 0 {
|
|
+ if foo.isEmpty {
|
|
|
|
- if foo.count > 0 {
|
|
+ if !foo.isEmpty {
|
|
|
|
- if foo?.count == 0 {
|
|
+ if foo?.isEmpty == true {
|
|
```
|
|
|
|
***NOTE:*** In rare cases, the `isEmpty` rule may insert an `isEmpty` call for
|
|
a type that doesn't implement that property, breaking the program. For this
|
|
reason, the rule is disabled by default, and must be manually enabled via the
|
|
`--enable isEmpty` option.
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## leadingDelimiters
|
|
|
|
Move leading delimiters to the end of the previous line.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- guard let foo = maybeFoo // first
|
|
- , let bar = maybeBar else { ... }
|
|
|
|
+ guard let foo = maybeFoo, // first
|
|
+ let bar = maybeBar else { ... }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## linebreakAtEndOfFile
|
|
|
|
Add empty blank line at end of file.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
struct Foo {↩
|
|
let bar: Bar↩
|
|
- }
|
|
+ }↩
|
|
+
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## linebreaks
|
|
|
|
Use specified linebreak character for all linebreaks (CR, LF or CRLF).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--linebreaks` | Linebreak character to use: "cr", "crlf" or "lf" (default)
|
|
|
|
## markTypes
|
|
|
|
Add a MARK comment before top-level types and extensions.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--mark-types` | Mark types: "always" (default), "never" or "if-not-empty"
|
|
`--type-mark` | Template for type mark comments. Defaults to "MARK: - %t"
|
|
`--mark-extensions` | Mark extensions: "always" (default), "never" or "if-not-empty"
|
|
`--extension-mark` | Mark for standalone extensions. Defaults to "MARK: - %t + %c"
|
|
`--grouped-extension` | Mark for extension grouped with extended type. ("MARK: %c")
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
+ // MARK: - FooViewController
|
|
+
|
|
final class FooViewController: UIViewController { }
|
|
|
|
+ // MARK: UICollectionViewDelegate
|
|
+
|
|
extension FooViewController: UICollectionViewDelegate { }
|
|
|
|
+ // MARK: - String + FooProtocol
|
|
+
|
|
extension String: FooProtocol { }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## modifierOrder
|
|
|
|
Use consistent ordering for member modifiers.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--modifier-order` | Comma-delimited list of modifiers in preferred order
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- lazy public weak private(set) var foo: UIView?
|
|
+ public private(set) lazy weak var foo: UIView?
|
|
```
|
|
|
|
```diff
|
|
- final public override func foo()
|
|
+ override public final func foo()
|
|
```
|
|
|
|
```diff
|
|
- convenience private init()
|
|
+ private convenience init()
|
|
```
|
|
|
|
**NOTE:** If the `--modifier-order` option isn't set, the default order will be:
|
|
`override`, `private`, `fileprivate`, `internal`, `package`, `public`, `open`, `private(set)`, `fileprivate(set)`, `internal(set)`, `package(set)`, `public(set)`, `open(set)`, `final`, `dynamic`, `optional`, `required`, `convenience`, `indirect`, `isolated`, `nonisolated`, `nonisolated(unsafe)`, `lazy`, `weak`, `unowned`, `unowned(safe)`, `unowned(unsafe)`, `static`, `class`, `borrowing`, `consuming`, `mutating`, `nonmutating`, `prefix`, `infix`, `postfix`, `async`
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## modifiersOnSameLine
|
|
|
|
Ensure that all modifiers are on the same line as the declaration keyword.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- @MainActor
|
|
- public
|
|
- private(set)
|
|
- var foo: Foo
|
|
|
|
+ @MainActor
|
|
+ public private(set) var foo: Foo
|
|
```
|
|
|
|
```diff
|
|
- nonisolated
|
|
- func bar() {}
|
|
|
|
+ nonisolated func bar() {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## noExplicitOwnership
|
|
|
|
Don't use explicit ownership modifiers (borrowing / consuming).
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- borrowing func foo(_ bar: consuming Bar) { ... }
|
|
+ func foo(_ bar: Bar) { ... }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## noForceTryInTests
|
|
|
|
Write tests that use `throws` instead of using `try!`.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import Testing
|
|
|
|
struct MyFeatureTests {
|
|
- @Test func doSomething() {
|
|
+ @Test func doSomething() throws {
|
|
- try! MyFeature().doSomething()
|
|
+ try MyFeature().doSomething()
|
|
}
|
|
}
|
|
|
|
import XCTeset
|
|
|
|
class MyFeatureTests: XCTestCase {
|
|
- func test_doSomething() {
|
|
+ func test_doSomething() throws {
|
|
- try! MyFeature().doSomething()
|
|
+ try MyFeature().doSomething()
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## noForceUnwrapInTests
|
|
|
|
Use XCTUnwrap or #require in test cases, rather than force unwrapping.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import Testing
|
|
|
|
struct MyFeatureTests {
|
|
- @Test func myFeature() {
|
|
- let myValue = foo.bar!.value as! Value
|
|
- let otherValue = (foo! as! Other).bar
|
|
- otherValue.manager!.prepare()
|
|
- #expect(myValue!.property! == other)
|
|
+ @Test func myFeature() throws {
|
|
+ let myValue = try #require(foo.bar?.value as? Value)
|
|
+ let otherValue = try #require((foo as? Other)?.bar)
|
|
+ otherValue.manager?.prepare()
|
|
+ #expect(myValue?.property == other)
|
|
}
|
|
}
|
|
|
|
import XCTest
|
|
|
|
class MyFeatureTests: XCTestCase {
|
|
- func testMyFeature() {
|
|
- let myValue = foo.bar!.value as! Value
|
|
- let otherValue = (foo! as! Other).bar
|
|
- XCTAssertEqual(myValue!.property!, "foo")
|
|
+ func testMyFeature() throws {
|
|
+ let myValue = try XCTUnwrap(foo.bar?.value as? Value)
|
|
+ let otherValue = try XCTUnwrap((foo as? Other)?.bar)
|
|
+ XCTAssertEqual(myValue?.property, otherValue)
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## noGuardInTests
|
|
|
|
Convert guard statements in unit tests to `try #require(...)` / `#expect(...)`
|
|
or `try XCTUnwrap(...)` / `XCTAssert(...)`.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import XCTest
|
|
|
|
final class SomeTestCase: XCTestCase {
|
|
- func test_something() {
|
|
+ func test_something() throws {
|
|
- guard let value = optionalValue, value.matchesCondition else {
|
|
- XCTFail()
|
|
- return
|
|
- }
|
|
+ let value = try XCTUnwrap(optionalValue)
|
|
+ XCTAssert(value.matchesCondition)
|
|
}
|
|
}
|
|
```
|
|
|
|
```diff
|
|
import Testing
|
|
|
|
struct SomeTests {
|
|
@Test
|
|
func something() throws {
|
|
- guard let value = optionalValue, value.matchesCondition else {
|
|
- return
|
|
- }
|
|
+ let value = try #require(optionalValue)
|
|
+ #expect(value.matchesCondition)
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## numberFormatting
|
|
|
|
Use consistent grouping for numeric literals. Groups will be separated by `_`
|
|
delimiters to improve readability. For each numeric type you can specify a group
|
|
size (the number of digits in each group) and a threshold (the minimum number of
|
|
digits in a number before grouping is applied).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--decimal-grouping` | Decimal grouping and threshold (default: 3,6) or "none", "ignore"
|
|
`--binary-grouping` | Binary grouping and threshold (default: 4,8) or "none", "ignore"
|
|
`--octal-grouping` | Octal grouping and threshold (default: 4,8) or "none", "ignore"
|
|
`--hex-grouping` | Hex grouping and threshold (default: 4,8) or "none", "ignore"
|
|
`--fraction-grouping` | Grouping of decimal digits after the '.': "enabled" or "disabled" (default)
|
|
`--exponent-grouping` | Grouping of exponent digits: "enabled" or "disabled" (default)
|
|
`--hex-literal-case` | Case for letters in hex literals: "uppercase" (default) or "lowercase"
|
|
`--exponent-case` | Case for 'e' in exponent literals: "uppercase" or "lowercase" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let color = 0xFF77A5
|
|
+ let color = 0xff77a5
|
|
```
|
|
|
|
```diff
|
|
- let big = 123456.123
|
|
+ let big = 123_456.123
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## opaqueGenericParameters
|
|
|
|
Use opaque generic parameters (`some Protocol`) instead of generic parameters
|
|
with constraints (`T where T: Protocol`, etc) where equivalent. Also supports
|
|
primary associated types for common standard library types, so definitions like
|
|
`T where T: Collection, T.Element == Foo` are updated to `some Collection<Foo>`.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--some-any` | Use `some Any` types: "true" (default) or "false"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- func handle<T: Fooable>(_ value: T) {
|
|
+ func handle(_ value: some Fooable) {
|
|
print(value)
|
|
}
|
|
|
|
- func handle<T>(_ value: T) where T: Fooable, T: Barable {
|
|
+ func handle(_ value: some Fooable & Barable) {
|
|
print(value)
|
|
}
|
|
|
|
- func handle<T: Collection>(_ value: T) where T.Element == Foo {
|
|
+ func handle(_ value: some Collection<Foo>) {
|
|
print(value)
|
|
}
|
|
|
|
// With `--some-any enabled` (the default)
|
|
- func handle<T>(_ value: T) {
|
|
+ func handle(_ value: some Any) {
|
|
print(value)
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## organizeDeclarations
|
|
|
|
Organize declarations within class, struct, enum, actor, and extension bodies.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--category-mark` | Template for category mark comments. Defaults to "MARK: %c"
|
|
`--mark-categories` | Insert MARK comments between categories: "true" (default) or "false"
|
|
`--before-marks` | Declarations placed before first mark (e.g. `typealias,struct`)
|
|
`--lifecycle` | Names of additional Lifecycle methods (e.g. `viewDidLoad`)
|
|
`--organize-types` | Declarations to organize (default: `class,actor,struct,enum`)
|
|
`--struct-threshold` | Minimum line count to organize struct body. Defaults to 0
|
|
`--class-threshold` | Minimum line count to organize class body. Defaults to 0
|
|
`--enum-threshold` | Minimum line count to organize enum body. Defaults to 0
|
|
`--extension-threshold` | Minimum line count to organize extension body. Defaults to 0
|
|
`--mark-struct-threshold` | Minimum line count to add MARK comments in struct body. Defaults to 0
|
|
`--mark-class-threshold` | Minimum line count to add MARK comments in class body. Defaults to 0
|
|
`--mark-enum-threshold` | Minimum line count to add MARK comments in enum body. Defaults to 0
|
|
`--mark-extension-threshold` | Minimum line count to add MARK comments in extension body. Defaults to 0
|
|
`--organization-mode` | Organize declarations by: "visibility" (default) or "type"
|
|
`--type-body-marks` | MARK comments in type bodies: "preserve" (default) or "remove"
|
|
`--visibility-order` | Order for visibility groups inside declaration
|
|
`--type-order` | Order for declaration type groups inside declaration
|
|
`--visibility-marks` | Marks for visibility groups (public:Public Fields,..)
|
|
`--type-marks` | Marks for declaration type groups (classMethod:Baaz,..)
|
|
`--group-blank-lines` | Require a blank line after each subgroup. Default: true
|
|
`--sort-swiftui-properties` | SwiftUI property sorting: "none" (default), "alphabetize" or "first-appearance-sort"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
Default value for `--visibility-order` when using `--organization-mode visibility`:
|
|
`beforeMarks, instanceLifecycle, open, public, package, internal, fileprivate, private`
|
|
|
|
Default value for `--visibility-order` when using `--organization-mode type`:
|
|
`open, public, package, internal, fileprivate, private`
|
|
|
|
**NOTE:** When providing custom arguments for `--visibility-order` the following entries must be included:
|
|
`open, public, package, internal, fileprivate, private`
|
|
|
|
Default value for `--type-order` when using `--organization-mode visibility`:
|
|
`nestedType, staticProperty, staticPropertyWithBody, classPropertyWithBody, overriddenProperty, swiftUIPropertyWrapper, instanceProperty, instancePropertyWithBody, swiftUIProperty, swiftUIMethod, overriddenMethod, staticMethod, classMethod, instanceMethod`
|
|
|
|
Default value for `--type-order` when using `--organization-mode type`:
|
|
`beforeMarks, nestedType, staticProperty, staticPropertyWithBody, classPropertyWithBody, overriddenProperty, swiftUIPropertyWrapper, instanceProperty, computedProperty, instanceLifecycle, swiftUIProperty, swiftUIMethod, overriddenMethod, staticMethod, classMethod, instanceMethod`
|
|
|
|
**NOTE:** The follow declaration types must be included in either `--type-order` or `--visibility-order`:
|
|
`beforeMarks, nestedType, instanceLifecycle, instanceProperty, instanceMethod`
|
|
|
|
**NOTE:** The Swift compiler automatically synthesizes a memberwise `init` for `struct` types.
|
|
|
|
To allow SwiftFormat to reorganize your code effectively, you must explicitly declare an `init`.
|
|
Without this declaration, only functions will be reordered, while properties will remain in their original order.
|
|
|
|
`--organization-mode visibility` (default)
|
|
|
|
```diff
|
|
public class Foo {
|
|
- public func c() -> String {}
|
|
-
|
|
- public let a: Int = 1
|
|
- private let g: Int = 2
|
|
- let e: Int = 2
|
|
- public let b: Int = 3
|
|
-
|
|
- public func d() {}
|
|
- func f() {}
|
|
- init() {}
|
|
- deinit() {}
|
|
}
|
|
|
|
public class Foo {
|
|
+
|
|
+ // MARK: Lifecycle
|
|
+
|
|
+ init() {}
|
|
+ deinit() {}
|
|
+
|
|
+ // MARK: Public
|
|
+
|
|
+ public let a: Int = 1
|
|
+ public let b: Int = 3
|
|
+
|
|
+ public func c() -> String {}
|
|
+ public func d() {}
|
|
+
|
|
+ // MARK: Internal
|
|
+
|
|
+ let e: Int = 2
|
|
+
|
|
+ func f() {}
|
|
+
|
|
+ // MARK: Private
|
|
+
|
|
+ private let g: Int = 2
|
|
+
|
|
}
|
|
```
|
|
|
|
`--organization-mode type`
|
|
|
|
```diff
|
|
public class Foo {
|
|
- public func c() -> String {}
|
|
-
|
|
- public let a: Int = 1
|
|
- private let g: Int = 2
|
|
- let e: Int = 2
|
|
- public let b: Int = 3
|
|
-
|
|
- public func d() {}
|
|
- func f() {}
|
|
- init() {}
|
|
- deinit() {}
|
|
}
|
|
|
|
public class Foo {
|
|
+
|
|
+ // MARK: Properties
|
|
+
|
|
+ public let a: Int = 1
|
|
+ public let b: Int = 3
|
|
+
|
|
+ let e: Int = 2
|
|
+
|
|
+ private let g: Int = 2
|
|
+
|
|
+ // MARK: Lifecycle
|
|
+
|
|
+ init() {}
|
|
+ deinit() {}
|
|
+
|
|
+ // MARK: Functions
|
|
+
|
|
+ public func c() -> String {}
|
|
+ public func d() {}
|
|
+
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## preferCountWhere
|
|
|
|
Prefer `count(where:)` over `filter(_:).count`.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- planets.filter { !$0.moons.isEmpty }.count
|
|
+ planets.count(where: { !$0.moons.isEmpty })
|
|
|
|
- planets.filter { planet in
|
|
- planet.moons.filter { moon in
|
|
- moon.hasAtmosphere
|
|
- }.count > 1
|
|
- }.count
|
|
+ planets.count(where: { planet in
|
|
+ planet.moons.count(where: { moon in
|
|
+ moon.hasAtmosphere
|
|
+ }) > 1
|
|
+ })
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## preferExplicitFalse
|
|
|
|
Prefer `== false` over `!` prefix negation.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if !flag {
|
|
+ if flag == false {
|
|
```
|
|
|
|
```diff
|
|
- guard !array.isEmpty else { return }
|
|
+ guard array.isEmpty == false else { return }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## preferFinalClasses
|
|
|
|
Prefer defining `final` classes. To suppress this rule, add "Base" to the class name, add a doc comment mentioning "base class" or "subclass", make the class `open`, or use a `// swiftformat:disable:next preferFinalClasses` directive.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- class Foo {}
|
|
+ final class Foo {}
|
|
```
|
|
|
|
```diff
|
|
- public class Bar {}
|
|
+ public final class Bar {}
|
|
```
|
|
|
|
```diff
|
|
// Preserved classes:
|
|
open class Baz {}
|
|
|
|
class BaseClass {}
|
|
|
|
class MyClass {} // Subclassed in this file
|
|
class MySubclass: MyClass {}
|
|
|
|
/// Base class to be subclassed by other features
|
|
class MyCustomizationPoint {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## preferForLoop
|
|
|
|
Convert functional `forEach` calls to for loops.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--anonymous-for-each` | Convert anonymous forEach closures to for loops: "ignore" or "convert" (default)
|
|
`--single-line-for-each` | Convert single-line forEach closures to for loops: "ignore" (default) or "convert"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
let strings = ["foo", "bar", "baaz"]
|
|
- strings.forEach { placeholder in
|
|
+ for placeholder in strings {
|
|
print(placeholder)
|
|
}
|
|
|
|
// Supports anonymous closures
|
|
- strings.forEach {
|
|
+ for string in strings {
|
|
- print($0)
|
|
+ print(string)
|
|
}
|
|
|
|
- foo.item().bar[2].baazValues(option: true).forEach {
|
|
+ for baazValue in foo.item().bar[2].baazValues(option: true) {
|
|
- print($0)
|
|
+ print(baazValue)
|
|
}
|
|
|
|
// Doesn't affect long multiline functional chains
|
|
placeholderStrings
|
|
.filter { $0.style == .fooBar }
|
|
.map { $0.uppercased() }
|
|
.forEach { print($0) }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## preferKeyPath
|
|
|
|
Convert trivial `map { $0.foo }` closures to keyPath-based syntax.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let barArray = fooArray.map { $0.bar }
|
|
+ let barArray = fooArray.map(\.bar)
|
|
|
|
- let barArray = fooArray.compactMap { $0.optionalBar }
|
|
+ let barArray = fooArray.compactMap(\.optionalBar)
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## preferSwiftStringAPI
|
|
|
|
Replace Objective-C bridged String methods with Swift equivalents.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- str.replacingOccurrences(of: "foo", with: "bar")
|
|
+ str.replacing("foo", with: "bar")
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## preferSwiftTesting
|
|
|
|
Prefer the Swift Testing library over XCTest.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--xctest-symbols` | Comma-delimited list of symbols that depend on XCTest
|
|
`--default-test-suite-attributes` | Comma-delimited list of attributes to add when converting from XCTest. e.g. "@MainActor,@Suite(.serialized)"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
@testable import MyFeatureLib
|
|
- import XCTest
|
|
+ import Testing
|
|
+ import Foundation
|
|
|
|
- final class MyFeatureTests: XCTestCase {
|
|
- func testMyFeatureHasNoBugs() {
|
|
- let myFeature = MyFeature()
|
|
- myFeature.runAction()
|
|
- XCTAssertFalse(myFeature.hasBugs, "My feature has no bugs")
|
|
- XCTAssertEqual(myFeature.crashes.count, 0, "My feature doesn't crash")
|
|
- XCTAssertNil(myFeature.crashReport)
|
|
- }
|
|
- }
|
|
+ final class MyFeatureTests {
|
|
+ @Test func myFeatureHasNoBugs() {
|
|
+ let myFeature = MyFeature()
|
|
+ myFeature.runAction()
|
|
+ #expect(!myFeature.hasBugs, "My feature has no bugs")
|
|
+ #expect(myFeature.crashes.isEmpty, "My feature doesn't crash")
|
|
+ #expect(myFeature.crashReport == nil)
|
|
+ }
|
|
+ }
|
|
|
|
- final class MyFeatureTests: XCTestCase {
|
|
- var myFeature: MyFeature!
|
|
-
|
|
- override func setUp() async throws {
|
|
- myFeature = try await MyFeature()
|
|
- }
|
|
-
|
|
- override func tearDown() {
|
|
- myFeature = nil
|
|
- }
|
|
-
|
|
- func testMyFeatureWorks() {
|
|
- myFeature.runAction()
|
|
- XCTAssertTrue(myFeature.worksProperly)
|
|
- XCTAssertEqual(myFeature.screens.count, 8)
|
|
- }
|
|
- }
|
|
+ final class MyFeatureTests {
|
|
+ var myFeature: MyFeature!
|
|
+
|
|
+ init() async throws {
|
|
+ myFeature = try await MyFeature()
|
|
+ }
|
|
+
|
|
+ deinit {
|
|
+ myFeature = nil
|
|
+ }
|
|
+
|
|
+ @Test func myFeatureWorks() {
|
|
+ myFeature.runAction()
|
|
+ #expect(myFeature.worksProperly)
|
|
+ #expect(myFeature.screens.count == 8)
|
|
+ }
|
|
+ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## privateStateVariables
|
|
|
|
Adds `private` access control to @State properties without existing access control modifiers.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- @State var anInt: Int
|
|
+ @State private var anInt: Int
|
|
|
|
- @StateObject var myInstance: MyObject
|
|
+ @StateObject private var myInstace: MyObject
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## propertyTypes
|
|
|
|
Convert property declarations to use inferred types (`let foo = Foo()`) or explicit types (`let foo: Foo = .init()`).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--property-types` | Types in property declarations: "explicit", "inferred" or "infer-locals-only" (default)
|
|
`--inferred-types` | Prefer inferred types: "exclude-cond-exprs" or "always" (default)
|
|
`--preserved-property-types` | Comma-delimited list of symbols to be ignored and preserved as-is by the propertyTypes rule
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
// with --propertytypes inferred
|
|
- let view: UIView = .init()
|
|
+ let view = UIView()
|
|
|
|
- let color: Color = .red
|
|
+ let color = Color.red
|
|
|
|
- let array: [Int] = []
|
|
+ let array = [Int]()
|
|
|
|
- let set: Set<Int> = []
|
|
+ let set = Set<Int>()
|
|
|
|
- let dict: [String: Int] = [:]
|
|
+ let dict = [String: Int]()
|
|
|
|
// with --propertytypes explicit
|
|
- let view = UIView()
|
|
+ let view: UIView = .init()
|
|
|
|
- let color = Color.red
|
|
+ let color: Color = .red
|
|
|
|
- let array = [Int]()
|
|
+ let array: [Int] = []
|
|
|
|
- let set = Set<Int>()
|
|
+ let set: Set<Int> = []
|
|
|
|
- let dict = [String: Int]()
|
|
+ let dict: [String: Int] = [:]
|
|
|
|
// with --propertytypes infer-locals-only
|
|
class Foo {
|
|
- let view: UIView = UIView()
|
|
+ let view: UIView = .init()
|
|
|
|
func method() {
|
|
- let view: UIView = UIView()
|
|
+ let view = UIView()
|
|
}
|
|
}
|
|
|
|
// with --inferredtypes always:
|
|
- let foo: Foo =
|
|
+ let foo =
|
|
if condition {
|
|
- .init(bar)
|
|
+ Foo(bar)
|
|
} else {
|
|
- .init(baaz)
|
|
+ Foo(baaz)
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantAsync
|
|
|
|
Remove redundant `async` keyword from function declarations that don't contain any await expressions.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--redundant-async` | Remove redundant async from functions: "tests-only" (default) or "always"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
// With --redundant-async tests-only (default)
|
|
import Testing
|
|
|
|
- @Test func myFeature() async {
|
|
+ @Test func myFeature() {
|
|
#expect(foo == 1)
|
|
}
|
|
|
|
import XCTest
|
|
|
|
class TestCase: XCTestCase {
|
|
- func testMyFeature() async {
|
|
+ func testMyFeature() {
|
|
XCTAssertEqual(foo, 1)
|
|
}
|
|
}
|
|
```
|
|
|
|
Also supports `--redundant-async always`.
|
|
This will cause warnings anywhere the updated method is called with `await`, since `await` is now redundant at the callsite.
|
|
|
|
```diff
|
|
// With --redundant-async always
|
|
- func myNonAsyncMethod() async -> Int {
|
|
+ func myNonAsyncMethod() -> Int {
|
|
return 0
|
|
}
|
|
|
|
// Possibly elsewhere in codebase:
|
|
let value = await myNonAsyncMethod()
|
|
+ `- warning: no 'async' operations occur within 'await' expression
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantBackticks
|
|
|
|
Remove redundant backticks around identifiers.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let `infix` = bar
|
|
+ let infix = bar
|
|
```
|
|
|
|
```diff
|
|
- func foo(with `default`: Int) {}
|
|
+ func foo(with default: Int) {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantBreak
|
|
|
|
Remove redundant `break` in switch case.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
switch foo {
|
|
case bar:
|
|
print("bar")
|
|
- break
|
|
default:
|
|
print("default")
|
|
- break
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantClosure
|
|
|
|
Removes redundant closures bodies, containing a single statement,
|
|
which are called immediately.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let foo = { Foo() }()
|
|
+ let foo = Foo()
|
|
```
|
|
|
|
```diff
|
|
- lazy var bar = {
|
|
- Bar(baaz: baaz,
|
|
- quux: quux)
|
|
- }()
|
|
+ lazy var bar = Bar(baaz: baaz,
|
|
+ quux: quux)
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantEmptyView
|
|
|
|
Remove redundant `else { EmptyView() }` branches in SwiftUI result builders.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
var body: some View {
|
|
if condition {
|
|
Text("Hello")
|
|
- } else {
|
|
- EmptyView()
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantEquatable
|
|
|
|
Omit a hand-written Equatable implementation when the compiler-synthesized conformance would be equivalent.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--equatable-macro` | For example: "@Equatable,EquatableMacroLib"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
struct Foo: Equatable {
|
|
let bar: Bar
|
|
let baaz: Baaz
|
|
|
|
- static func ==(lhs: Foo, rhs: Foo) -> Bool {
|
|
- lhs.bar == rhs.bar
|
|
- && lhs.baaz == rhs.baaz
|
|
- }
|
|
}
|
|
|
|
class Bar: Equatable {
|
|
let baaz: Baaz
|
|
|
|
static func ==(lhs: Bar, rhs: Bar) -> Bool {
|
|
lhs.baaz == rhs.baaz
|
|
}
|
|
}
|
|
```
|
|
|
|
If your project includes a macro that generates the `static func ==` implementation
|
|
for the attached class, you can specify `--equatable-macro @Equatable,MyMacroLib`
|
|
and this rule will also migrate eligible classes to use your macro instead of
|
|
a hand-written Equatable conformance:
|
|
|
|
```diff
|
|
// --equatable-macro @Equatable,MyMacroLib
|
|
import FooLib
|
|
+ import MyMacroLib
|
|
|
|
+ @Equatable
|
|
+ class Bar {
|
|
- class Bar: Equatable {
|
|
let baaz: Baaz
|
|
|
|
- static func ==(lhs: Bar, rhs: Bar) -> Bool {
|
|
- lhs.baaz == rhs.baaz
|
|
- }
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantExtensionACL
|
|
|
|
Remove redundant access control modifiers.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
public extension URL {
|
|
- public func queryParameter(_ name: String) -> String { ... }
|
|
}
|
|
|
|
public extension URL {
|
|
+ func queryParameter(_ name: String) -> String { ... }
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantFileprivate
|
|
|
|
Prefer `private` over `fileprivate` where equivalent.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- fileprivate let someConstant = "someConstant"
|
|
+ private let someConstant = "someConstant"
|
|
```
|
|
|
|
In Swift 4 and above, `fileprivate` can also be replaced with `private` for
|
|
members that are only accessed from extensions in the same file:
|
|
|
|
```diff
|
|
class Foo {
|
|
- fileprivate var foo = "foo"
|
|
+ private var foo = "foo"
|
|
}
|
|
|
|
extension Foo {
|
|
func bar() {
|
|
print(self.foo)
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantGet
|
|
|
|
Remove unneeded `get` clause inside computed properties.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
var foo: Int {
|
|
- get {
|
|
- return 5
|
|
- }
|
|
}
|
|
|
|
var foo: Int {
|
|
+ return 5
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantInit
|
|
|
|
Remove explicit `init` if not required.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- String.init("text")
|
|
+ String("text")
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantInternal
|
|
|
|
Remove redundant internal access control.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- internal class Foo {
|
|
+ class Foo {
|
|
- internal let bar: String
|
|
+ let bar: String
|
|
|
|
- internal func baaz() {}
|
|
+ func baaz() {}
|
|
|
|
- internal init() {
|
|
+ init() {
|
|
bar = "bar"
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantLet
|
|
|
|
Remove redundant `let`/`var` from ignored variables.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let _ = foo()
|
|
+ _ = foo()
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantLetError
|
|
|
|
Remove redundant `let error` from `catch` clause.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- do { ... } catch let error { log(error) }
|
|
+ do { ... } catch { log(error) }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantMemberwiseInit
|
|
|
|
Remove explicit internal memberwise initializers that are redundant.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--prefer-synthesized-init-for-internal-structs` | For internal structs, remove private access control from properties to enable the synthesized initializer: "never" (default), "always", or comma-separated list of conformances (e.g. "View,ViewModifier")
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
struct User {
|
|
var name: String
|
|
var age: Int
|
|
|
|
- init(name: String, age: Int) {
|
|
- self.name = name
|
|
- self.age = age
|
|
- }
|
|
}
|
|
```
|
|
|
|
```diff
|
|
struct MyView<Content: View>: View {
|
|
+ @ViewBuilder let content: Content
|
|
- let content: Content
|
|
-
|
|
- init(@ViewBuilder content: () -> Content) {
|
|
- self.content = content()
|
|
- }
|
|
|
|
var body: some View {
|
|
content
|
|
}
|
|
}
|
|
```
|
|
|
|
`--prefer-synthesized-init-for-internal-structs View,ViewModifier`:
|
|
|
|
```diff
|
|
struct ProfileView: View {
|
|
- init(user: User, settings: Settings) {
|
|
- self.user = user
|
|
- self.settings = settings
|
|
- }
|
|
-
|
|
- private let user: User
|
|
- private let settings: Settings
|
|
+ let user: User
|
|
+ let settings: Settings
|
|
|
|
var body: some View { ... }
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantNilInit
|
|
|
|
Remove/insert redundant `nil` default value (Optional vars are nil by default).
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--nil-init` | Explicit nil init value for Optional properties: "remove" (default) or "insert"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
`--nil-init remove`
|
|
|
|
```diff
|
|
- var foo: Int? = nil
|
|
+ var foo: Int?
|
|
```
|
|
|
|
```diff
|
|
// doesn't apply to `let` properties
|
|
let foo: Int? = nil
|
|
```
|
|
|
|
```diff
|
|
// doesn't affect non-nil initialization
|
|
var foo: Int? = 0
|
|
```
|
|
|
|
`--nil-init insert`
|
|
|
|
```diff
|
|
- var foo: Int?
|
|
+ var foo: Int? = nil
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantObjc
|
|
|
|
Remove redundant `@objc` annotations.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- @objc @IBOutlet var label: UILabel!
|
|
+ @IBOutlet var label: UILabel!
|
|
```
|
|
|
|
```diff
|
|
- @IBAction @objc func goBack() {}
|
|
+ @IBAction func goBack() {}
|
|
```
|
|
|
|
```diff
|
|
- @objc @NSManaged private var foo: String?
|
|
+ @NSManaged private var foo: String?
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantOptionalBinding
|
|
|
|
Remove redundant identifiers in optional binding conditions.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if let foo = foo {
|
|
+ if let foo {
|
|
print(foo)
|
|
}
|
|
|
|
- guard let self = self else {
|
|
+ guard let self else {
|
|
return
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantParens
|
|
|
|
Remove redundant parentheses.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if (foo == true) {}
|
|
+ if foo == true {}
|
|
```
|
|
|
|
```diff
|
|
- while (i < bar.count) {}
|
|
+ while i < bar.count {}
|
|
```
|
|
|
|
```diff
|
|
- queue.async() { ... }
|
|
+ queue.async { ... }
|
|
```
|
|
|
|
```diff
|
|
- let foo: Int = ({ ... })()
|
|
+ let foo: Int = { ... }()
|
|
```
|
|
|
|
```diff
|
|
- @Test()
|
|
+ @Test
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantPattern
|
|
|
|
Remove redundant pattern matching parameter syntax.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if case .foo(_, _) = bar {}
|
|
+ if case .foo = bar {}
|
|
```
|
|
|
|
```diff
|
|
- let (_, _) = bar
|
|
+ let _ = bar
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantProperty
|
|
|
|
Simplifies redundant variable definitions that are immediately returned.
|
|
|
|
*Note: redundantProperty rule is deprecated. Use redundantVariable instead.*
|
|
|
|
## redundantPublic
|
|
|
|
Remove redundant public access control from declarations in internal or private types.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
struct Foo {
|
|
- public let bar: Bar
|
|
+ let bar: Bar
|
|
- public func baz() {}
|
|
+ func baz() {}
|
|
}
|
|
|
|
extension Foo {
|
|
- public func quux() {}
|
|
+ func quux() {}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantRawValues
|
|
|
|
Remove redundant raw string values for enum cases.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
enum Foo: String {
|
|
- case bar = "bar"
|
|
case baz = "quux"
|
|
}
|
|
|
|
enum Foo: String {
|
|
+ case bar
|
|
case baz = "quux"
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantReturn
|
|
|
|
Remove unneeded `return` keyword.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- array.filter { return $0.foo == bar }
|
|
+ array.filter { $0.foo == bar }
|
|
|
|
// Swift 5.1+ (SE-0255)
|
|
var foo: String {
|
|
- return "foo"
|
|
+ "foo"
|
|
}
|
|
|
|
// Swift 5.9+ (SE-0380) and with conditionalAssignment rule enabled
|
|
func foo(_ condition: Bool) -> String {
|
|
if condition {
|
|
- return "foo"
|
|
+ "foo"
|
|
} else {
|
|
- return "bar"
|
|
+ "bar"
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantSelf
|
|
|
|
Insert/remove explicit `self` where applicable.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--self` | Explicit self: "insert", "remove" (default) or "init-only"
|
|
`--self-required` | Comma-delimited list of functions / types with @autoclosure arguments
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func foobar(foo: Int, bar: Int) {
|
|
self.foo = foo
|
|
self.bar = bar
|
|
- self.baz = 42
|
|
}
|
|
|
|
func foobar(foo: Int, bar: Int) {
|
|
self.foo = foo
|
|
self.bar = bar
|
|
+ baz = 42
|
|
}
|
|
```
|
|
|
|
In the rare case of functions with `@autoclosure` arguments, `self` may be
|
|
required at the call site, but SwiftFormat is unable to detect this
|
|
automatically. You can use the `--self-required` command-line option to specify
|
|
a list of such methods, and the `redundantSelf` rule will then ignore them.
|
|
|
|
An example of such a method is the `expect()` function in the Nimble unit
|
|
testing framework (https://github.com/Quick/Nimble), which is common enough that
|
|
SwiftFormat excludes it by default.
|
|
|
|
There is also an option to always use explicit `self` but *only* inside `init`,
|
|
by using `--self init-only`:
|
|
|
|
```diff
|
|
init(foo: Int, bar: Int) {
|
|
self.foo = foo
|
|
self.bar = bar
|
|
- baz = 42
|
|
}
|
|
|
|
init(foo: Int, bar: Int) {
|
|
self.foo = foo
|
|
self.bar = bar
|
|
+ self.baz = 42
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantSendable
|
|
|
|
Remove redundant explicit Sendable conformance from non-public structs and enums.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- struct CacheEntry: Sendable {
|
|
+ struct CacheEntry {
|
|
let id: String
|
|
}
|
|
|
|
- fileprivate enum ParsingState: Sendable {
|
|
+ fileprivate enum ParsingState {
|
|
case idle
|
|
case running
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantStaticSelf
|
|
|
|
Remove explicit `Self` where applicable.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
enum Foo {
|
|
static let bar = Bar()
|
|
|
|
static func baaz() -> Bar {
|
|
- Self.bar()
|
|
+ bar()
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantSwiftTestingSuite
|
|
|
|
Remove redundant @Suite attribute with no arguments.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import Testing
|
|
|
|
- @Suite
|
|
struct MyFeatureTests {
|
|
@Test func myFeature() {
|
|
#expect(true)
|
|
}
|
|
}
|
|
|
|
- @Suite()
|
|
struct OtherTests {
|
|
@Test func otherFeature() {
|
|
#expect(true)
|
|
}
|
|
}
|
|
|
|
// Not redundant - @Suite has arguments
|
|
@Suite(.serialized)
|
|
struct SerializedTests {
|
|
@Test func feature() {
|
|
#expect(true)
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantThrows
|
|
|
|
Remove redundant `throws` keyword from function declarations that don't throw any errors.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--redundant-throws` | Remove redundant throws from functions: "tests-only" (default) or "always"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
// With --redundant-throws tests-only (default)
|
|
import Testing
|
|
|
|
- @Test func myFeature() throws {
|
|
+ @Test func myFeature() throws {
|
|
#expect(foo == 1)
|
|
}
|
|
|
|
import XCTest
|
|
|
|
class TestCase: XCTestCase {
|
|
- func testMyFeature() throws {
|
|
+ func testMyFeature() {
|
|
XCTAssertEqual(foo, 1)
|
|
}
|
|
}
|
|
```
|
|
|
|
Also supports `--redundant-throws always`.
|
|
This will cause warnings anywhere the updated method is called with `try`, since `try` is now redundant at the callsite.
|
|
|
|
```diff
|
|
// With --redundant-throws always
|
|
- func myNonThrowingMethod() throws -> Int {
|
|
+ func myNonThrowingMethod() -> Int {
|
|
return 0
|
|
}
|
|
|
|
// Possibly elsewhere in codebase:
|
|
let value = try myNonThrowingMethod()
|
|
+ `- warning: no calls to throwing functions occur within 'try' expression
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantType
|
|
|
|
Remove redundant type from variable declarations.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--property-types` | Types in property declarations: "explicit", "inferred" or "infer-locals-only" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
// with --propertytypes inferred
|
|
- let view: UIView = UIView()
|
|
+ let view = UIView()
|
|
|
|
// with --propertytypes explicit
|
|
- let view: UIView = UIView()
|
|
+ let view: UIView = .init()
|
|
|
|
// with --propertytypes infer-locals-only
|
|
class Foo {
|
|
- let view: UIView = UIView()
|
|
+ let view: UIView = .init()
|
|
|
|
func method() {
|
|
- let view: UIView = UIView()
|
|
+ let view = UIView()
|
|
}
|
|
}
|
|
|
|
// Swift 5.9+, with --propertytypes inferred (SE-0380)
|
|
- let foo: Foo = if condition {
|
|
+ let foo = if condition {
|
|
Foo("foo")
|
|
} else {
|
|
Foo("bar")
|
|
}
|
|
|
|
// Swift 5.9+, with --propertytypes explicit (SE-0380)
|
|
let foo: Foo = if condition {
|
|
- Foo("foo")
|
|
+ .init("foo")
|
|
} else {
|
|
- Foo("bar")
|
|
+ .init("foo")
|
|
}
|
|
```
|
|
|
|
</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/>
|
|
|
|
## redundantVariable
|
|
|
|
Simplifies redundant variable definitions that are immediately returned.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
func foo() -> Foo {
|
|
- let foo = Foo()
|
|
- return foo
|
|
+ return Foo()
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantViewBuilder
|
|
|
|
Remove redundant @ViewBuilder attribute when it's not needed.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
struct MyView: View {
|
|
- @ViewBuilder
|
|
var body: some View {
|
|
Text("foo")
|
|
Text("bar")
|
|
}
|
|
|
|
- @ViewBuilder
|
|
var helper: some View {
|
|
VStack {
|
|
Text("baaz")
|
|
Text("quux")
|
|
}
|
|
}
|
|
|
|
// Not redundant - multiple top-level views
|
|
@ViewBuilder
|
|
var helper2: some View {
|
|
Text("foo")
|
|
Text("bar")
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## redundantVoidReturnType
|
|
|
|
Remove explicit `Void` return type.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--closure-void` | Explicit Void return types in closures: "remove" (default) or "preserve"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- func foo() -> Void {
|
|
// returns nothing
|
|
}
|
|
|
|
+ func foo() {
|
|
// returns nothing
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## semicolons
|
|
|
|
Remove semicolons.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--semicolons` | Allow semicolons: "inline-only" (default) or "never"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let foo = 5;
|
|
+ let foo = 5
|
|
```
|
|
|
|
```diff
|
|
- let foo = 5; let bar = 6
|
|
+ let foo = 5
|
|
+ let bar = 6
|
|
```
|
|
|
|
```diff
|
|
// semicolon is not removed if it would affect the behavior of the code
|
|
return;
|
|
goto(fail)
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## simplifyGenericConstraints
|
|
|
|
Use inline generic constraints (`<T: Foo>`) instead of where clauses
|
|
(`<T> where T: Foo`) for simple protocol conformance constraints.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- struct Foo<T, U> where T: Hashable, U: Codable {}
|
|
+ struct Foo<T: Hashable, U: Codable> {}
|
|
|
|
- class Bar<Element> where Element: Equatable {
|
|
+ class Bar<Element: Equatable> {
|
|
// ...
|
|
}
|
|
|
|
- enum Result<Value, Error> where Value: Decodable, Error: Swift.Error {}
|
|
+ enum Result<Value: Decodable, Error: Swift.Error> {}
|
|
|
|
- func process<T>(_ value: T) where T: Codable {}
|
|
+ func process<T: Codable>(_ value: T) {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## singlePropertyPerLine
|
|
|
|
Use a separate let/var declaration on its own line for every property definition.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let a, b, c: Int
|
|
+ let a: Int
|
|
+ let b: Int
|
|
+ let c: Int
|
|
|
|
- public var foo = 10, bar = false
|
|
+ public var foo = 10
|
|
+ public var bar = false
|
|
|
|
- var (foo, bar) = ("foo", "bar")
|
|
+ var foo = "foo"
|
|
+ var bar = "bar"
|
|
|
|
- private let (foo, bar): (Int, Bool) = (10, false)
|
|
+ private let foo: Int = 10
|
|
+ private let bar: Bool = false
|
|
|
|
// Preserved:
|
|
let (foo, bar) = methodCallWithPossibleSideEffects()
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## sortDeclarations
|
|
|
|
Sorts the body of declarations with // swiftformat:sort
|
|
and declarations between // swiftformat:sort:begin and
|
|
// swiftformat:sort:end comments.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--sorted-patterns` | List of patterns to sort alphabetically without `:sort` mark
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
// swiftformat:sort
|
|
enum FeatureFlags {
|
|
- case upsellB
|
|
- case fooFeature
|
|
- case barFeature
|
|
- case upsellA(
|
|
- fooConfiguration: Foo,
|
|
- barConfiguration: Bar)
|
|
+ case barFeature
|
|
+ case fooFeature
|
|
+ case upsellA(
|
|
+ fooConfiguration: Foo,
|
|
+ barConfiguration: Bar)
|
|
+ case upsellB
|
|
}
|
|
|
|
/// With --sortedpatterns Feature
|
|
enum FeatureFlags {
|
|
- case upsellB
|
|
- case fooFeature
|
|
- case barFeature
|
|
- case upsellA(
|
|
- fooConfiguration: Foo,
|
|
- barConfiguration: Bar)
|
|
+ case barFeature
|
|
+ case fooFeature
|
|
+ case upsellA(
|
|
+ fooConfiguration: Foo,
|
|
+ barConfiguration: Bar)
|
|
+ case upsellB
|
|
}
|
|
|
|
enum FeatureFlags {
|
|
// swiftformat:sort:begin
|
|
- case upsellB
|
|
- case fooFeature
|
|
- case barFeature
|
|
- case upsellA(
|
|
- fooConfiguration: Foo,
|
|
- barConfiguration: Bar)
|
|
+ case barFeature
|
|
+ case fooFeature
|
|
+ case upsellA(
|
|
+ fooConfiguration: Foo,
|
|
+ barConfiguration: Bar)
|
|
+ case upsellB
|
|
// swiftformat:sort:end
|
|
|
|
var anUnsortedProperty: Foo {
|
|
Foo()
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## sortImports
|
|
|
|
Sort and group import statements.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--import-grouping` | Comma-delimited list of import sorting/grouping options: "alpha", "access-control", "length", "testable-first", "testable-last". Defaults to "access-control,alpha"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- import Foo
|
|
- import Bar
|
|
+ import Bar
|
|
+ import Foo
|
|
```
|
|
|
|
```diff
|
|
- import B
|
|
- import A
|
|
- #if os(iOS)
|
|
- import Foo-iOS
|
|
- import Bar-iOS
|
|
- #endif
|
|
+ import A
|
|
+ import B
|
|
+ #if os(iOS)
|
|
+ import Bar-iOS
|
|
+ import Foo-iOS
|
|
+ #endif
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## sortSwitchCases
|
|
|
|
Sort switch cases alphabetically.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```dif
|
|
switch self {
|
|
- case .b, .a, .c, .e, .d:
|
|
+ case .a, .b, .c, .d, .e:
|
|
return nil
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## sortTypealiases
|
|
|
|
Sort protocol composition typealiases alphabetically.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- typealias Placeholders = Foo & Bar & Baaz & Quux
|
|
+ typealias Placeholders = Baaz & Bar & Foo & Quux
|
|
|
|
typealias Dependencies
|
|
- = FooProviding
|
|
+ = BaazProviding
|
|
& BarProviding
|
|
- & BaazProviding
|
|
+ & FooProviding
|
|
& QuuxProviding
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## sortedImports
|
|
|
|
Sort import statements alphabetically.
|
|
|
|
*Note: sortedImports rule is deprecated. Use sortImports instead.*
|
|
|
|
## sortedSwitchCases
|
|
|
|
Sort switch cases alphabetically.
|
|
|
|
*Note: sortedSwitchCases rule is deprecated. Use sortSwitchCases instead.*
|
|
|
|
## spaceAroundBraces
|
|
|
|
Add or remove space around curly braces.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- foo.filter{ return true }.map{ $0 }
|
|
+ foo.filter { return true }.map { $0 }
|
|
```
|
|
|
|
```diff
|
|
- foo( {} )
|
|
+ foo({})
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceAroundBrackets
|
|
|
|
Add or remove space around square brackets.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- foo as[String]
|
|
+ foo as [String]
|
|
```
|
|
|
|
```diff
|
|
- foo = bar [5]
|
|
+ foo = bar[5]
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceAroundComments
|
|
|
|
Add space before and/or after comments.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let a = 5// assignment
|
|
+ let a = 5 // assignment
|
|
```
|
|
|
|
```diff
|
|
- func foo() {/* ... */}
|
|
+ func foo() { /* ... */ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceAroundGenerics
|
|
|
|
Remove space around angle brackets.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- Foo <Bar> ()
|
|
+ Foo<Bar>()
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceAroundOperators
|
|
|
|
Add or remove space around operators or delimiters.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--operator-func` | Operator function spacing: "spaced" (default), "no-space" or "preserve"
|
|
`--no-space-operators` | Comma-delimited list of operators without surrounding space
|
|
`--ranges` | Range operator spacing: "spaced" (default), "no-space" or "preserve"
|
|
`--type-delimiter` | Type delimiter spacing: "spaced", "space-after" (default) or "no-space"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- foo . bar()
|
|
+ foo.bar()
|
|
```
|
|
|
|
```diff
|
|
- a+b+c
|
|
+ a + b + c
|
|
```
|
|
|
|
```diff
|
|
- func ==(lhs: Int, rhs: Int) -> Bool
|
|
+ func == (lhs: Int, rhs: Int) -> Bool
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceAroundParens
|
|
|
|
Add or remove space around parentheses.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- init (foo)
|
|
+ init(foo)
|
|
```
|
|
|
|
```diff
|
|
- switch(x){
|
|
+ switch (x) {
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceInsideBraces
|
|
|
|
Add space inside curly braces.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- foo.filter {return true}
|
|
+ foo.filter { return true }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceInsideBrackets
|
|
|
|
Remove space inside square brackets.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- [ 1, 2, 3 ]
|
|
+ [1, 2, 3]
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceInsideComments
|
|
|
|
Add leading and/or trailing space inside comments.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let a = 5 //assignment
|
|
+ let a = 5 // assignment
|
|
```
|
|
|
|
```diff
|
|
- func foo() { /*...*/ }
|
|
+ func foo() { /* ... */ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceInsideGenerics
|
|
|
|
Remove space inside angle brackets.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- Foo< Bar, Baz >
|
|
+ Foo<Bar, Baz>
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## spaceInsideParens
|
|
|
|
Remove space inside parentheses.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- ( a, b)
|
|
+ (a, b)
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## specifiers
|
|
|
|
Use consistent ordering for member modifiers.
|
|
|
|
*Note: specifiers rule is deprecated. Use modifierOrder instead.*
|
|
|
|
## strongOutlets
|
|
|
|
Remove `weak` modifier from `@IBOutlet` properties.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
As per Apple's recommendation
|
|
(https://developer.apple.com/videos/play/wwdc2015/407/ @ 32:30).
|
|
|
|
```diff
|
|
- @IBOutlet weak var label: UILabel!
|
|
+ @IBOutlet var label: UILabel!
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## strongifiedSelf
|
|
|
|
Remove backticks around `self` in Optional unwrap expressions.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- guard let `self` = self else { return }
|
|
+ guard let self = self else { return }
|
|
```
|
|
|
|
**NOTE:** assignment to un-escaped `self` is only supported in Swift 4.2 and
|
|
above, so the `strongifiedSelf` rule is disabled unless the Swift version is
|
|
set to 4.2 or above.
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## swiftTestingTestCaseNames
|
|
|
|
Format Swift Testing @Test and @Suite names.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--test-case-name-format` | Swift Testing test case name format: "preserve", "raw-identifiers" (default) or "standard-identifiers"
|
|
`--suite-name-format` | Swift Testing suite name format: "preserve" (default), "raw-identifiers" or "standard-identifiers"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import Testing
|
|
|
|
struct MyFeatureTests {
|
|
- @Test func testMyFeatureHasNoBugs() {
|
|
+ @Test func `my feature has no bugs`() {
|
|
let myFeature = MyFeature()
|
|
myFeature.runAction()
|
|
#expect(!myFeature.hasBugs, "My feature has no bugs")
|
|
#expect(myFeature.crashes.isEmpty, "My feature doesn't crash")
|
|
#expect(myFeature.crashReport == nil)
|
|
}
|
|
|
|
- @Test func `test feature works as expected`(_ feature: Feature) {
|
|
+ @Test func `feature works as expected`(_ feature: Feature) {
|
|
let myFeature = MyFeature()
|
|
myFeature.run(feature)
|
|
#expect(myFeature.worksAsExpected)
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## testSuiteAccessControl
|
|
|
|
Test methods should have the configured access control (default internal), and other properties / functions in a test suite should be private.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--test-case-access-control` | Access control for test methods: "open", "public", "package", "internal" (default), "fileprivate" or "private"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import XCTest
|
|
|
|
final class MyTests: XCTestCase {
|
|
- public func testExample() {
|
|
+ func testExample() {
|
|
XCTAssertTrue(true)
|
|
}
|
|
|
|
- func helperMethod() {
|
|
+ private func helperMethod() {
|
|
// helper code
|
|
}
|
|
}
|
|
```
|
|
|
|
```diff
|
|
import Testing
|
|
|
|
struct MyFeatureTests {
|
|
- @Test public func featureWorks() {
|
|
+ @Test func featureWorks() {
|
|
#expect(true)
|
|
}
|
|
|
|
- func helperMethod() {
|
|
+ private func helperMethod() {
|
|
// helper code
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## throwingTests
|
|
|
|
Write tests that use `throws` instead of using `try!`.
|
|
|
|
*Note: throwingTests rule is deprecated. Renamed to `noForceTryInTests`.*
|
|
|
|
## todos
|
|
|
|
Use correct formatting for `TODO:`, `MARK:` or `FIXME:` comments.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- /* TODO fix this properly */
|
|
+ /* TODO: fix this properly */
|
|
```
|
|
|
|
```diff
|
|
- // MARK - UIScrollViewDelegate
|
|
+ // MARK: - UIScrollViewDelegate
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## trailingClosures
|
|
|
|
Use trailing closure syntax where applicable.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--trailing-closures` | Comma-delimited list of functions that use trailing closures
|
|
`--never-trailing` | List of functions that should never use trailing closures
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- DispatchQueue.main.async(execute: { ... })
|
|
+ DispatchQueue.main.async {
|
|
```
|
|
|
|
```diff
|
|
- let foo = bar.map({ ... }).joined()
|
|
+ let foo = bar.map { ... }.joined()
|
|
```
|
|
|
|
```diff
|
|
- withAnimation(.spring, {
|
|
- isVisible = true
|
|
- }, completion: {
|
|
- handleCompletion()
|
|
- })
|
|
+ withAnimation(.spring) {
|
|
+ isVisible = true
|
|
+ } completion: {
|
|
+ handleCompletion()
|
|
+ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## trailingCommas
|
|
|
|
Add or remove trailing commas in comma-separated lists.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--trailing-commas` | Include trailing commas: "never", "always" (default), "collections-only" or "multi-element-lists"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
let array = [
|
|
foo,
|
|
bar,
|
|
- baz
|
|
+ baz,
|
|
]
|
|
```
|
|
|
|
Swift 6.1 and later with `--trailing-commas always`:
|
|
|
|
```diff
|
|
func foo(
|
|
bar: Int,
|
|
- baaz: Int
|
|
+ baaz: Int,
|
|
) {}
|
|
```
|
|
|
|
```diff
|
|
foo(
|
|
bar: 1,
|
|
- baaz: 2
|
|
+ baaz: 2,
|
|
)
|
|
```
|
|
|
|
```diff
|
|
struct Foo<
|
|
Bar,
|
|
Baaz,
|
|
- Quux
|
|
+ Quux,
|
|
> {}
|
|
```
|
|
|
|
`--trailing-commas multi-element-lists`
|
|
|
|
```diff
|
|
let foo = [
|
|
- bar,
|
|
+ bar
|
|
]
|
|
|
|
foo(
|
|
- bar,
|
|
+ bar
|
|
)
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## trailingSpace
|
|
|
|
Remove trailing space at end of a line.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--trim-whitespace` | Trim trailing whitespace: "always" (default) or "nonblank-lines"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let foo: Foo␣
|
|
+ let foo: Foo
|
|
- ␣␣␣␣
|
|
+
|
|
- func bar() {␣␣
|
|
+ func bar() {
|
|
␣␣␣␣print("foo")
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## typeSugar
|
|
|
|
Prefer shorthand syntax for Arrays, Dictionaries and Optionals.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--short-optionals` | Prefer ? shorthand for optionals: "preserve-struct-inits" (default) or "always"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- var foo: Optional<String>
|
|
+ var foo: String?
|
|
```
|
|
|
|
```diff
|
|
- var foo: Array<String>
|
|
+ var foo: [String]
|
|
```
|
|
|
|
```diff
|
|
- var foo: Dictionary<String, Int>
|
|
+ var foo: [String: Int]
|
|
```
|
|
|
|
By default, preserves `Optional` types that affect a struct's synthesized memberwise initializer:
|
|
|
|
```swift
|
|
struct Foo {
|
|
var bar: Optional<String>
|
|
}
|
|
```
|
|
|
|
With `var bar: Optional<String>`, `Foo`'s initializer is `init(bar: String?)`. If updated to `var bar String?`, `Foo`'s initializer would become `init(bar: String? = nil)`, which may be unexpected.
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## unusedArguments
|
|
|
|
Mark unused function arguments with `_`.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--strip-unused-args` | Strip unused arguments: "unnamed-only", "closure-only" or "always" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- func foo(bar: Int, baz: String) {
|
|
print("Hello \(baz)")
|
|
}
|
|
|
|
+ func foo(bar _: Int, baz: String) {
|
|
print("Hello \(baz)")
|
|
}
|
|
```
|
|
|
|
```diff
|
|
- func foo(_ bar: Int) {
|
|
...
|
|
}
|
|
|
|
+ func foo(_: Int) {
|
|
...
|
|
}
|
|
```
|
|
|
|
```diff
|
|
- request { response, data in
|
|
self.data += data
|
|
}
|
|
|
|
+ request { _, data in
|
|
self.data += data
|
|
}
|
|
```
|
|
|
|
```diff
|
|
- for (key, value) in dictionary {
|
|
print(key)
|
|
}
|
|
|
|
+ for (key, _) in dictionary {
|
|
print(key)
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## unusedPrivateDeclarations
|
|
|
|
Remove unused private and fileprivate declarations.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--preserve-decls` | Comma separated list of declaration names to exclude
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
struct Foo {
|
|
- fileprivate var foo = "foo"
|
|
- fileprivate var baz = "baz"
|
|
var bar = "bar"
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## urlMacro
|
|
|
|
Replace force-unwrapped `URL(string:)` initializers with the configured `#URL(_:)` macro.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--url-macro` | For example: --url-macro "#URL,URLFoundation"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
With `--url-macro "#URL,URLFoundation"`:
|
|
|
|
```diff
|
|
- let url = URL(string: "https://example.com")!
|
|
+ import URLFoundation
|
|
+ let url = #URL("https://example.com")
|
|
```
|
|
|
|
```diff
|
|
- return URL(string: "https://api.example.com/users")!
|
|
+ import URLFoundation
|
|
+ return #URL("https://api.example.com/users")
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## validateTestCases
|
|
|
|
Ensure test case methods have the correct `test` prefix or `@Test` attribute.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
import XCTest
|
|
|
|
final class MyTests: XCTestCase {
|
|
- func myFeatureWorksCorrectly() {
|
|
+ func testMyFeatureWorksCorrectly() {
|
|
XCTAssertTrue(myFeature.worksCorrectly)
|
|
}
|
|
}
|
|
```
|
|
|
|
```diff
|
|
import Testing
|
|
|
|
struct MyFeatureTests {
|
|
- func testMyFeatureWorksCorrectly() {
|
|
+ @Test func myFeatureWorksCorrectly() {
|
|
#expect(myFeature.worksCorrectly)
|
|
}
|
|
|
|
- func myFeatureHasNoBugs() {
|
|
+ @Test func myFeatureHasNoBugs() {
|
|
#expect(myFeature.hasNoBugs)
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## void
|
|
|
|
Use `Void` for type declarations and `()` for values.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--void-type` | How Void types are represented: "Void" (default) or "tuple"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let foo: () -> ()
|
|
+ let foo: () -> Void
|
|
```
|
|
|
|
```diff
|
|
- let bar: Void -> Void
|
|
+ let bar: () -> Void
|
|
```
|
|
|
|
```diff
|
|
- let baz: (Void) -> Void
|
|
+ let baz: () -> Void
|
|
```
|
|
|
|
```diff
|
|
- func quux() -> (Void)
|
|
+ func quux() -> Void
|
|
```
|
|
|
|
```diff
|
|
- callback = { _ in Void() }
|
|
+ callback = { _ in () }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrap
|
|
|
|
Wrap lines that exceed the specified maximum width.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--max-width` | Maximum length of a line before wrapping. Defaults to "none"
|
|
`--no-wrap-operators` | Comma-delimited list of operators that shouldn't be wrapped
|
|
`--asset-literals` | Formatting of color/image literals: "actual-width" or "visual-width" (default)
|
|
`--wrap-ternary` | Ternary expression wrapping: "default" (wrap if needed) or "before-operators"
|
|
`--wrap-string-interpolation` | String interpolation wrapping: "default" (wrap if needed) or "preserve"
|
|
|
|
## wrapArguments
|
|
|
|
Align wrapped function arguments or collection elements.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--wrap-arguments` | Function argument wrapping: "before-first", "after-first", "preserve" (default) or "disabled"
|
|
`--wrap-parameters` | Function call parameter wrapping: "before-first", "after-first", "preserve" or "disabled"
|
|
`--wrap-collections` | Collection literal element wrapping: "before-first", "after-first", "preserve" (default) or "disabled"
|
|
`--closing-paren` | Closing paren placement: "balanced" (default) or "same-line"
|
|
`--call-site-paren` | Closing paren placement at function call sites: "balanced" or "same-line"
|
|
`--wrap-return-type` | Function return type wrapping: "preserve" (default), "if-multiline" or "never"
|
|
`--wrap-conditions` | Conditional expression wrapping: "before-first", "after-first", "preserve" (default) or "disabled"
|
|
`--wrap-type-aliases` | Typealias wrapping: "before-first", "after-first", "preserve" (default) or "disabled"
|
|
`--wrap-effects` | Function effects (throws, async) wrapping: "preserve" (default), "if-multiline" or "never"
|
|
`--wrap-string-interpolation` | String interpolation wrapping: "default" (wrap if needed) or "preserve"
|
|
`--allow-partial-wrapping` | Allow partial argument wrapping: "true" (default) or "false"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
**NOTE:** For backwards compatibility with previous versions, if no value is
|
|
provided for `--wrap-parameters`, the value for `--wrap-arguments` will be used.
|
|
|
|
`--wrap-arguments before-first`
|
|
|
|
```diff
|
|
- foo(bar: Int,
|
|
- baz: String)
|
|
|
|
+ foo(
|
|
+ bar: Int,
|
|
+ baz: String
|
|
+ )
|
|
```
|
|
|
|
```diff
|
|
- class Foo<Bar,
|
|
- Baz>
|
|
|
|
+ class Foo<
|
|
+ Bar,
|
|
+ Baz
|
|
+ >
|
|
```
|
|
|
|
`--wrap-parameters after-first`
|
|
|
|
```diff
|
|
- func foo(
|
|
- bar: Int,
|
|
- baz: String
|
|
- ) {
|
|
...
|
|
}
|
|
|
|
+ func foo(bar: Int,
|
|
+ baz: String)
|
|
+ {
|
|
...
|
|
}
|
|
```
|
|
|
|
`--wrap-collections before-first`:
|
|
|
|
```diff
|
|
- let foo = [bar,
|
|
baz,
|
|
- quuz]
|
|
|
|
+ let foo = [
|
|
+ bar,
|
|
baz,
|
|
+ quuz
|
|
+ ]
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapAttributes
|
|
|
|
Wrap @attributes onto a separate line, or keep them on the same line.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--func-attributes` | Placement for function @attributes: "prev-line", "same-line" or "preserve" (default)
|
|
`--type-attributes` | Placement for type @attributes: "prev-line", "same-line" or "preserve" (default)
|
|
`--stored-var-attributes` | Placement for stored var @attributes: "prev-line", "same-line" or "preserve" (default)
|
|
`--computed-var-attributes` | Placement for computed var @attributes: "prev-line", "same-line" or "preserve" (default)
|
|
`--complex-attributes` | Placement for complex @attributes: "prev-line", "same-line" or "preserve" (default)
|
|
`--non-complex-attributes` | List of @attributes to exclude from --complexattributes options
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
`--func-attributes prev-line`
|
|
|
|
```diff
|
|
- @objc func foo() {}
|
|
|
|
+ @objc
|
|
+ func foo() { }
|
|
```
|
|
|
|
`--func-attributes same-line`
|
|
|
|
```diff
|
|
- @objc
|
|
- func foo() { }
|
|
|
|
+ @objc func foo() {}
|
|
```
|
|
|
|
`--type-attributes prev-line`
|
|
|
|
```diff
|
|
- @objc class Foo {}
|
|
|
|
+ @objc
|
|
+ class Foo { }
|
|
```
|
|
|
|
`--type-attributes same-line`
|
|
|
|
```diff
|
|
- @objc
|
|
- enum Foo { }
|
|
|
|
+ @objc enum Foo {}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapCaseBodies
|
|
|
|
Wrap the bodies of inline switch cases onto a new line.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- case .foo: return bar
|
|
+ case .foo:
|
|
+ return bar
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapConditionalBodies
|
|
|
|
Wrap the bodies of inline conditional statements onto a new line.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- guard let foo = bar else { return baz }
|
|
+ guard let foo = bar else {
|
|
+ return baz
|
|
+ }
|
|
```
|
|
|
|
```diff
|
|
- if foo { return bar }
|
|
+ if foo {
|
|
+ return bar
|
|
+ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapEnumCases
|
|
|
|
Rewrite comma-delimited enum cases to one case per line.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--wrap-enum-cases` | Enum case wrapping: "always" (default) or "with-values"
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
enum Foo {
|
|
- case bar, baz
|
|
}
|
|
|
|
enum Foo {
|
|
+ case bar
|
|
+ case baz
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapFunctionBodies
|
|
|
|
Wrap single-line function, init, and subscript bodies onto multiple lines.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- func foo() { print("bar") }
|
|
+ func foo() {
|
|
+ print("bar")
|
|
+ }
|
|
|
|
- init() { self.value = 0 }
|
|
+ init() {
|
|
+ self.value = 0
|
|
+ }
|
|
|
|
- subscript(index: Int) -> Int { array[index] }
|
|
+ subscript(index: Int) -> Int {
|
|
+ array[index]
|
|
+ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapLoopBodies
|
|
|
|
Wrap the bodies of inline loop statements onto a new line.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- for foo in array { print(foo) }
|
|
+ for foo in array {
|
|
+ print(foo)
|
|
+ }
|
|
```
|
|
|
|
```diff
|
|
- while let foo = bar.next() { print(foo) }
|
|
+ while let foo = bar.next() {
|
|
+ print(foo)
|
|
+ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapMultilineConditionalAssignment
|
|
|
|
Wrap multiline conditional assignment expressions after the assignment operator.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- let planetLocation = if let star = planet.star {
|
|
- "The \(star.name) system"
|
|
- } else {
|
|
- "Rogue planet"
|
|
- }
|
|
+ let planetLocation =
|
|
+ if let star = planet.star {
|
|
+ "The \(star.name) system"
|
|
+ } else {
|
|
+ "Rogue planet"
|
|
+ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapMultilineFunctionChains
|
|
|
|
Wraps chained function calls to either all on the same line, or one per line.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
let evenSquaresSum = [20, 17, 35, 4]
|
|
- .filter { $0 % 2 == 0 }.map { $0 * $0 }
|
|
.reduce(0, +)
|
|
|
|
let evenSquaresSum = [20, 17, 35, 4]
|
|
+ .filter { $0 % 2 == 0 }
|
|
+ .map { $0 * $0 }
|
|
.reduce(0, +)
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapMultilineStatementBraces
|
|
|
|
Wrap the opening brace of multiline statements.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
if foo,
|
|
- bar {
|
|
// ...
|
|
}
|
|
|
|
if foo,
|
|
+ bar
|
|
+ {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```diff
|
|
guard foo,
|
|
- bar else {
|
|
// ...
|
|
}
|
|
|
|
guard foo,
|
|
+ bar else
|
|
+ {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```diff
|
|
func foo(
|
|
bar: Int,
|
|
- baz: Int) {
|
|
// ...
|
|
}
|
|
|
|
func foo(
|
|
bar: Int,
|
|
+ baz: Int)
|
|
+ {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```diff
|
|
class Foo: NSObject,
|
|
- BarProtocol {
|
|
// ...
|
|
}
|
|
|
|
class Foo: NSObject,
|
|
+ BarProtocol
|
|
+ {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapPropertyBodies
|
|
|
|
Wrap single-line property bodies onto multiple lines.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- var bar: String { "bar" }
|
|
+ var bar: String {
|
|
+ "bar"
|
|
+ }
|
|
|
|
- var foo: Int { didSet { bar() } }
|
|
+ var foo: Int {
|
|
+ didSet { bar() }
|
|
+ }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## wrapSingleLineComments
|
|
|
|
Wrap single line `//` comments that exceed the specified `--max-width`.
|
|
|
|
## wrapSwitchCases
|
|
|
|
Wrap comma-delimited switch cases onto multiple lines.
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
switch foo {
|
|
- case .bar, .baz:
|
|
break
|
|
}
|
|
|
|
switch foo {
|
|
+ case .foo,
|
|
+ .bar:
|
|
break
|
|
}
|
|
```
|
|
|
|
</details>
|
|
<br/>
|
|
|
|
## yodaConditions
|
|
|
|
Prefer constant values to be on the right-hand-side of expressions.
|
|
|
|
Option | Description
|
|
--- | ---
|
|
`--yoda-swap` | Swap yoda expression operands: "literals-only" or "always" (default)
|
|
|
|
<details>
|
|
<summary>Examples</summary>
|
|
|
|
```diff
|
|
- if 5 == foo,
|
|
+ if foo == 5,
|
|
- nil != bar,
|
|
+ bar != nil,
|
|
- .default == baaz,
|
|
+ baaz == .default,
|
|
{ ... }
|
|
```
|
|
|
|
</details>
|
|
<br/>
|