swiftfmt
A tool for formatting Swift code according to style guidelines.
Live Demo
https://swiftfmt.kishikawakatsumi.com/
A Work In Progress
swiftfmt is still in active development.
Requirements
Swiftfmt requires Swift trunk toolchains.
Installation
Download and install the latest trunk Swift development toolchain.
git clone https://github.com/kishikawakatsumi/swiftfmt
cd swiftfmt
~/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swift package update
~/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swift build -c release
Copy the file (.build/release/swiftfmt
) to your binary location.
Getting Started
swiftfmt [file or directory]
Usage
swiftfmt .
Configurations
Tabs and Indents
Use tab character
git clone https://github.com/kishikawakatsumi/swiftfmt
class Shape {
- var numberOfSides = 0
- func simpleDescription() -> String {
- return "A shape with \(numberOfSides) sides."
- }
+ var numberOfSides = 0
+
+ func simpleDescription() -> String {
+ return "A shape with \(numberOfSides) sides."
+ }
}
Indent
"indent" : 2
class Shape {
- var numberOfSides = 0
- func simpleDescription() -> String {
- return "A shape with \(numberOfSides) sides."
- }
+ var numberOfSides = 0
+
+ func simpleDescription() -> String {
+ return "A shape with \(numberOfSides) sides."
+ }
}
Keep indents on empty lines
class Shape {
var numberOfSides = 0
+
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
Indent 'case' branches
let someCharacter: Character = "z"
switch someCharacter {
-case "a":
- print("The first letter of the alphabet")
-case "z":
- print("The last letter of the alphabet")
-default:
- print("Some other character")
+ case "a":
+ print("The first letter of the alphabet")
+ case "z":
+ print("The last letter of the alphabet")
+ default:
+ print("Some other character")
}
Spaces
Before Parentheses
Method/function declaration parentheses
class Counter {
var count = 0
-
- func increment() {
+
+ func increment () {
count += 1
}
- func increment(by amount: Int) {
+ func increment (by amount: Int) {
count += amount
}
- func reset() {
+ func reset () {
count = 0
}
}
Method/function call parentheses
struct Point {
var x = 0.0, y = 0.0
+
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
- self = Point(x: x + deltaX, y: y + deltaY)
+ self = Point (x: x + deltaX, y: y + deltaY)
}
}
'if' parentheses
-if(temperatureInFahrenheit <= 32) {
+if (temperatureInFahrenheit <= 32) {
print("It's very cold. Consider wearing a scarf.")
-} else if(temperatureInFahrenheit >= 86) {
+} else if (temperatureInFahrenheit >= 86) {
print("It's really warm. Don't forget to wear sunscreen.")
}
'while' parentheses
var square = 0
var diceRoll = 0
-while(square < finalSquare) {
+while (square < finalSquare) {
// roll the dice
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
'switch' parentheses
let someCharacter: Character = "z"
-switch(someCharacter) {
+switch (someCharacter) {
case "a":
print("The first letter of the alphabet")
case "z":
'catch' parentheses
do {
try throwable()
} catch Error.unexpected(let cause) {
print("unexpected error!")
-} catch(Error.unknown) {
+} catch (Error.unknown) {
print("unknown error!")
}
Attribute parentheses
-@available (swift 3.0.2)
-@available (macOS 10.12, *)
+@available(swift 3.0.2)
+@available(macOS 10.12, *)
struct MyStruct {
// struct definition
}
Around Operators
Assignment Operators (=, +=, ...)
-let contentHeight=40
-let hasHeader=true
+let contentHeight = 40
+let hasHeader = true
let rowHeight: Int
if hasHeader {
- rowHeight=contentHeight+50
+ rowHeight = contentHeight + 50
} else {
- rowHeight=contentHeight+20
+ rowHeight = contentHeight + 20
}
Logical Operators (&&, ||)
-if enteredDoorCode&&passedRetinaScan||hasDoorKey||knowsOverridePassword {
+if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
Equality Operator (==)
let name = "world"
-if name=="world" {
+if name == "world" {
print("hello, world")
} else {
print("I'm sorry \(name), but I don't recognize you")
Relational Operators (<, >, <=, >=)
-2>1 // true because 2 is greater than 1
-1<2 // true because 1 is less than 2
-1>=1 // true because 1 is greater than or equal to 1
-2<=1 // false because 2 is not less than or equal to 1
+2 > 1 // true because 2 is greater than 1
+1 < 2 // true because 1 is less than 2
+1 >= 1 // true because 1 is greater than or equal to 1
+2 <= 1 // false because 2 is not less than or equal to 1
Bitwise Operators (&, |, ^)
for i in 0..<x {
- y += (y^0x123) << 2
+ y += (y ^ 0x123) << 2
}
Additive Operators (+, -)
while (x != y) {
- x = f(x * 3+5)
+ x = f(x * 3 + 5)
}
Multiplicative Operators (*, /, %)
while (x != y) {
- x = f(x*3 + 5)
+ x = f(x * 3 + 5)
}
Shift Operators (<<, >>)
for i in 0..<x {
- y += (y ^ 0x123)<<2
+ y += (y ^ 0x123) << 2
}
if (0 < x && x <= 10) {
while (x != y) {
Range Operators (..., ..<)
-for index in 1 ... 5 {
+for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
Closure Arrow (->)
-func greet(person: String)->String {
+func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
Before Left Brace
Type declaration left brace
-struct Resolution{
+struct Resolution {
var width = 0
var height = 0
}
-class VideoMode{
+
+class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
Method/function left brace
-func greet(person: String) -> String{
+func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
'if' left brace
var temperatureInFahrenheit = 30
-if temperatureInFahrenheit <= 32{
+if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
}
'else' left brace
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
-} else{
+} else {
print("It's not that cold. Wear a t-shirt.")
}
'for' left brace
let names = ["Anna", "Alex", "Brian", "Jack"]
-for name in names{
+for name in names {
print("Hello, \(name)!")
}
'while' left brace
var square = 0
var diceRoll = 0
-while square < finalSquare{
+while square < finalSquare {
// roll the dice
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
'do' left brace
-do{
+do {
try throwable()
} catch Error.unexpected(let cause) {
print("unexpected error!")
'switch' left brace
let someCharacter: Character = "z"
-switch someCharacter{
+switch someCharacter {
case "a":
print("The first letter of the alphabet")
case "z":
'catch' left brace
do {
try throwable()
-} catch Error.unexpected(let cause){
+} catch Error.unexpected(let cause) {
print("unexpected error!")
-} catch (Error.unknown){
+} catch (Error.unknown) {
print("unknown error!")
}
Before Keywords
'else' keyword
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
-}else {
+} else {
print("It's not that cold. Wear a t-shirt.")
}
'while' keyword
if diceRoll == 7 { diceRoll = 1 }
// move by the rolled amount
square += diceRoll
-}while square < finalSquare
+} while square < finalSquare
print("Game over!")
'catch' keyword
do {
try throwable()
-}catch Error.unexpected(let cause) {
+} catch Error.unexpected(let cause) {
print("unexpected error!")
-}catch (Error.unknown) {
+} catch (Error.unknown) {
print("unknown error!")
}
Within
Code braces
Brackets
"brackets" : true
len = 10
}
repeat {
- text[ext++] = "$"
+ text[ ext++ ] = "$"
} while (ext < len)
len = len > 10000 ? len : 0
Array and dictionary literal brackets
"arrayAndDictionaryLiteralBrackets" : true
-var shoppingList = ["Eggs", "Milk"]
-shoppingList += ["Baking Powder"]
-shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
+var shoppingList = [ "Eggs", "Milk" ]
+shoppingList += [ "Baking Powder" ]
+shoppingList += [ "Chocolate Spread", "Cheese", "Butter" ]
Grouping parenthesese
var ext = x
var len = y
for i in 0..<x {
- y += (y ^ 0x123) << 2
+ y += ( y ^ 0x123 ) << 2
}
repeat {
text[ext++] = "$"
Method/function declaration parenthesese
"functionDeclarationParentheses" : true
-func greet(person: String) -> String {
+func greet( person: String ) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
Empty method/function declaration parenthesese
-func sayHelloWorld() -> String {
+func sayHelloWorld( ) -> String {
return "hello, world"
}
print(sayHelloWorld())
Method/function call parenthesese
func greet(person: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
- return greetAgain(person: person)
+ return greetAgain( person: person )
} else {
- return greet(person: person)
+ return greet( person: person )
}
}
Empty method/function call parenthesese
func sayHelloWorld() -> String {
return "hello, world"
}
-print(sayHelloWorld())
+print(sayHelloWorld( ))
'if' parenthesese
while square < finalSquare {
// roll the dice
diceRoll += 1
- if (diceRoll == 7) { diceRoll = 1 }
+ if ( diceRoll == 7 ) { diceRoll = 1 }
// move by the rolled amount
square += diceRoll
- if (square < board.count) {
+ if ( square < board.count ) {
// if we're still on the board, move up or down for a snake or a ladder
square += board[square]
}
'while' parenthesese
var square = 0
var diceRoll = 0
-while (square < finalSquare) {
+while ( square < finalSquare ) {
repeat {
// move up or down for a snake or ladder
square += board[square]
@@ -9,5 +9,5 @@ while (square < finalSquare) {
if diceRoll == 7 { diceRoll = 1 }
// move by the rolled amount
square += diceRoll
- } while (square < finalSquare)
+ } while ( square < finalSquare )
}
'switch' parenthesese
let someCharacter: Character = "z"
-switch (someCharacter) {
+switch ( someCharacter ) {
case "a":
print("The first letter of the alphabet")
case "z":
'catch' parenthesese
try throwable()
} catch Error.unexpected(let cause) {
print("unexpected error!")
-} catch (Error.unknown) {
+} catch ( Error.unknown ) {
print("unknown error!")
}
Attribute parenthesese
-@available(swift 3.0.2)
-@available(macOS 10.12, *)
+@available( swift 3.0.2 )
+@available( macOS 10.12, * )
struct MyStruct {
// struct definition
}
In Ternary Operator (:?)
After '?'
let contentHeight = 40
let hasHeader = true
-let rowHeight = contentHeight + (hasHeader ?50:20)
+let rowHeight = contentHeight + (hasHeader ? 50:20)
Before ':'
let contentHeight = 40
let hasHeader = true
-let rowHeight = contentHeight + (hasHeader ?50:20)
+let rowHeight = contentHeight + (hasHeader ?50: 20)
After ':'
let contentHeight = 40
let hasHeader = true
-let rowHeight = contentHeight + (hasHeader ?50:20)
+let rowHeight = contentHeight + (hasHeader ?50: 20)
Around colons
Before colon in type annotations
-func greet(person: String, alreadyGreeted: Bool) -> String {
+func greet(person : String, alreadyGreeted : Bool) -> String {
if alreadyGreeted {
- return greetAgain(person: person)
+ return greetAgain(person : person)
} else {
- return greet(person: person)
+ return greet(person : person)
}
}
After colon in type annotations
-func greet(person:String, alreadyGreeted:Bool) -> String {
+func greet(person: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
- return greetAgain(person:person)
+ return greetAgain(person: person)
} else {
- return greet(person:person)
+ return greet(person: person)
}
}
Before colon in type inheritance clauses
-class Movie: MediaItem {
+class Movie : MediaItem {
var director: String
init(name: String, director: String) {
self.director = director
After colon in type inheritance clauses
-class Movie :MediaItem {
+class Movie : MediaItem {
var director: String
init(name: String, director: String) {
self.director = director
Before colon in dictionary types
-var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
-var emptyDictionary: [String: Int] = [:]
+var airports: [String : String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
+var emptyDictionary: [String : Int] = [:]
After colon in dictionary types
-var airports: [String:String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
-var emptyDictionary: [String:Int] = [:]
+var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
+var emptyDictionary: [String: Int] = [:]
Before colon in dictionary literal 'key:value' pair
-var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
+var airports: [String: String] = ["YYZ" : "Toronto Pearson", "DUB" : "Dublin"]
var emptyDictionary: [String: Int] = [:]
After colon in dictionary literal 'key:value' pair
-var airports: [String: String] = ["YYZ":"Toronto Pearson", "DUB":"Dublin"]
+var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
var emptyDictionary: [String: Int] = [:]
Within Type Arguments
After comma
-func allItemsMatch<C1: Container,C2: Container>
+func allItemsMatch<C1: Container, C2: Container>
(_ someContainer: C1,_ anotherContainer: C2) -> Bool
-where C1.Item == C2.Item,C1.Item:Equatable {
+where C1.Item == C2.Item, C1.Item: Equatable {
// Check that both containers contain the same number of items.
if someContainer.count != anotherContainer.count {
return false
Other
Before comma
enum State {
- case none, all
+ case none , all
}
-typealias Status = (Int, String)
+typealias Status = (Int , String)
-func +++(l: String, r: String) -> String {
+func +++(l: String , r: String) -> String {
return ""
}
-let array = ["One", "Two", "Three", "Four", "Five"]
+let array = ["One" , "Two" , "Three" , "Four" , "Five"]
-let dictionary = ["One": 1, "Two": 2, "Three": 3, "Four": 4, "Five": 5]
+let dictionary = ["One": 1 , "Two": 2 , "Three": 3 , "Four": 4 , "Five": 5]
After comma
enum State {
- case none,all
+ case none, all
}
-typealias Status = (Int,String)
+typealias Status = (Int, String)
struct S {
}
@@ -15,16 +15,16 @@ struct S {
protocol P {
}
-func +++(l: String,r: String) -> String {
+func +++(l: String, r: String) -> String {
return ""
}
-let array = ["One","Two","Three","Four","Five"]
+let array = ["One", "Two", "Three", "Four", "Five"]
var emptyArray = []
-let dictionary = ["One": 1,"Two": 2,"Three": 3,"Four": 4,"Five": 5]
+let dictionary = ["One": 1, "Two": 2, "Three": 3, "Four": 4, "Five": 5]
var emptyDictionary: [String: Int] = [:]
Before semicolon
After semicolon
Wrapping and Braces
Blank Lines
Keep Maximum Blank Lines
In declarations
In code
Before '}'
Minimum Blank Lines
Before imports
"beforeImports" : 1
//
// Created by Kishikawa Katsumi on 2018/02/14.
//
+
import Foundation
import Basic
import SwiftSyntax
After imports
"afterImports" : 1
import Foundation
import Basic
import SwiftSyntax
+
public struct Processor {
private let options: [String]
Around type declarations
"aroundTypeDeclarations" : 1
@@ -9,6 +9,7 @@ fileprivate class Bracket : Indentation {
self.lineNumber = lineNumber
}
}
+
fileprivate class SwitchStatement {
var lineNumber: Int
@@ -16,6 +17,7 @@ fileprivate class SwitchStatement {
self.lineNumber = lineNumber
}
}
+
fileprivate class CaseBranch {
var lineNumber: Int
@@ -23,6 +25,7 @@ fileprivate class CaseBranch {
self.lineNumber = lineNumber
}
}
+
protocol Indentation {
var indent: Bool { get set }
var alignment: Int { get set }
Around property in protocol
"aroundPropertyInProtocol" : 0
Around property
"aroundProperty" : 1
Around method/function in protocol
"aroundFunctionInProtocol" : 0
Around method/function
"aroundFunction" : 1
Before method/function body
"beforeFunctionBody" : 0
Author
Kishikawa Katsumi, [email protected]
License
Swiftfmt is available under the Apache 2.0 license. See the LICENSE file for more info.