iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

日本人のための SwiftFormat【ルール編】

ルール一覧

SwiftFormat の Rules 一覧を日本語でまとめました。

andOperator

if, guard, whileの条件分岐の際の条件式で && を使う場合はカンマを使うようにする。

サンプル

- if true && true {
+ if true, true {

anyObjectProtocol

プロトコルの定義で、classAnyObject に変更する。

class の代わりに AnyObject を使用するガイドラインは Swift4.1から導入されたので、anyObjectProtocol のルールは Swift4.1以上でない限り無効になる。

サンプル

- protocol Foo: class {}
+ protocol Foo: AnyObject {}

blankLinesAroundMark

MARK:コメントの前後に空白行を入れる。

サンプル

func foo() {
  // foo
}
// MARK: bar
func bar() {
  // bar
}

func foo() {
  // foo
}
+
// MARK: bar
+
func bar() {
  // bar
}

blankLinesAtEndOfScope

スコープの末尾にある空白行を削除する。

サンプル

func foo() {
  // foo
-
}

func foo() {
  // foo
}
array = [
  foo,
  bar,
  baz,
-
]

array = [
  foo,
  bar,
  baz,
]

blankLinesAtStartOfScope

スコープの先頭にある空白行を削除する。

サンプル

func foo() {
-
  // foo
}

func foo() {
  // foo
}
array = [
-
  foo,
  bar,
  baz,
]

array = [
  foo,
  bar,
  baz,
]

blankLinesBetweenScopes

class, struct, enum, extension, protocol, function の宣言の前に空白行を 入れる。

サンプル

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

字下げスタイルを選択する。(K&R or Allman) デフォルトでは、K&Rが適用される。

option description
--allman allmanインデントスタイルを使用: "true" or "false"(default)

サンプル

- if x
- {
    // foo
  }
- else
- {
    // bar
  }

+ if x {
    // foo
  }
+ else {
    // bar
  }

consecutiveBlankLines

連続する空白行を1行にまとめる。

サンプル

func foo() {
  let x = "bar"
-

  print(x)
}

func foo() {
  let x = "bar"

  print(x)
}

consecutiveSpaces

連続するスペースを1つのスペースをに置き換える。

サンプル

- let     foo = 5
+ let foo = 5

duplicateImports

重複する import 文を削除する。

サンプル

import Foo
import Bar
- import Foo
import B
#if os(iOS)
  import A
-   import B
#endif

elseOnSameLine

else, catch, while キーワードのポジションを "同じ行" または "次の行" に調整する。

option description
--elseposition else/catchのポジション: "same-line"(Default) or "next-line"
--guardelse guard elseのポジション: "same-line" or "next-line" or "auto"(default)

emptyBraces

カッコ内の空白を削除する。

サンプル

- func foo() {
-
- }

+ func foo() {}

fileHeader

全てのファイルに指定されたソースファイルヘッダーテンプレートを使用する。

option description
--header ヘッダーのコメント: "stripe", "ignore" または任意のテキスト

hoistPatternLet

let または varバインディングをパターン内に再配置する。

option description
--paternlet let/ var のパターン: "hoist"(default) or "inline"

サンプル

- (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

スコープレベルでコードをインデントする。

option description
--indent インデントするスペースの数。タブを使用する場合は"tab"
--tabwidth タブ文字の幅。デフォルトは"unspecified"
--smarttabs タブ幅に関係なくコードを揃える。デフォルトは"enabled"
--indentcase switch 内のケースをインデント: "true" or "false"
--ifdef #if インデント: "indent"(default) or "no-indent" or "outdent"
--xcodeindentation Xcode インデント guard/enum: "enabled" or "disabled"(default)

サンプル

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

count == 0isEmpty に変換する

※ まれに、isEmpty プロパティが無い型で挿入される可能性があるため。ルールはデフォルトで無効になって いる。--enable isEmpty を使用して有効にする必要がある。

サンプル

- if foo.count == 0 {
+ if foo.isEmpty {

- if foo.count > 0 {
+ if !foo.isEmpty {

- if foo?.count == 0 {
+ if foo?.isEmpty == true {

leadingDelimiters

先頭のカンマを前の行の末尾に移動する。

サンプル

- guard let foo = maybeFoo // first
-     , let bar = maybeBar else { ... }

+ guard let foo = maybeFoo, // first
+      let bar = maybeBar else { ... }

linebreakAtEndOfFile

ファイルの最後に空行を入れる。

linebreaks

全ての改行に指定された改行文字を使用する。(CR, LF or CRLF)

option description
--linebreaks 使用する改行文字: "cr", "crlf" or "lf"(default)

modifierOrder

修飾子に一貫した順序を使用する。

option description
--modifierorder 修飾子をカンマで区切ったリスト(優先度順)

サンプル

- 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()

numberFormatting

数値リテラルを一貫性のあるグループにする。可読性をあげるためグループは _ 区切り文字で区切られる。 数値タイプごとに、グループサイズ(各グループの桁数)としきい値(グループ化を適用する前の数値の最小桁数) を指定できる。

option description
--decimalgrouping 10進数のグループ化、しきい値(default: 3, 6) or "none", "ignore"
--binarygrouping バイナリグループ化、しきい値(default: 4, 8) or "none", "ignore"
--octalgrouping 8進数のグループ化、しきい値(default: 4, 8) or "none", "ignore"
--hexgrouping 16進数のグループ化、しきい値(default: 4, 8) or "none", "ignore"
--fractiongrouping .の後の数字をグループ化: "enabled" or "disabled"(default)
--exponentgrouping グループ指数桁数: "enabled" or "disabled"
--hexliteralcase 16進数リテラルのケーシング: "uppercase" (default) or "lowercase"
--exponentcase 数字の e の大文字小文字: "lowercase" or "uppercase" (default)

サンプル

- let color = 0xFF77A5
+ let color = 0xff77a5
- let big = 123456.123
+ let big = 123_456.123

preferKeyPath

簡易的な map { $0.foo } クロージャーを keyPath ベースの構文にする。

サンプル

- let barArray = fooArray.map { $0.bar }

+ let barArray = fooArray.map(\.bar)

redundantBackticks

識別子の周りの冗長なバックティックを削除する。

サンプル

- let `infix` = bar
+ let infix = bar
- func foo(with `default`: Int) {}
+ func foo(with default: Int) {}

redundantBreak

スイッチケースの冗長なブレークケースを削除する。

サンプル

switch foo {
  case bar:
      print("bar")
-       break
  default:
      print("default")
-       break
}

redundantGet

computedProperty 内の不要な get 句を削除する。

サンプル

var foo: Int {
-   get {
-     return 5
-   }
}

var foo: Int {
+   return 5
}

redundantInit

必要なければ明示的に init を削除する。

サンプル

- String.init("text")
+ String("text")

redundantLet

定数名・変数名が必要無い場合は冗長な let/var を削除する。

サンプル

- let _ = foo()
+ _ = foo()

redundantLetError

catch 句から冗長な let error を削除する。

サンプル

- do { ... } catch let error { log(error) }
+ do { ... } catch { log(error) }

redundantNilInit

オプショナルの場合に不必要な nil 宣言を削除する。

サンプル

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

redundantObjc

不必要な @objc アノテーションを削除する。

サンプル

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

redundantParens

サンプル

- 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

不必要なパターンマッチングパラメータ構文を削除する。

サンプル

- if case .foo(_, _) = bar {}
+ if case .foo = bar {}
- let (_, _) = bar
+ let _ = bar

redundantRawValues

enum の不必要な raw string value を削除する。

サンプル

enum Foo: String {
-   case bar = "bar"
  case baz = "quux"
}

enum Foo: String {
+   case bar
  case baz = "quux"
}

redundantReturn

不必要な return キーワードを削除する。

サンプル

- array.filter { return $0.foo == bar }
+ array.filter { $0.foo == bar }

redundantSelf

self を挿入または削除する。

@autoclosure 引数を持つ関数では、呼び出しで self が必要になる場合があるが、SwiftFormat はこれを自動的に検出できないので注意が必要。もし、@autoclosure 引数を持つ関数がある場合には、 --selfrequired で関数を指定することで redundantSelf ルールを無視することができる。

option description
--self self の明示的な設定: "insert" or "remove"(default) or "init-only"
--selfrequired @autoclosure 引数を持つ関数のカンマ区切りリスト

サンプル

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
}

--self オプションの init-onlyinit内でのみ有効。

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

不必要な void の return を削除する。

サンプル

- func foo() -> Void {
    // returns nothing
  }

+ func foo() {
    // returns nothing
  }

semicolons

セミコロンの削除。なお、コードの動作に影響があるようなセミコロンは削除されない。

option description
--semicolons セミコロンの許可: "never" or "inline"(default)

サンプル

- let foo = 5;
+ let foo = 5
- let foo = 5; let bar = 6
+ let foo = 5
+ let bar = 6

spaceAroundBraces

中括弧周りのスペースを追加または削除する。

サンプル

- foo.filter{ return true }.map{ $0 }
+ foo.filter { return true }.map { $0 }
- foo( {} )
+ foo({})

spaceAroundBrackets

角括弧周りのスペースを追加または削除する。

サンプル

- foo as[String]
+ foo as [String]
- foo = bar [5]
+ foo = bar[5]

spaceAroundComments

コメントの前後にスペースを追加する。

サンプル

- let a = 5// assignment
+ let a = 5 // assignment
- func foo() {/* ... */}
+ func foo() { /* ... */ }

spaceAroundGenerics

山括弧周りのスペースを削除する。

サンプル

- Foo <Bar> ()
+ Foo<Bar>()

spaceAroundOperators

演算子・区切り文字周りのスペースを追加または削除する。

option description
--operatorfunc オペレータ関数のスペース間隔: "spaced"(default) or "no-space"
--nospaceoperators スペースを含まない演算子のリスト

サンプル

- foo . bar()
+ foo.bar()
- a+b+c
+ a + b + c
- func ==(lhs: Int, rhs: Int) -> Bool
+ func == (lhs: Int, rhs: Int) -> Bool

spaceAroundParens

括弧の前後のスペースを追加または削除する。

サンプル

- init (foo)
+ init(foo)
- switch(x){
+ switch (x) {

spaceInsideBraces

中括弧の内側にスペースを追加する。

サンプル

- foo.filter {return true}
+ foo.filter { return true }

spaceInsideBrackets

角括弧内のスペースを削除する。

サンプル

- [ 1, 2, 3 ]
+ [1, 2, 3]

spaceInsideComments

コメント内に先頭と末尾のスペースを追加する。

サンプル

- let a = 5 //assignment
+ let a = 5 // assignment
- func foo() { /*...*/ }
+ func foo() { /* ... */ }

spaceInsideGenerics

山括弧内のスペースを削除する。

サンプル

- Foo< Bar, Baz >
+ Foo<Bar, Baz>

spaceInsideParens

括弧内のスペースを削除する。

サンプル

- ( a, b)
+ (a, b)

strongOutlets

@IBOutlet から weak 修飾子を削除する。Apple の推奨

サンプル

- @IBOutlet weak var label: UILabel!
+ @IBOutlet var label: UILabel!

strongifiedSelf

optional の unwrap 式で、self の周りのバックティックを削除する。

エスケープされていない self への割り当ては Swift4.2以降でのみサポートされているため、Swift のバージョンが 4.2以降に設定されていない場合はこのルールは無効になる。

サンプル

- guard let `self` = self else { return }
+ guard let self = self else { return }

todos

TODO:, MARK:, FIXME: に正しいフォーマットを適用する。

サンプル

- /* TODO fix this properly */
+ /* TODO: fix this properly */
- // MARK - UIScrollViewDelegate
+ // MARK: - UIScrollViewDelegate

trailingClosures

該当する場合は、末尾の閉鎖構文を使用する。

option description
--trailingclosures 末尾のクロージャを使用するカンマ区切りのリスト

サンプル

- DispatchQueue.main.async(execute: { ... })
+ DispatchQueue.main.async {
- let foo = bar.map({ ... }).joined()
+ let foo = bar.map { ... }.joined()

trailingCommas

コレクションリテラルの最後の項目の末尾のコンマを追加または削除する。

option description
--commas コレクションリテラル内のカンマ: "always"(default) or "inline"

サンプル

let array = [
  foo,
  bar,
-   baz
]

let array = [
  foo,
  bar,
+   baz,
]

trailingSpace

行末の末尾のスペースを削除する。

option description
--trimwhitespace 行末のスペーストリム: "always"(default) : "nonblank-lines"

typeSugar

Array, Dictionary, Optional の短縮構文を優先する。

option description
--shortoptionals Optionalを使用する: "always"(default) : "except-properties"

サンプル

- 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

関数で使用していない引数を _ でマークする。

option description
--stripunusedargs "closure-only", "unnamed-only" or "always" (default)

サンプル

- 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

型の宣言には Void を使用する。

option description
--voidtype Void タイプの表現方法: "void"(default) : "tuple"

サンプル

- 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

wrap

指定された最大幅を超える行を折り返す。

option description
--maxwidth 折り返す行の最大長: "none"(default)
--nowrapoperators ラップされるべきでない演算子のカンマ区切りのリスト

wrapArguments

ラップされた関数の引数またはコレクションの要素を揃える。

※ 以前のバージョンとの互換性の関係で --wrapparameters に値が指定されていない場合は、--wraparguments の値が使用される。

option description
--wraparguments 全ての引数をラップする: "before-list", "after-list", "preserve"
--wrapparameters 関数のパラメーターをラップする: "before-first", "after-first", "preserve"
--wrapcollections 配列・辞書をラップする: "before-first", "after-first", "preserve"
--closingparen 閉じ括弧の位置: "balanced" (default) or "same-line"

サンプル

--wraparguments before-first

- foo(bar: Int,
-     baz: String)

+ foo(
+   bar: Int,
+   baz: String
+ )
- class Foo<Bar,
-           Baz>

+ class Foo<
+   Bar,
+   Baz
+ >

--wrapparameters after-first

- func foo(
-   bar: Int,
-   baz: String
- ) {
    ...
  }

+ func foo(bar: Int,
+          baz: String) {
    ...
  }

--wrapcollections before-first

- let foo = [bar,
             baz,
-            quuz]

+ let foo = [
+   bar,
    baz,
+   quuz
+ ]

wrapAttributes

@attributes の折り返しを設定する。

option description
--funcattributes 関数について: "preserve", "prev-line", or "same-line"
--typeattributes タイプについて: "preserve", "prev-line", or "same-line"

サンプル

--funcattributes prev-line

- @objc func foo() {}

+ @objc
+ func foo() { }

--funcattributes same-line

- @objc
- func foo() { }

+ @objc func foo() {}

--typeattributes prev-line

- @objc class Foo {}

+ @objc
+ class Foo { }

--typeattributes same-line

- @objc
- enum Foo { }

+ @objc enum Foo {}

wrapMultilineStatementBraces

複数行のステートメントの開始括弧の位置を一段下げる。(if / guard / while / func)

サンプル

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)
+ {
  // ...
}

yodaConditions

式の右側にある定数値を優先する。

関連する記事

その他の記事