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?) -> Boolfunc 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 == 2foo == barprefixedFoo == foofoo.aProperty == foo.anotherPropertyself.aProperty == self.anotherProperty"1 == 1"self.aProperty == aPropertylhs.aProperty == rhs.aPropertylhs.identifier == rhs.identifieri == index$0 == 0keyValues?.count ?? 0 == 01 != 2foo != barprefixedFoo != foofoo.aProperty != foo.anotherPropertyself.aProperty != self.anotherProperty"1 != 1"self.aProperty != aPropertylhs.aProperty != rhs.aPropertylhs.identifier != rhs.identifieri != index$0 != 0keyValues?.count ?? 0 != 01 === 2foo === barprefixedFoo === foofoo.aProperty === foo.anotherPropertyself.aProperty === self.anotherProperty"1 === 1"self.aProperty === aPropertylhs.aProperty === rhs.aPropertylhs.identifier === rhs.identifieri === index$0 === 0keyValues?.count ?? 0 === 01 !== 2foo !== barprefixedFoo !== foofoo.aProperty !== foo.anotherPropertyself.aProperty !== self.anotherProperty"1 !== 1"self.aProperty !== aPropertylhs.aProperty !== rhs.aPropertylhs.identifier !== rhs.identifieri !== index$0 !== 0keyValues?.count ?? 0 !== 01 > 2foo > barprefixedFoo > foofoo.aProperty > foo.anotherPropertyself.aProperty > self.anotherProperty"1 > 1"self.aProperty > aPropertylhs.aProperty > rhs.aPropertylhs.identifier > rhs.identifieri > index$0 > 0keyValues?.count ?? 0 > 01 >= 2foo >= barprefixedFoo >= foofoo.aProperty >= foo.anotherPropertyself.aProperty >= self.anotherProperty"1 >= 1"self.aProperty >= aPropertylhs.aProperty >= rhs.aPropertylhs.identifier >= rhs.identifieri >= index$0 >= 0keyValues?.count ?? 0 >= 01 < 2foo < barprefixedFoo < foofoo.aProperty < foo.anotherPropertyself.aProperty < self.anotherProperty"1 < 1"self.aProperty < aPropertylhs.aProperty < rhs.aPropertylhs.identifier < rhs.identifieri < index$0 < 0keyValues?.count ?? 0 < 01 <= 2foo <= barprefixedFoo <= foofoo.aProperty <= foo.anotherPropertyself.aProperty <= self.anotherProperty"1 <= 1"self.aProperty <= aPropertylhs.aProperty <= rhs.aPropertylhs.identifier <= rhs.identifieri <= index$0 <= 0keyValues?.count ?? 0 <= 0func 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 = 0var myVar = 0private let _myLet = 0class Abc { static let MyLet = 0 }let URL: NSURL? = nillet XMLString: String? = niloverride var i = 0enum Foo { case myEnum }func isOperator(name: String) -> Boolfunc typeForKind(_ kind: SwiftDeclarationKind) -> Stringfunc == (lhs: SyntaxToken, rhs: SyntaxToken) -> Booloverride func IsOperator(name: String) -> Boolenum Foo { case `private` }enum Foo { case value(String) }
触发
↓let MyLet = 0↓let _myLet = 0private ↓let myLet_ = 0↓let myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0↓var myExtremelyVeryVeryVeryVeryVeryVeryLongVar = 0private ↓let _myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0↓let i = 0↓var id = 0private ↓let _i = 0↓func IsOperator(name: String) -> Boolenum 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? = 42let int: Int? = nil
触发
let label: UILabel!let IBOutlet: UILabel!let labels: [UILabel!]var ints: [Int!] = [42, nil, 42]let label: IBOutlet!let int: Int! = 42let int: Int! = nilvar int: Int! = 42let 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).isEmptylet 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) -> Voidlet foo: (Int, Int, Int) throws -> Voidfunc 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.widthrect.heightrect.minXrect.midXrect.maxXrect.minYrect.midYrect.maxYrect.isNullrect.isEmptyrect.isInfiniterect.standardizedrect.integralrect.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.infiniteCGPoint.zeroCGRect.zeroCGSize.zeroNSPoint.zeroNSRect.zeroNSSize.zeroCGRect.nullCGFloat.piFloat.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.widthrect.heightrect.minXrect.midXrect.maxXrect.minYrect.midYrect.maxYrect.isEmptyrect.integralrect.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 = 0var x = 1x = 2a = 5var x = 1struct X { var a = 0}let a = 1 + 2let b = 5var x: Int { return 0}var x: Int { let a = 0 return a}#if os(macOS)let a = 0#endif@available(swift 4)let a = 0class 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_castlet x = bar as! Barvar x: Int { let a = 0 return a}
触发
var x = 1↓x = 2a = 5↓var x = 1struct 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 markstruct MarkTest {}↓// MARK:- Bad markextension MarkTest {}
Missing Docs
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
missing_docs |
否 |
否 |
lint |
否 |
4.1.0 |
声明必须有文档
示例
非触发
/// docspublic class A {/// docspublic func b() {}}/// docspublic class B: A { override public func b() {} }import Foundation/// docspublic class B: NSObject {// no docsoverride public var description: String { fatalError() } }
触发
public func a() {}// regular commentpublic func a() {}/* regular comment */public func a() {}/// docspublic protocol A {// no docsvar b: Int { get } }/// docspublic 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" }