The contributing rules of this project follows the Swift API Design Guidelines with exceptions, which are described below.
You can format your code running swift format
with our given format file. Due to swift-format
lacking in features, some of the exceptions outlined in this document are not enforceable nor auto-corrected. The maintainers will modify any code you commit to adhere to this document.
At the end of the day, you can write however you want. The maintainers will modify the syntax after merging.
All public facing functions and variables should use lowerCamelCase
. Non-public functions and variables should use snake_case
, but it is not required. Snake case is recommended for package
, private
and fileprivate
declarations.
lowerCamelCase
is recommended by the Swift Language. snake_case
is more readable and maintainable with larger projects.
Declaring a native Swift type never contains spaces. The only exception is type aliases.
Example: declaring a dictionary should look like [String:String]
instead of Dictionary<String, String>
.
As protocols outline an implementation, conformances and variables should always be separated by a single space between each token. Conformances should always be sorted alphabetically.
// ✅ DO
protocol Something : CustomStringConvertible, Hashable, Identifiable {
var name : String { get }
var digits : Int { get set }
var headers : [String:String]? { mutating get }
}
// ❌ DON'T
protocol Something: Identifiable, Hashable,CustomStringConvertible {
var name:String { get }
var digits :Int { get set }
var headers: [String:String]?{mutating get}
}
Always type annotate your variables. The syntax of the annotation should not contain any whitespace between the variable name, colon and the declared type. Computed properties should always be separated by a single space between each token.
// ✅ DO
let _:Int = 1
let string:String? = nil
let array:[UInt8] = []
let _:[String:String] = [:]
let _:[String:String] = [
"one" : 1,
"two": 2,
"three": 3
]
// ❌ DON'T
let _ :Int = 1
let _: Int = -1
let _ : Int = 1
let _:[String :String] = [:]
let _:[String: String] = [:]
let _:[String : String] = [:]
// ⚠️ Exceptions
// sequence iteration
for _ in array {
}
// Closure parameters
let _:(Int, String) -> Void = { one, two in }
let _:(Int, String) -> Void = { $0; $1 }
// Unwrapping same name optional
if let string {
}
// Computed properties
var name : String {
"rly"
}
var headers : [String:String] {
[
"one": 1,
"two": 2
"three" : 3
]
}
- when iterating over a sequence
- declaring or referencing parameters in a closure
- unwrapping same name optional variables
- computed properties
Reduces syntax noise, improves readability
If you're making an extension
where all content is the same visibility: declare the visibility at the extension level. There are no exceptions.
Waste of disk space to declare the same visibility for every declaration.
Documenting your code is required if you have justification for a change or implementation, otherwise it is not required (but best practice to do so).