SwiftLint 的理解和使用
目的:
iOS APP在下一个版本会用swift开发,在多人开发中,即使有官网的规范模板.但每个人的代码风格和规范难以做到完全一致,对后期项目维护会增加一定的困难,这里主要是对一个规范代码风格工具swiftlint使用的一个评估。
前言:
随着项目的扩大,依靠人工codereview来保证项目的质量,越来越不现实,这时就有必要借助于一种自动化的代码审查工具:程序静态分析。
程序静态分析(Program Static Analysis)是指在不运行代码的方式下,通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描,验证代码是否满足规范性、安全性、可靠性、可维护性等指标的一种代码分析技术。(来自百度百科)
介绍:
SwiftLint 是 realm 公司开发的一个插件,专门用于管理 Swift 代码的规范。Swift 是 Apple 在 2014 年推出的用于 Apple 系列产品开发的新一代编程语言,目标是取代原来的 Object-C . 和其他编程语言,比如 C、Java、Python 等一样,Swift 中也规定了基本的编码规范,用于定义采用 Swift 编程时, 对于「美」的倾向。基本标准已经在git 开源Swift 编程官网规范。realm 公司开发 SwiftLint 插件,就是用来规范开发者在编程时对 Swift 规范进行贯彻执行。
这里简要介绍下 realm 公司。它主要的开发产品是用于移动端的数据库,可以跨多个现有的移动端系统(Android/iOS 等),API 简单易用,而且效率较高, 号称现在拥有 10 亿用户。它诞生于美国著名孵化器 Y combinator (就是年初从百度辞职的副董事长陆奇新加入的公司)项目。
SwiftLint 的工作原理是检查 Swift 代码编译过程中的 AST 和 SourceKit 环节,从而可以摆脱不同版本 Swift 语法变化的影响。AST 是编译前端形成的抽象语法书(Abstract Symbolic Tree), SourceKit 过程用来对 AST 进行代码优化,减少内存开销,提高执行效率。如果对编译过程理解不太清楚,可以参考:AST和LLVM优点
SwiftLint 是一个用于强制检查 Swift 代码风格和规定的一个工具。它的实现是 Hook 了 Clang 和 SourceKit 从而能够使用AST来表示源代码文件的更多精确结果。Clange我们了解了,那SourceKit是干什么用的?
SourceKit包含在Swift项目的主仓库,它是一套工具集,支持Swift的大多数源代码操作特性:源代码解析、语法突出显示、排版、自动完成、跨语言头生成等工作。
安装使用:
安装:
1:可以使用homebrew进行全局安装:
需要在已经安装了homebrew 前提下:
打开终端输入:
brew install SwiftLint
如果已安装SwiftLint ,可更新至当前最新版本:0.40.1
更新命令:
brew upgrade swiftlint
查看当前版本号
$ swiftlint version
//查看所有命令
$ swiftlint help
//忽略空格导致的警告和错误
$ swiftlint autocorrect
//输出所有的警告和错误
$ swiftlint lint
//查看所有可获得的规则以及对应的 ID
$ swiftlint rules
如果我们想将此次分析生成一份报告,也是可以的(该命令是通过homebrew安装的swiftlint
# reporter type (xcode, json, csv, checkstyle, junit, html, emoji, sonarqube, markdown)
$ swiftlint lint--reporter html>swiftlint.html
2:使用cocoaPods安装:
pod ’SwiftLint’,这个方式可以安装不同版本的SwiftLint但是只能针对单个项目.
pod 'SwiftLint','0.39.2' 或者指定调用版本;
3:SwiftLint支持pkg安装包安装.
使用:
安装完成后,需要在Xcode中的Build Phases新建一个 Run Script Phase 配置项添加脚本,
3.1:全局安装添加脚本
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
3.2:CocoaPods安装添加脚本
"${PODS_ROOT}/SwiftLint/swiftlint"
这个脚本在安装了swiftlint后每次运行都会执行,如果没有安装swiftlint,会警告异常或者报错.
3.3:.swiftlint.yml:
这是一个配置文件,可以通过这个配置文件来自定义规则或者修改默认规则.
这里是自用的一个.swiftlint.yml 配置内容
excluded: # 执行 linting 时忽略的路径。 优先级比 `included` 更高。
- Pods
disabled_rules: #执行时排除掉的规则
- identifier_name #命名规则必须按照驼峰原则,与后台传的Json字段命名冲突,建议排除掉
- trailing_whitespace #每一个空行不能有空格,会与Xcode换行后自动对齐生成的空格冲突,建议排除掉
- vertical_whitespace #垂直方向上的空格行,限制为一行(注释除外)
- trailing_newline #末尾空行,文件末尾应该有一个空行
- unused_closure_parameter #函数的参数必须被使用
- class_delegate_protocol #delegate protocol 应该被设定为 class-only,才能被弱引用
- weak_delegate #代理要设置为弱引用和上面的
- control_statement #if while 等判断条件不要用括号 括起来,另外注意条件出的空格
- leading_whitespace #文件末尾不应该存在空格符
- statement_position #else and catch 应该与 } 在同一行,以空格间隔
- orphaned_doc_comment #注释要写在声明中
- type_body_length #类型体长度。类型体长度不应该跨越太多行,超过200行给warning,超过350行给error,可自定义enum或struct
- notification_center_detachment #移除通知要在 'deinit'中
# variable_name与identifier_name冲突,启用后identifier_name需关闭,否则build不通过。
# - variable_name # 变量名应该只包含字符数字字符, 并且只能以小写字母开头或者应该只包含大写字母。此外,当变量名被声明为static(静态)变量时或者immutable不可变的时候,这时或许可以以一个大写字母开头。最后,变量名不应该太长或者太短(应该在3-40个字符间,否则会触发警告!!!)。注意:目前变量名只适用于自己写的方法的参数和自己写的class中的全局常量或变量, 对于系统自带的方法里面和自己写的方法里面没有作用
- multiple_closures_with_trailing_closure #当函数有多个闭包时, 不建议使用尾随闭包语法/多个闭包与尾随闭包冲突:在传递多个闭包参数时不应该使用尾随关闭语法。
- trailing_comma # 数组最后一个元素后面有空格
- file_length #文件长度
- for_where #使用 `for where` 代替 简单的 `for { if }`
- unneeded_break_in_switch # 在switch-case语句中, 有方法调用或操作时,避免使用break语句
- large_tuple #元祖成员 元组冲突:元组应该最多有2个成员,多余两个会报错
- redundant_string_enum_value #在定义字符串枚举的时候, 当字符串枚举值等于枚举名称时,可以不用赋值
- syntactic_sugar #语法糖[Int] 代替Array / 例:要使用 [] ? 等数组字典可选项的语法糖
- line_length # 行的字符长度,这个强烈不推荐使用。官方的规定是超过120字符就给warning,
# 函数参数计数违例:函数应该有5个参数,多余会报错 函数参数个数, 函数参数数量(init方法除外)应该少点,不要太多,swiftlint规定函数参数数量超过5个给warning, 超过8个直接报error。这个属性推荐使用,由于简单就不举例了。
#注:function_parameter_count: error 这样并不能改变它的警告或错误,该属性不允许修改,但是可以禁用
- function_parameter_count #函数参数个数 默认5 warning 8 error
- operator_whitespace #当定义空格操作符的时候,被定义的名字或类型两边应该各有一个单行空格操作符
- closure_parameter_position #闭包参数位置, 闭包参数应该 { 左边在同一行
- unused_capture_list #闭包中没有被使用的参数应该删除
- redundant_void_return #在不必要的时候, 不需要写 ->() and -> Void
- mark # //MARK: - 正确使用 mark 的格式 `// MARK: - message`
- redundant_optional_initialization # 默认值赋值为nil
- return_arrow_whitespace # -> 前后要有空格,函数定义返回的 -> 前后有空格, 不换行
- unused_optional_binding #在使用if判断某变量是否为nil的时候, 不建议使用下划线(_)
- vertical_parameter_alignment #函数参数分为多行书写的时候, 头部(小括号后面一位)必须对齐
- number_separator #使用 _ 分割大数, 让数字更清晰
opt_in_rules: # some rules are only opt-in 一些规则仅仅是可选的
- opening_brace # 右括号之前应有一个空格,并与声明在同一行
- unused_import # import 的文件要被使用 All imported modules should be required to make the file compile.
- comma #逗号 [a, b, c, d] 后面必须有一个空格, 前面不要空格 --->项目中扫描到不少,待调整
force_unwrapping: error #避免强制解包
cyclomatic_complexity: error #代码复杂度,默认为10,循环复杂度。函数体的复杂度的限制,这个属性主要约束条件句、循环句中的循环嵌套问题, 当嵌套太多的循环时,则会触发swiftlint中的warning和error,当达到10个循环嵌套时就会报warning,达到20个循环嵌套时就会报error,强烈推荐这个属性。嵌套太多,可读性差!
trailing_semicolon: error #末尾跟分号
legacy_constructor: error #使用 swift 提供的 struct 构造函数, 避免使用 遗留的构造函数 比如 CGPointMake(10, 10)
empty_count: error #建议使用isEmpty判断,而不是使用count==0判断
prohibited_interface_builder: error #禁止用interface Builder 创建视图
function_body_length: error #函数体长度 默认超过40行warning,超过100行直接报错。推荐使用。
type_name: error #类型名应该只包含字母数字字符, 并且以大写字母开头,长度在3-40个字符
shorthand_operator: error # 使用+= , -=, *=, /= 222222 代替 a = a + 1
implicit_getter: error # read-only参数不应该有getter方法
nesting: error #类型定义嵌套不要超过1层 , 声明嵌套不要超过5层
private_unit_test: error #单元测试方法 不能设置为 private
unused_enumerated: error #默认-当参数没有被全部使用的时候, 不要使用容器的 enumerated 方法
valid_ibinspectable: error #默认-IBInspectable 必须是可变参数
explicit_type_interface: error #需要跑明确参数的类型定义
fatal_error_message: error #fatalError 必须拥有一个 message
first_where: error #使用 `.first(where:)` 代替 `.filter { }.first`
implicitly_unwrapped_optional: error #避免隐式解析可选类型的使用 / 避免隐式解包(定义 ! 类型)
switch_case_on_newline: error #switch 的 case 需要新启一行
object_literal: error #避免 image and color 使用字面量初始化, 需要把相关图片名,颜色RGB 等参数定义为 enum struct 或者常量
overridden_super_call: error #override 方法需要调用 super method
private_action: error #IBActions应该是私有的
private_outlet: error #IBOutlets 应该设置为 private, 来避免泄露
prohibited_super_call: error #某些特殊的 override 方法, 禁止调用 super method
redundant_nil_coalescing: error #避免使用 `object ?? nil`
explicit_init: error #避免直接调用 init 方法
operator_usage_whitespace: error #操作符需要使用一个空格间隔
nimble_operator: error #避免 expect 一个确定的判断
attributes: error #Attributes 针对类和func重启一行, 针对变量在同一行
duplicate_imports: error #重复导入
convenience_type: error #用于检测静态成员的类型应实现为无大小写的枚举,以避免实例化
explicit_enum_raw_value: error #枚举应设置默认值
file_name_no_space: error #文件名不应包含任何空格
ibinspectable_in_extension: error #扩展不应添加@IBInspectable属性
identical_operands: error #比较两个相同的操作数可能是一个错误
lower_acl_than_parent: error #确保定义的访问控制级别低于其父级
missing_docs: error #声明应记录在案
no_extension_access_modifier: error #禁止使用扩展访问修饰符,例如不建议:private extension String {}
no_grouping_extension: error #扩展名不应用于对同一源文件中的代码进行分组 不推荐如下注释写法
# class Ham { class Spam {}}
# ↓extension Ham.Spam {}
optional_enum_case_matching: error #将枚举大小写与不带'?'的可选枚举匹配 在Swift 5.1及更高版本中受支持。
prefixed_toplevel_constant: error #顶级常量的前缀应为k
quick_discouraged_call: error #不鼓励在“describe”和/或“context” 框中进行调用。
#| identifier | opt-in | correctable | enabled in your config
#----------------------+
# | 以下是默认规则 swiftlint版本:0.40.1 默认:warning 少数是:error
# | empty_parameters | no | yes | yes 使用 `() -> ` 代替 `Void ->
# | empty_parentheses_with_trailing_closure | no | yes | yes 尾闭包避免空参数括号
# | colon no | yes | yes 冒号左边没有空格, 右边有且只有一个空格
# | comma no | yes | yes 逗号左边没有空格, 右边有空格
# | legacy_cggeometry_functions | no | yes | yes 避免使用 C 风格 的 CG 遗留函数, 使用 struct extension
# | legacy_constant | no | yes | yes 避免使用 遗留的全局常量, 使用 struct 内定义的 常量
# | legacy_constructor | no | yes | yes 使用 swift 提供的 struct 构造函数, 避免使用 遗留的构造函数 比如 CGPointMake(10, 10)
# | legacy_nsgeometry_functions | no | yes | yes 避免使用 C 风格 的 NS 遗留函数, 使用 struct extension
# | opening_brace | no | yes | yes 需要正确书写大括号格式
# | redundant_discardable_let | no | yes | yes 使用 `_ = foo()` 代替 `let _ = foo()`
# | redundant_optional_initialization | no | yes | yes 不需要写默认值为 nil
# | closing_brace | no | yes | yes 小括号内包含函数(大括号)的时候,之间没有空格
# | redundant_void_return | no | yes | yes 在不必要的时候, 不需要写 ->() and -> Void
# | return_arrow_whitespace | no | yes | yes 函数定义返回的 -> 前后有空格, 不换行
# | statement_position | no | yes | yes else and catch 应该与 } 在同一行, 以空格间隔
# | trailing_newline | no | yes | yes 文件末尾应该有一个空行
# | trailing_semicolon | no | yes | yes 行末尾不加分号,warning
# | trailing_whitespace | no | yes | yes 行末尾不加空格
# | unused_closure_parameter | no | yes | yes 函数的参数必须被使用
# | vertical_whitespace | no | yes | yes 不能有连续多个空行
# | void_return | no | yes | yes 使用 `-> Void` 代替 `-> ()
# | compiler_protocol_init | no | no | yes 不应该直接调用字面量转换的初始化方法,诸如编译器协议中声明的初始化程序ExpressibleByArrayLiteral不应直接调用
# | control_statement | no | no | yes if while 等判断条件不要用括号 括起来
# | cyclomatic_complexity | no | no | yes 不应该存在太复杂的函数(判断语句过多)
# | discarded_notification_center_observer | no | no | yes 当使用 block 注册通知中心 observer 的时候, 应该存储函数返回的 observer, 以便之后的删除
# | force_cast | no | no | yes error:避免强制的类型转化,这里表示强解类型警告 as! Int
# | force_try | no | no | yes error:对会抛出异常(throws)的方法,不建议try,强解, 避免 `try!`
# | function_body_length | no | no | yes body 长度限制 warning: 40, error: 100
# | generic_type_name | no | no | yes 类型命名规则限制,以大写字母开头,且长度在1到20个字符之间,(min_length) w/e: 1/0, (max_length) w/e: 20/1000, excluded: [], allowed_symbols: [], validates_start_with_lowercase: true
# | implicit_getter | no | no | yes read-only 参数不应该有 getter
# | nesting | no | no | yes 类型定义嵌套不要超过1层 , 声明嵌套不要超过5层
# | private_unit_test | no | no | yes 单元测试方法 不能设置为 private
# | redundant_string_enum_value | no | no | yes 字符串类型枚举, 会有默认 string 值,与名字相同, 不要再次设置
# | shorthand_operator | no | no | yes 使用 +=, -=, *=, /=
# | syntactic_sugar | no | no | yes 要使用 [] ? 等数组字典可选项的语法糖
# | todo no | no | yes error:避免 TODOs and FIXMEs 标识
# | trailing_comma | no | no | yes 数组末尾不要加空格,warning mandatory_comma: false
# | type_body_length | no | no | yes 类型体行数限制
# | type_name | no | no | yes 类型名字限制规则,类型名称只能包含字母数字字符,以大写字母开头,并且长度在3到40个字符之间, (min_length) w/e: 3/0, (max_length) w/e: 40/1000, excluded: [], allowed_symbols: [], validates_start_with_lowercase: true
# | unused_enumerated | no | no | yes error:当参数没有被全部使用的时候, 不要使用容器的 enumerated 方法
# | unused_optional_binding | no | no | yes 必须使用定义的 optional binding
# | valid_ibinspectable | no | no | yes error: IBInspectable 必须是可变参数
# | vertical_parameter_alignment | no | no | yes 函数参数分为多行书写的时候, 头部(小括号后面一位)必须对其
# | weak_delegate | no | no | yes delegate 应该被设置为 weak
# | block_based_kvo | no | no | yes 计算的属性和下标中的Getter和setter应该保持一致的顺序。
# | discouraged_direct_init | no | no | yes 不鼓励直接初始化并声明的类型 warning:types: ["Bundle", "Bundle.init", "UIDevice", "UIDevice.init"]
# | duplicate_enum_cases | no | no | yes error:枚举不能设置两个或者以上相同的名字
# | duplicate_imports | no | no | yes 重复导入
# | dynamic_inline | no | no | yes error:避免同时使用'dynamic'和'@inline(__ always)'
# | empty_enum_arguments | no | yes | yes 如果将枚举与关联的类型匹配(如果不使用),则可以忽略参数
# | inert_defer | no | no | yes 如果defer在其父范围的末尾,则无论如何它都会被执行
# | is_disjoint | no | no | yes 优先:Set.isDisjoint(with:) 不建议:Set.intersection(_:).isEmpty
# | legacy_hashing | no | no | yes hash(into:)优先使用函数而不是覆盖hashValue
# | no_fallthrough_only | no | no | yes 仅当case包含至少一个其他语句时,才能使用穿透。
# | no_space_in_method_call | no | yes | yes error:不要在方法名称和括号之间添加空格
# | nsobject_prefer_isequal | no | no | yes NSObject子类应实现isEqual而不是==
# | private_over_fileprivate | no | yes | yes 推荐:private 不建议:fileprivate; warning:validate_extensions: false
# | protocol_property_accessors_order | no | yes | yes error:在协议中声明属性 要按顺序先写 get set方法
# | reduce_boolean | no | no | yes 优先使用.allSatisfy()或.contains() 不建议使用:reduce(true)或reduce(false)
# | redundant_objc_attribute | no | yes | yes Objective-C属性(@objc)在声明中是多余的,warning
# | redundant_set_access_control | no | no | yes 如果属性设置程序访问级别与变量访问级别相同,则不应明确
# | superfluous_disable_command | no | no | yes 当禁用规则不会在禁用区域触发违规时,SwiftLint的“禁用”命令是多余的。如果要记录命令,请使用“-”,warning
# | switch_case_alignment | no | no | yes Case语句应与其封闭的switch语句垂直对齐,如果没有其他配置,则缩进
# | unneeded_notification_center_removal | no | no | yes 观察者会自动在dealloc(iOS 9 / macOS 10.11)上取消注册,因此您不应调用removeObserver(self)deinit
# | unused_control_flow_label | no | yes | yes 未使用的控制流标签应被删除,warning
# | unused_import | yes | yes | yes 严重警告, 所以导入的类文件需要编译 severity: warning, require_explicit_imports: false, allowed_transitive_imports: []
# | unused_setter_value | no | no | yes 不使用设定值
# | xctfail_message | no | no | yes XCTFail调用应包括断言的描述,描述不能为空
# | 以下是可选规则, 需要额外添加
# +------------------------------------------+--------+-------------+------------------------+-------------+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
# | identifier | opt-in | correctable | enabled in your config | kind | analyzer | configuration
# | anyobject_protocol | yes | yes | no | lint | no | warning:对于纯类协议,建议AnyObject 不推荐 class
# | array_init | yes | no | no | lint | no | warning:推荐使用 Array(seq) 不推荐语法: seq.map { $0 } 将序列转换为Array。
# | attributes | yes | no | no | style | no | warning, always_on_same_line: ["@IBAction", "@NSManaged"], always_on_line_above: []
# | class_delegate_protocol | no | no | no | lint | no | warning delegate protocol 应该被设定为 class-only,才能被弱引用
# | closure_body_length | yes | no | no | metrics | no | warning: 20, error: 100 封闭体不应跨越太多行
# | closure_end_indentation | yes | yes | no | style | no | warning 闭包前后缩进应相同
# | closure_parameter_position | no | no | no | style | no | warning 闭包参数位置, 闭包参数应该 { 左边在同一行
# | closure_spacing | yes | yes | no | style | no | warning 闭包表达式在每个大括号 { } 内前后应有一个空格
# | collection_alignment | yes | no | no | style | no | warning, align_colons: false 集合文字中的所有元素应垂直对齐
# | conditional_returns_on_newline | yes | no | no | style | no | warning, if_only: false 条件语句与结果不建议写在一行 ,例如:guard true else { return } ;if true { return "YES" } else { return "NO" } 会有 warning提示
# | contains_over_filter_count | yes | no | no | performance | no | warning 推荐使用 contains,避免使用 filter(where:).count 与 0 相比较
# | contains_over_filter_is_empty | yes | no | no | performance | no | warning 推荐使用 contains,避免使用 filter(where:).isEmpty
# | contains_over_first_not_nil | yes | no | no | performance | no | warning 推荐使用 contains,避免使用 first(where:) != nil 与 firstIndex(where:) != nil
# | contains_over_range_nil_comparison | yes | no | no | performance | no | warning 推荐使用 contains,不建议使用与nil的比较
# | convenience_type | yes | no | no | idiomatic | no | warning 用于检测静态成员的类型应实现为无大小写的枚举,以避免实例化
# | custom_rules | no | no | no | style | no | user-defined 通过提供正则表达式字符串来创建自定义规则
# | discouraged_object_literal | yes | no | no | idiomatic | no | warning, image_literal: true, color_literal: true 避免使用图片和颜色的字面量(Ltiteral),尽量使用初始化的方式
# | discouraged_optional_boolean | yes | no | no | idiomatic | no | warning 推荐使用非可选的bool值
# | discouraged_optional_collection | yes | no | no | idiomatic | no | warning 优先选择空集合而不是可选集合
# | empty_collection_literal | yes | no | no | performance | no | warning 优先使用isEmpty 空数组或字典文字进行值的比较
# | empty_count | yes | no | no | performance | no | error, only_after_dot: false 建议使用isEmpty判断,而不是使用count==0判断
# | empty_string | yes | no | no | performance | no | warning 优先使用isEmpty判断,而不是将字符串与空字符串文字进行比较
# | empty_xctest_method | yes | no | no | lint | no | warning 应避免使用空的XCTest方法
# | enum_case_associated_values_count | yes | no | no | metrics | no | warning: 5, error: 6 枚举情况下的关联值数量应少
# | expiring_todo | yes | no | no | lint | no | (approaching_expiry_severity) warning, (reached_or_passed_expiry_severity) error TODO和FIXME应该在其到期日之前解决
# | explicit_acl | yes | no | no | idiomatic | no | warning 所有声明都应明确指定访问控制级别关键字
# | explicit_enum_raw_value | yes | no | no | idiomatic | no | warning 枚举应设置默认值
# | explicit_init | yes | yes | no | idiomatic | no | warning 避免直接调用 init 方法
# | explicit_self | yes | yes | no | style | yes | warning 实例变量和函数应使用“self”显式访问
# | explicit_top_level_acl | yes | no | no | idiomatic | no | warning 顶级声明应明确指定访问控制级别关键字
# | explicit_type_interface | yes | no | no | idiomatic | no | warning, excluded: [], allow_redundancy: false 需要跑明确参数的类型定义
# | extension_access_modifier | yes | no | no | idiomatic | no | warning 优先使用扩展名访问修饰符
# | fallthrough | yes | no | no | idiomatic | no | warning 避免在 case语句中使用 fallthrough
# | fatal_error_message | yes | no | no | idiomatic | no | warning fatalError 必须拥有一个 message
# | file_header | yes | no | no | style | no | warning, 标头注释应与项目模式一致 required_string: None, required_pattern: None, forbidden_string: None, forbidden_pattern: None
# | file_length | no | no | no | metrics | no | warning: 文件长度限制 warning:400, error: 1000, ignore_comment_only_lines: false
# | file_name | yes | no | no | idiomatic | no | (severity) warning, 文件名应与文件中声明的类型或扩展名匹配(如果有) excluded: ["LinuxMain.swift", "main.swift"], prefixPattern: , suffixPattern: \+.*, nestedTypeSeparator: .
# | file_name_no_space | yes | no | no | idiomatic | no | (severity) warning, excluded: [] 文件名不应包含任何空格
# | file_types_order | yes | no | no | style | no | warning, 指定如何排序文件中的类型 order: [[SwiftLintFramework.FileType.supportingType], [SwiftLintFramework.FileType.mainType], [SwiftLintFramework.FileType.extension], [SwiftLintFramework.FileType.previewProvider]]
# | first_where | yes | no | no | performance | no | warning 使用 `.first(where:)` 代替 `.filter { }.first`
# | flatmap_over_map_reduce | yes | no | no | performance | no | warning 推荐使用 flatMap,避免使用 map 的 reduce([], +)
# | for_where | no | no | no | idiomatic | no | warning 使用 `for where` 代替 简单的 `for { if }`
# | force_unwrapping | yes | no | no | idiomatic | no | warning 避免强制解包
# | function_default_parameter_at_end | yes | no | no | idiomatic | no | warning 方法中参数列表,应将带有默认值的参数放在最后面
# | function_parameter_count | no | no | no | metrics | no | warning: 5, error: 8 ignores_default_parameters: true 函数参数个数 默认 5 warning 8 error
# | ibinspectable_in_extension | yes | no | no | lint | no | warning 扩展不应添加@IBInspectable属性
# | identical_operands | yes | no | no | lint | no | warning 比较两个相同的操作数可能是一个错误
# | identifier_name | no | no | no | style | no | 参数变量命名规则 (min_length) w/e: 3/2, (max_length) w/e: 40/60, excluded: [], allowed_symbols: [], validates_start_with_lowercase: true
# | implicit_return | yes | yes | no | style | no | warning, included: [closure, function, getter] 在闭包,函数和getter中更喜欢隐式返回
# | implicitly_unwrapped_optional | yes | no | no | idiomatic | no | warning, mode: allExceptIBOutlets 避免隐式解析可选类型的使用 / 避免隐式解包(定义 ! 类型)
# | indentation_width | yes | no | no | style | no | severity: warning, indentation_width: 4 include_comments: true 缩进长度
# | joined_default_parameter | yes | yes | no | idiomatic | no | warning 不推荐显式使用默认分隔符
# | large_tuple | no | no | no | metrics | no | warning: 2, error: 3 元祖成员 元组冲突:元组应该最多有2个成员,多余两个会报错
# | last_where | yes | no | no | performance | no | warning 推荐在集合中使用:.last(where:) 不推荐使用: .filter { }.last
# | leading_whitespace | no | yes | no | style | no | warning 文件末尾不应该存在空格符
# | legacy_multiple | yes | no | no | idiomatic | no | warning 推荐使用isMultiple(of:)函数,不推荐使用余数运算符(%)
# | legacy_random | yes | no | no | idiomatic | no | warning 随机函数 优先使用type.random(in :),不建议使用旧版函数。
# | let_var_whitespace | yes | no | no | style | no | warning Let和var应该用空白行与其他语句分开
# | line_length | no | no | no | metrics | no | warning: 120, error: 200, 行的字符长度,这个强烈不推荐使用。官方的规定是超过120字符就给warning, ignores urls: false, ignores function declarations: false, ignores comments: false, ignores interpolated strings: false
# | literal_expression_end_indentation | yes | yes | no | style | no | warning 数组和字典文字的结尾应与开始它的行具有相同的缩进
# | lower_acl_than_parent | yes | no | no | lint | no | warning 确保定义的访问控制级别低于其父级
# | mark | no | yes | no | lint | no | warning 正确使用 mark 的格式 `// MARK: - message`
# | missing_docs | yes | no | no | lint | no | warning: open, public 声明应记录在案
# | modifier_order | yes | yes | no | style | no | warning, 修饰符顺序应一致 preferred_modifier_order: [override, acl, setterACL, dynamic, mutators, lazy, final, required, convenience, typeMethods, owned]
# | multiline_arguments | yes | no | no | style | no | warning, 参数应该在同一行,或者每行一个 first_argument_location: any_line, only_enforce_after_first_closure_on_first_line: false
# | multiline_arguments_brackets | yes | no | no | style | no | warning 多行参数应在其新行中包含方括号 []
# | multiline_function_chains | yes | no | no | style | no | warning 链接的函数调用应该在同一行上,或者每行一个
# | multiline_literal_brackets | yes | no | no | style | no | warning 多行文字应在其新行中包含方括号 []
# | multiline_parameters | yes | no | no | style | no | warning 函数和方法参数应该在同一行上,或者每行一个
# | multiline_parameters_brackets | yes | no | no | style | no | warning 多行参数应在其新行中包含方括号
# | multiple_closures_with_trailing_closure | no | no | no | style | no | warning 传递多个闭包参数时,不应使用结尾的闭包语法
# | nimble_operator | yes | yes | no | idiomatic | no | warning 避免 expect 一个确定的判断
# | no_extension_access_modifier | yes | no | no | idiomatic | no | error 禁止使用扩展访问修饰符
# | no_grouping_extension | yes | no | no | idiomatic | no | warning 扩展名不应用于对同一源文件中的代码进行分组
# | notification_center_detachment | no | no | no | lint | no | warning `NotificationCenter.default.removeObserver` 只在 `deinit` 中被调用
# | nslocalizedstring_key | yes | no | no | lint | no | warning 应将静态字符串用作NSLocalizedString中的键。
# | nslocalizedstring_require_bundle | yes | no | no | lint | no | warning 调用NSLocalizedString应该指定包含字符串文件的捆绑软件
# | number_separator | yes | yes | no | style | no | warning, minimum_length: 0 下划线数字分隔符
# | object_literal | yes | no | no | idiomatic | no | warning, image_literal: true, color_literal: true 避免 image and color 使用字面量初始化, 需要把相关图片名,颜色RGB 等参数定义为 enum struct 或者常量
# | operator_usage_whitespace | yes | yes | no | style | no | warning 操作符需要使用一个空格间隔
# | operator_whitespace | no | no | no | style | no | warning 当定义空格操作符的时候,被定义的名字或类型两边应该各有一个单行空格操作符
# | optional_enum_case_matching | yes | yes | no | style | no | warning 将枚举大小写与不带'?'的可选枚举匹配 在Swift 5.1及更高版本中受支持
# | orphaned_doc_comment | no | no | no | lint | no | warning 注释要写在声明中
# | overridden_super_call | yes | no | no | lint | no | warning, excluded: [[]], included: [["*"]] override 方法需要调用 super method
# | override_in_extension | yes | no | no | lint | no | warning 扩展不应覆盖声明
# | pattern_matching_keywords | yes | no | no | idiomatic | no | warning 通过将关键字移出元组来组合多个模式匹配绑定
# | prefer_self_type_over_type_of_self | yes | yes | no | style | no | warning 访问属性或调用方法时,最好将“自类型”设置为(of:self)。
# | prefer_zero_over_explicit_init | yes | yes | no | idiomatic | no | warning 优先使用.zero而不是具有零参数的显式init(例如CGPoint(x:0,y:0))
# | prefixed_toplevel_constant | yes | no | no | style | no | warning, only_private: false 顶级常量的前缀应为k
# | private_action | yes | no | no | lint | no | warning IBActions应该是私有的
# | private_outlet | yes | no | no | lint | no | warning, IBOutlets 应该设置为 private, 来避免泄露 allow_private_set: false
# | prohibited_interface_builder | yes | no | no | lint | no | warning 禁止用interface Builder 创建视图
# | prohibited_super_call | yes | no | no | lint | no | warning, 某些特殊的 override 方法, 禁止调用 super method excluded: [[]], included: [["*"]]
# | quick_discouraged_call | yes | no | no | lint | no | warning 不鼓励在“describe”和/或“context” 框中进行调用。
# | quick_discouraged_focused_test | yes | no | no | lint | no | warning 不鼓励重点测试。专注于此测试时,其他测试将不会运行
# | quick_discouraged_pending_test | yes | no | no | lint | no | warning 不推荐:未开始的测试。标记为待定时,该测试不会运行
# | raw_value_for_camel_cased_codable_enum | yes | no | no | lint | no | warning 设置枚举建议设置默认值
# | reduce_into | yes | no | no | performance | no | warning 对于 copy-on-write 类型,推荐使用 reduce(into:_:) 不建议使用 reduce(_:_:)
# | redundant_nil_coalescing | yes | yes | no | idiomatic | no | warning #避免使用 `object ?? nil` 仅当lhs为nil时才评估nil合并运算符,而n为rhs则合并nil合并运算符
# | redundant_optional_initialization | no | yes | no | idiomatic | no | warning 用nil初始化可选变量是多余的。 # 默认值赋值为nil 不需要写默认值为 nil
# | redundant_string_enum_value | no | no | no | idiomatic | no | warning #在定义字符串枚举的时候, 当字符串枚举值等于枚举名称时,可以不用赋值
# | redundant_type_annotation | yes | yes | no | idiomatic | no | warning 变量不应具有冗余类型注释 建议 var url = URL() 不建议 var url : URL = URL()
# | redundant_void_return | no | yes | no | idiomatic | no | warning 在函数声明中返回Void是多余的。#在不必要的时候, 不需要写 ->() and -> Void
# | required_deinit | yes | no | no | lint | no | warning 类应具有显式的deinit方法。
# | required_enum_case | yes | no | no | lint | no | No protocols configured. 符合指定协议的枚举必须实现特定情况。 In config add 'required_enum_case' to 'opt_in_rules' and config using :\n\n'required_enum_case:\n {Protocol Name}:\n {Case Name}:{warning|error}\n {Case Name}:{warning|error}\n
# | return_arrow_whitespace | no | yes | no | style | no | warning # -> 前后要有空格,函数定义返回的 -> 前后有空格, 不换行
# | shorthand_operator | no | no | no | style | no | error # 使用+= , -=, *=, /= 代替 a = a + 1
# | single_test_class | yes | no | no | style | no | warning 测试文件应只包含一个QuickSpec或XCTestCase类。
# | sorted_first_last | yes | no | no | performance | no | warning 优先使用min()或max() 不建议使用 sorted().first或sorted().last
# | sorted_imports | yes | yes | no | style | no | warning Imports 应排序.
# | statement_position | no | yes | no | style | no | (statement_mode) default, (severity) warning #这里主要指的是 else 和 catch 前面要加一个空格, 也不能大于1个空格
# | static_operator | yes | no | no | idiomatic | no | warning 应该将运算符声明为静态函数,而不是自由函数。
# | strict_fileprivate | yes | no | no | idiomatic | no | warning fileprivate 应该避免。
# | strong_iboutlet | yes | no | no | lint | no | warning @IBOutlets不应被声明为weak 应该为 strong。
# | switch_case_on_newline | yes | no | no | style | no | warning #switch 的 case 需要新启一行
# | syntactic_sugar | no | yes | no | idiomatic | no | warning #语法糖[Int] 代替Array / 例:要使用 [] ? 等数组字典可选项的语法糖
# | toggle_bool | yes | yes | no | idiomatic | no | warning 不让使用 A = !A 建议使用 A.toggle()
# | trailing_closure | yes | no | no | style | no | warning, only_single_muted_parameter: false 尽可能使用尾随闭包语法。
# | trailing_newline | no | yes | no | style | no | warning #末尾空行,文件末尾应该有一个空行
# | type_body_length | no | no | no | metrics | no | warning: 200, error: 350 #类型体长度。类型体长度不应该跨越太多行,超过200行给warning,超过350行给error,可自定义enum或struct
# | type_contents_order | yes | no | no | style | no | warning, 指定类型内子类型,属性,方法及更多内容的顺序。 order: [[SwiftLintFramework.TypeContent.case], [SwiftLintFramework.TypeContent.typeAlias, SwiftLintFramework.TypeContent.associatedType], [SwiftLintFramework.TypeContent.subtype], [SwiftLintFramework.TypeContent.typeProperty], [SwiftLintFramework.TypeContent.instanceProperty], [SwiftLintFramework.TypeContent.ibInspectable], [SwiftLintFramework.TypeContent.ibOutlet], [SwiftLintFramework.TypeContent.initializer],... |
# | unavailable_function | yes | no | no | idiomatic | no | warning 未实现的功能应标记为不可用。
# | unneeded_break_in_switch | no | no | no | idiomatic | no | warning # 在switch-case语句中, 有方法调用或操作时,避免使用break语句
# | unneeded_parentheses_in_closure_argument | yes | yes | no | style | no | warning 声明闭包参数时,不需要括号。
# | unowned_variable_capture | yes | no | no | lint | no | warning 最好将引用捕获为弱引用以避免潜在的崩溃。
# | untyped_error_in_catch | yes | yes | no | idiomatic | no | warning 没有类型转换,catch语句不应声明错误变量。
# | unused_capture_list | no | no | no | lint | no | warning #闭包中没有被使用的参数应该删除
# | unused_closure_parameter | no | yes | no | lint | no | warning #函数的参数必须被使用
# | unused_declaration | yes | no | no | lint | yes | severity: error, include_public_and_open: false 在所有被删除的文件中,声明至少应被引用一次。
# | unused_optional_binding | no | no | no | style | no | warning, ignore_optional_try: false #在使用if判断某变量是否为nil的时候, 不建议使用下划线(_) 必须使用定义的 optional binding
# | vertical_parameter_alignment | no | no | no | style | no | warning #函数参数分为多行书写的时候, 头部(小括号后面一位)必须对齐 函数参数分为多行书写的时候, 头部(小括号后面一位)必须对其
# | vertical_parameter_alignment_on_call | yes | no | no | style | no | warning 如果函数参数在方法调用中位于多行中,则应垂直对齐。
# | vertical_whitespace | no | yes | no | style | no | warning, max_empty_lines: 1 #垂直方向上的空格行,限制为一行(注释除外) 不能有连续多个空行
# | vertical_whitespace_between_cases | yes | yes | no | style | no | warning 在 switch cases 之间包括一条空行。
# | vertical_whitespace_closing_braces | yes | yes | no | style | no | N/A 在关闭大括号之前,请勿包括垂直空格(空行)。
# | vertical_whitespace_opening_braces | yes | yes | no | style | no | N/A 打开花括号后,请勿包括垂直空格(空行)。
# | weak_delegate | no | yes | no | lint | no | warning 代表应有弱势,以避免参考周期。
# | xct_specific_matcher | yes | no | no | idiomatic | no | warning 优先使用特定的XCTest匹配器,XCTAssertEqual而不是XCTAssertNotEqual
# | yoda_condition | yes | no | no | lint | no | warning 变量应位于比较运算符的左侧,常数应位于右侧。
可去官方自定查找对应属性说明:
(GitHub 链接:https://github.com/realm/SwiftLint)
3.4.swiftlint.yml配置文件的嵌套
在我们使用.swift.yml配置文件的时候,如果在系统扫描的过程中发现了一个新的配置文件,那么子目录下的规则就会改为新的配置规则。
总的来说,swiftlint对于代码规范管理是利远大于弊的,只要在前期需要一些时间建立一个规范体系.在后期由于代码整体的规范性,能利于项目的维护,以及可以节省代码Review的时间.
参考:
SwiftLint GitHub地址:https://github.com/realm/SwiftLint
SwiftLint 官网说明.:https://realm.github.io/SwiftLint/index.html
AST:http://clang.llvm.org/docs/IntroductionToTheClangAST.html
LLVM优点:https://www.cnblogs.com/zuopeng/p/4141467.html
swift代码规范工具:https://www.jianshu.com/p/eea2520f34ae
iOS- 工程配置SwiftLint:https://www.it610.com/article/1282270515729285120.htm
SwiftLint 规则:https://cloud.tencent.com/developer/article/1617958
作者:技术进阶在路上
链接:https://www.jianshu.com/p/abb4057db849
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。