静态分析工具
SwiftLint,OCLint, Clang, Infer
Clang
Clang 是 C,C++,Objective-C 的编译前端。Swift 有自己的编译前端: SL optimizer。
Clang 会对代码进行词法分析,将代码切分成 Token
用以下命令可以查看:clang -fmodules -E -Xclang -dump-tokens main.m
可以把 Token 分为四类:
- 关键字:语法中的关键字,比如 if,else,while 等
- 标识符:变量名
- 字面值:值,数字,字符串
- 特殊符号:加减乘除等符号
语法分析
将输出的 Token 按照语法组合语义,生成类似 VarDecl 这样的节点。这些节点按照层次关系生成抽象语法树(AST)。
用以下命令查看:clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
类似的输出有:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20TranslationUnitDecl 0xc75b450 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0xc75b740 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list ‘char *’
`-FunctionDecl 0xc75b7b0 <test.cpp:1:1, line:7:1> line:1:5 main ‘int (void)’
`-CompoundStmt 0xc75b978 <line:2:1, line:7:1>
|-DeclStmt 0xc75b870 <line:3:2, col:7>
| `-VarDecl 0xc75b840 <col:2, col:6> col:6 used a ‘int’
|-DeclStmt 0xc75b8d8 <line:4:2, col:12>
| `-VarDecl 0xc75b890 <col:2, col:10> col:6 used b ‘int’ cinit
| `-IntegerLiteral 0xc75b8c0 <col:10> ‘int’ 10
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< a = b <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|-BinaryOperator 0xc75b928 <line:5:2, col:6> ‘int’ lvalue ‘=‘
| |-DeclRefExpr 0xc75b8e8 <col:2> ‘int’ lvalue Var 0xc75b840 ‘a’ ‘int’
| `-ImplicitCastExpr 0xc75b918 <col:6> ‘int’ <LValueToRValue>
| `-DeclRefExpr 0xc75b900 <col:6> ‘int’ lvalue Var 0xc75b890 ‘b’ ‘int’
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
`-ReturnStmt 0xc75b968 <line:6:2, col:9>
`-ImplicitCastExpr 0xc75b958 <col:9> ‘int’ <LValueToRValue>
`-DeclRefExpr 0xc75b940 <col:9> ‘int’ lvalue Var 0xc75b840 ‘a’ ‘int
其中 TranslationUnitDecl
是根节点,表示一个编译单元。Decl
表示一个声明,Expr
表示的是表达式。Literal
表示字面量,是一个特殊的 Expr。Stmt
表示陈述。
节点主要分为三种:Type
类型,Decl
声明,Stmt
陈述,其他都是有这三种派生的。通过扩展三类节点,能够将无限的代码形态用有限的形式表达出来。
提供的能力
Clang 为一些需要分析代码语法,语义信息的工具提供了基础设施。有:LibClang,ClangPlugin 和 LibTooling。
LibClang
LibClang 可以访问 Clang 的上层高级抽象能力,例如:获取所有 Token,遍历语法树,代码补全等。但并不能访问到 Clang AST 信息。
ClangPlugin
ClangPlugin 可以在 AST 上做些操作,这些操作能够集成到编译中,成为编译的一部分。插件是在运行时由编译器加载的动态库,方便集成构建系统中。
LibTooling
LibTooling 是一个 C++ 接口,通过 LibTooling 能够编写独立运行的语法检查和代码重构工具。
LibTooling 有以下优势:
- 所写工具不依赖构建系统,可以作为一个命令单独使用,比如:clang-check(语法检查工具),clang-fixit(自动修复编译错误工具),clang-format(自动代码格式工具)。
- 可以完全控制 Clang AST。
- 能够和 ClangPlugin 共用一份代码。
由于 LibTooling 可以完全控制 AST,所以可以做到很多事:
- 改变代码:可以改变 Clang 生成代码的方式。基于现有代码可以做大量的修改。还可以进行语言的转换。
- 做检查:检查命名规范,增加更强的类型检查,还可以按照自己的定义进行代码的检查分析。
- 做分析:对源码做任意类型分析,甚至重写程序。给 Clang 添加以一些自定义分析,创建自己的重构器,还可以基于工程生成相关的图形或文档进行分析。