其實已經(jīng)有一個不錯的用Swift寫的命令行工具檢測不用的圖片資源了,就是喵神的FengNiao语稠,至于為什么要再寫一個呢,主要是為了學(xué)習(xí)SwiftSyntax输涕,前段時間我寫了篇文章簡單的介紹了SwiftSyntax慨畸,文章在這里SwiftSyntax詳解,對SwiftSyntax不熟悉的可以先看看型奥。
項目在這里UnusedResources,下面來簡單介紹一下原理厢汹。
1. 找到項目中所有的圖片資源
我這里找的圖片資源有以下幾種:
let imageExtensions: [String] = ["png", "jpg", "gif", "pdf"]
這里不得不提以下Homebrew的作者mxcl開源的庫Path,這個庫真的很好用界弧。我們先定義一個方法來來查找所需擴展名的文件
func recursiveFiles(withExtensions exts: [String], at path: Path) throws -> [Path] {
if path.isFile {
if exts.contains(path.extension) {
return [path]
}
return []
} else if path.isDirectory {
var files: [Path] = []
for entry in try path.ls() {
let list = try recursiveFiles(withExtensions: exts, at: entry.path)
files.append(contentsOf: list)
}
return files
}
return []
}
找到所有的圖片資源就只要下面簡單的一段代碼就可以了
var images: [Path] = try recursiveFiles(withExtensions: imageExtensions, at: path)
2. 查看項目中源代碼文件
找到源代碼文件
var files: [Path] = try recursiveFiles(withExtensions: ["swift", "h", "m", "mm"], at: path)
這里就需要用到SwiftSyntax垢箕,我們定義一個StringVisitor遍歷語法樹兑巾,提取字符串并判斷是否和圖片名稱一樣,一樣就說明圖片被使用了帅掘。
我們一個簡單的swift代碼的語法樹,可以用xcrun swiftc -frontend -emit-syntax ./Cat.swift | python -m json.tool
命令查看源代碼語法樹結(jié)構(gòu)修档,但是還是比較復(fù)雜府框,包含import庫的部分,所以我選擇用Swift AST Explorer院峡,這個是基于SwiftSyntax實現(xiàn)系宜,語法樹更簡潔。
我們只要拿到StringSegmentSyntax的內(nèi)容就好了实抡,然后和圖片進行對比欢策,和圖片一樣赏淌,就表示圖片被使用到了。
public struct StringVisitor: SyntaxVisitor {
public var images: [Path] = []
public init(_ images: [Path]) {
self.images = images
}
// Ignore string interpolated literal because it's too complex to compare
public mutating func visit(_ node: StringLiteralExprSyntax) -> SyntaxVisitorContinueKind {
guard node.segments.count == 1 else {
return .skipChildren
}
return .visitChildren
}
public mutating func visit(_ node: StringSegmentSyntax) -> SyntaxVisitorContinueKind {
let text = node.content.text
.trimmingCharacters(in: .whitespacesAndNewlines)
guard !text.isEmpty else {
return .skipChildren
}
images = images.filter { $0.basename(dropExtension: true) != text }
return .skipChildren
}
}
OC和Swift的語法書稍微有點不一樣俺孙,所以我們可以得到所有的TokenSyntax,然后找到類型是stringLiteral的荣茫,這里我處理比較簡單场靴,直接判斷stringLiteral是否包含圖片名稱,如果包含就表示圖片被使用了旨剥。
所以我們再給StringVisitor添加一個方法
// for Objective-C
public mutating func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
switch token.tokenKind {
case .stringLiteral(let text):
images = images.filter { !text.contains($0.basename(dropExtension: true)) }
default:
break
}
return .visitChildren
}
3. 查看XML文件
let xmlExtensions: [String] = ["xib", "storyboard"]
var xmlFiles: [Path] = try recursiveFiles(withExtensions: xmlExtensions, at: path)
這里需要用到XMLParser找到attributeDict中key為“image”的value魄咕,如果和圖片名稱一樣就表示圖片被使用了。
4. Makefile
使用Makefile來build項目哮兰,自動將生成的unused-resources拷貝到/usr/local/bin
中梢什。
5. 總結(jié)
水文一篇,最近在研究編譯相關(guān)的知識囤躁,進展十分緩慢荔睹,心累。