79 KiB
Default Rules (enabled by default)
- andOperator
- anyObjectProtocol
- applicationMain
- assertionFailures
- blankLineAfterImports
- blankLinesAroundMark
- blankLinesAtEndOfScope
- blankLinesAtStartOfScope
- blankLinesBetweenChainedFunctions
- blankLinesBetweenScopes
- braces
- conditionalAssignment
- consecutiveBlankLines
- consecutiveSpaces
- consistentSwitchCaseSpacing
- docCommentsBeforeModifiers
- duplicateImports
- elseOnSameLine
- emptyBraces
- enumNamespaces
- extensionAccessControl
- fileHeader
- fileMacro
- genericExtensions
- headerFileName
- hoistAwait
- hoistPatternLet
- hoistTry
- indent
- initCoderUnavailable
- leadingDelimiters
- linebreakAtEndOfFile
- linebreaks
- modifierOrder
- modifiersOnSameLine
- numberFormatting
- opaqueGenericParameters
- preferCountWhere
- preferForLoop
- preferKeyPath
- redundantBackticks
- redundantBreak
- redundantClosure
- redundantExtensionACL
- redundantFileprivate
- redundantGet
- redundantInit
- redundantInternal
- redundantLet
- redundantLetError
- redundantNilInit
- redundantObjc
- redundantOptionalBinding
- redundantParens
- redundantPattern
- redundantPublic
- redundantRawValues
- redundantReturn
- redundantSelf
- redundantStaticSelf
- redundantType
- redundantTypedThrows
- redundantVoidReturnType
- semicolons
- sortDeclarations
- sortImports
- sortTypealiases
- spaceAroundBraces
- spaceAroundBrackets
- spaceAroundComments
- spaceAroundGenerics
- spaceAroundOperators
- spaceAroundParens
- spaceInsideBraces
- spaceInsideBrackets
- spaceInsideComments
- spaceInsideGenerics
- spaceInsideParens
- strongOutlets
- strongifiedSelf
- swiftTestingTestCaseNames
- todos
- trailingClosures
- trailingCommas
- trailingSpace
- typeSugar
- unusedArguments
- void
- wrap
- wrapArguments
- wrapAttributes
- wrapLoopBodies
- wrapMultilineStatementBraces
- wrapSingleLineComments
- yodaConditions
Opt-in Rules (disabled by default)
- acronyms
- blankLineAfterSwitchCase
- blankLinesAfterGuardStatements
- blankLinesBetweenImports
- blockComments
- docComments
- emptyExtensions
- environmentEntry
- isEmpty
- markTypes
- noExplicitOwnership
- noForceTryInTests
- noForceUnwrapInTests
- noGuardInTests
- organizeDeclarations
- preferFinalClasses
- preferSwiftTesting
- privateStateVariables
- propertyTypes
- redundantAsync
- redundantEquatable
- redundantMemberwiseInit
- redundantProperty
- redundantThrows
- singlePropertyPerLine
- sortSwitchCases
- unusedPrivateDeclarations
- urlMacro
- wrapConditionalBodies
- wrapEnumCases
- wrapMultilineConditionalAssignment
- wrapMultilineFunctionChains
- wrapSwitchCases
Deprecated Rules (do not use)
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 |
Examples
- let destinationUrl: URL
- let urlRouter: UrlRouter
- let screenIds: [String]
- let entityUuid: UUID
+ let destinationURL: URL
+ let urlRouter: URLRouter
+ let screenIDs: [String]
+ let entityUUID: UUID
andOperator
Prefer comma over && in if, guard or while conditions.
Examples
- if true && true {
+ if true, true {
- guard true && true else {
+ guard true, true else {
- if functionReturnsBool() && true {
+ if functionReturnsBool(), true {
- if functionReturnsBool() && variable {
+ if functionReturnsBool(), variable {
anyObjectProtocol
Prefer AnyObject over class in protocol definitions.
Examples
- 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.
applicationMain
Replace obsolete @UIApplicationMain and @NSApplicationMain attributes with @main for Swift 5.3 and above.
Examples
- @UIApplicationMain
+ @main
class AppDelegate: UIResponder, UIApplicationDelegate {}
assertionFailures
Changes all instances of assert(false, ...) to assertionFailure(...) and precondition(false, ...) to preconditionFailure(...).
Examples
- assert(false)
+ assertionFailure()
- assert(false, "message", 2, 1)
+ assertionFailure("message", 2, 1)
- precondition(false, "message", 2, 1)
+ preconditionFailure("message", 2, 1)
blankLineAfterImports
Insert blank line after import statements.
Examples
import A
import B
@testable import D
+
class Foo {
// foo
}
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) |
Examples
--blank-line-after-switch-case multiline-only (default)
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()
}
}
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
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()
}
}
func handle(_ action: SpaceshipAction) {
switch action {
case .engageWarpDrive:
warpDrive.activate()
+
case let .scanPlanet(planet):
scanner.scanForArticialLife()
+
case .handleIncomingEnergyBlast:
energyShields.engage()
}
}
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) |
Examples
--line-between-guards false (default)
// 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()
// 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
// 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()
// 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()
blankLinesAroundMark
Insert blank line before and after MARK: comments.
| Option | Description |
|---|---|
--line-after-marks |
Insert blank line after "MARK:": "true" (default) or "false" |
Examples
func foo() {
// foo
}
// MARK: bar
func bar() {
// bar
}
func foo() {
// foo
}
+
// MARK: bar
+
func bar() {
// bar
}
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" |
Examples
func foo() {
// foo
-
}
func foo() {
// foo
}
array = [
foo,
bar,
baz,
-
]
array = [
foo,
bar,
baz,
]
With --type-blank-lines insert:
struct Foo {
let bar: Bar
+
}
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" |
Examples
func foo() {
-
// foo
}
func foo() {
// foo
}
array = [
-
foo,
bar,
baz,
]
array = [
foo,
bar,
baz,
]
With --type-blank-lines insert:
struct Foo {
+
let bar: Bar
}
blankLinesBetweenChainedFunctions
Remove blank lines between chained functions but keep the linebreaks.
Examples
[0, 1, 2]
.map { $0 * 2 }
-
-
-
.map { $0 * 3 }
blankLinesBetweenImports
Remove blank lines between import statements.
Examples
import A
-
import B
import C
-
-
@testable import D
import E
blankLinesBetweenScopes
Insert blank line before class, struct, enum, extension, protocol or function declarations.
Examples
func foo() {
// foo
}
func bar() {
// bar
}
var baz: Bool
var quux: Int
func foo() {
// foo
}
+
func bar() {
// bar
}
+
var baz: Bool
var quux: Int
blockComments
Convert block comments to consecutive single line comments.
Examples
- /*
- * foo
- * bar
- */
+ // foo
+ // bar
- /**
- * foo
- * bar
- */
+ /// foo
+ /// bar
braces
Wrap braces in accordance with selected style (K&R or Allman).
| Option | Description |
|---|---|
--allman |
Use Allman indentation style: "true" or "false" (default) |
Examples
- if x
- {
// foo
}
- else
- {
// bar
}
+ if x {
// foo
}
+ else {
// bar
}
conditionalAssignment
Assign properties using if / switch expressions.
| Option | Description |
|---|---|
--conditional-assignment |
Use if/switch expressions for conditional assignment: "after-property" (default) or "always" |
Examples
- 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"
}
consecutiveBlankLines
Replace consecutive blank lines with a single blank line.
Examples
func foo() {
let x = "bar"
-
print(x)
}
func foo() {
let x = "bar"
print(x)
}
consecutiveSpaces
Replace consecutive spaces with a single space.
Examples
- let foo = 5
+ let foo = 5
consistentSwitchCaseSpacing
Ensures consistent spacing among all of the cases in a switch statement.
Examples
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()
}
}
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"
}
docComments
Use doc comments for API declarations, otherwise use regular comments.
| Option | Description |
|---|---|
--doc-comments |
Preserve doc comments: "preserve" or "before-declarations" (default) |
Examples
- // 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
}
}
docCommentsBeforeModifiers
Place doc comments before any declaration modifiers or attributes.
Examples
+ /// Doc comment on this function declaration
@MainActor
- /// Doc comment on this function declaration
func foo() {}
duplicateImports
Remove duplicate import statements.
Examples
import Foo
import Bar
- import Foo
import B
#if os(iOS)
import A
- import B
#endif
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) |
Examples
if x {
// foo
- }
- else {
// bar
}
if x {
// foo
+ } else {
// bar
}
do {
// try foo
- }
- catch {
// bar
}
do {
// try foo
+ } catch {
// bar
}
repeat {
// foo
- }
- while {
// bar
}
repeat {
// foo
+ } while {
// bar
}
emptyBraces
Remove whitespace inside empty braces.
| Option | Description |
|---|---|
--empty-braces |
Empty brace spacing: "spaced", "no-space" (default) or "linebreak" |
Examples
- func foo() {
-
- }
+ func foo() {}
emptyExtensions
Remove empty, non-conforming, extensions.
Examples
- extension String {}
-
extension String: Equatable {}
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" |
Examples
- class FeatureConstants {
+ enum FeatureConstants {
static let foo = "foo"
static let bar = "bar"
}
environmentEntry
Updates SwiftUI EnvironmentValues definitions to use the @Entry macro.
Examples
- 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")
}
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" |
Examples
--extension-acl on-extension (default)
- extension Foo {
- public func bar() {}
- public func baz() {}
}
+ public extension Foo {
+ func bar() {}
+ func baz() {}
}
--extension-acl on-declarations
- public extension Foo {
- func bar() {}
- func baz() {}
- internal func quux() {}
}
+ extension Foo {
+ public func bar() {}
+ public func baz() {}
+ func quux() {}
}
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 |
Examples
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
- // 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.
--date-format iso
- // Created {created}
+ // Created 2023-08-10
--date-format dmy
- // Created {created}
+ // Created 10/08/2023
--date-format mdy
- // Created {created}
+ // Created 08/10/2023
--date-format 'yyyy.MM.dd.HH.mm'
- // 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
- // Created {created}
+ // Created 2023-08-10 11:00 GMT
--date-format 'yyyy-MM-dd HH:mm ZZZZ' --timezone Pacific/Fiji
- // Created 2023-08-10 11:00 GMT
+ // Created 2023-08-10 23:00 GMT+12:00
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" |
Examples
// --filemacro #file
- func foo(file: StaticString = #fileID) { ... }
+ func foo(file: StaticString = #file) { ... }
// --filemacro #fileID
- func foo(file: StaticString = #file) { ... }
+ func foo(file: StaticString = #fileID) { ... }
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;StateStore<State, Action>" |
Examples
- 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> {}
headerFileName
Ensure file name in header comment matches the actual file name.
Examples
For a file named Bar.swift:
- // Foo.swift
+ // Bar.swift
// SwiftFormat
//
// Created by Nick Lockwood on 5/3/23.
struct Bar {}
hoistAwait
Move inline await keyword(s) to start of expression.
| Option | Description |
|---|---|
--async-capturing |
List of functions with async @autoclosure arguments |
Examples
- greet(await forename, await surname)
+ await greet(forename, surname)
- let foo = String(try await getFoo())
+ let foo = await String(try getFoo())
hoistPatternLet
Reposition let or var bindings within pattern.
| Option | Description |
|---|---|
--pattern-let |
Placement of let/var in patterns: "hoist" (default) or "inline" |
Examples
- (let foo, let bar) = baz()
+ let (foo, bar) = baz()
- if case .foo(let bar, let baz) = quux {
// inner foo
}
+ if case let .foo(bar, baz) = quux {
// inner foo
}
hoistTry
Move inline try keyword(s) to start of expression.
| Option | Description |
|---|---|
--throw-capturing |
List of functions with throwing @autoclosure arguments |
Examples
- foo(try bar(), try baz())
+ try foo(bar(), baz())
- let foo = String(try await getFoo())
+ let foo = try String(await getFoo())
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" or "outdent" |
--xcode-indentation |
Match Xcode indenting: "enabled" or "disabled" (default) |
--indent-strings |
Indent multiline strings: "true" or "false" (default) |
Examples
if x {
- // foo
} else {
- // bar
- }
if x {
+ // foo
} else {
+ // bar
+ }
let array = [
foo,
- bar,
- baz
- ]
let array = [
foo,
+ bar,
+ baz
+ ]
switch foo {
- case bar: break
- case baz: break
}
switch foo {
+ case bar: break
+ case baz: break
}
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) |
Examples
+ @available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
isEmpty
Prefer isEmpty over comparing count against zero.
Examples
- 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.
leadingDelimiters
Move leading delimiters to the end of the previous line.
Examples
- guard let foo = maybeFoo // first
- , let bar = maybeBar else { ... }
+ guard let foo = maybeFoo, // first
+ let bar = maybeBar else { ... }
linebreakAtEndOfFile
Add empty blank line at end of file.
Examples
struct Foo {↩
let bar: Bar↩
- }
+ }↩
+
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") |
Examples
+ // MARK: - FooViewController
+
final class FooViewController: UIViewController { }
+ // MARK: UICollectionViewDelegate
+
extension FooViewController: UICollectionViewDelegate { }
+ // MARK: - String + FooProtocol
+
extension String: FooProtocol { }
modifierOrder
Use consistent ordering for member modifiers.
| Option | Description |
|---|---|
--modifier-order |
Comma-delimited list of modifiers in preferred order |
Examples
- lazy public weak private(set) var foo: UIView?
+ public private(set) lazy weak var foo: UIView?
- final public override func foo()
+ override public final func foo()
- 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
modifiersOnSameLine
Ensure that all modifiers are on the same line as the declaration keyword.
Examples
- @MainActor
- public
- private(set)
- var foo: Foo
+ @MainActor
+ public private(set) var foo: Foo
- nonisolated
- func bar() {}
+ nonisolated func bar() {}
noExplicitOwnership
Don't use explicit ownership modifiers (borrowing / consuming).
Examples
- borrowing func foo(_ bar: consuming Bar) { ... }
+ func foo(_ bar: Bar) { ... }
noForceTryInTests
Write tests that use throws instead of using try!.
Examples
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()
}
}
noForceUnwrapInTests
Use XCTUnwrap or #require in test cases, rather than force unwrapping.
Examples
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)
}
}
noGuardInTests
Convert guard statements in unit tests to try #require(...) / #expect(...)
or try XCTUnwrap(...) / XCTAssert(...).
Examples
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)
}
}
import Testing
struct SomeTests {
@Test
func something() throws {
- guard let value = optionalValue, value.matchesCondition else {
- return
- }
+ let value = try #require(optionalValue)
+ #expect(value.matchesCondition)
}
}
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) |
Examples
- let color = 0xFF77A5
+ let color = 0xff77a5
- let big = 123456.123
+ let big = 123_456.123
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" |
Examples
- 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)
}
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" |
Examples
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)
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
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() {}
+
}
preferCountWhere
Prefer count(where:) over filter(_:).count.
Examples
- 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
+ })
preferFinalClasses
Prefer defining final classes. To suppress this rule, add "Base" to the class name, add a doc comment with mentioning "base class" or "subclass", make the class open, or use a // swiftformat:disable:next preferFinalClasses directive.
Examples
- class Foo {}
+ final class Foo {}
- public class Bar {}
+ public final class Bar {}
// 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 {}
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" |
Examples
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) }
preferKeyPath
Convert trivial map { $0.foo } closures to keyPath-based syntax.
Examples
- let barArray = fooArray.map { $0.bar }
+ let barArray = fooArray.map(\.bar)
- let barArray = fooArray.compactMap { $0.optionalBar }
+ let barArray = fooArray.compactMap(\.optionalBar)
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)" |
Examples
@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)
+ }
+ }
privateStateVariables
Adds private access control to @State properties without existing access control modifiers.
Examples
- @State var anInt: Int
+ @State private var anInt: Int
- @StateObject var myInstance: MyObject
+ @StateObject private var myInstace: MyObject
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 |
Examples
// with --propertytypes inferred
- let view: UIView = .init()
+ let view = UIView()
- let color: Color = .red
+ let color = Color.red
- let array: [Int] = []
+ let array = [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] = []
// 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)
}
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" |
Examples
// 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.
// 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
redundantBackticks
Remove redundant backticks around identifiers.
Examples
- let `infix` = bar
+ let infix = bar
- func foo(with `default`: Int) {}
+ func foo(with default: Int) {}
redundantBreak
Remove redundant break in switch case.
Examples
switch foo {
case bar:
print("bar")
- break
default:
print("default")
- break
}
redundantClosure
Removes redundant closures bodies, containing a single statement, which are called immediately.
Examples
- let foo = { Foo() }()
+ let foo = Foo()
- lazy var bar = {
- Bar(baaz: baaz,
- quux: quux)
- }()
+ lazy var bar = Bar(baaz: baaz,
+ quux: quux)
redundantEquatable
Omit a hand-written Equatable implementation when the compiler-synthesized conformance would be equivalent.
| Option | Description |
|---|---|
--equatable-macro |
For example: "@Equatable,EquatableMacroLib" |
Examples
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:
// --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
- }
}
redundantExtensionACL
Remove redundant access control modifiers.
Examples
public extension URL {
- public func queryParameter(_ name: String) -> String { ... }
}
public extension URL {
+ func queryParameter(_ name: String) -> String { ... }
}
redundantFileprivate
Prefer private over fileprivate where equivalent.
Examples
- 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:
class Foo {
- fileprivate var foo = "foo"
+ private var foo = "foo"
}
extension Foo {
func bar() {
print(self.foo)
}
}
redundantGet
Remove unneeded get clause inside computed properties.
Examples
var foo: Int {
- get {
- return 5
- }
}
var foo: Int {
+ return 5
}
redundantInit
Remove explicit init if not required.
Examples
- String.init("text")
+ String("text")
redundantInternal
Remove redundant internal access control.
Examples
- internal class Foo {
+ class Foo {
- internal let bar: String
+ let bar: String
- internal func baaz() {}
+ func baaz() {}
- internal init() {
+ init() {
bar = "bar"
}
}
redundantLet
Remove redundant let/var from ignored variables.
Examples
- let _ = foo()
+ _ = foo()
redundantLetError
Remove redundant let error from catch clause.
Examples
- do { ... } catch let error { log(error) }
+ do { ... } catch { log(error) }
redundantMemberwiseInit
Remove explicit internal memberwise initializers that are redundant.
Examples
struct Person {
var name: String
var age: Int
- init(name: String, age: Int) {
- self.name = name
- self.age = age
- }
}
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" |
Examples
--nil-init remove
- var foo: Int? = nil
+ var foo: Int?
// doesn't apply to `let` properties
let foo: Int? = nil
// doesn't affect non-nil initialization
var foo: Int? = 0
--nil-init insert
- var foo: Int?
+ var foo: Int? = nil
redundantObjc
Remove redundant @objc annotations.
Examples
- @objc @IBOutlet var label: UILabel!
+ @IBOutlet var label: UILabel!
- @IBAction @objc func goBack() {}
+ @IBAction func goBack() {}
- @objc @NSManaged private var foo: String?
+ @NSManaged private var foo: String?
redundantOptionalBinding
Remove redundant identifiers in optional binding conditions.
Examples
- if let foo = foo {
+ if let foo {
print(foo)
}
- guard let self = self else {
+ guard let self else {
return
}
redundantParens
Remove redundant parentheses.
Examples
- if (foo == true) {}
+ if foo == true {}
- while (i < bar.count) {}
+ while i < bar.count {}
- queue.async() { ... }
+ queue.async { ... }
- let foo: Int = ({ ... })()
+ let foo: Int = { ... }()
redundantPattern
Remove redundant pattern matching parameter syntax.
Examples
- if case .foo(_, _) = bar {}
+ if case .foo = bar {}
- let (_, _) = bar
+ let _ = bar
redundantProperty
Simplifies redundant property definitions that are immediately returned.
Examples
func foo() -> Foo {
- let foo = Foo()
- return foo
+ return Foo()
}
redundantPublic
Remove redundant public access control from declarations in internal or private types.
Examples
struct Foo {
- public let bar: Bar
+ let bar: Bar
- public func baz() {}
+ func baz() {}
}
extension Foo {
- public func quux() {}
+ func quux() {}
}
redundantRawValues
Remove redundant raw string values for enum cases.
Examples
enum Foo: String {
- case bar = "bar"
case baz = "quux"
}
enum Foo: String {
+ case bar
case baz = "quux"
}
redundantReturn
Remove unneeded return keyword.
Examples
- 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"
}
}
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 with @autoclosure arguments |
Examples
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:
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
}
redundantStaticSelf
Remove explicit Self where applicable.
Examples
enum Foo {
static let bar = Bar()
static func baaz() -> Bar {
- Self.bar()
+ bar()
}
}
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" |
Examples
// 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.
// 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
redundantType
Remove redundant type from variable declarations.
| Option | Description |
|---|---|
--property-types |
Types in property declarations: "explicit", "inferred" or "infer-locals-only" (default) |
Examples
// 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")
}
redundantTypedThrows
Converts throws(any Error) to throws, and converts throws(Never) to non-throwing.
Examples
- func foo() throws(Never) -> Int {
+ func foo() -> Int {
return 0
}
- func foo() throws(any Error) -> Int {
+ func foo() throws -> Int {
throw MyError.foo
}
redundantVoidReturnType
Remove explicit Void return type.
| Option | Description |
|---|---|
--closure-void |
Explicit Void return types in closures: "remove" (default) or "preserve" |
Examples
- func foo() -> Void {
// returns nothing
}
+ func foo() {
// returns nothing
}
semicolons
Remove semicolons.
| Option | Description |
|---|---|
--semicolons |
Allow semicolons: "inline-only" (default) or "never" |
Examples
- let foo = 5;
+ let foo = 5
- let foo = 5; let bar = 6
+ let foo = 5
+ let bar = 6
// semicolon is not removed if it would affect the behavior of the code
return;
goto(fail)
singlePropertyPerLine
Use a separate let/var declaration on its own line for every property definition.
Examples
- 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()
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 |
Examples
// 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()
}
}
sortImports
Sort import statements alphabetically.
| Option | Description |
|---|---|
--import-grouping |
Import statement grouping: "alpha" (default), "length", "testable-first" or "testable-last" |
Examples
- import Foo
- import Bar
+ import Bar
+ import Foo
- 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
sortSwitchCases
Sort switch cases alphabetically.
Examples
switch self {
- case .b, .a, .c, .e, .d:
+ case .a, .b, .c, .d, .e:
return nil
}
sortTypealiases
Sort protocol composition typealiases alphabetically.
Examples
- typealias Placeholders = Foo & Bar & Baaz & Quux
+ typealias Placeholders = Baaz & Bar & Foo & Quux
typealias Dependencies
- = FooProviding
+ = BaazProviding
& BarProviding
- & BaazProviding
+ & FooProviding
& QuuxProviding
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.
Examples
- foo.filter{ return true }.map{ $0 }
+ foo.filter { return true }.map { $0 }
- foo( {} )
+ foo({})
spaceAroundBrackets
Add or remove space around square brackets.
Examples
- foo as[String]
+ foo as [String]
- foo = bar [5]
+ foo = bar[5]
spaceAroundComments
Add space before and/or after comments.
Examples
- let a = 5// assignment
+ let a = 5 // assignment
- func foo() {/* ... */}
+ func foo() { /* ... */ }
spaceAroundGenerics
Remove space around angle brackets.
Examples
- Foo <Bar> ()
+ Foo<Bar>()
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" |
Examples
- foo . bar()
+ foo.bar()
- a+b+c
+ a + b + c
- func ==(lhs: Int, rhs: Int) -> Bool
+ func == (lhs: Int, rhs: Int) -> Bool
spaceAroundParens
Add or remove space around parentheses.
Examples
- init (foo)
+ init(foo)
- switch(x){
+ switch (x) {
spaceInsideBraces
Add space inside curly braces.
Examples
- foo.filter {return true}
+ foo.filter { return true }
spaceInsideBrackets
Remove space inside square brackets.
Examples
- [ 1, 2, 3 ]
+ [1, 2, 3]
spaceInsideComments
Add leading and/or trailing space inside comments.
Examples
- let a = 5 //assignment
+ let a = 5 // assignment
- func foo() { /*...*/ }
+ func foo() { /* ... */ }
spaceInsideGenerics
Remove space inside angle brackets.
Examples
- Foo< Bar, Baz >
+ Foo<Bar, Baz>
spaceInsideParens
Remove space inside parentheses.
Examples
- ( a, b)
+ (a, b)
specifiers
Use consistent ordering for member modifiers.
Note: specifiers rule is deprecated. Use modifierOrder instead.
strongOutlets
Remove weak modifier from @IBOutlet properties.
Examples
As per Apple's recommendation (https://developer.apple.com/videos/play/wwdc2015/407/ @ 32:30).
- @IBOutlet weak var label: UILabel!
+ @IBOutlet var label: UILabel!
strongifiedSelf
Remove backticks around self in Optional unwrap expressions.
Examples
- 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.
swiftTestingTestCaseNames
In Swift Testing, don't prefix @Test methods with 'test'.
Examples
import Testing
struct MyFeatureTests {
- @Test func testMyFeatureHasNoBugs() {
+ @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)
}
- @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)
}
}
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.
Examples
- /* TODO fix this properly */
+ /* TODO: fix this properly */
- // MARK - UIScrollViewDelegate
+ // MARK: - UIScrollViewDelegate
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 |
Examples
- DispatchQueue.main.async(execute: { ... })
+ DispatchQueue.main.async {
- let foo = bar.map({ ... }).joined()
+ let foo = bar.map { ... }.joined()
- withAnimation(.spring, {
- isVisible = true
- }, completion: {
- handleCompletion()
- })
+ withAnimation(.spring) {
+ isVisible = true
+ } completion: {
+ handleCompletion()
+ }
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" |
Examples
let array = [
foo,
bar,
- baz
+ baz,
]
Swift 6.1 and later with --trailing-commas always:
func foo(
bar: Int,
- baaz: Int
+ baaz: Int,
) {}
foo(
bar: 1,
- baaz: 2
+ baaz: 2,
)
struct Foo<
Bar,
Baaz,
- Quux
+ Quux,
> {}
--trailing-commas multi-element-lists
let foo = [
- bar,
+ bar
]
foo(
- bar,
+ bar
)
trailingSpace
Remove trailing space at end of a line.
| Option | Description |
|---|---|
--trim-whitespace |
Trim trailing whitespace: "always" (default) or "nonblank-lines" |
Examples
- let foo: Foo␣
+ let foo: Foo
- ␣␣␣␣
+
- func bar() {␣␣
+ func bar() {
␣␣␣␣print("foo")
}
typeSugar
Prefer shorthand syntax for Arrays, Dictionaries and Optionals.
| Option | Description |
|---|---|
--short-optionals |
Prefer ? shorthand for optionals: "except-properties" (default) or "always" |
Examples
- var foo: Array<String>
+ var foo: [String]
- var foo: Dictionary<String, Int>
+ var foo: [String: Int]
- var foo: Optional<(Int) -> Void>
+ var foo: ((Int) -> Void)?
unusedArguments
Mark unused function arguments with _.
| Option | Description |
|---|---|
--strip-unused-args |
Strip unused arguments: "unnamed-only", "closure-only" or "always" (default) |
Examples
- func foo(bar: Int, baz: String) {
print("Hello \(baz)")
}
+ func foo(bar _: Int, baz: String) {
print("Hello \(baz)")
}
- func foo(_ bar: Int) {
...
}
+ func foo(_: Int) {
...
}
- request { response, data in
self.data += data
}
+ request { _, data in
self.data += data
}
unusedPrivateDeclarations
Remove unused private and fileprivate declarations.
| Option | Description |
|---|---|
--preserve-decls |
Comma separated list of declaration names to exclude |
Examples
struct Foo {
- fileprivate var foo = "foo"
- fileprivate var baz = "baz"
var bar = "bar"
}
urlMacro
Replace force-unwrapped URL(string:) initializers with the configured #URL(_:) macro.
| Option | Description |
|---|---|
--url-macro |
For example: --url-macro "#URL,URLFoundation" |
Examples
With --url-macro "#URL,URLFoundation":
- let url = URL(string: "https://example.com")!
+ import URLFoundation
+ let url = #URL("https://example.com")
- return URL(string: "https://api.example.com/users")!
+ import URLFoundation
+ return #URL("https://api.example.com/users")
void
Use Void for type declarations and () for values.
| Option | Description |
|---|---|
--void-type |
How Void types are represented: "Void" (default) or "tuple" |
Examples
- let foo: () -> ()
+ let foo: () -> Void
- let bar: Void -> Void
+ let bar: () -> Void
- let baz: (Void) -> Void
+ let baz: () -> Void
- func quux() -> (Void)
+ func quux() -> Void
- callback = { _ in Void() }
+ callback = { _ in () }
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" |
Examples
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
- foo(bar: Int,
- baz: String)
+ foo(
+ bar: Int,
+ baz: String
+ )
- class Foo<Bar,
- Baz>
+ class Foo<
+ Bar,
+ Baz
+ >
--wrap-parameters after-first
- func foo(
- bar: Int,
- baz: String
- ) {
...
}
+ func foo(bar: Int,
+ baz: String)
+ {
...
}
--wrap-collections before-first:
- let foo = [bar,
baz,
- quuz]
+ let foo = [
+ bar,
baz,
+ quuz
+ ]
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 |
Examples
--func-attributes prev-line
- @objc func foo() {}
+ @objc
+ func foo() { }
--func-attributes same-line
- @objc
- func foo() { }
+ @objc func foo() {}
--type-attributes prev-line
- @objc class Foo {}
+ @objc
+ class Foo { }
--type-attributes same-line
- @objc
- enum Foo { }
+ @objc enum Foo {}
wrapConditionalBodies
Wrap the bodies of inline conditional statements onto a new line.
Examples
- guard let foo = bar else { return baz }
+ guard let foo = bar else {
+ return baz
+ }
- if foo { return bar }
+ if foo {
+ return bar
+ }
wrapEnumCases
Rewrite comma-delimited enum cases to one case per line.
| Option | Description |
|---|---|
--wrap-enum-cases |
Enum case wrapping: "always" (default) or "with-values" |
Examples
enum Foo {
- case bar, baz
}
enum Foo {
+ case bar
+ case baz
}
wrapLoopBodies
Wrap the bodies of inline loop statements onto a new line.
Examples
- for foo in array { print(foo) }
+ for foo in array {
+ print(foo)
+ }
- while let foo = bar.next() { print(foo) }
+ while let foo = bar.next() {
+ print(foo)
+ }
wrapMultilineConditionalAssignment
Wrap multiline conditional assignment expressions after the assignment operator.
Examples
- 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"
+ }
wrapMultilineFunctionChains
Wraps chained function calls to either all on the same line, or one per line.
Examples
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, +)
wrapMultilineStatementBraces
Wrap the opening brace of multiline statements.
Examples
if foo,
- bar {
// ...
}
if foo,
+ bar
+ {
// ...
}
guard foo,
- bar else {
// ...
}
guard foo,
+ bar else
+ {
// ...
}
func foo(
bar: Int,
- baz: Int) {
// ...
}
func foo(
bar: Int,
+ baz: Int)
+ {
// ...
}
class Foo: NSObject,
- BarProtocol {
// ...
}
class Foo: NSObject,
+ BarProtocol
+ {
// ...
}
wrapSingleLineComments
Wrap single line // comments that exceed the specified --max-width.
wrapSwitchCases
Wrap comma-delimited switch cases onto multiple lines.
Examples
switch foo {
- case .bar, .baz:
break
}
switch foo {
+ case .foo,
+ .bar:
break
}
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) |
Examples
- if 5 == foo,
+ if foo == 5,
- nil != bar,
+ bar != nil,
- .default == baaz,
+ baaz == .default,
{ ... }