注意: "dyld: Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib" 或缺失的警告是由 SwiftSyntax 问题引起的, SwiftSyntax 与 Swift 5.1.

Pecker

Pecker 用于检测未使用的代码。它基于 IndexStoreDBSwiftSyntax.

中文版 Readme: 中文版readme.

动机

随着你的 Swift 项目代码库的增长,很难找到未使用的代码。 你需要知道某些结构是否还在使用。 pecker 可以帮你完成这项工作,简单而准确。

特性

pecker 可以检测以下 Swift 结构

  1. 类 (class)
  2. 结构体 (struct)
  3. 枚举 (enum)
  4. 协议 (protocol)
  5. 函数 (func)
  6. 类型别名 (typealias)
  7. 运算符 (operator)

安装

安装 pecker 有多种方式。

使用 Homebrew

$ brew install woshiccm/homebrew-tap/pecker

使用 CocoaPods

pod 'Pecker'

这将在下次运行 pod install 时下载 pecker 二进制文件和依赖项到 Pods/ 目录下,并允许你通过在脚本构建阶段调用 ${PODS_ROOT}/Pecker/bin/pecker 来使用它。

这是推荐的安装 pecker 特定版本的方式,因为它支持安装特定的稳定版本,而不是 head 版本。

使用 Mint

mint install woshiccm/Pecker

从源码编译

$ git clone https://github.com/woshiccm/Pecker.git
$ cd Pecker
$ make install

安装完成后,并且 bin 文件夹已经配置好,就可以开始使用了。

使用方法

Xcode

pecker 集成到 Xcode scheme 中,以在 IDE 中显示警告和错误。 只需添加一个新的 "Run Script Phase",内容如下:

if which pecker >/dev/null; then
  pecker
else
  echo "warning: Pecker not installed, download from https://github.com/woshiccm/Pecker"
fi

或者,如果你通过 CocoaPods 安装了 Pecker,脚本应该如下所示:

${PODS_ROOT}/Pecker/bin/pecker

终端

注意

  1. 在终端中,由于项目索引路径无法自动检索,因此你需要通过 -i/--index-store-path 设置索引路径。
  2. 需要将 reporter 设置为 json 并设置 output_file,路径可以是相对路径或绝对路径。 如果未指定 output_file,则默认为项目中的 pecker.result.json

例如

.pecker.yml 中,配置如下:

reporter: "json"
output_file: pecker.result.json

在终端中,你输入:

$ pecker --path /Users/ming/Desktop/Testttt -i /Users/ming/Library/Developer/Xcode/DerivedData/Testttt-aohluxvofrwtfagozexmpeifvryf/Index/DataStore

命令行

pecker [OPTIONS]

在项目 target 中运行 pecker 进行检测。 项目将递归搜索 Swift 文件。

规则

目前 Pecker 中只包含 5 条规则,它们是 skip_public, xctest, attributes, xml, comment。 如果你不需要它们,可以将它们添加到 disabled_rules 中。你还可以查看 Source/PeckerKit/Rules 目录以查看它们的实现。

skip_public

此规则意味着跳过检测 public 类、结构体、函数等。 通常,public 代码是为其他用户提供的,因此很难确定是否被使用。 因此,默认情况下我们不检测它。 但在某些情况下,例如使用 submodule 来组织代码,你需要检测 public 代码,你可以将其添加到 disabled_rules 中。

xctest

XCTest 很特殊,我们规定忽略从 XCTestCase 继承的类,以及此类的具有 "test" 前缀且不包含参数的函数。

class ExampleUITests: XCTestCase {

    func testExample() { //used
    }

    func test(name: String) { // unused
    }
    
    func get() { // unused
    }
}

attributes

如果声明包含 BlackListAttribute 中的属性,则跳过。 例如 IBAction,我们正在不断收集,如果你发现新的案例,请告诉我们。

@IBAction func buttonTap(_ sender: Any) { // used       
}

XML

如果在 .xib 或 storyboard 中使用了代码,我们认为它正在使用中。

comment

可以使用以下格式的注释来忽略源代码文件中的代码

// pecker:ignore 

例如

// pecker:ignore
class TestCommentObject { // skip
    
    // pecker:ignore
    func test1() { // skip
    }
    
    func test2() { // unused
    }
}
// pecker:ignore all

例如

// pecker:ignore all
class TestCommentObject { // skip
    
    func test1() { // skip
    }
    
    struct SubClass { // skip
        
        func test2() { // skip
        }
    }
}

其他规则

这些规则默认使用,你无法配置它们。

override

跳过覆盖另一个的声明。 这适用于子类重写和协议扩展重写。

protocol ExampleProtocol {
	func test() // used
}

class Example: ExampleProtocol {
    func test() { // used
    }
}

class Animal {
    func run() {  // used
    }
}

class Dog: Animal {
    override func run() { // used
    }
}

extensions

在其他地方引用意味着被使用,除了扩展之外。

class UnusedExample { // unused
    
}

extension UnusedExample {
    
}

配置

这是可选的,如果未指定,将使用默认值。 通过从运行 pecker 的目录添加 .pecker.yml 文件来配置 pecker。 可以配置以下参数

规则包含

报告器包含

reporter: "xcode"

disabled_rules:
  - skip_public

included: # paths to include during detecting. `--path` is ignored if present.
  - ./
  
excluded: # paths to ignore during detecting. Takes precedence over `included`.
  - Carthage
  - Pods

excludedGroupName: # names of group to ignore during detecting.
  - SwiftPeckerTestUITests

blacklist_files: # files to ignore during detecting, only need to add file name, the file extension default is swift.
  - HomeViewController

blacklist_symbols: # symbols to ignore during detecting, contains class, struct, enum, etc.
  - AppDelegate
  - viewDidLoad

blacklist_superclass: # all the class inherit from class specified in the list will ignore
  - UITableViewCell

# If output_file is not specified, the defaults to be pecker.result.json in your project

output_file: pecker.result.jsonthe path can be both relative and absolute.

贡献和支持

pecker 是完全开放开发的。

欢迎任何贡献和 pull request。 如果你有兴趣开发 pecker,请提交想法并提交 pull request!

许可

pecker 是在 MIT 许可证 下发布的。