OldJii/dead-code-pruner

GitHub: OldJii/dead-code-pruner

基于 tree-sitter 的多语言源码级死代码清理工具,通过布尔常量传播和项目级引用分析安全移除废弃代码。

Stars: 64 | Forks: 0

# dead-code-pruner `dead-code-pruner` 是一款基于 [tree-sitter](https://tree-sitter.github.io/) 驱动的、稳健的源码级死代码清理工具。 给定一组永远为 `true` 或 `false` 的表达式,它会将这些事实传播到源代码树中,简化生成的控制流,并移除那些被证明已不再使用的声明和文件。 该工具目前支持 Java、Kotlin、Go、Swift 和 Dart。它专为 Android、JVM 服务、Go 服务、iOS 和 Flutter 仓库设计,包括多模块项目。 ## 可清理的内容 从配置的常量开始,该工具可以产生如下源代码更改: - 将废弃的 feature flags 和编译时条件替换为布尔字面量。 - 简化布尔表达式、逻辑非、相等性检查、短路表达式、三元运算符以及特定语言的 conditional 表达式。 - 移除废弃的 `if` 分支,以及在 `return`、`throw`、`break` 或 `continue` 之后变得不可达的代码。 - 传播不可变的局部布尔变量,并在其所有使用处消失后移除其声明。 - 内联总是返回 `true` 或 `false` 的无参方法,然后继续清理新暴露出来的分支。 - 移除空方法、未使用的返回常量的辅助方法及其安全的调用处。 - 当全项目范围的引用和项目边界规则证明删除是安全的时,移除未使用的不可变字段。 - 移除未引用的空类以及不再包含任何声明的源文件。 - 重复级联清理,直到无法再得出进一步的源代码更改为止。 例如,一个已废弃的 feature 可以跨多个文件折叠到剩余的活跃路径中: ``` diff --git a/LegacyFeatureController.java b/LegacyFeatureController.java --- a/LegacyFeatureController.java +++ b/LegacyFeatureController.java @@ final class LegacyFeatureController { - private static final boolean RETIRED_DEFAULT = false; - - private boolean isLegacyMode() { - return false; - } - - private void recordLegacyExposure() {} - void render() { - final boolean legacyEnabled = FeatureFlags.LEGACY_MODE; - recordLegacyExposure(); - if (!legacyEnabled - && (LegacyFeatureController.RETIRED_DEFAULT || isLegacyMode())) { - RetiredFeature.renderLegacy(); - return; - unreachableLegacyCleanup(); - } else { - renderCurrent(); - } + renderCurrent(); } } diff --git a/LegacyScreen.kt b/LegacyScreen.kt --- a/LegacyScreen.kt +++ b/LegacyScreen.kt @@ -val title = if (false) legacyTitle else currentTitle +val title = currentTitle diff --git a/RetiredFeature.java b/RetiredFeature.java deleted file mode 100644 --- a/RetiredFeature.java +++ /dev/null @@ -package com.example.legacy; - -final class RetiredFeature { - static void renderLegacy() {} -} ``` 这种清理是刻意保持稳健的。除非该工具能证明移除它们是安全的,否则被注解的声明、框架 entry point、契约、override、动态引用以及可能在扫描的仓库之外使用的 public API 都会被保留。 ## 用法 需要 Python 3.10 或更高版本。 ``` git clone https://github.com/OldJii/dead-code-pruner.git cd dead-code-pruner pip install -r requirements.txt cp pruner.example.yaml pruner.yaml ``` 编辑 `pruner.yaml` 并将示例替换为您项目中废弃的常量: ``` project_boundary: mode: auto replacements: - pattern: "FeatureFlags.LEGACY_MODE" value: false - pattern: "BuildConfig.CURRENT_VARIANT" value: true ``` 针对项目目录运行清理: ``` python3 -m pruner /path/to/your/project --config pruner.yaml ``` 请在单独的 Git 分支上运行,检查生成的 diff,并在合并更改之前对目标项目进行编译和测试。 ## 在 Android 之外使用 该实现包含针对 Java、Kotlin、Go、Swift 和 Dart 的语言适配器和测试,但到目前为止,其大规模生产使用仅在 Android 项目上得到了验证。 对于非 Android 仓库,请从 fork 开始。如果某个语言结构未被正确处理,请将该有问题的源代码作为一个小型的可复现测试用例,让 AI 编程代理分析 AST 或引用解析的缺失,并在调整适配器或清理规则之前添加输入/预期输出的测试。一旦新用例和现有测试套件全部通过,该行为就被固定为一条可重复的规则,您可以放心地将清理应用到目标仓库。 扩展该工具后,请运行完整的测试集: ``` python3 tests/run_tests.py python3 tests/run_project_tests.py python3 tests/test_language_matrix.py python3 tests/test_project_boundary.py ``` ## 工作原理 tree-sitter 将源文件解析为语法树,使得该工具能够区分表达式、声明、调用、注释、字符串和控制流边界,而无需依赖脆弱的文本替换。 该工具首先根据配置的布尔事实简化每个文件。然后,它为声明、引用、继承、契约、生成的 accessor 和动态 entry point 构建项目级别的索引。只有没有剩余安全引用的声明才会被移除。修改后的文件会被再次分析,从而允许一次删除暴露出下一次删除,直到项目达到稳定的结果。 语言适配器为每个生态系统提供语法和框架规则,而项目边界检测则在库中保留外部可见的 API,并允许在应用程序和已部署的服务中进行更广泛的清理。 主要 pipeline 包含两个阶段: 1. **源代码简化** 按源代码顺序运行八个语法级别的步骤,并对每个文件重复执行,直到该文件稳定。 2. **项目清理** 扫描项目一次,移除被证明已废弃的声明,对更改过的文件重新运行源代码简化,在项目索引中刷新这些文件,并重复执行直到稳定。然后移除未引用的空类和文件。 全项目范围的布尔方法内联也作为独立的实用工具公开,用于集中的集成,但它并不是一个单独的 pipeline 阶段。 ## 许可证 MIT
标签:IPv6支持, JS文件枚举, 日志审计, 逆向工具