美文网首页
基于SwiftSyntax写一个命令行工具检测Xcode项目中不

基于SwiftSyntax写一个命令行工具检测Xcode项目中不

作者: 小凉介 | 来源:发表于2019-11-06 19:06 被阅读0次

其实已经有一个不错的用Swift写的命令行工具检测不用的图片资源了,就是喵神的FengNiao,至于为什么要再写一个呢,主要是为了学习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命令查看源代码语法树结构,但是还是比较复杂,包含import库的部分,所以我选择用Swift AST Explorer,这个是基于SwiftSyntax实现,语法树更简洁。

屏幕快照 2019-11-06 下午6.44.40.png

我们只要拿到StringSegmentSyntax的内容就好了,然后和图片进行对比,和图片一样,就表示图片被使用到了。

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是否包含图片名称,如果包含就表示图片被使用了。

屏幕快照 2019-11-06 下午6.39.09.png

所以我们再给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. 总结

水文一篇,最近在研究编译相关的知识,进展十分缓慢,心累。

相关文章

网友评论

      本文标题:基于SwiftSyntax写一个命令行工具检测Xcode项目中不

      本文链接:https://www.haomeiwen.com/subject/eikpbctx.html