#分析 #提交 #文件 # #tree-sitter #关系 #历史

bin+lib gossiphs

一个用于通用代码文件关系分析的 Rust 库。基于 tree-sitter 和 git 分析。

14 个版本 (5 个破坏性更新)

新版本 0.6.1 2024 年 8 月 18 日
0.5.2 2024 年 7 月 7 日

402解析实现

Download history 149/week @ 2024-04-22 116/week @ 2024-04-29 155/week @ 2024-05-06 162/week @ 2024-05-20 205/week @ 2024-05-27 86/week @ 2024-06-03 140/week @ 2024-06-10 126/week @ 2024-06-17 41/week @ 2024-06-24 170/week @ 2024-07-01 47/week @ 2024-07-08 110/week @ 2024-07-29 16/week @ 2024-08-05

每月下载量 130

Apache-2.0

81KB
2K SLoC

Gossiphs = Gossip Graphs

Crates.io Version RealWorld Test

一个用于通用代码文件关系分析的实验性 Rust 库。基于 tree-sitter 和 git 分析。

它是做什么的

Gossiphs 可以分析代码库中提交的历史和变量声明与引用之间的关系,以获得代码文件的关系图。

它还允许开发者查询每个文件中声明的内容,从而在整个代码库中自由搜索其引用,以实现更复杂的分析。

graph TD
    A[main.py] --- B[module_a.py]
    A ---  C[module_b.py]
    B --- D[utils.py]
    C --- D
    A --- E[module_c.py]
    E --- F[module_d.py]
    E --- H[module_e.py]
    H --- I[module_f.py]
    I --- D

目标与动机

代码导航是一个迷人的主题,在各个领域发挥着关键作用,如

  • 在 IDE 开发过程中的上下文引导。
  • 简化网站上的代码浏览。
  • 分析持续集成 (CI) 系统中代码更改的影响。
  • ...

在过去,我努力将 LSP/LSIF 技术 和类似 Github 的 Stack-Graphs 的技术应用于影响分析,沿途遇到了不同的挑战。对于我们来说,类似于 Stack-Graphs 的方法与我们期望最为接近。然而,挑战是明显的:它需要制定高度语言特定的规则,这对于我们来说是一项相当大的投资,因为我们不需要这样高精度数据。

我们试图在某些方面对当前遇到的 stack-graphs 的挑战做出一些权衡,以在一定程度上实现我们期望的目标

  • 零仓库特定配置:它可以应用于大多数语言和仓库而无需额外配置。
  • 低扩展成本:添加语言规则的成本不高。
  • 可接受的精度:我们已经牺牲了一定程度的精度,但我们希望它仍然保持在可接受的水平。

它是如何工作的

Gossiphs 构建一个连接定义和引用符号的图。

  1. 提取导入和导出:识别每个文件的导入和导出。
  2. 连接节点:在潜在的定义和引用节点之间建立连接。
  3. 使用提交历史来细化边缘:利用提交历史来细化节点之间的关系。

与堆栈图不同,我们省略了高度复杂的范围分析,而是选择使用提交历史来细化我们的边缘。这种方法显著降低了规则编写复杂性,因为规则只需要指定每个文件应导出或导入哪种类型的符号。

虽然无疑会有精度上的权衡,但好处是明显的

  1. 对准确性的影响最小:在实际场景中,精度损失并不像预期的那样显著。
  2. 提交历史相关性:使用提交历史来反映代码段之间的相互影响与我们的目标相吻合。
  3. 语言支持:我们可以轻松支持绝大多数编程语言,满足各种类型存储库的分析需求。

支持的语言

基于Tree-Sitter 查询扩展语言支持,这并不太耗费成本。如果您感兴趣,可以查看贡献部分。

语言 状态
Rust
Python
TypeScript
JavaScript
Golang
Java
Kotlin
Swift

您可以在这里看到规则文件。

使用方法

该项目仍处于实验阶段。

作为一个命令行工具

您可以在我们的发布页面找到适用于您的平台的预编译文件。解压后,您可以使用gossiphs --help来获取相应的帮助。

将文件关系矩阵导出到csv

gossiphs relation
gossiphs relation --csv abc.csv

您可以使用类似pandas的工具处理这个矩阵,并进一步分析而无需访问Rust部分。

带上下文的差异

# diff between HEAD and HEAD~1
gossiphs diff

# custom diff
gossiphs diff --target HEAD~5
gossiphs diff --target d18a5db39752d244664a23f74e174448b66b5b7e

# output json
gossiphs diff --json

输出

src/services/user-info/index.ts
├── src/background-script/driveUploader.ts (ADDED)
├── src/background-script/task.ts (DELETED)
├── scripts/download-config.js (DELETED)
├── src/background-script/sdk.ts
├── src/services/user-info/listener.ts
├── src/services/config/index.ts
├── src/content-script/modal.ts
├── src/background-script/help-center.ts
  • 新增:指在此差异中添加的文件关系
  • 删除:指在此差异中删除的文件关系
  • 其他:指在此差异中未受到影响且原本存在的文件关系

Obsidian 图

例如,您可以使用此命令生成一个obsidian 仓库

gossiphs obsidian --project-path . --vault-dir ./target_vault

并获得代码关系图

image

作为一个Rust库

请参阅示例了解用法。

fn main() {
    let config = GraphConfig::default();
    let g = Graph::from(config);

    // done! just try it
    let all_files = g.files();
    for file in &all_files {
        // related file search
        let related_files = g.related_files(file);
        for each_related in &related_files {
            println!("{} -> {}: {}", file, each_related.name, each_related.score);
        }

        // file details
        if !related_files.is_empty() {
            let random_file = related_files[0].name.clone();
            let meta = g.file_metadata(&random_file);
            println!("symbols in {}: {:?}", random_file, meta.symbols.len());

            // and query the symbol infos
        }
    }
}

作为一个本地服务器

启动一个类似于LSP的本地服务器供其他客户端使用可能是一个合理的做法,这正是我们目前所做的事情。

./gossiphs server --project-path ./your/project --strict

API描述可以在这里找到。

精度

静态分析有其局限性,例如动态绑定。因此,不太可能达到LSP提供的精度水平,但可以在其主要应用领域提供足够的精度。

我们用来展示精度的方法是将其与LSP/LSIF的结果进行比较。必须承认,静态推理几乎不可能获得像LSP那样的所有引用关系,但在严格模式下,我们的计算精度仍然相当可观。在正常模式下,您可以根据返回的权重决定是否采用该关系。

存储库 精度(严格模式) 生成的图时间
https://github.com/williamfzc/srctx 80/80 = 100 % 83.139791ms
https://github.com/gin-gonic/gin 160/167 = 95.80838 % 310.6805ms

贡献

该项目仍处于非常早期和实验阶段。如果您感兴趣,请通过问题反馈您的想法。短期内,我们希望为更多语言提供更好的支持。

您只需

  1. src/rule.rs中编辑规则
  2. src/extractor.rs中进行测试
  3. src/graph.rs中使用您的仓库进行测试

许可证

Apache 2.0

依赖项

~116MB
~3M SLoC