通过Clang提供的丰富接口功能可以开发出静态分析工具,进而管控代码质量。还可以开发出用于代码增量分析、代码可视化、代码质量报告来保障App质量的系统平台。CodeChecker
什么是Clang
Clang是C、C++、Objective-C的编译前端,而Swift有自己的编译前端。
优势:
编译的速度非常快,对内存的使用率非常低,并且兼容GCC代码诊断,精确的显示出问题所在的行和具体位置,可以确切的说明这个问题的原因,并指出错误类型。对typedef的保留和展开也处理的很好Fix-it提示,宏的处理架构是模块化的。其输出的接口可以代码静态分析,开发代码转义、代码生成、代码重构的工具
Clang是基于C++开发的,源码质量很高。目录清晰、功能解耦做的很好、分类清晰方便组合和复用、代码风格统一而且规范、注释量大便于阅读等。Clang源码
Clang做的事
首先,Clang会对代码进行语法分析,将代码切分成Token。
//输入一个命令可以查看代码所有的tokenclang-fmodules-E-Xclang-dump-tokensmain.m
这个命令的作用是,显示每个Token的类型、值以及位置。Token类型分为四类:
关键字:语法中的关键字标识符:变量名字面量:值、数字、字符串特殊符号:加减乘除等符号
接下来,进行语法分析
将输出的Token先按照语法组成语义,生成节点,然后将这些节点按照层级关系构成抽象语法树(AST)。
//查看语法树clang-fmodules-fsyntax-only-Xclang-ast-dumpmain.m
TranslationUnitDecl0xc75b50invalidslocinvalidsloc
-TypedefDecl0xc75b70invalidslocinvalidslocimplicit__builtin_va_list‘char*’`-FunctionDecl0xc75b7b0test.cpp:1:1,line:7:1line:1:5main‘int(void)’`-CompoundStmt0xc75bline::1,line:7:1
-DeclStmt0xc75bline::,col:7
`-VarDecl0xc75b80col:,col:6col:6useda‘int’
-DeclStmt0xc75b8d8line::,col:1
`-VarDecl0xc75bcol:,col:10col:6usedb‘int’cinit
`-IntegerLiteral0xc75b8c0col:10‘int’10a=b
-BinaryOperator0xc75b98line:5:,col:6‘int’lvalue‘=‘
-DeclRefExpr0xc75b8e8col:‘int’lvalueVar0xc75b80‘a’‘int’
`-ImplicitCastExpr0xc75bcol:6‘int’LValueToRValue
`-DeclRefExpr0xc75bcol:6‘int’lvalueVar0xc75b‘b’‘int’`-ReturnStmt0xc75bline:6:,col:9`-ImplicitCastExpr0xc75bcol:9‘int’LValueToRValue`-DeclRefExpr0xc75b90col:9‘int’lvalueVar0xc75b80‘a’‘int
其中TranslationUnitDecl是根节点,表示一个编译单元;Decl表示一个声明;Expr表示的是表达式;Literal表示字面量,是一个特殊的Exper;Stmt表示陈述。
Clang还有众多种类的节点类型。节点主要分为Type类型、Decl声明、Stmt陈述这三种,其他的都是这三种的派生。通过扩展这三类节点,就能够将无限的代码形态用有限的形式表现出来了。
Clang提供的能力
LibClang
LibClang提供了一个稳定的高级的C接口,LibClang可以访问Clang的上层高级抽象的能力,比如获取所有Token、遍历语法树、代码补全等。由于API很稳定,Clang版本更新对其影响不大。但是,LibClang并不能完全访问到ClangAST信息。
使用LibClang可以直接使用它的CAPI。官方也提供了Pythonbinding脚本供你调用。还有开源的node-js/rubybinding。你要是不熟悉其他语言,还有个第三方开源的Objective-C写的ClangKit库可供使用。
ClangPlugins
ClangPlugins可以让你在AST上做些操作,这些操作能够集成到编译中,成为编译的一部分。插件是在运行时由编译器加载的动态库,方便集成到构建系统中。
使用ClangPlugins一般都是希望能够完全控制ClangAST,同时能够集成在编译流程中,可以影响编译的过程,进行中断或者提示。
LibTooling
通过LibTooling能够编写独立运行的语法检查和代码重构工具。与ClangPlugins相比,无法影响编译过程,与LibClang相比,接口没那么稳定,也无法开箱即用。能够完全控制ClangAST和可独立运行。可以做:
改变代码:可以改变Clang生成代码的方式。基于现有代码可以做出大量的修改。还可以进行语言的转换,比如把OC语言转成JavaScript或者Swif...做检查:检查命名规范,增加更强的类型检查,还可以按照自己的定义进行代码的检查分析做分析:对源码做任意类型分析,甚至重写程序。
在LibTooling的基础之上有个开发人员工具合集Clangtools,Clangtools作为Clang项目的一部分,已经提供了一些工具,主要包括:
语法检查工具clang-check;自动修复编译错误工具clang-fixit;自动代码格式工具clang-format;新语言和新功能的迁移工具;重构工具。