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 进行代码优化,减少内存开销,提高执行效率。如果对编译过程理解不太清楚,可以参考:ASTLLVM优点

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349