14 个版本 (5 个破坏性更新)
新版本 0.6.1 | 2024 年 8 月 18 日 |
---|---|
0.5.2 | 2024 年 7 月 7 日 |
402 在 解析实现 中
每月下载量 130
81KB
2K SLoC
Gossiphs = Gossip Graphs
一个用于通用代码文件关系分析的实验性 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 构建一个连接定义和引用符号的图。
- 提取导入和导出:识别每个文件的导入和导出。
- 连接节点:在潜在的定义和引用节点之间建立连接。
- 使用提交历史来细化边缘:利用提交历史来细化节点之间的关系。
与堆栈图不同,我们省略了高度复杂的范围分析,而是选择使用提交历史来细化我们的边缘。这种方法显著降低了规则编写复杂性,因为规则只需要指定每个文件应导出或导入哪种类型的符号。
虽然无疑会有精度上的权衡,但好处是明显的
- 对准确性的影响最小:在实际场景中,精度损失并不像预期的那样显著。
- 提交历史相关性:使用提交历史来反映代码段之间的相互影响与我们的目标相吻合。
- 语言支持:我们可以轻松支持绝大多数编程语言,满足各种类型存储库的分析需求。
支持的语言
基于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
并获得代码关系图
作为一个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 |
贡献
该项目仍处于非常早期和实验阶段。如果您感兴趣,请通过问题反馈您的想法。短期内,我们希望为更多语言提供更好的支持。
您只需
- 在src/rule.rs中编辑规则
- 在src/extractor.rs中进行测试
- 在src/graph.rs中使用您的仓库进行测试
许可证
依赖项
~116MB
~3M SLoC