24 KiB
Rules
- andOperator
- anyObjectProtocol
- blankLinesAroundMark
- blankLinesAtEndOfScope
- blankLinesAtStartOfScope
- blankLinesBetweenScopes
- braces
- consecutiveBlankLines
- consecutiveSpaces
- duplicateImports
- elseOnSameLine
- emptyBraces
- fileHeader
- hoistPatternLet
- indent
- isEmpty
- leadingDelimiters
- linebreakAtEndOfFile
- linebreaks
- numberFormatting
- ranges
- redundantBackticks
- redundantBreak
- redundantExtensionACL
- redundantFileprivate
- redundantGet
- redundantInit
- redundantLet
- redundantLetError
- redundantNilInit
- redundantObjc
- redundantParens
- redundantPattern
- redundantRawValues
- redundantReturn
- redundantSelf
- redundantVoidReturnType
- semicolons
- sortedImports
- spaceAroundBraces
- spaceAroundBrackets
- spaceAroundComments
- spaceAroundGenerics
- spaceAroundOperators
- spaceAroundParens
- spaceInsideBraces
- spaceInsideBrackets
- spaceInsideComments
- spaceInsideGenerics
- spaceInsideParens
- specifiers
- strongOutlets
- strongifiedSelf
- todos
- trailingClosures
- trailingCommas
- trailingSpace
- typeSugar
- unusedArguments
- void
- wrapArguments
- yodaConditions
andOperator
Replaces the && operator with a comma inside if, guard and 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
Replaces class with AnyObject in protocol definitions, as recommended in
modern Swift guidelines.
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.
blankLinesAroundMark
Adds a blank line before and after each MARK: comment.
Examples
func foo() {
// foo
}
// MARK: bar
func bar() {
// bar
}
func foo() {
// foo
}
+
// MARK: bar
+
func bar() {
// bar
}
blankLinesAtEndOfScope
Removes trailing blank lines from inside braces, brackets, parens or chevrons.
Examples
func foo() {
// foo
-
}
func foo() {
// foo
}
array = [
foo,
bar,
baz,
-
]
array = [
foo,
bar,
baz,
]
blankLinesAtStartOfScope
Removes leading blank lines from inside braces, brackets, parens or chevrons.
Examples
func foo() {
-
// foo
}
func foo() {
// foo
}
array = [
-
foo,
bar,
baz,
]
array = [
foo,
bar,
baz,
]
blankLinesBetweenScopes
Adds a blank line before each class, struct, enum, extension, protocol or function.
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
braces
Implements K&R or Allman-style braces.
| Option | Description |
|---|---|
--allman |
Use allman indentation style: "true" or "false" (default) |
Examples
- if x
- {
// foo
}
- else
- {
// bar
}
+ if x {
// foo
}
+ else {
// bar
}
consecutiveBlankLines
Reduces multiple sequential blank lines to a single blank line.
Examples
func foo() {
let x = "bar"
-
print(x)
}
func foo() {
let x = "bar"
print(x)
}
consecutiveSpaces
Reduces a sequence of spaces to a single space.
Examples
- let foo = 5
+ let foo = 5
duplicateImports
Removes duplicate import statements.
Examples
import Foo
import Bar
- import Foo
import B
#if os(iOS)
import A
- import B
#endif
elseOnSameLine
Controls whether an else, catch or while keyword after a } appears on
the same line.
| Option | Description |
|---|---|
--elseposition |
Placement of else/catch: "same-line" (default) or "next-line" |
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
Removes all white space between otherwise empty braces.
Examples
- func foo() {
-
- }
+ func foo() {}
fileHeader
Allows the replacement or removal of Xcode source file comment headers.
| Option | Description |
|---|---|
--header |
Header comments: "strip", "ignore", or the text you wish use |
hoistPatternLet
Moves let or var bindings inside patterns to the start of the expression
(or vice-versa).
| Option | Description |
|---|---|
--patternlet |
let/var placement 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
}
indent
Adjusts leading whitespace based on scope and line wrapping.
| Option | Description |
|---|---|
--indent |
Number of spaces to indent, or "tab" to use tabs |
--indentcase |
Indent cases inside a switch: "true" or "false" (default) |
--ifdef |
#if indenting: "indent" (default), "no-indent" or "outdent" |
--xcodeindentation |
Xcode indent guard/enum: "enabled" or "disabled" (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
}
isEmpty
Replaces count == 0 checks with isEmpty, which is preferred for performance
reasons (especially for Strings where count has O(n) complexity).
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
Moves delimiters such as : or ; or , placed at the start of a line to the end of the previous line instead.
Examples
- guard let foo = maybeFoo // first
- , let bar = maybeBar else { ... }
+ guard let foo = maybeFoo, // first
+ let bar = maybeBar else { ... }
linebreakAtEndOfFile
Ensures that the last line of the file is empty.
linebreaks
Normalizes all linebreaks to use the same character.
| Option | Description |
|---|---|
--linebreaks |
Linebreak character to use: "cr", "crlf" or "lf" (default) |
numberFormatting
Handles case and grouping of number literals.
| Option | Description |
|---|---|
--decimalgrouping |
Decimal grouping,threshold (default: 3,6) or "none", "ignore" |
--binarygrouping |
Binary grouping,threshold (default: 4,8) or "none", "ignore" |
--octalgrouping |
Octal grouping,threshold (default: 4,8) or "none", "ignore" |
--hexgrouping |
Hex grouping,threshold (default: 4,8) or "none", "ignore" |
--fractiongrouping |
Group digits after '.': "enabled" or "disabled" (default) |
--exponentgrouping |
Group exponent digits: "enabled" or "disabled" (default) |
--hexliteralcase |
Casing for hex literals: "uppercase" (default) or "lowercase" |
--exponentcase |
Case of 'e' in numbers: "lowercase" or "uppercase" (default) |
Examples
- let color = 0xFF77A5
+ let color = 0xff77a5
- let big = 123456.123
+ let big = 123_456.123
ranges
Controls the spacing around range operators.
| Option | Description |
|---|---|
--ranges |
Spacing for ranges: "spaced" (default) or "no-space" |
Examples
- for i in 0..<5 {}
+ for i in 0 ..< 5 {}
- if (0...5).contains(i) {}
+ if (0 ... 5).contains(i) {}
redundantBackticks
Removes unnecessary escaping of identifiers using backticks, e.g. in cases where the escaped word is not a keyword, or is not ambiguous in that context.
Examples
- let `infix` = bar
+ let infix = bar
- func foo(with `default`: Int) {}
+ func foo(with default: Int) {}
redundantBreak
Removes redundant break statements from inside switch cases.
Examples
switch foo {
case bar:
print("bar")
- break
default:
print("default")
- break
}
redundantExtensionACL
Removes access control level keywords from extension members when the access level matches the extension itself.
Examples
public extension URL {
- public func queryParameter(_ name: String) -> String { ... }
}
public extension URL {
+ func queryParameter(_ name: String) -> String { ... }
}
redundantFileprivate
Replaces fileprivate access control keyword with private when they are
equivalent, e.g. for top-level constants, functions or types within a file.
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
Removes unnecessary get { } clauses from inside read-only computed properties.
Examples
var foo: Int {
- get {
- return 5
- }
}
var foo: Int {
+ return 5
}
redundantInit
Removes unnecessary init when instantiating types.
Examples
- String.init("text")
+ String("text")
redundantLet
Removes redundant let or var from ignored variables in bindings (which is a
warning in Xcode).
Examples
- let _ = foo()
+ _ = foo()
redundantLetError
Removes redundant let error from catch statements, where it is declared
implicitly.
Examples
- do { ... } catch let error { log(error) }
+ do { ... } catch { log(error) }
redundantNilInit
Removes unnecessary nil initialization of Optional vars (which are nil by default anyway).
Examples
- 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
redundantObjc
Removes unnecessary @objc annotation from properties and functions.
Examples
- @objc @IBOutlet var label: UILabel!
+ @IBOutlet var label: UILabel!
- @IBAction @objc func goBack() {}
+ @IBOutlet func goBack() {}
- @objc @NSManaged private var foo: String?
+ @NSManaged private var foo: String?
redundantParens
Removes unnecessary parens from expressions and branch conditions.
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
Removes redundant pattern matching arguments for ignored variables.
Examples
- if case .foo(_, _) = bar {}
+ if case .foo = bar {}
- let (_, _) = bar
+ let _ = bar
redundantRawValues
Removes raw string values from enum cases when they match the case name.
Examples
enum Foo: String {
- case bar = "bar"
case baz = "quux"
}
enum Foo: String {
+ case bar
case baz = "quux"
}
redundantReturn
Removes unnecessary return keyword from single-line closures.
Examples
- array.filter { return $0.foo == bar }
+ array.filter { $0.foo == bar }
redundantSelf
Adds or removes explicit self prefix from class and instance member
references.
| Option | Description |
|---|---|
--self |
Explicit self: "insert", "remove" (default) or "init-only" |
--selfrequired |
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 --selfrequired 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
}
redundantVoidReturnType
Removes unnecessary Void return type from function declarations.
Examples
- func foo() -> Void {
// returns nothing
}
+ func foo() {
// returns nothing
}
semicolons
Removes semicolons at the end of lines, and (optionally) replaces inline semicolons with a linebreak.
| Option | Description |
|---|---|
--semicolons |
Allow semicolons: "never" or "inline" (default) |
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)
sortedImports
Rearranges import statements so that they are sorted.
| Option | Description |
|---|---|
--importgrouping |
"testable-top", "testable-bottom" or "alphabetized" (default) |
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
spaceAroundBraces
Contextually adds or removes space around { ... }.
Examples
- foo.filter{ return true }.map{ $0 }
+ foo.filter { return true }.map { $0 }
- foo( {} )
+ foo({})
spaceAroundBrackets
Contextually adjusts the space around [ ... ].
Examples
- foo as[String]
+ foo as [String]
- foo = bar [5]
+ foo = bar[5]
spaceAroundComments
Adds space around /* ... */ comments and before // comments.
Examples
- let a = 5// assignment
+ let a = 5 // assignment
- func foo() {/* ... */}
+ func foo() { /* ... */ }
spaceAroundGenerics
Removes the space around < ... >.
Examples
- Foo <Bar> ()
+ Foo<Bar>()
spaceAroundOperators
Contextually adjusts the space around infix operators. Also adds or removes the space between an operator function declaration and its arguments.
| Option | Description |
|---|---|
--operatorfunc |
Spacing for operator funcs: "spaced" (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
Contextually adjusts the space around ( ... ).
Examples
- init (foo)
+ init(foo)
- switch(x){
+ switch (x) {
spaceInsideBraces
Adds space inside { ... }.
Examples
- foo.filter {return true}
+ foo.filter { return true }
spaceInsideBrackets
Removes the space inside [ ... ].
Examples
- [ 1, 2, 3 ]
+ [1, 2, 3]
spaceInsideComments
Adds a space inside /* ... */ comments and at the start of // comments.
Examples
- let a = 5 //assignment
+ let a = 5 // assignment
- func foo() { /*...*/ }
+ func foo() { /* ... */ }
spaceInsideGenerics
Removes the space inside < ... >.
Examples
- Foo< Bar, Baz >
+ Foo<Bar, Baz>
spaceInsideParens
Removes the space inside ( ... ).
Examples
- ( a, b)
+ (a, b)
specifiers
Normalizes the order for property/function/class specifiers (public, weak, lazy, etc.)
Examples
- lazy public weak private(set) var foo: UIView?
+ public private(set) lazy weak var foo: UIView?
- override public final func foo()
+ public final override func foo()
- convenience private init()
+ private convenience init()
strongOutlets
Removes the weak specifier 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
Replaces `self` with self when using the common guard let `self` = self
pattern for strongifying weak self references.
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.
todos
Ensures that TODO:, MARK: and FIXME: comments include the trailing colon
(else they're ignored by Xcode).
Examples
- /* TODO fix this properly */
+ /* TODO: fix this properly */
- // MARK - UIScrollViewDelegate
+ // MARK: - UIScrollViewDelegate
trailingClosures
Converts the last closure argument in a function call to trailing closure syntax where possible. By default this is restricted to anonymous closure arguments, as removing named closures can result in call-site ambiguity.
| Option | Description |
|---|---|
--trailingclosures |
Comma-delimited list of functions that use trailing closures |
Examples
- DispatchQueue.main.async(execute: { ... })
+ DispatchQueue.main.async {
- let foo = bar.map({ ... }).joined()
+ let foo = bar.map { ... }.joined()
trailingCommas
Adds or removes trailing commas from the last item in an array or dictionary literal.
| Option | Description |
|---|---|
--commas |
Commas in collection literals: "always" (default) or "inline" |
Examples
let array = [
foo,
bar,
- baz
]
let array = [
foo,
bar,
+ baz,
]
trailingSpace
Removes the whitespace at the end of a line.
| Option | Description |
|---|---|
--trimwhitespace |
Trim trailing space: "always" (default) or "nonblank-lines" |
typeSugar
Replaces Array, Dictionary and Optional types with their shorthand forms.
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
Marks unused arguments in functions and closures with _ to make it clear they
aren't used.
| Option | Description |
|---|---|
--stripunusedargs |
"closure-only", "unnamed-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
}
void
Standardizes the use of Void vs an empty tuple ().
| Option | Description |
|---|---|
--empty |
How empty values 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
wrapArguments
Wraps function arguments and collection literals.
| Option | Description |
|---|---|
--wraparguments |
Wrap function args: "before-first", "after-first", "preserve" |
--wrapcollections |
Wrap array/dict: "before-first", "after-first", "preserve" |
--closingparen |
Closing paren position: "balanced" (default) or "same-line" |
Examples
- func foo(bar: Int,
- baz: String) {
...
}
+ func foo(
+ bar: Int,
+ baz: String
+ ) {
...
}
Or for --wrapcollections before-first:
- let foo = [bar,
baz,
- quuz]
+ let foo = [
+ bar,
baz,
+ quuz
+ ]
yodaConditions
Reorders so-called "yoda conditions" where the constant is placed on the left-hand side of a comparison instead of the right.