1 | 简介: |
1 | SwiftLint 是 realm 公司开发的一个插件,专门用于管理 Swift 代码的规范。 |
SwiftLint 的工作原理是检查 Swift 代码编译过程中的 AST 和 SourceKit 环节,从而可以摆脱不同版本 Swift 语法变化的影响。AST 是编译前端形成的抽象语法树(Abstract Symbolic Tree), SourceKit 过程用来对 AST 进行代码优化,减少内存开销,提高执行效率。如果对编译过程理解不太清楚,可以参考:Clang官方文档以及网络上两篇比较好的文章AST 和 LLVM优点以及戴铭的深入剖析 iOS 编译 Clang / LLVM
预处理 -> 词法分析 -> Token -> 语法分析 -> AST -> 代码生成 -> LLVM IR -> 优化 -> 生成汇编代码 -> Link -> 目标文件
Ast,什么是抽象语法树,在llvm架构中,分为前端,优化器和后端三块,而clang是llvm的编译前端,当编译源代码c,c++,oc,swift时候。会对源代码进行词法分析,进行分词,变成token,包括(关键字,if,else,while等。标志符,函数名称。字面量,值,数字,字符串等,特殊符号+-*/)然后进行语法分析将token组合成语义生成节点。然后将这些节点根据层级关系生成抽象语法树。
抽象语法树,顶层是一个编译单元。又包含很多个字节点,其中有一些内置定义。然后函数声明。
Sourcekit是独立于Xcode的存在,它主要对swift源代码层面的操作性进行一个支持,例如语法解析,代码高亮,排版,自动补全等等。sourcekit主要借助与clang的符号解析usr,为源代码令牌(token,类,属性,方法)生成唯一的标志符,然后通过commad+点击源代码任意一处代码令牌,导航到对应的定义处。
如果有些时候你的代码全变白了,commad+点击失效了,类型推断失效了,这时候就是sourcekit出现了问题,可能是内存占用过高了。
SourceKit 是一套工具集,使得大多数 Swift 源代码层面的操作特性得以支持,例如源代码解析、语法高亮、排版(typesetting)、自动补全、跨语言头文件生成,等等
由于 SourceKit 是独立于Xcode之外的,所以可以利用以构建从 Swift IDE 到文档生成器等任何东西
例如第三方的工具
1.jazzy是一个命令行实用程序,可为Swift或Objective-C生成文档
1.3.1 swiftlint配置
具体环境安装配置详见官方文档,写的比较详细就不一一赘述了 swiftlint官方文档以及触发规则文档。
swiftlint操作大体流程:
->安装swiftlint
->配置工程脚本
->配置.swiftlint.yml规则文件到项目根目录
->编译代码
->触发规则的项目报error和warning
->通过命令行进行具体操作(见下文)
->根据触发的规则对比触发规则文档修改代码
看一下配置的文件.swiftlint.yml(通过配置.swiflint.yml,控制禁用/启用哪个规则,并为给定规则设置警告和错误的阈值)
1 | disabled_rules: # 执行时排除掉的规则 |
强制转换,严重级别设置warning和error两个等级
1 | force_cast: warning # 隐式 |
force_cast
非触发例子
1 | NSNumber() as? Int |
触发例子
1 | NSNumber() as! Int |
force_try 非触发例子
1 | func a() throws {} |
触发例子
1 | func a() throws {} |
也可以自定义规则:
1 | custom_rules: |
输出样式:
swiftlint lint
1 | swiftlint lint --path ~/Desktop --reporter html > swiftlint.html |
swiftlint autocorrect
swiftlint docs
swiftlint generate-docs --path
swiftlint rules
identifier:规则名称
Opt-in:启用非默认设置的规则
correctable:可纠正的规则
enabled in your config:配置中已经启用
Kind:规则的种类
也可以用fastlane官方的SwiftLint功能来运行SwiftLint作为你的Fastlane程序的一部分
1 | swiftlint( |
1.Flutter工程沿用Dart的静态代码检查器dartanalyzer, 并使用内置在Flutter Tools内的终端工具进行代码扫描和分析, 相关代码位于:commands
一般情况下, 在工程文件下配有分析脚本的情况下, 可以直接使用flutter analyze命令进行静态检查, 这和开发工具Android Studio自带的检查插件的效果是一样的, 最终结果会显示在AS下方的Dart Analysis Tab下.
检查器会根据项目根目录下的分析脚本执行检查, 该文件通常会与pubspec文件处于同一层级.
老版本的分析脚本命名为.analysis_options, 没有yaml后缀, 新版本统一命名为:analysis_options.yaml
除了这么放还能怎么放,如果遇到更加复杂的情况怎么办,比如说不同的文件夹下适应不同的规则,见下图:
检查器会使用#1检查other package和other other package, 使用#2检查my package.
在flutter 1.22 版本后有默认的分析脚本,内置在flutter包中analysis_options_user.yml
如果不想使用默认的分析脚本,当然也可以自己进行配置,如果嫌一条条配置lint规则麻烦, 可以直接集成Google的开源项目pedantic或者effective dart(二选一).
analysis_options.yaml配置
dart语言的代码规范以及相关触发规则详见linter
1). pedantic: Google内部执行的规则
在 pubspec.yaml
中添加如下,再flutter pub get
1 | dev_dependencies: |
在 analysis_options.yaml
中引入
1 | include: package:pedantic/analysis_options.yaml |
2). effective_dart : 与 effective-dart指南 相对应的规则
在pubspec.yaml中
1 | dev_dependencies: |
执行 flutter pub get
然后在 analysis_options.yaml
中引入
1 | include: package:effective_dart/analysis_options.yaml |
3). Flutter官方在1.22版本默认使用的分析脚本 : analysis_options_user.yml
在flutter 1.22 版本默认使用的分析脚本 (注:flutter版本查看 flutter --version
)当然也可以导入之后进行自定义,如下
1 | include: package:flutter/analysis_options_user.yaml |
示例一个以google的pedantic为例 自定义 analysis_options.yaml
1 | # 指定引用第三方库中预设文件的路径 |
我们知道dart使用语法糖实现了伪动态类型 - dynamic, 可以在编译器不确定类型时, 使用dynamic代替, implicit-dynamic可以阻止这种操作. implicit-casts表示禁止Object类型隐式转换为其他类型.
1 | analyzer: |
lint规则有两种配置方式一种是list方式 另一种是key-value方式,两者不能混用
list方式
1 | linter: |
key-value方式
1 | linter: |
对于具体规则什么意思呢,咱们以上文中提到的 annotate_overrides和await_only_futures为例
可以看到文档写的非常清楚,其他规则触发详见 dart语言的代码规范以及相关触发规则linter
1).忽略文件
要忽略特定文件的特定非错误规则,请在文件中添加ignore_for_file注释
1 | //ignore_for_file: unnecessary_new |
这在注释之前或之后对整个文件起作用,并且对于生成的代码特别有用。
忽略多个规则
1 | //ignore_for_file: unnecessary_new, unused_import, unused_local_variable |
忽略单行
1 | // ignore: unnecessary_new |
每个linter规则都有默认的严重性。您可以使用分析选项文件来更改单个规则的严重性,或者始终忽略某些规则。
支持三种严重性级别:
忽略规则
1 | analyzer: |
更改规则的严重性
1 | analyzer: |
万事具备只欠东风 通过 dart analyze
挑出其中两条.
触发规则
1 | info • Unnecessary new keyword at lib/business/home/home_page.dart:36:40 • (unnecessary_new) |
具体代码
查看规则文档可知unnecessary_new应避免使用new关键字创建实例。
1 | error • Missing return type for 'saveStringList' at lib/core/storage/shared_preferences_storage.dart:25:3 • (implicit_dynamic_return) |
具体代码
查看所给的提示可知没有添加函数的返回值,找了规则文档没有找到这条implicit_dynamic_return规则。
原来我启用了更为严格的类型检查,所以才会触发这个error级别的错误。
上文说过这里就不多解释了。
可以使用查看全部命令
dart analyzer –help
1 | Global options: |