Documentation
¶
Overview ¶
Package parser 定义解析器插件接口与 Go 实现(impl §5)。 核心引擎与语言无关,语言解析是插件:输入源文件,输出符号列表 + 代码单元边界与双哈希。
Index ¶
- func ExcludedPath(rel string) bool
- func FileHash(syms []Symbol) string
- func HashFileFor(p Parser, syms []Symbol, src []byte) string
- func IsGenerated(src []byte) bool
- func PythonAvailable() bool
- func Signature(sym Symbol) string
- type CallExtractor
- type CallRef
- type ContextParser
- type FileCalls
- type FileHasher
- type Generic
- type Golang
- func (Golang) Extensions() []string
- func (Golang) FileCalls(path string, src []byte) (*FileCalls, error)
- func (g Golang) HashFile(src []byte) string
- func (Golang) HashParsedFile(syms []Symbol, src []byte) string
- func (Golang) Language() string
- func (Golang) Parse(path string, src []byte) ([]Symbol, error)
- type IfaceDecl
- type Java
- type ParsedFileHasher
- type Parser
- type Python
- type Registry
- type Rust
- type Symbol
- type TypeScript
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExcludedPath ¶
ExcludedPath 判断 repo 相对路径(正斜杠)是否落在默认排除段内: vendor/、testdata/、.knowledge/(impl §5)。任意一段命中即排除。
func HashFileFor ¶
HashFileFor 统一出口:插件自定义优先,否则符号级联(engine 各锚定点共用)。
func IsGenerated ¶
IsGenerated 判断源码是否为生成代码:首行匹配官方约定(impl §5 定案按首行)。 全程 []byte 操作:原实现两次 string(src) 整文件拷贝,init 全库扫描是热路径。
Types ¶
type CallExtractor ¶
CallExtractor 是解析器插件的可选能力:提取调用引用(第一期仅 Go 实现)。 不并入 Parser 接口——多语言插件可以只做符号提取不做调用图。
type CallRef ¶
type CallRef struct {
Qual string // 选择器限定名;"" 表示同包直呼或接收者自调
Name string // 目标基名;接收者自调为 "Type.Method" 形式
}
CallRef 是一条未归位的调用引用。
静态近似的边界(有类型检查才能做的都不做,留痕):
- 接口分发经方法集匹配近似解析(engine 层,2026-07-04 codegraph 启发; 函数值/闭包的分发仍不解析);
- 链式选择器(a.b.C())不解析;
- 非接收者局部变量上的方法调用只带基名,归位靠包内唯一基名启发 + 接口分发兜底。
type ContextParser ¶ added in v0.4.0
type ContextParser interface {
ParseContext(ctx context.Context, path string, src []byte) ([]Symbol, error)
}
ContextParser is an optional parser capability for implementations that may block in an external tool. Engine request paths prefer it so MCP cancellation can terminate the child process instead of waiting for the parser's independent timeout.
type FileCalls ¶
type FileCalls struct {
Package string // package 声明名
Imports map[string]string // 本地限定名 → import 路径(别名已应用;dot/blank 不入)
Decls []string // 本文件符号规范名(与 Parse 同序同名,~n 消歧一致)
Calls map[string][]CallRef // 调用方规范名 → 出边引用(同方去重,按出现序)
Interfaces []IfaceDecl // 接口声明(接口→实现的方法集匹配用,2026-07-04 增)
}
FileCalls 是一个源文件的调用引用提取结果(impl §5 修订:全仓调用图,AST 近似)。 引用在这里只提取不归位——跨文件/跨包解析需要包符号表与 go.mod 模块路径, 属 engine 层职责;parser 保持单文件视角(插件接口语言无关)。
type FileHasher ¶
FileHasher 是插件的可选能力:自定义文件级锚定哈希(2026-07-04 多语言修订)。 缺省(不实现)用 FileHash(syms)=符号哈希级联——依赖真 AST 的格式化免疫; 无符号提取的插件(Generic)必须实现它,否则空符号级联出常量哈希,腐烂检测失明。
type Generic ¶
type Generic struct {
// contains filtered or unexported fields
}
Generic 是通用文件级插件(2026-07-04 多语言 T0,impl §5 修订): 任何扩展名(config.yaml extensions 白名单,缺省关)→ 只建 file/dir 节点, 零符号提取。账本/经验/hook 注入/腐烂检测在文件粒度全部可用; 放弃的是符号粒度、格式化免疫(内容哈希:重排格式即 suspect,批量出口 reanchor_all)与调用图(热区自动退化为纯 git 频率)。 覆盖 proto/SQL/前端/配置等一切文本——账本价值的大头本就常挂文件级。
func NewGeneric ¶
NewGeneric 建通用插件;exts 形如 [".proto", ".sql"](调用方负责去掉已被 专职插件占用的扩展名——Registry.Register 不做覆盖检查)。
func (Generic) Extensions ¶
type Golang ¶
type Golang struct{}
Golang 是 go/ast 实现的解析器插件(impl §5,第一版唯一插件,零新依赖)。
func (Golang) Extensions ¶
func (Golang) FileCalls ¶
FileCalls 提取 Go 文件的调用引用(CallExtractor 实现)。 规范名与 Parse 完全同法计算(接收者去指针去类型参数、~n 消歧), 保证 engine 拼出的 node ID 与骨架节点一致。
func (Golang) HashFile ¶ added in v0.3.0
HashFile 是 FileHasher 能力的独立出口。常规引擎路径会优先调用 HashParsedFile 复用已有符号;直接调用本方法时才自行解析。
func (Golang) HashParsedFile ¶ added in v0.3.0
HashParsedFile 复用符号 Hash 级联,另用 ImportsOnly 快速读取全量文件上下文。 符号锚对显式 alias 只纳入实际使用者,对无法证明真实包名的隐式 import 保守全纳入;文件锚始终覆盖全部 import。
type IfaceDecl ¶
type IfaceDecl struct {
Name string // 接口类型名(与 Decls 中的规范名一致)
Methods []string // 显式方法名(签名不参与——AST 近似,同名不同签名可能过匹配,靠 ≥2 方法阈值兜)
Embeds []CallRef // 内嵌接口引用(Qual=""同包 / 限定名跨包);仓外内嵌无从展开,整个接口跳过匹配
}
IfaceDecl 是一个接口声明的提取结果(方法名集 + 内嵌引用,归位在 engine)。
type Java ¶
type Java struct{}
Java 解析器(R29-续 多语言 T1)。
同 Rust/TypeScript 决策:纯 Go 轻量词法分析(零运行时依赖,不经 javac)。 Java 语法规整:package/import/class/interface/enum/record + 方法。
两遍扫描(比单遍状态机更可靠):
- 找所有顶层 type 声明(class/interface/enum/record),记录名 + body 花括号范围;
- 在每个 type body 内找方法(Type.method 规范名)。
粒度:顶层 class/interface/enum/record(type) + 类内方法。 取舍(宁缺不要错):泛型、注解、嵌套类精度有限;漏符号降级文件级。
哈希:Hash = sha256("jv\0"+归一化body);StructHash = 名换占位(改名免疫,迁移匹配)。
func (Java) Extensions ¶
type ParsedFileHasher ¶ added in v0.3.0
ParsedFileHasher 让已有符号结果的插件复用 Parse 成果,避免为文件锚 再做一次完整解析。优先级高于只接收原文的 FileHasher。
type Parser ¶
type Parser interface {
Language() string // "go"
Extensions() []string // [".go"]
Parse(path string, src []byte) ([]Symbol, error)
}
Parser 是解析器插件接口(impl §5)。
type Python ¶
type Python struct{}
Python 解析器(2026-07-04 多语言 T1,自托管范式):让语言用**自己的工具链** 解析自己——python3 内置 ast 模块经助手脚本吐 JSON,Go 侧零新依赖(铁律一); 运行时依赖仅在仓库真有 .py 时才需要(python3 不在 PATH → 不注册,.py 不索引, 可用 config extensions 白名单降级为文件级覆盖)。
粒度与哈希语义对齐 Go 插件:
- 符号 = 顶层 def/async def/class + 类方法(Class.method 规范名;嵌套函数属外层 body);
- Hash = sha256("py\0"+kind+"\0"+ast.dump(节点)):格式化/缩进/# 注释免疫 (# 注释不在 AST——注释变更不失配,弱于 Go 的 doc 参与,留痕;docstring 在 AST 内,变更失配,与 Go 的 doc 语义等效);
- StructHash = 自身名换占位符后的 dump:改名免疫,仅迁移匹配;
- class 符号的哈希剥离方法体(方法另有符号)——方法改动不连坐 class 节点。
成本留痕:每文件一次 python3 子进程(~30-50ms);init 全库扫描在纯 Python 大仓上分钟级,增量路径(remember/recall 单文件)无感。调用图暂不提供 (CallExtractor 需要 Python 自己的 import 归位规则,等真实使用信号)。
func (Python) Extensions ¶
func (Python) HashFile ¶ added in v0.3.0
HashFile 以整棵 Python AST 为锚,不再只级联函数/类符号。 因此 import、模块常量和顶层执行语句的语义变更都会使文件腐烂。
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry 按扩展名分发解析器。
func NewRegistry ¶
func NewRegistry() *Registry
NewRegistry 返回注册了全部内置解析器的注册表:Go(go/ast)恒在; Python(自托管助手,2026-07-04 多语言 T1)按本机 python3 可用性注册—— 不可用则 .py 不索引(可经 config extensions 白名单降级为文件级覆盖)。 TypeScript/JavaScript(R29 批次6,纯 Go 词法,零运行时依赖)恒注册。
type Rust ¶
type Rust struct{}
Rust 解析器(R29-续 多语言 T1)。
同 TypeScript 决策:纯 Go 轻量词法分析(零运行时依赖,rustc 不经子进程调用)。 Rust 语法比 JS 更规整——`fn`/`pub fn`/`impl Type`/`struct`/`enum`/`trait` 关键字明确, 花括号/圆括号配对提取符号,跳过字符串/注释防误匹配。
粒度:顶层 fn、impl 块内的方法(Type.method 规范名)、struct/enum/trait 声明(type)。 取舍(宁缺不要错):宏调用、复杂泛型 where 子句、嵌套 fn 精度有限;漏符号降级文件级。
哈希:Hash = sha256("rs\0"+归一化body);StructHash = 名换占位(改名免疫,迁移匹配)。
func (Rust) Extensions ¶
type Symbol ¶
type Symbol struct {
Name string // 规范名,文法见 impl §3(接收者去指针去类型参数;同名符号带 ~n 序号)
Kind string // func | method | type | var | const
Start int // 字节偏移,含 doc comment
End int
Body []byte // [Start:End) 原文
Lines [2]int
// 双哈希在 Parse 时计算(依赖 AST,离开 parser 无从复算):
Hash string // 锚定/腐烂检测:go/printer 标准重打印(gofmt 免疫),含 doc comment
StructHash string // 迁移匹配:剥全部注释、自身标识符换占位符;绝不用于腐烂检测
DocStructHash string // doc 敏感的迁移护栏:仅自身名免疫,契约 doc 改动必失配
}
Symbol 是从源文件提取出的一个符号(impl §5 定稿)。
type TypeScript ¶
type TypeScript struct{}
TypeScript/JavaScript 解析器(R29 批次6 多语言 T1)。
策略决策(零重依赖铁律下):Node.js 不自带 JS/TS AST 解析库(vm 只解析 JS, 不支持 TS;acorn/babel 需 npm 装,违反零依赖哲学)。故用**纯 Go 轻量词法分析**: 扫描顶层 function/class/method/export 声明关键字 + 大括号配对算行范围。
这是近似解析(像 codegraph 的"宁缺不要错",knowledge.md §16.3):
- 优点:零运行时依赖、跨平台无差异、对所有 JS/TS 变体(含 TS 类型注解)都能词法提取;
- 取舍:不解析完整 AST,嵌套函数/箭头函数/装饰器精度有限;复杂泛型/JSX 可能漏符号。 漏符号不致错(降级为文件级),错符号会致错——所以倾向漏(宁缺)。
粒度与哈希语义对齐 Go/Python 插件:
- 符号 = 顶层 function/class + 类方法(Class.method 规范名);
- Hash = sha256("ts\0"+kind+"\0"+归一化body):归一化 = 横向空白压缩 + LineTerminator 归一为 `\n` + 去注释。JS 的 ASI/受限产生式让换行可能改变 语义,故只对横向格式免疫,换行保守敏感(弱于 Go 的 AST 精确重打印,留痕);
- StructHash = 自身名换占位符后的归一化:改名免疫,仅迁移匹配;
- class 符号的哈希剥离方法体(方法另有符号)——方法改动不连坐 class 节点。
func (TypeScript) Extensions ¶
func (TypeScript) Extensions() []string
.ts/.tsx/.js/.jsx/.mjs/.cjs/.mts/.cts 全覆盖(JS/TS 生态全扩展名)。
func (TypeScript) HashFile ¶
func (TypeScript) HashFile(src []byte) string
实现 FileHasher:文件级哈希(无符号时不能空级联出常量,见 parser.go FileHasher 注释)。
func (TypeScript) Language ¶
func (TypeScript) Language() string