Skip to content

Latest commit

 

History

History
1585 lines (1181 loc) · 24.4 KB

Rules.md

File metadata and controls

1585 lines (1181 loc) · 24.4 KB

Rules


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"
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/).

- @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.