Function Default Parameter at End
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
function_default_parameter_at_end |
否 |
否 |
idiomatic |
否 |
3.0.0 |
最好给函数的最后一个参数赋上默认值
示例
非触发
func foo(baz: String, bar: Int = 0) {}
func foo(x: String, y: Int = 0, z: CGFloat = 0) {}
func foo(bar: String, baz: Int = 0, z: () -> Void) {}
func foo(bar: String, z: () -> Void, baz: Int = 0) {}
func foo(bar: Int = 0) {}
func foo() {}
class A: B {
override func foo(bar: Int = 0, baz: String) {}
func foo(bar: Int = 0, completion: @escaping CompletionHandler) {}
func foo(a: Int, b: CGFloat = 0) {
let block = { (error: Error?) in }
}
触发
↓func foo(bar: Int = 0, baz: String) {}
Function Parameter Count
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
function_parameter_count |
是 |
否 |
metrics |
否 |
3.0.0 |
函数的参数应该尽可能的少
示例
非触发
init(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
init (a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
`init`(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
init?(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
init?<T>(a: T, b: Int, c: Int, d: Int, e: Int, f: Int) {}
init?<T: String>(a: T, b: Int, c: Int, d: Int, e: Int, f: Int) {}
func f2(p1: Int, p2: Int) { }
func f(a: Int, b: Int, c: Int, d: Int, x: Int = 42) {}
func f(a: [Int], b: Int, c: Int, d: Int, f: Int) -> [Int] {
let s = a.flatMap { $0 as? [String: Int] } ?? []}}
override func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
触发
↓func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
↓func initialValue(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
↓func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int = 2, g: Int) {}
struct Foo {
init(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
↓func bar(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}}
Generic Type Name
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
generic_type_name |
是 |
否 |
idiomatic |
否 |
3.0.0 |
泛型应当只包含字母,首字母大写并且不超过20个字符。
示例
非触发
func foo<T>() {}
func foo<T>() -> T {}
func foo<T, U>(param: U) -> T {}
func foo<T: Hashable, U: Rule>(param: U) -> T {}
struct Foo<T> {}
class Foo<T> {}
enum Foo<T> {}
func run(_ options: NoOptions<CommandantError<()>>) {}
func foo(_ options: Set<type>) {}
func < <T: Comparable>(lhs: T?, rhs: T?) -> Bool
func configureWith(data: Either<MessageThread, (project: Project, backing: Backing)>)
typealias StringDictionary<T> = Dictionary<String, T>
typealias BackwardTriple<T1, T2, T3> = (T3, T2, T1)
typealias DictionaryOfStrings<T : Hashable> = Dictionary<T, String>
触发
func foo<↓T_Foo>() {}
func foo<T, ↓U_Foo>(param: U_Foo) -> T {}
func foo<↓TTTTTTTTTTTTTTTTTTTTT>() {}
func foo<↓type>() {}
typealias StringDictionary<↓T_Foo> = Dictionary<String, T_Foo>
typealias BackwardTriple<T1, ↓T2_Bar, T3> = (T3, T2_Bar, T1)
typealias DictionaryOfStrings<↓T_Foo: Hashable> = Dictionary<T_Foo, String>
class Foo<↓T_Foo> {}
class Foo<T, ↓U_Foo> {}
class Foo<↓T_Foo, ↓U_Foo> {}
class Foo<↓TTTTTTTTTTTTTTTTTTTTT> {}
class Foo<↓type> {}
struct Foo<↓T_Foo> {}
struct Foo<T, ↓U_Foo> {}
struct Foo<↓T_Foo, ↓U_Foo> {}
struct Foo<↓TTTTTTTTTTTTTTTTTTTTT> {}
struct Foo<↓type> {}
enum Foo<↓T_Foo> {}
enum Foo<T, ↓U_Foo> {}
enum Foo<↓T_Foo, ↓U_Foo> {}
enum Foo<↓TTTTTTTTTTTTTTTTTTTTT> {}
enum Foo<↓type> {}
Identical Operands
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
identical_operands |
否 |
否 |
lint |
否 |
3.0.0 |
比较两个相同的对象是错误的行为
示例
非触发
1 == 2
foo == bar
prefixedFoo == foo
foo.aProperty == foo.anotherProperty
self.aProperty == self.anotherProperty
"1 == 1"
self.aProperty == aProperty
lhs.aProperty == rhs.aProperty
lhs.identifier == rhs.identifier
i == index
$0 == 0
keyValues?.count ?? 0 == 0
1 != 2
foo != bar
prefixedFoo != foo
foo.aProperty != foo.anotherProperty
self.aProperty != self.anotherProperty
"1 != 1"
self.aProperty != aProperty
lhs.aProperty != rhs.aProperty
lhs.identifier != rhs.identifier
i != index
$0 != 0
keyValues?.count ?? 0 != 0
1 === 2
foo === bar
prefixedFoo === foo
foo.aProperty === foo.anotherProperty
self.aProperty === self.anotherProperty
"1 === 1"
self.aProperty === aProperty
lhs.aProperty === rhs.aProperty
lhs.identifier === rhs.identifier
i === index
$0 === 0
keyValues?.count ?? 0 === 0
1 !== 2
foo !== bar
prefixedFoo !== foo
foo.aProperty !== foo.anotherProperty
self.aProperty !== self.anotherProperty
"1 !== 1"
self.aProperty !== aProperty
lhs.aProperty !== rhs.aProperty
lhs.identifier !== rhs.identifier
i !== index
$0 !== 0
keyValues?.count ?? 0 !== 0
1 > 2
foo > bar
prefixedFoo > foo
foo.aProperty > foo.anotherProperty
self.aProperty > self.anotherProperty
"1 > 1"
self.aProperty > aProperty
lhs.aProperty > rhs.aProperty
lhs.identifier > rhs.identifier
i > index
$0 > 0
keyValues?.count ?? 0 > 0
1 >= 2
foo >= bar
prefixedFoo >= foo
foo.aProperty >= foo.anotherProperty
self.aProperty >= self.anotherProperty
"1 >= 1"
self.aProperty >= aProperty
lhs.aProperty >= rhs.aProperty
lhs.identifier >= rhs.identifier
i >= index
$0 >= 0
keyValues?.count ?? 0 >= 0
1 < 2
foo < bar
prefixedFoo < foo
foo.aProperty < foo.anotherProperty
self.aProperty < self.anotherProperty
"1 < 1"
self.aProperty < aProperty
lhs.aProperty < rhs.aProperty
lhs.identifier < rhs.identifier
i < index
$0 < 0
keyValues?.count ?? 0 < 0
1 <= 2
foo <= bar
prefixedFoo <= foo
foo.aProperty <= foo.anotherProperty
self.aProperty <= self.anotherProperty
"1 <= 1"
self.aProperty <= aProperty
lhs.aProperty <= rhs.aProperty
lhs.identifier <= rhs.identifier
i <= index
$0 <= 0
keyValues?.count ?? 0 <= 0
func evaluate(_ mode: CommandMode) -> Result<AutoCorrectOptions, CommandantError<CommandantError<()>>>
触发
↓1 == 1
↓foo == foo
↓foo.aProperty == foo.aProperty
↓self.aProperty == self.aProperty
↓$0 == $0
↓1 != 1
↓foo != foo
↓foo.aProperty != foo.aProperty
↓self.aProperty != self.aProperty
↓$0 != $0
↓1 === 1
↓foo === foo
↓foo.aProperty === foo.aProperty
↓self.aProperty === self.aProperty
↓$0 === $0
↓1 !== 1
↓foo !== foo
↓foo.aProperty !== foo.aProperty
↓self.aProperty !== self.aProperty
↓$0 !== $0
↓1 > 1
↓foo > foo
↓foo.aProperty > foo.aProperty
↓self.aProperty > self.aProperty
↓$0 > $0
↓1 >= 1
↓foo >= foo
↓foo.aProperty >= foo.aProperty
↓self.aProperty >= self.aProperty
↓$0 >= $0
↓1 < 1
↓foo < foo
↓foo.aProperty < foo.aProperty
↓self.aProperty < self.aProperty
↓$0 < $0
↓1 <= 1
↓foo <= foo
↓foo.aProperty <= foo.aProperty
↓self.aProperty <= self.aProperty
↓$0 <= $0
Identifier Name
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
identifier_name |
是 |
否 |
style |
否 |
3.0.0 |
标识符名称应当只包含字母并且以小写字母开头,或者只包含大写字母。当定义static或者let时,可以以大写字母开头。变量名长度不应太长或太短。
示例
非触发
let myLet = 0
var myVar = 0
private let _myLet = 0
class Abc { static let MyLet = 0 }
let URL: NSURL? = nil
let XMLString: String? = nil
override var i = 0
enum Foo { case myEnum }
func isOperator(name: String) -> Bool
func typeForKind(_ kind: SwiftDeclarationKind) -> String
func == (lhs: SyntaxToken, rhs: SyntaxToken) -> Bool
override func IsOperator(name: String) -> Bool
enum Foo { case `private` }
enum Foo { case value(String) }
触发
↓let MyLet = 0
↓let _myLet = 0
private ↓let myLet_ = 0
↓let myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0
↓var myExtremelyVeryVeryVeryVeryVeryVeryLongVar = 0
private ↓let _myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0
↓let i = 0
↓var id = 0
private ↓let _i = 0
↓func IsOperator(name: String) -> Bool
enum Foo { case ↓MyEnum }
Implicit Getter
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
implicit_getter |
是 |
否 |
style |
否 |
3.0.0 |
算值可读属性和下标语法应该避免使用get关键字
示例
非触发
class Foo {
var foo: Int {
get { return 3 }
set { _abc = newValue }
}
}
class Foo {
var foo: Int {
return 20
}
}
class Foo {
static var foo: Int {
return 20
}
}
class Foo {
static var foo: Int {
get { return 3 }
set { _abc = newValue }
}
}
class Foo {
var foo: Int
}
class Foo {
var foo: Int {
return getValueFromDisk()
}
}
class Foo {
var foo: String {
return "get"
}
}
protocol Foo {
var foo: Int { get }
protocol Foo {
var foo: Int { get set }
class Foo {
var foo: Int {
struct Bar {
var bar: Int {
get { return 1 }
set { _ = newValue }
}
}
return Bar().bar
}
}
var _objCTaggedPointerBits: UInt {
@inline(__always) get { return 0 }
}
var next: Int? {
mutating get {
defer { self.count += 1 }
return self.count
}
}
class Foo {
subscript(i: Int) -> Int {
return 20
}
}
class Foo {
subscript(i: Int) -> Int {
get { return 3 }
set { _abc = newValue }
}
}
protocol Foo {
subscript(i: Int) -> Int { get }
}
protocol Foo {
subscript(i: Int) -> Int { get set }
}
触发
class Foo {
var foo: Int {
↓get {
return 20
}
}
}
class Foo {
var foo: Int {
↓get{ return 20 }
}
}
class Foo {
static var foo: Int {
↓get {
return 20
}
}
}
var foo: Int {
↓get { return 20 }
}
class Foo {
@objc func bar() {}
var foo: Int {
↓get {
return 20
}
}
}
class Foo {
subscript(i: Int) -> Int {
↓get {
return 20
}
}
}
补充
这里并不是说不能使用get关键字,而是说get应当以隐式调用的方式存在,显示调用并不是那么的合理,因为限定了可读。
Properties
Subscripts
Implicit Return
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
implicit_return |
否 |
是 |
style |
否 |
3.0.0 |
闭包中优先使用隐式返回。
示例
非触发
foo.map { $0 + 1 }
foo.map({ $0 + 1 })
foo.map { value in value + 1 }
func foo() -> Int {
return 0
}
if foo {
return 0
}
var foo: Bool { return true }
触发
foo.map { value in
↓return value + 1
}
foo.map {
↓return $0 + 1
}
foo.map({ ↓return $0 + 1})
[1, 2].first(where: {
↓return true
})
Implicitly Unwrapped Optional
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
implicitly_unwrapped_optional |
否 |
否 |
idiomatic |
否 |
3.0.0 |
尽可能少的使用隐式解包类型
示例
非触发
@IBOutlet private var label: UILabel!
@IBOutlet var label: UILabel!
@IBOutlet var label: [UILabel!]
if !boolean {}
let int: Int? = 42
let int: Int? = nil
触发
let label: UILabel!
let IBOutlet: UILabel!
let labels: [UILabel!]
var ints: [Int!] = [42, nil, 42]
let label: IBOutlet!
let int: Int! = 42
let int: Int! = nil
var int: Int! = 42
let int: ImplicitlyUnwrappedOptional<Int>
let collection: AnyCollection<Int!>
func foo(int: Int!) {}
补充
隐式解包Optional
Inert Defer
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
inert_defer |
是 |
否 |
lint |
否 |
3.0.0 |
如果defer写在最后,应该确保无论如何都要执行到它。
示例
非触发
func example3() {
defer { /* deferred code */ }
print("other code")
}
func example4() {
if condition {
defer { /* deferred code */ }
print("other code")
}
}
触发
func example0() {
↓defer { /* deferred code */ }
}
func example1() {
↓defer { /* deferred code */ }
// comment
}
func example2() {
if condition {
↓defer { /* deferred code */ }
// comment
}
}
补充
guard&defer
个人理解:defer类似与try..catch中的final,不同的是defer可以单独来写,比较常见的场景是资源的关闭、释放。但要确保defer可以被执行到,而不是方法提前return。惰性的
Is Disjoint
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
is_disjoint |
是 |
否 |
idiomatic |
否 |
3.0.0 |
优先使用Set.isDisjoint(with:)
而不是Set.intersection(_:).isEmpty
示例
非触发
_ = Set(syntaxKinds).isDisjoint(with: commentAndStringKindsSet)
let isObjc = !objcAttributes.isDisjoint(with: dictionary.enclosedSwiftAttributes)
_ = Set(syntaxKinds).intersection(commentAndStringKindsSet)
_ = !objcAttributes.intersection(dictionary.enclosedSwiftAttributes)
触发
_ = Set(syntaxKinds).↓intersection(commentAndStringKindsSet).isEmpty
let isObjc = !objcAttributes.↓intersection(dictionary.enclosedSwiftAttributes).isEmpty
补充
intersection(_:)
isDisjoint(with:)
Joined Default Parameter
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
joined_default_parameter |
否 |
是 |
idiomatic |
否 |
3.0.0 |
不鼓励使用默认分隔符
示例
非触发
let foo = bar.joined()
let foo = bar.joined(separator: ",")
let foo = bar.joined(separator: toto)
触发
let foo = bar.joined(↓separator: "")
let foo = bar.filter(toto)
.joined(↓separator: "")
func foo() -> String {
return ["1", "2"].joined(↓separator: "")
}
Large Tuple
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
large_tuple |
是 |
否 |
metrics |
否 |
3.0.0 |
元组不应该包含过多成员,过多成员的情况应当使用自定义类型。
示例
非触发
let foo: (Int, Int)
let foo: (start: Int, end: Int)
let foo: (Int, (Int, String))
func foo() -> (Int, Int)
func foo() -> (Int, Int) {}
func foo(bar: String) -> (Int, Int)
func foo(bar: String) -> (Int, Int) {}
func foo() throws -> (Int, Int)
func foo() throws -> (Int, Int) {}
let foo: (Int, Int, Int) -> Void
let foo: (Int, Int, Int) throws -> Void
func foo(bar: (Int, String, Float) -> Void)
func foo(bar: (Int, String, Float) throws -> Void)
var completionHandler: ((_ data: Data?, _ resp: URLResponse?, _ e: NSError?) -> Void)!
func getDictionaryAndInt() -> (Dictionary<Int, String>, Int)?
func getGenericTypeAndInt() -> (Type<Int, String, Float>, Int)?
触发
↓let foo: (Int, Int, Int)
↓let foo: (start: Int, end: Int, value: String)
↓let foo: (Int, (Int, Int, Int))
func foo(↓bar: (Int, Int, Int))
func foo() -> ↓(Int, Int, Int)
func foo() -> ↓(Int, Int, Int) {}
func foo(bar: String) -> ↓(Int, Int, Int)
func foo(bar: String) -> ↓(Int, Int, Int) {}
func foo() throws -> ↓(Int, Int, Int)
func foo() throws -> ↓(Int, Int, Int) {}
func foo() throws -> ↓(Int, ↓(String, String, String), Int) {}
func getDictionaryAndInt() -> (Dictionary<Int, ↓(String, String, String)>, Int)?
Leading Whitespace
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
leand_whitespace |
是 |
是 |
style |
否 |
3.0.0 |
文件不应该包含空行
示例
非触发
//
触发
//
补充
不赞同,有时候空行是为了代码美观,看着舒服,强迫不留空很难受。
Legacy CGGeometry Functions
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
legacy_cggeometry_functions |
是 |
是 |
idiomatic |
否 |
3.0.0 |
结构体扩展的属性和方法优于遗留的方法
示例
非触发
rect.width
rect.height
rect.minX
rect.midX
rect.maxX
rect.minY
rect.midY
rect.maxY
rect.isNull
rect.isEmpty
rect.isInfinite
rect.standardized
rect.integral
rect.insetBy(dx: 5.0, dy: -7.0)
rect.offsetBy(dx: 5.0, dy: -7.0)
rect1.union(rect2)
rect1.intersect(rect2)
rect1.contains(rect2)
rect.contains(point)
rect1.intersects(rect2)
触发
↓CGRectGetWidth(rect)
↓CGRectGetHeight(rect)
↓CGRectGetMinX(rect)
↓CGRectGetMidX(rect)
↓CGRectGetMaxX(rect)
↓CGRectGetMinY(rect)
↓CGRectGetMidY(rect)
↓CGRectGetMaxY(rect)
↓CGRectIsNull(rect)
↓CGRectIsEmpty(rect)
↓CGRectIsInfinite(rect)
↓CGRectStandardize(rect)
↓CGRectIntegral(rect)
↓CGRectInset(rect, 10, 5)
↓CGRectOffset(rect, -2, 8.3)
↓CGRectUnion(rect1, rect2)
↓CGRectIntersection(rect1, rect2)
↓CGRectContainsRect(rect1, rect2)
↓CGRectContainsPoint(rect, point)
↓CGRectIntersectsRect(rect1, rect2)
legacy Constant
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
legacy_constant |
是 |
是 |
idiomatic |
否 |
3.0.0 |
结构体范围内的常量优于遗留的全局常量
示例
非触发
CGRect.infinite
CGPoint.zero
CGRect.zero
CGSize.zero
NSPoint.zero
NSRect.zero
NSSize.zero
CGRect.null
CGFloat.pi
Float.pi
触发
↓CGRectInfinite
↓CGPointZero
↓CGRectZero
↓CGSizeZero
↓NSZeroPoint
↓NSZeroRect
↓NSZeroSize
↓CGRectNull
↓CGFloat(M_PI)
↓Float(M_PI)
Legacy Constructor
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
legacy_constructor |
是 |
是 |
idiocmatic |
否 |
3.0.0 |
Swift的构造方法优于遗留的构造方法
示例
非触发
CGPoint(x: 10, y: 10)
CGPoint(x: xValue, y: yValue)
CGSize(width: 10, height: 10)
CGSize(width: aWidth, height: aHeight)
CGRect(x: 0, y: 0, width: 10, height: 10)
CGRect(x: xVal, y: yVal, width: aWidth, height: aHeight)
CGVector(dx: 10, dy: 10)
CGVector(dx: deltaX, dy: deltaY)
NSPoint(x: 10, y: 10)
NSPoint(x: xValue, y: yValue)
NSSize(width: 10, height: 10)
NSSize(width: aWidth, height: aHeight)
NSRect(x: 0, y: 0, width: 10, height: 10)
NSRect(x: xVal, y: yVal, width: aWidth, height: aHeight)
NSRange(location: 10, length: 1)
NSRange(location: loc, length: len)
UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 10)
UIEdgeInsets(top: aTop, left: aLeft, bottom: aBottom, right: aRight)
NSEdgeInsets(top: 0, left: 0, bottom: 10, right: 10)
NSEdgeInsets(top: aTop, left: aLeft, bottom: aBottom, right: aRight)
UIOffset(horizontal: 0, vertical: 10)
UIOffset(horizontal: horizontal, vertical: vertical)
触发
↓CGPointMake(10, 10)
↓CGPointMake(xVal, yVal)
↓CGPointMake(calculateX(), 10)
↓CGSizeMake(10, 10)
↓CGSizeMake(aWidth, aHeight)
↓CGRectMake(0, 0, 10, 10)
↓CGRectMake(xVal, yVal, width, height)
↓CGVectorMake(10, 10)
↓CGVectorMake(deltaX, deltaY)
↓NSMakePoint(10, 10)
↓NSMakePoint(xVal, yVal)
↓NSMakeSize(10, 10)
↓NSMakeSize(aWidth, aHeight)
↓NSMakeRect(0, 0, 10, 10)
↓NSMakeRect(xVal, yVal, width, height)
↓NSMakeRange(10, 1)
↓NSMakeRange(loc, len)
↓UIEdgeInsetsMake(0, 0, 10, 10)
↓UIEdgeInsetsMake(top, left, bottom, right)
↓NSEdgeInsetsMake(0, 0, 10, 10)
↓NSEdgeInsetsMake(top, left, bottom, right)
↓CGVectorMake(10, 10)
↓NSMakeRange(10, 1)
↓UIOffsetMake(0, 10)
↓UIOffsetMake(horizontal, vertical)
Legacy NSGeometry Functions
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
legacy_nsgeometry |
是 |
是 |
idiomatic |
否 |
3.0.0 |
结构体扩展的属性和方法优于遗留的方法
示例
非触发
rect.width
rect.height
rect.minX
rect.midX
rect.maxX
rect.minY
rect.midY
rect.maxY
rect.isEmpty
rect.integral
rect.insetBy(dx: 5.0, dy: -7.0)
rect.offsetBy(dx: 5.0, dy: -7.0)
rect1.union(rect2)
rect1.intersect(rect2)
rect1.contains(rect2)
rect.contains(point)
rect1.intersects(rect2)
触发
↓NSWidth(rect)
↓NSHeight(rect)
↓NSMinX(rect)
↓NSMidX(rect)
↓NSMaxX(rect)
↓NSMinY(rect)
↓NSMidY(rect)
↓NSMaxY(rect)
↓NSEqualRects(rect1, rect2)
↓NSEqualSizes(size1, size2)
↓NSEqualPoints(point1, point2)
↓NSEdgeInsetsEqual(insets2, insets2)
↓NSIsEmptyRect(rect)
↓NSIntegralRect(rect)
↓NSInsetRect(rect, 10, 5)
↓NSOffsetRect(rect, -2, 8.3)
↓NSUnionRect(rect1, rect2)
↓NSIntersectionRect(rect1, rect2)
↓NSContainsRect(rect1, rect2)
↓NSPointInRect(rect, point)
↓NSIntersectsRect(rect1, rect2)
Legacy Random
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
legacy_random |
Disabled |
否 |
idiomatic |
否 |
4.2.0 |
优先使用type.random(in:)
而不是遗留的方法
示例
非触发
Int.random(in: 0..<10)
Double.random(in: 8.6...111.34)
Float.random(in: 0 ..< 1)
触发
↓arc4random(10)
↓arc4random_uniform(83)
↓drand48(52)
Variable Declaration Whitespace
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
let_var_whitespace |
否 |
否 |
style |
否 |
3.0.0 |
let
和var
关键字声明应该和其他语句用空白行分开
示例
非触发
let a = 0
var x = 1
x = 2
a = 5
var x = 1
struct X {
var a = 0
}
let a = 1 +
2
let b = 5
var x: Int {
return 0
}
var x: Int {
let a = 0
return a
}
#if os(macOS)
let a = 0
#endif
@available(swift 4)
let a = 0
class C {
@objc
var s: String = ""
}
class C {
@objc
func a() {}
}
class C {
var x = 0
lazy
var y = 0
}
@available(OSX, introduced: 10.6)
@available(*, deprecated)
var x = 0
// swiftlint:disable superfluous_disable_command
// swiftlint:disable force_cast
let x = bar as! Bar
var x: Int {
let a = 0
return a
}
触发
var x = 1
↓x = 2
a = 5
↓var x = 1
struct X {
let a
↓func x() {}
}
var x = 0
↓@objc func f() {}
var x = 0
↓@objc
func f() {}
@objc func f() {
}
↓var x = 0
Line Length
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
line_length |
是 |
否 |
metrics |
否 |
3.0.0 |
一行不应包含过多的字符
示例
非触发
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")
触发
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")
补充
举例存疑 貌似例子都是一样的。。。
查看源码 可知默认配置是一行不要超过120个字符
Literal Expression End Indentation
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
literal_expression_end_indentation |
否 |
是 |
style |
否 |
3.0.0 |
Array
和Dictionary
的开头和末尾应当有相同的缩进
示例
非触发
[1, 2, 3]
[1,
2
]
[
1,
2
]
[
1,
2]
let x = [
1,
2
]
[key: 2, key2: 3]
[key: 1,
key2: 2
]
[
key: 0,
key2: 20
]
触发
let x = [
1,
2
↓]
let x = [
1,
2
↓]
let x = [
key: value
↓]
Lower ACL than parent
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
lower_acl_than_parent |
否 |
否 |
lint |
否 |
3.0.0 |
确保定义的(属性、方法)的访问控制权限小于包裹它的(类、结构体)访问控制权限
示例
非触发
public struct Foo { public func bar() {} }
internal struct Foo { func bar() {} }
struct Foo { func bar() {} }
open class Foo { public func bar() {} }
open class Foo { open func bar() {} }
fileprivate struct Foo { private func bar() {} }
private struct Foo { private func bar(id: String) }
extension Foo { public func bar() {} }
private struct Foo { fileprivate func bar() {} }
private func foo(id: String) {}
触发
struct Foo { public func bar() {} }
enum Foo { public func bar() {} }
public class Foo { open func bar() }
class Foo { public private(set) var bar: String? }
Mark
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
mark |
是 |
是 |
lint |
否 |
3.0.0 |
MARK 标记应当使用正确的格式 比如:// MARK: ...
或 // MARK: -...
示例
非触发
// MARK: good
// MARK: - good
// MARK: -
// BOOKMARK
//BOOKMARK
// BOOKMARKS
触发
↓//MARK: bad
↓// MARK:bad
↓//MARK:bad
↓// MARK: bad
↓// MARK: bad
↓// MARK: -bad
↓// MARK:- bad
↓// MARK:-bad
↓//MARK: - bad
↓//MARK:- bad
↓//MARK: -bad
↓//MARK:-bad
↓//Mark: bad
↓// Mark: bad
↓// MARK bad
↓//MARK bad
↓// MARK - bad
↓//MARK : bad
↓// MARKL:
↓// MARKR
↓// MARKK -
↓//MARK:- Top-Level bad mark
↓//MARK:- Another bad mark
struct MarkTest {}
↓// MARK:- Bad mark
extension MarkTest {}
Missing Docs
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
missing_docs |
否 |
否 |
lint |
否 |
4.1.0 |
声明必须有文档
示例
非触发
/// docs
public class A {
/// docs
public func b() {}
}
/// docs
public class B: A { override public func b() {} }
import Foundation
/// docs
public class B: NSObject {
// no docs
override public var description: String { fatalError() } }
触发
public func a() {}
// regular comment
public func a() {}
/* regular comment */
public func a() {}
/// docs
public protocol A {
// no docs
var b: Int { get } }
/// docs
public struct C: A {
public let b: Int
}
Modifier Order
标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
modifier_order |
否 |
否 |
style |
否 |
4.1.0 |
修饰符的顺序应该是一致的
示例
非触发
public class Foo {
public convenience required init() {}
}
public class Foo {
public static let bar = 42
}
public class Foo {
public static var bar: Int {
return 42 }}
public class Foo {
public class var bar: Int {
return 42
}
}
public class Bar {
public class var foo: String {
return "foo"
}
}
public class Foo: Bar {
override public final class var foo: String {
return "bar"
}
}
open class Bar {
public var foo: Int? {
return 42
}
}
open class Foo: Bar {
override public var foo: Int? {
return 43
}
}
open class Bar {
open class func foo() -> Int {
return 42
}
}
class Foo: Bar {
override open class func foo() -> Int {
return 43
}
}
protocol Foo: class {}
class Bar {
public private(set) weak var foo: Foo?
}
@objc
public final class Foo: NSObject {}
@objcMembers
public final class Foo: NSObject {}
@objc
override public private(set) weak var foo: Bar?
@objc
public final class Foo: NSObject {}
@objc
open final class Foo: NSObject {
open weak var weakBar: NSString? = nil
}
public final class Foo {}
class Bar {
func bar() {}
}
internal class Foo: Bar {
override internal func bar() {}
}
public struct Foo {
internal weak var weakBar: NSObject? = nil
}
class Foo {
internal lazy var bar: String = "foo"
}
触发
class Foo {
convenience required public init() {}
}
public class Foo {
static public let bar = 42
}
public class Foo {
static public var bar: Int {
return 42
}
}
public class Foo {
class public var bar: Int {
return 42
}
}
public class RootFoo {
class public var foo: String {
return "foo"
}
}
public class Foo: RootFoo {
override final class public var foo: String {
return "bar"
}
}
open class Bar {
public var foo: Int? {
return 42
}
}
open class Foo: Bar {
public override var foo: Int? {
return 43
}
}
protocol Foo: class {}
class Bar {
private(set) public weak var foo: Foo?
}
open class Bar {
open class func foo() -> Int {
return 42
}
}
class Foo: Bar {
class open override func foo() -> Int {
return 43
}
}
open class Bar {
open class func foo() -> Int {
return 42
}
}
class Foo: Bar {
open override class func foo() -> Int {
return 43
}
}
@objc
final public class Foo: NSObject {}
@objcMembers
final public class Foo: NSObject {}
@objc
final open class Foo: NSObject {
weak open var weakBar: NSString? = nil
}
final public class Foo {}
internal class Foo: Bar {
internal override func bar() {}
}
public struct Foo {
weak internal var weakBar: NSObjetc? = nil
}
class Foo {
lazy internal var bar: String = "foo"
}