-
Notifications
You must be signed in to change notification settings - Fork 48
Rules
- [upper-camel-case] UpperCamelCase naming
- [lower-camel-case] lowerCamelCase naming
- [constant-naming] Constant naming
- [constant-k-prefix] Flag "k-prefixed" constants
- [arrow-whitespace] Flag arrows that are not space delimited
- [angle-bracket-whitespace] Check whitespace in and around angular brackets
- [colon-whitespace] Flag incorrect whitespace around colons
- [comma-whitespace] Flag commas that are not left associated
- [operator-whitespace] Flag operators that are not space delimited (only in operator declarations)
- [leading-whitespace] Flag leading whitespace in a file
- [parentheses-whitespace] Check whitespace in and around parenthesis
- [terminating-newline] Single newline at end of source file
- [trailing-whitespace] Flag trailing whitespace
- [comment-whitespace] Comment whitespace checks
- [function-whitespace] Blank lines around functions
- Restrict number of lines per file and construct body
- Restrict number of characters per line and construct name
- [redundant-parentheses] Flag redundant parentheses
- [brace-style] One true brace style
- [forced-type-cast] Flag force casts
- [multiple-imports] One import per line
- [terminating-semicolon] Flag semicolon terminated statements
- [todo-syntax] Verify TODO syntax
-
[redundant-optional-binding] Flag redundant
let
/var
bindings in optional binding lists - [trailing-closure] Closures that are the last argument of a function should be passed using 'trailing closure' syntax.
Total: 31
class
, enum
, struct
, and protocol
names should follow UpperCamelCase naming convention : several words are joined together, and the first letter of every word is capitalized.
Preferred
class SomeClass {
// class definition goes here
}
class SomeClass : SomeSuperClass {
// class definition goes here
}
Not Preferred
class invalidClassName {
// class definition goes here
}
class inval1dCla$$Name : SomeSuperClass {
// class definition goes here
}
Preferred
enum SomeEnumeration {
// enumeration definition goes here
}
Not Preferred
enum S0me_Enumer4t!on {
// enumeration definition goes here
}
Preferred
struct SomeStructure {
// structure definition goes here
}
Not Preferred
struct Some-Structure {
// structure definition goes here
}
Preferred
protocol SomeProtocol {
// protocol definition goes here
}
Not Preferred
protocol someprotocol {
// protocol definition goes here
}
method
, var
, and enum value
names should follow lowerCamelCase naming convention: first letter of the entire word is lowercase, but subsequent first letters are uppercase.
Preferred
func someMethod() {
// method definition goes here
}
Not Preferred
func some-method() {
// method definition goes here
}
Preferred
var someVariable = someValue
Not Preferred
var Some_Var1able = someValue
Preferred
enum CompassPoint {
case north
case south
case east
case west
}
Not Preferred
enum CompassPoint {
case N0rth
case Sou-th
case East
case WEST
}
Global constants should follow either UpperCamelCase or lowerCamelCase naming conventions. Local constants should follow lowerCamelCase naming conventions.
Preferred
let MaxHeight = 42
let maxHeight = 42
Not Preferred
let max_height = 42
Flag "k-prefixed" constants.
Preferred
let maxHeight = 42
let MaxHeight = 42
Not Preferred
let kMaxHeight = 42
Prefer a single space before and after '->'.
Preferred
func onePlusTwo() -> Int {
return 1 + 2
}
names.map() {
(name) -> Int in
return 1
}
Not Preferred
func onePlusTwo()->Int {
return 1 + 2
}
names.map() {
(name) -> Int in
return 1
}
class SomeClass: SomeSuperClass{
}
Preferred
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
Not Preferred
struct TimesTable {
let multiplier: Int
subscript(index: Int)-> Int {
return multiplier * index
}
}
struct SomeStruct : SomeParentStruct {
}
Preferred
func something() -> (Int, Int) -> (Int) {
// do something
}
Not Preferred
func something() -> (Int, Int)-> (Int) {
// do something
}
func something() -> (Int, Int) -> (Int){
// do something
}
There should be no whitespace immediately before/after an opening chevron <
and before the closing chevron >
.
Preferred
func simpleMax<T: Comparable>(x: T, _ y: T) -> T {
if x < y {
return y
}
return x
}
Not Preferred
func simpleMax < T: Comparable >(x: T, _ y: T) -> T {
if x < y {
return y
}
return x
}
Preferred
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, _ anotherContainer: C2) -> Bool {}
Not Preferred
func allItemsMatch <
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable >
(someContainer: C1, _ anotherContainer: C2) -> Bool {}
An exception to this rule is made for operator declarations. The opening angle bracket (if used) in an operator declaration must have a single space preceding it.
Preferred
func ++< <T where T: Comparable>(op1: T, op2: T) -> Bool {
}
Not Preferred
func ++<<T where T: Comparable>(op1: T, op2: T) -> Bool {
}
There should be no whitespace preceding the colon, exactly one whitespace after the colon for:
-
var
,class
,struct
,protocol
,extension
,func
, andtuple
declarations -
dict
literals and types -
case
statements
However, for conditional expressions there should be a single whitespace before and after the colon.
Preferred
var x: Int = 2
Not Preferred
var x : Int
var y: String
Preferred
var x = [ 'key1': 1, 'key2': 2 ]
var y: [ Int: String ]
Not Preferred
var x = [ 'key1' : 1, 'key2': 3]
var y: [ Int : String ]
Preferred
switch character {
case "a": doSomething(a);
default: alert();
}
Not Preferred
switch character {
case "a" : doSomething(a);
default: alert();
}
Preferred
class ClassName: BaseClass {
}
struct StructName: BaseStruct {
}
protocol ProtocolName: AnotherProtocol {
}
extension TypeName: ProtocolName {
}
Not Preferred
class ClassName : BaseClass {
}
struct StructName: BaseStruct {
}
protocol ProtocolName:AnotherProtocol {
}
extension TypeName : ProtocolName {
}
Preferred
var y = (key: 1, value: 2)
Not Preferred
var y = (key:1, value : 2)
Preferred
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
}
Not Preferred
func someFunction<T : SomeClass, U:SomeProtocol>(someT: T, someU: U) {
}
Preferred
var x = condition ? a : b
Not Preferred
var x = condition ? a: b
var x = condition ? a : b
Prefer no spaces before and exactly one space after a comma (',') in the following structures:
- Generics
- Type Inheritance Clauses
- Condition Clauses
- Availability Arguments
- Generic Argument Lists
- Pattern Initializer Lists
- Parameter Lists
- Enum Case Lists
- Tuple Pattern Lists
- Tuple Type Lists
- Expression Lists
- Array Literal Items
- Dictionary Literal Items
- Capture List Items
- Paranthesized Expressions
- Identifier Lists
- Switch Case Item Lists
Preferred
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// function body goes here
}
func someFunction<T: SomeClass, U: SomeProtocol,
V: AnotherClass>(someT: T, someU: U) {
// function body goes here
}
class Bicycle: Vehicle, TwoWheeler {
var hasBasket = false
}
if x < 2, var y = val {
println(x + y)
}
if let roomCount = john.residence?.numberOfRooms, roomCountTwo = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
}
if #available(iOS 9, OSX 10.10, *) {
// Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X
}
struct Dictionary<Key: Hashable, Value>: CollectionType {}
let numX = 2, func_y = { x in println(x) }
func initialize(x: Int, y: Int, z: Int) {}
enum Planet {
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
enum ASCIIControlCharacter: Character {
case Tab = "\t", LineFeed = "\n"
case CarriageReturn = "\r"
}
var (x, y): (Int, Int)
for (i = 0, j = n - 1; i < n && j >= 0; i++, j--) {
println(mat[i][j])
}
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
lazy var someClosure: Void -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
var arr = [ (1, 2, 3), (3, 4, 5) ]
reversed = names.sort( { s1, s2 in s1 > s2 } )
switch character {
case "a", "e", "i", "o", "u", " ": continue
default: puzzleOutput.append(character)
}
Not Preferred
func someFunction<T: SomeClass,U: SomeProtocol>(someT: T, someU: U) {
// function body goes here
}
func someFunction<T: SomeClass , U: SomeProtocol>(someT: T, someU: U) {
// function body goes here
}
class Bicycle: Vehicle, TwoWheeler {
var hasBasket = false
}
if x < 2 , var y = val {
println(x + y)
}
if let roomCount = john.residence?.numberOfRooms,roomCountTwo = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
}
if #available(iOS 9, OSX 10.10,*) {
// Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X
}
struct Dictionary<Key: Hashable, Value>: CollectionType {}
let numX = 2 , func_y = { x in println(x) }
func initialize(x: Int,y: Int,z: Int) {}
enum Planet {
case Mercury,Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
enum ASCIIControlCharacter: Character {
case Tab = "\t" , LineFeed = "\n"
case CarriageReturn = "\r"
}
var (x,y): (Int , Int)
for (i = 0,j = n - 1; i < n && j >= 0; i++,j--) {
println(mat[i][j])
}
shoppingList += ["Chocolate Spread" , "Cheese", "Butter"]
var airports: [String: String] = ["YYZ": "Toronto Pearson","DUB": "Dublin"]
lazy var someClosure: Void -> String = {
[unowned self , weak delegate = self.delegate!] in
// closure body goes here
}
var arr = [ (1,2, 3), (3 , 4, 5) ]
reversed = names.sort( { s1,s2 in s1 > s2 } )
switch character {
case "a" , "e", "i","o", "u", " ": continue
default: puzzleOutput.append(character)
}
Prefer single space around operator in operator declarations.
Preferred
infix operator -+* { precedence 70 associativity right }
Not Preferred
infix operator-+* { precedence 70 associativity right }
infix operator -+* { precedence 70 associativity right }
infix operator -+*{ precedence 70 associativity right }
infix operator -+* { precedence 70 associativity right }
Verify that source files begin with a non-whitespace character.
Preferred
1 import Foundation
Not Preferred
1 ¬
2 import Foundation
1 ••import Foundation
Verify that source files terminate with exactly one \n
character. This ensures that the last line of the file is valid according to the POSIX standard. Also see No Newline at End of File for more information.
Swift source files should terminate with exactly 1 \n
character, not 0 nor more than 1.
Preferred
let myConstant = 42¬
<EOF>
Not Preferred
let myConstant = 42<EOF>
let myConstant = 42¬
¬
¬
<EOF>
There should be no whitespace immediately before/after an opening parenthesis (
and before the closing parenthesis )
.
Preferred
func sum(a: Int, b: Int) -> Int {
return a + b;
}
print("Hello, World!")
Not Preferred
func sum ( a: Int, b: Int ) -> Int {
return a + b;
}
print( "Hello, World!" )
Preferred
let tuple = (5, 2)
Not Preferred
let tuple = ( 5, 2 )
Preferred
if (someCondition) {
...
}
Not Preferred
if ( someCondition ) {
...
}
Preferred
class SomeClass {
init() {
}
}
Not Preferred
class SomeClass {
init ( ) {
}
}
Flag whitespace after the last non-whitespace character on each line until the newline.
Preferred
let number = 42¬
Not Preferred
let number = 42••¬
Prefer at least one whitespace character after a comment opening symbol (//
, ///
, /*
, or /**
) and at least one whitespace character before a comment closing symbol (*/
).
Preferred
// This is a comment
/// This is a documentation comment
/* This is a
multi-line comment */
/* This is a
multi-line comment
*/
/** This is a
documentation multi-line
comment
*/
Not Preferred
//This is a comment
///This is a documentation comment
/*This is a
multi-line comment*/
/**This is a multi-line
documentation comment */
Every function and method declaration should have one blank line before and after itself. An exception to this rule are functions that are declared at the start of a file (only need one blank line after their declaration) or at the end of a file (only need one blank line before their declaration). Comments immediately before a function declaration (no blank lines between them and the function) are considered to be part of the declaration.
Preferred
func function1() {
var text = 1
var text = 2
}
function1()
// a comment
func function2() {
// something goes here
}
struct SomeStruct {
func function3() {
// something goes here
}
func function4() {
// something else goes here
};
}
func function5() {
// something goes here
}
Not Preferred
func function1() {
var text = 1
var text = 2
}
function1()
// a comment
func function2() {
// something goes here
}
struct SomeStruct {
func function3() {
// something goes here
}
func function4() {
// something else goes here
};
}
func function5() {
// something goes here
}
Enforce a line limit on the lengths of class bodies.
tailor [--max-class-length <x>]
For example, limiting classes to 2 lines would trigger a violation for the following 3 line class:
1 class ThreeLineClass {
2 // This class spans from lines 1-4.
3
4 }
Enforce a line limit on the lengths of closure bodies.
tailor [--max-closure-length <x>]
For example, limiting closures to 2 lines would trigger a violation for the following 3 line closure:
1 reversed = names.sort({ (s1: String, s2: String) -> Bool in
2 // This closure spans from lines 1-4.
3 return s1 > s2
4 })
Enforce a line limit on the length of each file.
tailor [--max-file-length <x>]
For example, limiting files to 2 lines would trigger a violation for the following 3 line file:
1 let myHello = "Hello,"
2 let myWorld = " world!"
3 println(myHello + myWorld)
Enforce a line limit on the lengths of function bodies.
tailor [--max-function-length <x>]
For example, limiting functions to 2 lines would trigger a violation for the following 3 line function:
1 func helloWorld() {
2 // This function spans from lines 1-4.
3 println("Hello, world!")
4 }
Enforce a line limit on the lengths of struct bodies.
tailor [--max-struct-length <x>]
For example, limiting structs to 2 lines would trigger a violation for the following 3 line struct:
1 struct ThreeLineStruct {
2 // This struct spans from lines 1-4.
3
4 }
Enforce a character limit on the length of each line.
tailor [-l <x>|--max-line-length <x>]
For example, limiting lines to 10 characters would trigger a violation for the following 14 character line:
let hello = 42
Enforce a character limit on the maximum length of each construct name for classes, enums, enumcases, structs, protocols, elements, functions, labels, setters, typealiases, types, variables, and constants.
tailor [--max-name-length <x>]
For example, limiting names to 10 characters would trigger a violation for the following 12 character constant name:
let my12CharName = 42
Enforce a character limit on the minimum length of each construct name for classes, enums, enumcases, structs, protocols, elements, functions, labels, setters, typealiases, types, variables, and constants.
tailor [--min-name-length <x>]
For example, limiting names to at least 3 characters would trigger a violation for the following single character constant name:
let a = 42
Control flow constructs (if
, else if
, switch
, for
, while
, repeat-while
, and guard
statements), Exception handling constructs (throw
, and do/catch
statements), and Initializers (array
, dictionary
, initializer patterns
) should not be enclosed in parentheses.
Additionally, method calls with no parameters and a trailing closure should not have empty parentheses following the method name.
- if, else if statement
Preferred
if SomeCondition {
} else if SomeOtherCondition {
}
Not Preferred
if (SomeCondition) {
} else if (SomeOtherCondition) {
}
- switch statement
Preferred
switch SomeData {
default:
break
}
Not Preferred
switch (SomeData) {
default:
break
}
- for loop
Preferred
for var i = 0; i < 10; i+=1 {
}
Not Preferred
for (var i = 0; i < 10; i+=1) {
}
- while loop
Preferred
while SomeCondition {
}
Not Preferred
while (SomeCondition) {
}
- repeat-while loop
Preferred
repeat {
} while SomeCondition
Not Preferred
repeat {
} while (SomeCondition)
- guard clause
Preferred
guard true else { }
Not Preferred
guard (true) else { }
- do/catch statement
Preferred
do {
} catch SomeException {
}
Not Preferred
do {
} catch (SomeException) {
}
- throw statement
Preferred
throw SomeException
Not Preferred
throw (SomeException)
- array items
Preferred
var shoppingList: [String] = ["Eggs", "Milk"]
Not Preferred
var shoppingList: [String] = [("Eggs"), ("Milk")]
- dictionary items
Preferred
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
Not Preferred
var airports: [String: String] = [("YYZ"): ("Toronto Pearson"), ("DUB"): ("Dublin")]
- initializer patterns
Preferred
var x: Int = 2
var y: String = "Sleekbyte"
var x = 2
Not Preferred
var x: Int = (2)
var y: String = ("Sleekbyte")
var x = (2)
Preferred
items.map {
item in item.transform()
}
Not Preferred
items.map() {
item in item.transform()
}
Definitions of
class
struct
function
-
Control flow constructs (
if
,else if
,else
,switch
,for
,while
,repeat-while
) init
protocol
enum
closure
-
Getters and Setters (
set
,get
) extension
should follow the One True Brace Style (1TBS): each construct has its opening brace one the same line along with the same indentation level as its header, the statements within the braces are indented, and the closing brace at the end is on the same indentation level as the header of the function at a line of its own. Braces are not omitted for a control statement with only a single statement in its scope. Every opening brace must also have one space preceding it.
Preferred
class SomeClass {
}
class SomeClass: SomeSuperClass {
}
Not Preferred
class SomeClass
{
}
class SomeClass: SomeSuperClass{
}
Preferred
struct SomeStruct {
}
struct SomeStruct : SomeParentStruct {
}
Not Preferred
struct SomeStruct
{
}
struct SomeStruct : SomeParentStruct {
}
Preferred
func someMethod() {
}
func someOtherFunction () -> () {
}
Not Preferred
func someMethod()
{
}
func someOtherFunction () -> ()
{
}
- if, else if, and else statement
Preferred
if SomeCondition {
} else if someOtherCondition {
} else {
}
Not Preferred
if SomeCondition
{
}
else if someOtherCondition
{
}
else
{
}
- switch statement
Preferred
switch SomeData {
default:
break
}
Not Preferred
switch SomeData
{
default:
break
}
- for loop
Preferred
for var i = 0; i < 10; i+=1 {
}
Not Preferred
for var i = 0; i < 10; i+=1
{
}
- while loop
Preferred
while SomeCondition {
}
Not Preferred
while SomeCondition
{
}
- repeat-while loop
Preferred
repeat {
} while SomeCondition
Not Preferred
repeat
{
} while SomeCondition
Preferred
init(someParameter:Double, someOtherParameter:Double) {
self.someMember = someParameter
self.someOtherMember = someOtherParameter
}
Not Preferred
init(someParameter:Double, someOtherParameter:Double)
{
self.someMember = someParameter
self.someOtherMember = someOtherParameter
}
Preferred
protocol SomeProtocol {
}
protocol SomeOtherProtocol : X {
}
Not Preferred
protocol SomeProtocol
{
}
protocol SomeOtherProtocol : X
{
}
Preferred
enum SomeEnum {
case A, B, C, D
}
enum SomeEnum {
case A
case B
case C
case D
}
enum SomeEnum: Int {
case A, B, C = 5, D
}
Not Preferred
enum SomeEnum
{
case A, B, C, D
}
enum SomeEnum
{
case A
case B
case C
case D
}
enum SomeEnum: Int
{
case A, B, C = 5, D
}
Preferred
func someFunction () -> () {
// closure
}
Not Preferred
func someFunction () -> ()
{
// closure
}
- set
Preferred
set {
oldValue = newValue / 2
}
Not Preferred
set
{
oldValue = newValue / 2
}
- get
Preferred
get {
return value * 2
}
Not Preferred
get
{
return value * 2
}
Preferred
extension someExtension {
}
Not Preferred
extension someExtension
{
}
Avoid using the forced form of the type cast operator (as!
) because Swift is not able to determine at compile time if the type conversion will succeed. In the event of an unsuccessful conversion, a runtime error will be triggered. The conditional form of the type cast operator (as?
) is safer and should be used when possible.
Preferred
if let movie = item as? Movie {
print("Movie: '\(movie.name)', dir. \(movie.director)")
}
Not Preferred
let movie = item as! Movie
print("Movie: '\(movie.name)', dir. \(movie.director)")
Multiple import
statements should not be defined on a single line.
Preferred
import Foundation
import Cocoa
Not Preferred
import Foundation; import Cocoa
Swift does not require a semicolon after each statement in your code unless you wish to combine multiple statements on a single line. Do not write multiple statements on a single line separated with semicolons.
Preferred
import Foundation
Not Preferred
import Foundation;
Preferred
enum CompassPoint {
case North
case South
case East
case West
}
Not Preferred
enum CompassPoint {
case North;
case South;
case East;
case West;
};
Preferred
protocol SomeProtocol {
var SomeMethod: String { get }
func SomeMethod()
func SomeMethod(f: Int)
func SomeMethod(bar: String, baz: Double)
}
Not Preferred
protocol SomeProtocol {
var SomeMethod: String { get };
func SomeMethod();
func SomeMethod(f: Int);
func SomeMethod(bar: String, baz: Double);
};
Preferred
extension SomeType {
}
Not Preferred
extension SomeType {
};
Preferred
struct DemoStruct {
var x: String // variables
}
Not Preferred
struct DemoStruct {
var x: String // variables
};
Preferred
class SomeClass {
let b = 2 // constants
}
Not Preferred
class SomeClass {
let b = 2 // constants
};
Preferred
// while loop
while true {
}
// for loop
for ; ; {
}
// repeat while
repeat {
} while true
Not Preferred
// while loop
while true {
};
// for loop
for ; ; {
};
// repeat while
repeat {
} while true;
TODO comments should be defined separately using non-nested single line comments. They should adhere to the <TODO: description>
or <TODO(developer-name): description>
syntax. Empty TODO comments will be flagged.
Preferred
// TODO: <insert mandatory todo comment>
// TODO(dev-name): <insert mandatory todo comment>
Not Preferred
// TODO:
/// TODO: Documentation comments should not have TODOs
//// TODO: Nested comments should not have TODOs
// //TODO: Nested comments should not have TODOs
// TODO: Nested comments should not have TODOs // some comment
//// TODO: Nested comments should not have TODOs
Optional binding lists should not have consecutive var
/let
bindings. All constants must be preceded by at most one let
binding. All variables must be preceded by only one var
binding.
Preferred
if var a = a, b = b, c = c where c != 0 {
print("(a + b) / c = \((a + b) / c)") // (a + b) / c = 5
}
if let a = a, b = b, var c = c where c != 0 {
print("(a + b) / c = \((a + b) / c)") // (a + b) / c = 5
}
Not Preferred
if var a = a, var b = b, var c = c where c != 0 {
print("(a + b) / c = \((a + b) / c)") // (a + b) / c = 5
}
if let a = a, let b = b, var c = c where c != 0 {
print("(a + b) / c = \((a + b) / c)") // (a + b) / c = 5
}
Closures that are the last argument of a function should be passed into the function using trailing closure syntax.
Preferred
reversed = names.sort { s1, s2 in return s1 > s2 }
Not Preferred
reversed = names.sort({ s1, s2 in return s1 > s2 })
Questions or need help? Get in touch via email or open an Issue!