ng-galien/code-moniker
GitHub: ng-galien/code-moniker
将代码符号图转化为可查询的原生类型,提供 CLI lint 和 PostgreSQL 扩展两种接口,支持跨文件依赖约束和架构治理。
Stars: 0 | Forks: 0
# code-moniker
[](https://github.com/ng-galien/code-moniker/actions/workflows/ci.yml)
[](#license)
[](https://www.rust-lang.org)
[](https://github.com/pgcentralfoundation/pgrx)
[](https://www.postgresql.org)
`code-moniker` 使符号图变得可查询。提供两种接口,一个提取器:
- 一个**独立的 CLI**,根据声明式规则包对项目进行 lint 检查 —— 可用作 agent 防护栏、pre-commit 门禁或 CI 任务;
- 一个 **PostgreSQL 扩展**,将相同的图作为原生 SQL 类型(`moniker`、`code_graph`)公开,并提供带索引的代数运算。
无需维护索引,无需守护进程 —— linter 可以在任何检出代码上运行而无需额外设置;基准测试详见 [`docs/perf.md`](docs/perf.md)。
支持的语言:TypeScript / JavaScript / TSX / JSX、Rust、Java、Python、Go、C#、SQL、PL/pgSQL。
## 为什么开发这个项目
**SCIP / LSIF / tree-sitter-graph** 将符号图导出为静态文件 —— 你需要在此基础上添加自己的使用者来查询它们。**Semgrep CE、ast-grep** 以及本地语法模式匹配器为你提供了查询语言,但它们匹配的是语法而不是符号图,因此跨文件引用和分层约束(例如 `domain/` 不能依赖 `infrastructure/`)作为基本操作仍然难以实现。
`code-moniker` 将结构上下文融入到了符号标识中。
`src/domain/order/` 下的 `class OrderEntity` 的 AST 具体表现为如下形式(以 `src/` 为根目录进行扫描):
```
// src/domain/order.ts
class OrderEntity { save(r: OrderRepo) {…} }
│ extract
▼
moniker (identity + structural path, one per def):
◆ code+moniker://app/lang:ts/dir:domain/module:order/class:OrderEntity
└────────┘
layering anchor — pattern-matchable
◆ …/class:OrderEntity/method:save(OrderRepo)
code_graph (edges between monikers):
…/method:save ── uses_type ──▶ …/dir:domain/module:repo/interface:OrderRepo
```
moniker URI 承载了标识和结构路径;`code_graph` 承载了 moniker 之间的关系(调用、导入、实现、扩展、uses_type)。像 `source ~ '**/dir:domain/**' => target ~ '**/dir:domain/**'` 这样的规则就可以变成一个单行命令,由 linter 逐个文件、无状态地执行。
Postgres 扩展就是将此模型移植到数据库中。
`moniker` 和 `code_graph` 变成了原生 SQL 类型;代数运算(`<@` 用于子树,`?=` 用于跨文件解析的 `bind_match`,`@>` 用于祖先关系)变成了由 GiST 和 GIN 索引支持的 SQL 操作符。现在符号图可以与你的领域表放在一起,并在一个查询中进行关联:
```
-- Which deployments in the last week touched code under dir:domain/?
SELECT d.id, d.deployed_at, m.source_uri
FROM module m
JOIN deployment d ON d.path = m.source_uri
WHERE graph_root(m.graph) <@ 'code+moniker://app/lang:ts/dir:domain'::moniker
AND d.deployed_at > now() - interval '7 days';
```
## 安装
CLI(独立运行,无需 Postgres):
```
cargo install --git https://github.com/ng-galien/code-moniker --features cli code-moniker
```
通过本地克隆安装:
```
cargo install --path . --features cli
```
Postgres 扩展(通过 pgrx 支持 PG17;Docker 变体请参见 [`docs/use-in-postgres.md`](docs/use-in-postgres.md)):
```
cargo install --locked cargo-pgrx
cargo pgrx init --pg17 download
cargo pgrx install --pg-config $HOME/.pgrx/17.9/pgrx-install/bin/pg_config
```
然后在任何 PG17 数据库中执行 `CREATE EXTENSION code_moniker;`。
## CLI — `code-moniker check`
```
# .code-moniker.toml
[[refs.where]]
id = "domain-no-infra"
expr = "source ~ '**/dir:domain/**' => NOT target ~ '**/dir:infrastructure/**'"
[[ts.class.where]]
id = "no-god-class"
expr = "count(method) <= 20 AND all(method, lines <= 60)"
```
```
$ code-moniker check src/
src/domain/order.ts:L42-L88 [ts.class.no-god-class] class `Order` fails `count(method) <= 20`
→ Class `Order` is too wide (24).
1 violation(s) across 1 file(s) (47 scanned).
$ echo $?
1
```
规则针对的是符号及其关系(调用、导入、继承、分层、命名),而不仅仅是语法。退出码 1 是 `PostToolUse` 钩子、pre-commit 和 CI 的拦截信号。
→ [docs/use-as-agent-harness.md](docs/use-as-agent-harness.md)
## Postgres 扩展 — `extract_
` + 带索引的代数运算
```
CREATE EXTENSION code_moniker;
SELECT extract_typescript(
'src/util.ts',
'export class Util { run() { return 1; } }',
'code+moniker://app'::moniker
);
SELECT 'code+moniker://app/lang:ts/dir:src/module:util/class:Util'::moniker
<@ 'code+moniker://app/lang:ts'::moniker; -- subtree containment, GiST-indexed
```
`moniker` 承载节点标识;`code_graph` 承载模块的定义和引用。跨文件链接只需在 `?=`(`bind_match`)上进行一次带索引的 JOIN。该扩展不拥有任何数据表 —— 仅包含类型、操作符和纯函数。
→ [docs/use-in-postgres.md](docs/use-in-postgres.md)
## 文档导览
| 目标 | 阅读 |
|---------------------------------------------------------------------|-------------------------------------------------------------------|
| 对项目进行 lint,拦截 agent,防护 pre-commit / CI | [docs/use-as-agent-harness.md](docs/use-as-agent-harness.md) |
| 在 Postgres 中索引代码库以进行跨文件查询 | [docs/use-in-postgres.md](docs/use-in-postgres.md) |
| CLI 参考(单文件探测、项目 linter、规则 DSL) | [docs/README.md](docs/README.md) |
| 添加语言,修改 SQL 接口,构建与测试 | [CONTRIBUTING.md](CONTRIBUTING.md) · [docs/design/spec.md](docs/design/spec.md) |
## 接口
- 类型:`moniker`、`code_graph`。
- 操作符:`=`、`?=`(`bind_match`)、`<` / `<=` / `>` / `>=`、`<@` / `@>`、`||`(组合子级)。
- 索引:`moniker` 上的 btree / hash / GiST 索引,`moniker[]` 上的 GIN 索引。
- 提取器:`extract_typescript`、`extract_rust`、`extract_java`、`extract_python`、`extract_go`、`extract_csharp`、`extract_plpgsql`。清单解析器:`extract_cargo`、`extract_package_json`、`extract_pom_xml`、`extract_pyproject`、`extract_go_mod`、`extract_csproj`。
- 用于合成图的构造器:`code_graph_declare(jsonb)` / `code_graph_to_spec(code_graph)`。
## 许可证
根据 [MIT](LICENSE-MIT) 或 [Apache 2.0](LICENSE-APACHE) 双重许可,任您选择。贡献将在相同的条款下被接受。标签:JSX, odt, pgrx, PostgreSQL扩展, Rust, SQL, TSX, 代码 lint, 代码依赖分析, 代码分析, 代码安全, 代码搜索, 代码查询, 代码索引, 依赖管理, 凭证管理, 可视化界面, 多线程, 威胁情报, 开发者工具, 开源, 抽象语法树, 数据结构, 架构治理, 测试用例, 源代码审计, 漏洞枚举, 符号图, 系统审计, 编译器前端, 网络流量审计, 跨语言分析, 通知系统, 错误基检测, 静态代码分析