使用说明
metacall的多语言解析器
一个跨平台的C/C++工具和库,用于解析多语言项目 树坐者。提取函数、类并构建依赖树,而无需运行时执行。
由以下人员拥有和维护 abhicodes 0324.
GSoC项目: 实现多语言解析器
演示视频: YouTube演示
特性
- 静态分析 -解析源文件而不执行代码
- 多语言 -Python、JavaScript/TypeScript和Ruby(可扩展到更多)
- 符号提取 -函数、类和方法
- 导入/需要检测 -构建依赖关系图
- MetaCall检查格式 -可选输出兼容
metacall_inspect(每个文件) - C API -可嵌入其他项目
- 命令行界面 -用于快速分析的命令行界面
构建
先决条件
- CMake 3.24+
- C11编译器(GCC、Clang、MSVC)
- 网络访问(用于首次下载FetchContent)
构建步骤
# Build (from project root) - Tree-sitter grammars are fetched automatically via CMake FetchContent
mkdir build && cd build
cmake ..
cmake --build .
在第一次配置时,CMake通过FetchContent获取Tree sitter语法(需要网络访问)。
安装
从项目根目录运行:
# Option A: Install to /usr/local (requires sudo)
cd ..
sudo cmake --build build --target install
# Option B: Install to user directory (no sudo)
cmake -B build -DCMAKE_INSTALL_PREFIX=$HOME/.local
cmake --build build --target install
# Add to PATH if needed: export PATH="$HOME/.local/bin:$PATH"
安装后 metacall-parser 二进制文件在PATH中可用。要在不安装的情况下运行,请使用 ./build/metacall-parser 从项目根目录(路径相对于当前目录)。
用法
命令行界面
# From project root (after install, or use ./build/metacall-parser without install)
metacall-parser parse tests/sample.py
# Parse and show human-readable output
metacall-parser parse tests/sample.py --format text
# Parse and show MetaCall inspect-compatible JSON
metacall-parser parse tests/sample.py --format inspect
# List functions and classes
metacall-parser list-functions tests/sample.js
# Build dependency graph for a directory
metacall-parser deps tests/
当从 build/ 目录,使用相对路径,如 ../tests/sample.py.
C API示例
#include "metacall_parser.h"
int main(void) {
metacall_parser *parser = metacall_parser_create();
metacall_result *result = metacall_parser_parse_file(parser, "script.py", NULL, 0);
if (result) {
const metacall_file_result *fr = metacall_result_get_file(result);
for (size_t i = 0; i < fr->symbol_count; i++) {
const metacall_symbol *s = &fr->symbols[i];
if (s->type == METACALL_SYMBOL_FUNCTION || s->type == METACALL_SYMBOL_METHOD) {
printf("%s%s: %s(",
s->is_async ? "async " : "",
s->type == METACALL_SYMBOL_METHOD ? "method" : "function",
s->name);
for (size_t p = 0; p < s->param_count; p++) {
if (p > 0) printf(", ");
printf("%s", s->param_names[p]);
}
printf(") [line %u]\n", s->line);
} else if (s->type == METACALL_SYMBOL_CLASS) {
printf("class: %s [line %u]\n", s->name, s->line);
}
}
metacall_result_free(result);
}
metacall_parser_destroy(parser);
return 0;
}
输出格式
解析结果(JSON)
{
"file": "sample.py",
"language": "python",
"functions": [
{
"name": "greet",
"line": 7,
"async": false,
"params": [{ "name": "name" }]
},
{
"name": "add",
"line": 11,
"async": false,
"params": [{ "name": "a" }, { "name": "b" }]
}
],
"classes": [
{ "name": "Calculator", "line": 14 },
{ "name": "DataProcessor", "line": 21 }
],
"imports": [
{"module": "os"},
{"module": "sys"},
{"module": "utils"}
]
}
依赖关系图(JSON)
{
"nodes": [
{"id": "/path/to/main.py", "path": "...", "symbols": [...]},
{"id": "/path/to/utils.py", "path": "...", "symbols": [...]}
],
"edges": [
{"from": "/path/to/main.py", "to": "/path/to/utils.py"}
]
}
样本输出
Python——JSON和文本
$ metacall-parser parse tests/sample.py
{"file":"tests/sample.py","language":"python","functions":[{"name":"greet","line":7,"async":false,"params":[{"name":"name"}]},{"name":"add","line":11,"async":false,"params":[{"name":"a"},{"name":"b"}]},{"name":"add","line":15,"async":false,"params":[{"name":"x"},{"name":"y"}]},{"name":"multiply","line":18,"async":false,"params":[{"name":"x"},{"name":"y"}]},{"name":"process","line":22,"async":false,"params":[{"name":"data"}]}],"classes":[{"name":"Calculator","line":14},{"name":"DataProcessor","line":21}],"imports":[{"module":"utils"}]}
$ metacall-parser parse tests/sample.py --format text
File: tests/sample.py
Language: python
Functions:
- greet (line 7)
- add (line 11)
- add (line 15) [Calculator]
- multiply (line 18) [Calculator]
- process (line 22) [DataProcessor]
Classes:
- Calculator (line 14)
- DataProcessor (line 21)
Imports:
- utils
Python——元调用检查格式
$ metacall-parser parse tests/sample.py --format inspect
{"py":[{"name":"tests/sample.py","scope":{"name":"sample","funcs":[{"name":"greet","async":false,"signature":{"ret":{"type":"Unknown"},"args":[{"name":"name","type":"Unknown"}]}},{"name":"add","async":false,"signature":{"ret":{"type":"Unknown"},"args":[{"name":"a","type":"Unknown"},{"name":"b","type":"Unknown"}]}},{"name":"add","async":false,"signature":{"ret":{"type":"Unknown"},"args":[{"name":"x","type":"Unknown"},{"name":"y","type":"Unknown"}]}},{"name":"multiply","async":false,"signature":{"ret":{"type":"Unknown"},"args":[{"name":"x","type":"Unknown"},{"name":"y","type":"Unknown"}]}},{"name":"process","async":false,"signature":{"ret":{"type":"Unknown"},"args":[{"name":"data","type":"Unknown"}]}}],"classes":[{"name":"Calculator"},{"name":"DataProcessor"}],"objects":[]}}]}
JavaScript——函数和导入
$ metacall-parser list-functions tests/sample.js
File: tests/sample.js
Language: javascript
Functions:
- greet (line 6)
- multiply (line 14)
- add (line 17) [Calculator]
- multiply (line 21) [Calculator]
- process (line 27) [DataProcessor]
Classes:
- Calculator (line 16)
- DataProcessor (line 26)
Imports:
- fs
- ./utils
跨语言依赖关系图
$ metacall-parser deps tests/
{"nodes":[{"id":"tests/utils.py","path":"tests/utils.py","symbols":[{"name":"helper","type":"function","line":3}]},{"id":"tests/sample.py","path":"tests/sample.py","symbols":[{"name":"greet","type":"function","line":7},{"name":"add","type":"function","line":11},{"name":"Calculator","type":"class","line":14},{"name":"add","type":"method","line":15},{"name":"multiply","type":"method","line":18},{"name":"DataProcessor","type":"class","line":21},{"name":"process","type":"method","line":22}]},{"id":"tests/utils.js","path":"tests/utils.js","symbols":[{"name":"helper","type":"function","line":3}]},{"id":"tests/sample.js","path":"tests/sample.js","symbols":[{"name":"greet","type":"function","line":6},{"name":"multiply","type":"function","line":14},{"name":"Calculator","type":"class","line":16},{"name":"add","type":"method","line":17},{"name":"multiply","type":"method","line":21},{"name":"DataProcessor","type":"class","line":26},{"name":"process","type":"method","line":27}]}],"edges":[{"from":"tests/sample.py","to":"tests/utils.py"},{"from":"tests/sample.js","to":"tests/utils.js"}]}
项目结构
metacall-parser/
├── include/
│ └── metacall_parser.h # Public C API
├── src/
│ ├── parser.c # Core parsing logic
│ ├── api.c # JSON export helpers
│ ├── dependency_builder.c
│ └── extractors/
│ ├── python_extractor.c
│ ├── js_extractor.c
│ └── ruby_extractor.c
├── cli/
│ └── main.c
├── tests/
│ ├── sample.py
│ ├── sample.js
│ ├── sample.rb
│ ├── utils.py
│ ├── utils.js
│ └── utils.rb
├── scripts/
│ └── fetch-deps.sh
└── CMakeLists.txt
测试
从项目根:
./tests/run_tests.sh ./build/metacall-parser
测试套件包括:
- python --符号提取(函数、类、方法)、导入检测
- JavaScript --符号提取,相对导入(
./utils) - 红宝石 --符号提取,
require_relative检测 - 依赖图 --边缘
sample.py→utils.py,sample.js→utils.js,sample.rb→utils.rb - 命令行界面 —
--format text,--format inspect
扩展到新语言
解析器的设计便于扩展。MetaCall支持Python、JavaScript、TypeScript、Ruby、C#、Go、Java、Rust、C等。要添加新语言,请执行以下操作:
- 添加Tree Sitter语法作为FetchContent依赖项
- 创建
src/extractors/<lang>_extractor.c实现提取逻辑 - 注册于
metacall_lang_from_path()和那个LANGUAGES[]桌子在parser.c - 将文件扩展名添加到
is_source_file()在dependency_builder.c所以metacall-parser deps包括它 - 为函数、类和导入节点添加查询/遍历
用例
- 智能感知 -将解析后的符号馈送到IDE插件(例如VS Code)
- 功能网格 -将多语言项目分解为可分发的子部分
- 文档 -从静态分析生成API文档
- 重构 -了解跨文件依赖关系