swift-format の Configuration
lineLength
を 1000 に設定してなるべくワンラインでコードを書いて検証。
改行状態が必要な場合はrespectsExistingLineBreaks
を true にして検証。
version
(number)
Configuration file のバージョン。今は常に1。
lineLength
(number)
一行あたりの最長文字数。これを超えると改行される。基本的にはこれが最も強力なルールになる。キリのいいところで改行が入る。
- 変数宣言の頭
-
=
での代入の直後 - クロージャーや関数の引数
- チェーンメソッド
- 開き中括弧
{
の直後 - 閉じ中括弧
}
など。
indentation
(object)
一段階インデントする時の空白の種類と幅。spaces
かtabs
のどちらか一方のみ。
-
spaces
(number): インデントは指定された個数のスペース -
tabs
(number): インデントは指定された個数のタブ
tabWidth
(number)
一つのタブに相当するとみなされるスペースの数。タブをインデントに指定したときに有効。
maximumBlankLines
(number)
連続した空白行の最大数。
respectsExistingLineBreaks
(boolean)
ソースコード中の既存の改行を尊重するかどうか。
if value1 < value2 {
} else if value2 < value3 {
} else {
}
if value1 < value2 {
} else if value2 < value3 {
} else {
}
if value1 < value2 {} else if value2 < value3 {} else {}
if value1 < value2 {
} else if value2 < value3 {
} else {
}
true の場合は before のまんま
lineBreakBeforeControlFlowKeywords
(boolean)
else
やcatch
の直前の改行動作。true だとキーワードの前で改行が入る。
if value1 < value2 { } else if value2 < value3 { } else { }
do { let _ = try something() } catch { print(error) }
if value1 < value2 {
}
else if value2 < value3 {
}
else {
}
do { let _ = try something() }
catch { print(error) }
lineBreakBeforeEachArgument
(boolean)
変数や引数の改行動作。変数宣言や関数の引数定義でlineLength
を超えた場合改行されるが、そのときの改行の仕方が変わる。true だと変数や引数ごとに改行される。false だとlineLength
を超えた場合のみ改行される。すなわち、lineLength
が非常に大きい数値だと機能しない。
lineLength=50
のときの例
func arguments(a: String, b: String, c: String, d: String) -> Bool { return false }
func arguments(
a: String, b: String, c: String, d: String
) -> Bool { return false }
func arguments(
a: String,
b: String,
c: String,
d: String
) -> Bool { return false }
lineBreakBeforeEachGenericRequirement
(boolean)
ジェネリックキーワードの改行動作。lineLength
を超えた場合ジェネリックキーワードの区切りに改行が入るが、その時の改行の仕方が変わる。true にするとジェネリックキーワードごとに改行される。false だとlineLength
を超えた場合のみ改行される。すなわち、lineLength
が非常に大きい数値だと機能しない。
lineLength=50
のときの例
class MyClass<S, T, U, W> where S: Collection, T: Equatable, U: Hashable, W: AnyObject { }
class MyClass<S, T, U, W>
where
S: Collection, T: Equatable, U: Hashable,
W: AnyObject
{}
class MyClass<S, T, U, W>
where
S: Collection,
T: Equatable,
U: Hashable,
W: AnyObject
{}
prioritizeKeepingFunctionOutputTogether
(boolean)
関数の戻り値の定義において、閉じ括弧)
とくっつけることを優先するかどうか。
lineLength=34
(つまり->
までの長さ)のときの例
func hoge(_ value1: Int) throws -> Int { return 0 }
func hoge(_ value1: Int) throws
-> Int
{ return 0 }
func hoge(
_ value1: Int
) throws -> Int { return 0 } // )とその後のthrows -> Intがひとまとまりになっている。
indentConditionalCompilationBlocks
(boolean)
条件付きコンパイルのブロックをインデントするかどうか。
#if someCondition
let a = 123
#else
let c = 456
#endif
#if someCondition
let a = 123
#else
let c = 456
#endif
lineBreakAroundMultilineExpressionChainComponents
(boolean)
lineLength
を超えた場合、キリのいいところで改行が入るが、チェーンメソッドにおいて改行した結果複数行に跨がる場合は、チェーンメソッド開始の.
のところで改行するというフラグ。複数行に跨がることがない場合は無視される。癖がすごいんじゃ。下の例では.map
の改行のされ方に注目して欲しい。
lineLength=45
のときの例
let hoge = "abc,def,ghi"
hoge.components(separatedBy: ",").map({ (item) -> String in item.uppercased() }).filter { $0.contains("E") }.joined().forEach { (char) in if char < "e" { print(char) } else { print("-")} }
let hoge = "abc,def,ghi"
hoge.components(separatedBy: ",").map({
(item) -> String in item.uppercased()
}).filter { $0.contains("E") }.joined()
.forEach { (char) in
if char < "e" {
print(char)
} else {
print("-")
}
}
let hoge = "abc,def,ghi"
hoge.components(separatedBy: ",")
.map({ (item) -> String in
item.uppercased()
})
.filter { $0.contains("E") }.joined()
.forEach { (char) in
if char < "e" {
print(char)
} else {
print("-")
}
}
indentSwitchCaseLabels
(boolean)
switch 文の case で段落下げをするかどうか。
switch value {
case 100: print()
case 200 ..< 300: print()
case 300: print()
default: break
}
switch value {
case 100: print()
case 200 ..< 300: print()
case 300: print()
default: break
}
fileScopedDeclarationPrivacy
(object)
rules
のFileScopedDeclarationPrivacy
を true に指定しているときに有効。
-
accessLevel
(string):private
またはfileprivate
を指定する。private
を指定すると、fileprivate
はprivate
になる。fileprivate
を指定すると、private
はfileprivate
になる。
rules
AllPublicDeclarationsHaveDocumentation
(boolean)
--mode lint
で有効。
true にするとpublic
またはopen
な宣言の直前にコメントがない場合に警告が出るようになる。
AlwaysUseLowerCamelCase
(boolean)
--mode lint
で有効。
true にするとローワーキャメルケースでない宣言がある場合に警告が出るようになる。
func GetValue() -> Int { } // GetValueはローワーキャメルケースじゃないよ
AmbiguousTrailingClosureOverload
(boolean)
--mode lint
で有効。
true にすると曖昧なクロージャーのオーバーロードを発見した場合に警告が出るようになる。
// 下の三つは曖昧で区別がつかないよ
func hoge(mad: () -> Int) {}
func hoge(bad: (Bool) -> Bool) {}
func hoge(sad: (String) -> Bool) {}
BeginDocumentationCommentWithOneLineSummary
(boolean)
--mode lint
で有効。
よくわかりませんが、コメントの書き方についての警告が出るみたいです。
DoNotUseSemicolons
(boolean)
true にすると命令の末尾のセミコロンを禁止して、改行が必要な場合は改行を挿入します。
var value1: Int = 0;
var value2: Int = 1
var value3: Int = 2; var value4: Int = 3; var value5: Int = 4
var value1: Int = 0
var value2: Int = 1
var value3: Int = 2
var value4: Int = 3
var value5: Int = 4
DontRepeatTypeInStaticProperties
(boolean)
--mode lint
で有効。
true にすると static や class で宣言されている変数名について、型被りしてると警告が出る。
class UIColor {
static let redColor: UIColor // redColor は冗長なので red を推奨
class var blueColor: UIColor // blueColor は冗長なので blue を推奨
}
protocol Person {
static let youngPerson: Person // youngPerson は冗長なので young を推奨
}
FileScopedDeclarationPrivacy
(boolean)
上述
FullyIndirectEnum
(boolean)
よくわかりませんが、indirect case
しかないときにindirect enum
に書き換えるみたいです。
public enum Piyo {
indirect case aaa(a: Piyo)
indirect case bbb(bbb: Piyo)
}
public indirect enum Piyo {
case aaa(a: Piyo)
case bbb(bbb: Piyo)
}
GroupNumericLiterals
(boolean)
true にすると数値をアンダースコアで分割して表記するようになる。
let a = 1234567890
let b = -1234567890
let c = 0x12345678
let d = -0x12345678
let e = 0b100101010110
let f = -0b100101010110
let a = 1_234_567_890
let b = -1_234_567_890
let c = 0x1234_5678
let d = -0x1234_5678
let e = 0b1001_01010110
let f = -0b1001_01010110
IdentifiersMustBeASCII
(boolean)
--mode lint
で有効。
true の場合、変数名や関数名などに ASCII 文字以外が含まれていると警告が出る。
let △Pattern: Int = 0 // △は禁止
NeverForceUnwrap
(boolean)
--mode lint
で有効。
true の場合、オプショナルを強制アンラップしている箇所に警告が出る。
let a: String? = nil
let b = a! // 強制アンラップ禁止
let c: Int? = nil
let d = c as! Double // 強制案ラップ禁止
NeverUseForceTry
(boolean)
--mode lint
で有効。
true の場合、強制 try している箇所に警告が出る。
func throwFunc() throws -> Int {
throw NSError()
}
let result = try! throwFunc() // try!は禁止
NeverUseImplicitlyUnwrappedOptionals
(boolean)
--mode lint
で有効。
true の場合、暗黙的アンラップ型の宣言箇所に警告が出る。
var num: Int! // 暗黙的アンラップ禁止
var str: String! = nil // 暗黙的アンラップ禁止
@IBOutlet var button: UIButton! // このパターンでは警告は出ない
NoAccessLevelOnExtensionDeclaration
(boolean)
true の場合、extension についている open 以外のアクセス修飾子を削除する。
open extension String {}
public extension String {}
internal extension String {}
fileprivate extension String {}
private extension String {}
open extension String {}
extension String {}
extension String {}
extension String {}
extension String {}
NoBlockComments
(boolean)
--mode lint
で有効。
true の場合、ブロックコメント/* */
を禁止。
var num: /* IOByteCout is UInt64 */ IOByteCount = 0 // ブロックコメント禁止
/* // ブロックコメント禁止
This open source software is created by kyome.
*/
NoCasesWithOnlyFallthrough
(boolean)
true の場合、switch 文においてfallthrough
だけしている case をなくす。
enum Type {
case ready
case start
case pause
case stop
}
var type = Type.ready
switch type {
case .ready:
print("ready")
case .start:
fallthrough
case .pause:
fallthrough
case .stop:
print("stop")
}
// (省略)
switch type {
case .ready:
print("ready")
case .start, .pause, .stop:
print("stop")
}
NoEmptyTrailingClosureParentheses
(boolean)
true の場合、Trailing Clousure の空括弧を取り除く。
DispatchQueue.main.async() {
print("Hi")
}
func meu(_ callback: () -> Void) {
callback()
}
meu() {
print("Bye")
}
DispatchQueue.main.async { // ()が取り除かれた
print("Hi")
}
// (中略)
meu { // ()が取り除かれた
print("Bye")
}
NoLabelsInCasePatterns
(boolean)
true の場合、Associated Value ありの case 文において、ラベルをなくす。
enum Type {
case one(left: Int, right: Int)
}
var type = Type.one(left: 0, right: 1)
switch type {
case .one(left: let left, right: let right):
print(left, right)
}
// (中略)
switch type {
case .one(let left, let right):
print(left, right)
}
NoLeadingUnderscores
(boolean)
--mode lint
で有効。
true の場合、変数名の前にアンダースコアがついていると警告が出る。
let _foo = "foo" // _fooの_は取り除くこと
func _piyo() { } // _piyoの_は取り除くこと
NoParensAroundConditions
(boolean)
true の場合、条件式の前後の不要な括弧を取り除く。括弧が必要な場合は除かれない。
if (x) { }
guard (x), (y), (z == 3) else { }
while (x) { }
repeat {
} while(x)
switch (4) {
default: break
}
if x {}
guard x, y, z == 3 else {}
while x {}
repeat {
} while x
switch 4 {
default: break
}
NoVoidReturnOnFunctionSignature
(boolean)
true の場合、Void を return する関数の-> Void
や-> ()
を取り除く。クロージャーの定義など必要な場合は除かれない。
func foo() -> () { }
func test() -> Void { }
func foo() { }
func test() { }
func hoge(_ callback: () -> Void) { }
let hoge = { () -> Void in print("") }
OneCasePerLine
(boolean)
true の場合、Associated Value ありの case、または rawValue を指定してある case は独立させる。
enum Type {
case typeA = "A", typeB = "B", typeC, typeD, typeE
case typeF(Int), typeG, typeH
}
enum Type {
case typeA = "A"
case typeB = "B"
case typeC, typeD, typeE
case typeF(Int)
case typeG, typeH
}
OneVariableDeclarationPerLine
(boolean)
true の場合、一行につき一つの変数を宣言するように変更する。
var a = 0, b = 1, (c, d) = (2, "3")
let e, f, g: Int
var h: Int, i: String, j: Float
var a = 0
var b = 1
var (c, d) = (2, "3")
let e: Int
let f: Int
let g: Int
var h: Int
var i: String
var j: Float
OnlyOneTrailingClosureArgument
(boolean)
--mode lint
で有効。
true の場合、通常の Closure と Trailing Closure を混ぜて使うと警告が出る。
(警告が出るのは func の引数に複数のクロージャーがある場合。)
func call(successHandler: () -> Void, failureHandler: () -> Void) {}
// これは禁止
call(successHandler: { }) {
// ...
}
// 以下はOK
call(successHandler: {}, failureHandler: {})
call {
// ...
} failureHandler: {
// ...
}
OrderedImports
(boolean)
true の場合、import の順序が整頓される。ただの import だとアルファベット順。@testable
やimport func
、import enum
などはそれぞれまとめられる。ソースコードの下のほうに import を書いていても、ソースコードの一番上に移動する。コメントが import の直前に書かれていた場合はそれも一緒についてくる。
import Foundation
// Starts Imports
import Core
// Comment with new lines
import UIKit
@testable import SwiftFormatRules
import enum Darwin.D.isatty
// Starts Test
@testable import MyModuleUnderTest
// Starts Ind
import func Darwin.C.isatty
let a = 3
import SwiftSyntax
// Starts Imports
import Core
import Foundation
import SwiftSyntax
// Comment with new lines
import UIKit
import func Darwin.C.isatty
import enum Darwin.D.isatty
// Starts Test
@testable import MyModuleUnderTest
@testable import SwiftFormatRules
let a = 3
ReturnVoidInsteadOfEmptyTuple
(boolean)
true の場合、戻り値の型が()
になっているところをVoid
に統一する。
let callback: () -> ()
typealias x = Int -> ()
func y() -> Int -> () { return }
func z(d: Bool -> ()) {}
let callback: () -> Void
typealias x = Int -> Void
func y() -> Int -> Void { return }
func z(d: Bool -> Void) {}
UseLetInEveryBoundCaseVariable
(boolean)
--mode lint
で有効。
true の場合、case 文においてそれぞれの定数前に let をつける書き方でない場合警告がでる。switch 文だけでなくif case
やguard case
なども対象。
enum Label {
case value(String, Int)
}
switch Label.value("hello", 100) {
case let .value(label, value): break // ダメな書き方
case .value(let label, let value): break // 良い書き方
}
switch ("hello", 100) {
case let (label, value): break // ダメな書き方
case (let label, let value): break // 良い書き方
}
UseShorthandTypeNames
(boolean)
true の場合、型指定において省略形式で表記できる箇所を省略形式に書き換える。
細かい挙動については本家のテストコードを見てください。
var a: Array<Int>
var b: Dictionary<String, Int>
var c: Optional<String>
var d: Array<[Int]>
var e: Array<Array<Int>>
var f: Optional<Int>?
var a: [Int]
var b: [String: Int]
var c: String?
var d: [[Int]]
var e: [[Int]]
var f: Int??
UseSingleLinePropertyGetter
(boolean)
true の場合、Computed Property でかつ get しか記述されていない箇所の get スコープを省略表記に変える。
var a: Int {
get {
return 1
}
}
var a: Int {
return 1
}
UseSynthesizedInitializer
(boolean)
--mode lint
で有効。
true の場合、可能な限り Synthesized Initializer を使用するように勧めてくる警告を出す。
public struct Person {
var name: String
let phoneNumber: String
let address: String
// ↓ Synthesized Initializer があるからこれは不要
init(name: String, phoneNumber: String, address: String) {
self.name = name
self.address = address
self.phoneNumber = phoneNumber
}
}
UseTripleSlashForDocumentationComments
(boolean)
true の場合、関数直前に書かれたコメントがドキュメンテーションコメントであれば、///
を用いた形式に統一する。
/**
* Returns a docLineComment.
*
* - Parameters:
* - withOutStar: Indicates if the comment start with a star.
* - Returns: docLineComment.
*/
func foo(withOutStar: Bool) {}
/// Returns a docLineComment.
///
/// - Parameters:
/// - withOutStar: Indicates if the comment start with a star.
/// - Returns: docLineComment.
func foo(withOutStar: Bool) {}
ValidateDocumentationComments
(boolean)
--mode lint
で有効。
true の場合、ドキュメンテーションコメントの構文チェックをしてくれる。間違いがあれば警告が出る。
Discussion