/UnusedCode

This is a Clang AST plugin, aims to clear zombie code what is not used in project.

Primary LanguageJavaScript

概述

这款工具可以帮助清理 iOS objc 项目中废弃的代码。在迭代开发过程中,伴随着功能更新、移除,代码也会更替。往往代码中的调用关系不知不觉都被删光了,但是开发者不会立即发现(即使发现了,也要考虑产品经理哪天又把这些东西加回来,呵呵),所以并不会立即把已经不用的类或者文件从项目中移除。久而久之,APP包大小只增不减,一个项目到一年多的时候,差不多就要开始清理了。

原理

调用关系

对于iOS应用程序来说,main()是主入口,接着是AppDelegate,进而是main ViewController、push notification等。对于任意有用代码,存在一条从main到它的调用关系路径。 开发者添加到项目中的代码,之间的调用关系一般都在项目代码中可见。但有一些例外,例如main()、+(void)load、UITableViewDelegate协议里的方法等,都是由“系统”调用。

把所有类中的实例方法、类方法以及全局的静态方法一起分析,记录所有的调用关系,是一种理想的方法,但这种方法不容易操作,因为这些路径中经常存在断点。例如“UITableViewDelegate协议中的方法被谁调用了”,通过分析项目中的代码是不可得知的。

而当我们吧类的实例方法、类方法合二为一,把调用关系中的节点替换为类,就会发现这些调用关系不容易被打断。

Clang AST插件

要分析代码中的调用关系,Clang AST插件是一种方便的方式。编译器在进行编译时,要生成一个叫做抽象语法树(AST)的数据结构,帮助其完成语法分析。Clang将处理AST的能力暴露出来,这就让人们能够方便地利用编译器的语法分析能力。

项目结构

项目分为两部分,UnusedCode和UnusedCodeAnalyzer。前者是clang插件,后者是针对前者输出内容,进行进一步分析的命令行工具。

clang插件在编译阶段会执行,且针对每一个编译单元都会重新执行。因此插件需要把数据写到中间文件中,最后再统一处理。

目标项目设置

需要在目标项目中选择本地编译好的clang编译器,在编译参数中加入UnusedCode插件。在所在项目结构下建立一个Analyzer的路径,用以放置处理数据和分析数据。

这些准备工作做完之后就可以开始编译目标项目。编译完成之后运行UnusedCodeAnalyzer。未使用到的代码会输出到unusedClass.json中。一般真正落实到删除的时候,还需要代码的作者把关,代码作者可从unusedClassWithAuthor.json文件中查看。