ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

GitNexus PDG Query 完全指南:用 cdg_query/REACHING_DEF 的 control-flows 两层依赖回答“什么守护了什么、值流向了哪里“

GitNexus PDG Query 完全指南:用 cdg_query/REACHING_DEF 的 control-flows 两层依赖回答“什么守护了什么、值流向了哪里“ GitNexus PDG Query 完全指南用 cdg_query/REACHING_DEF 的 control-flows 两层依赖回答什么守护了什么、值流向了哪里【免费下载链接】GitNexusGitNexus: The Zero-Server Code Intelligence Engine - GitNexus is a client-side knowledge graph creator that runs entirely in your browser. Drop in a git repository (Github, Gitlab, Azure, Local) or ZIP file, and get an interactive knowledge graph with a built in Graph RAG Agent. Perfect for code exploration项目地址: https://gitcode.com/GitHub_Trending/gi/GitNexus本指南以 GitNexus 技能文档 gitnexus-pdg-query.md 为核心系统讲解pdg_query这个 MCP 工具的完整使用面它背后的分层程序依赖图CFG / REACHING_DEF / CDG、controls与flows两种查询模式、guard-clause 发现方法与正确的 Cypher 写法以及必须锚定 必须限流等足以影响查询结果正确性的关键陷阱。读完你将能解释任何一条pdg_query结果包括空结果并能读懂、扩展它的底层读取链路_pdgQueryImpl/ CDG / REACHING_DEF。一句话背景pdg_query是控制/数据依赖视角的只读探针GitNexus 把每个仓库索引成一张以 LadybugDB 持久化的代码关系图。除了面向全局的impact()遍历和面向污点流的explain它还暴露了一个以基本块BasicBlock为粒度、完全限定在单个函数内的依赖查询工具pdg_query。它只回答两类问题这条语句在什么条件下才会执行guard 谓词 / 控制依赖读 CDG 边这个变量在函数内部流向了哪里def→use 数据依赖读 REACHING_DEF 边。它不是通用图搜索也不是污点分析——pdg_query是explain污点消费方的控制/数据依赖对偶二者共享同一套持久化基座见 tools.ts 中pdg_query的工具描述The control/data analog of explain。先决条件PDG 层是--pdg的 opt-in 层pdg_query运行的这张图与污点分析taint共用同一张图但所有依赖层都是可选的由gitnexus analyze --pdg显式开启L1 CFG 每函数的 basic blocks 控制流边 L2 REACHING_DEF GEN/KILL 风格的 def→use 数据依赖纯求解器 L5 CDG Ferrante 控制依赖基于 post-dominators在默认的gitnexus analyze不带--pdg下仓库索引产物与开启 PDG 的产物字节级一致——意思是默认运行不会记录上述任何一层。在 CLI 配置上--pdg是一个布尔开关见 analyze-config.ts 与 analyze-options.ts由run-analyze消费并最终把每函数的依赖上限写入RepoMeta.pdg元数据戳见下文no PDG layer探测。因此使用pdg_query前先确认仓库是用 PDG 层索引的gitnexus analyze --repo path --pdg否则工具不会报错而是返回一个携带说明性 note 的空结果详见下文空结果语义。三种边的存储形态同一个 CodeRelation 表靠type区分从底层存储看CFG / REACHING_DEF / CDG 三类边不是三张不同的表而是同一张CodeRelation关系表中的行靠type列区分。实现证据在 emit.tsCFG边第 408–409 行附近写入REACHING_DEF边第 613–617 行附近type: REACHING_DEFCDG边第 768–772 行附近type: CDG。这三类边全部是BasicBlock → BasicBlock方向的边并且图上不存在Function → BasicBlock边。这一点直接影响如何把某个函数解析成一组基本块也是后续所有对齐/行号陷阱的根源。pdg_query的两种模式与参数契约工具定义与 JSON Schema 位于 tools.ts 中pdg_query条目参数契约如下参数必填说明mode是controlsCDG或flowsREACHING_DEF枚举校验target是文件路径支持后缀匹配或符号/函数名按context()同款规则解析pdg_query没有无锚定模式variable否仅flows模式有效把 REACHING_DEF 结果过滤到某一个绑定名limit否返回边数上限默认 50、最大 200源码常量见 tools.tsPDG_QUERY_DEFAULT_LIMIT/PDG_QUERY_MAX_LIMIT越界返回参数错误而非静默截断repo否仓库名或路径单仓库可省略该工具被列入只读工具策略见 read-only-policy.ts是典型的看代码不写代码探针。controls 模式什么在守护什么{ mode: controls, target: src/workers/scheduler.ts }对锚定的函数返回每条控制依赖边controller控制谓词所在行、dependent被控块的起始行与文本、以及边方向label——T表示谓词的true/taken 分支F表示false/fall-through 分支。当目标依赖块是一个早退early return / throw / continue / break块时额外标记guard: true。flows 模式变量在函数内流向哪里{ mode: flows, target: validateUser, variable: input }返回 REACHING_DEF 的 def→use 边每条边给出variable、def定义行与use使用行 使用处文本。传variable可以把结果收敛到单个绑定不传则返回该函数内的全部 def→use 边。注意variable过滤在底层走的是 REACHING_DEF 边的reason字段匹配而不是对变量做名字解析——所以最好传与索引中一致的源码级标识符。守卫子句发现与修正版Cypher技能文档特别强调了一个易踩的坑早期的 RFC 草案RFC #567 §2中形如[:CDG {label:F}]的 Cypher并不能按原样运行。因为前面说过CDG 边是CodeRelation表type属性取值为CDG的行而分支方向存在reason字段里不存在label列。要在原生cypher里手动找 guard 子句应使用修正版MATCH (pred:BasicBlock)-[r:CodeRelation {type: CDG}]-(dep:BasicBlock) WHERE dep.text STARTS WITH return OR dep.text STARTS WITH throw RETURN pred.startLine, r.reason AS branch, dep.startLine, dep.textr.reason给出的就是谓词到达该早退点所走的分支方向。关键教训是不要硬编码某一种方向。以if (!ok) return;为例return 语句走的是谓词的true 臂T而被保护的主体则走false 臂F——polarity 取决于守卫怎么写所以按方向过滤守卫子句一定会漏。如果走pdg_query工具本身则不需要手写这条 Cyphercontrols模式会自动把进入return/throw/continue/break依赖块的边标上guard: true对应底层实现见_pdgQueryImpl中的守卫正则/^\s*(return|throw|continue|break)\b/源码位置在 local-backend.ts 的 controls 结果组装段。底层执行流程从参数到结果的完整链路理解_pdgQueryImpl的代码顺序local-backend.ts 从约 4925 行开始就能理解工具为什么是有界且诚实的模式校验虽然 JSON Schema 里有 enum但后端仍强制检查mode防止不合法的值穿透到查询组装。limit 校验必须是[1, 200]的整数否则返回参数错误。limit会被直接插值进 CypherLadybugDB 不支持参数化LIMIT因此先做白名单校验是安全边界。元数据探针no-layer 短路调用共享的pdgStampForMode检查RepoMeta.pdg上的每函数上限戳CDG 看maxCdgEdgesPerFunctionREACHING_DEF 看maxReachingDefEdgesPerFunction。该戳由 run-analyze.ts 在--pdg索引时写入结构定义在 repo-meta.ts。若戳明确缺失false直接返回no PDG layernote不做一次数据库扫描——这是廉价探测的关键。锚定解析调用共享的resolveBlockAnchor见下文把target变成一组基本块的匹配条件。target必填所以这里要么命中、要么返回 not-found / ambiguous 早退分支。构造匹配子句并双查询MATCH (a:BasicBlock)-[r:CodeRelation]-(b:BasicBlock) WHERE r.type CDG|REACHING_DEF AND anchorClause[ AND reason过滤]并行执行分页查询带LIMIT与COUNT(*)总数查询。edgeType是硬编码字面量target/variable只走绑定参数没有 Cypher 字符串拼接注入面。空结果兜底如果总数是 0 且元数据不可读undefined再做一次单条边类型探测区分该锚点确实无边与整个层不存在据此选择状态未知note。结果组装controls模式输出 controller/dependent/label即reason的分支方向 可选guard: trueflows模式用decodeReachingDefReason把编码过的 reason 解码成纯变量名输出def/use。返回结构统一带anchor、total当total results.length时置truncated: true提示结果页被裁剪。flows 模式背后的 REACHING_DEF reason 编码FU-B-2flows结果里的variable不是现成的列而是从边reason字段解码出来的。编码器在 reaching-def-reason-codec.ts早期形态就是裸变量名legacy新形态是带注解的name|1:defLine:useLine[;defLine:useLine...]——名字在最前、|分隔、1:是 codec 版本后面跟;分隔的 def/use 行号对。解码是永不抛错、退化为裸名的防御式设计遇到非字符串、无注解的裸名或畸形注解都返回{ name, pairs: [] }消费方退回到基本块粒度。这解释了工具实现中的一个细节variable过滤条件写的是r.reason $variable OR r.reason STARTS WITH $variablePrefix前缀为name|。由于源码标识符不可能含|name|前缀是精确的不会误配更长的同名前缀从而同时兼容 legacy 裸名与 FU-B-2 注解两种形态。锚定原理没有 Function→BasicBlock 边怎么把函数解析成基本块这是整个pdg_query最容易出 bug 的地方技能文档称之为最承重的陷阱之一。由于图中没有Function → BasicBlock边代码通过两块信息重建 joinid 前缀匹配BasicBlock 节点 id 形如BasicBlock:filePath:fnStartLine:fnCol:blockIdx文件路径中可能含:所以解析时从右侧切分。行号窗口匹配基本块startLine是1-based而符号Symbol节点的startLine/endLine是0-based。因此锚定时上下界都 1把窗口移动成[symStart1, symEnd1]上界1把落在函数最后一行的 guard / def / use 保留在窗口内下界1把紧贴函数上一行的相邻函数的块排除在外。这段逻辑就是 local-backend.ts 的resolveBlockAnchor约 4497 行起它被explain、pdg_query、impact三个工具共享。三种锚定形态看起来像文件路径target走文件锚定——a.id STARTS WITH BasicBlock:file:精确或a.filePath target完整路径或a.filePath ENDS WITH /file后缀匹配符号名命中先resolveSymbolCandidates有可用 span 就用id 前缀 1-based 行窗口符号无可用 span降级为只按文件级 id 前缀过滤实现里有注释说明这一降级是刻意的。同名的符号会返回ambiguous候选列表含totalCandidates与candidatesTruncated提示找不到则返回not-found。同一行内塞多个函数、嵌套函数等极端排布下锚定只能粗略对齐——这是文档明确承认的边界。那些承重的 Gotchas决定结果正确性的细节技能文档把下面几条列为load-bearing读结果前务必逐条对照必须锚定 必须 LIMIT 限流。LadybugDB没有关系属性rel-property索引一条不带锚点的[:CDG*]/[:REACHING_DEF*]路径扫描是无界的。pdg_query强制要求target并对分页限流如果你直接裸调cypher必须自己用文件 id 前缀或符号 span 做锚定。锚点本身就是界——这是架构选择不是疏漏。BasicBlock ↔ 符号的 join 是重建的没有Function→BasicBlock边全靠 id 前缀 行号窗口含上面说的 1-based / 0-based1偏移。没有 PDG 层 ⇒ 返回 note而不是错误。工具返回{ results: [], note: no PDG layer — run gitnexus analyze --pdg … }靠对RepoMeta.pdg上限戳的廉价探测判定绝不做全库扫描。元数据不可读 锚定结果为空时返回的是措辞更审慎的状态未知note——因为一个全线性函数、天然无边的仓库其边缘形态与缺层在数据上无法区分实现因此拒绝断言可参见_pdgQueryImpl中的设计注释。CDG 标签在 M5/M6 是二值的。所有switch的 case 臂都被记为T每个 case 内部更细的条件分支尚未区分——所以别指望用controls区分同一个 switch 内不同 case 的谓词条件。仅限函数内intra-procedural。跨函数流动属于污点分析explain的地盘不要用pdg_query推导跨函数调用链。Mirror, dont fork为什么_pdgQueryImpl应该只复用不重写_pdgQueryImpl在结构上是_explainImpl的前半段镜像WAL 包装、元数据 no-layer 探测、limit 校验、resolveSymbolCandidates锚定解析等全部共享只是把读的边从TAINTED换成CDG/REACHING_DEF并且完全没有污点那一套路径编解码与跨函数TAINT_PATH机制。注释中明确要求扩展或审查这条读取路径时复用这些共享 helperpdgStampForMode、resolveBlockAnchor、decodeReachingDefReason、fnLineOf等不要重新实现。顺着这条镜像关系还能找到它更广的上下文explainlocal-backend.ts 约 4591 行消费同一批 CDG/REACHING_DEF 层的兄弟数据——污点 TAINTED 边做 source→sink 查询两者都要求--pdg索引impact的mode: pdg见 pdg-impact.ts以及 eval-server.ts 对mode:pdg的处理把 CDG REACHING_DEF 进一步聚合成语句级affectedStatements切片无层/降级结果会给出 UNKNOWN risk note而不会静默给出空 blast radiusCLI 的--mode pdg --line N见 index.ts 帮助文本是这条能力的命令行走道。实战复盘一条完整的排查路径把上面所有机制串起来一次典型的这条语句被什么守护排查长这样用gitnexus analyze --repo path --pdg建索引确认RepoMeta.pdg两个上限戳写入对代码里好奇的语句所在函数调用pdg_query({ mode: controls, target: 函数名或文件路径 })如果空结果先看note是否为no PDG layer…——是则说明没开--pdg若 note 是状态未知且仓库确实是--pdg索引那大概率是锚点本身无边函数全线性、无分支这属于edge-free 层的正常表现若结果里出现guard: true的边且 dependent 是return/throw它就对应源码里某个 early-return 守卫对照controller.line与labelT/F即可还原谓词走哪个臂到达早退想知道某个变量在函数内的去向换pdg_query({ mode: flows, target, variable })对照每条def.line → use.line的配对跨函数的流动不要在这里找改用explaintaint或impact --mode pdg语句级切片。参考源码位置速查技能文档本身gitnexus-pdg-query.mdpdg_queryMCP 工具定义与 limit 常量tools.ts_pdgQueryImpl/pdgQuery/resolveBlockAnchor核心实现local-backend.tsCFG / REACHING_DEF / CDG 三类边的落盘写入emit.tsREACHING_DEF reason 编解码FU-B-2 注解reaching-def-reason-codec.tsPDG 元数据戳写入与结构run-analyze.ts、repo-meta.ts--pdg开关配置analyze-config.ts、analyze-options.tsmode:pdg的语句级影响切片pdg-impact.ts、eval-server.ts【免费下载链接】GitNexusGitNexus: The Zero-Server Code Intelligence Engine - GitNexus is a client-side knowledge graph creator that runs entirely in your browser. Drop in a git repository (Github, Gitlab, Azure, Local) or ZIP file, and get an interactive knowledge graph with a built in Graph RAG Agent. Perfect for code exploration项目地址: https://gitcode.com/GitHub_Trending/gi/GitNexus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表