FS-Yuao/cpp-semantic-graph

GitHub: FS-Yuao/cpp-semantic-graph

为AI编程助手构建C++代码语义知识图谱,通过MCP协议暴露查询工具,让AI精准理解代码结构。

Stars: 3 | Forks: 0

# cpp-semantic-graph 为 AI 编程助手(Claude Code、Cursor、Windsurf 等)构建 C++ 代码的语义知识图谱,通过 [MCP 协议](https://modelcontextprotocol.io/) 暴露 9 个查询工具,让 AI 能直接搜索类定义、查继承关系、追踪调用链、分析影响面——无需翻文件、无需 grep。 ## 为什么需要它? AI 编程助手理解 C++ 代码的常见痛点: | 痛点 | cpp-semantic-graph 的解法 | |------|--------------------------| | "这个类在哪定义的?" | `cpp_search_class("SocUpdate")` → 命名空间 + 文件位置 | | "谁调用了这个函数?" | `cpp_get_callers("GetSocBootChain")` → 所有调用方 | | "改这个头文件会影响什么?" | 增量更新自动递归 include 依赖,只重解析受影响的 TU | | "虚函数有哪些 override?" | `cpp_get_overrides("PerformUpgrade", "BasePeriUpdate")` → 所有实现 | | "这个模块的架构是怎样的?" | `cpp_traverse_graph("SocUpdate")` → 多跳遍历关联节点 | ## ✨ 核心特性 - **9 个 MCP 工具**:类搜索、函数搜索、继承关系、调用链(caller/callee)、override、文件符号、多跳遍历、文档搜索 - **增量更新**:基于 include 依赖图,改一个 `.cpp` 秒级刷新(16× 快于全量重建) - **文档融合**:项目文档与代码双向关联,搜索文档时自动定位相关代码 - **开箱即用**:一个 YAML 配置 + `compile_commands.json` 即可启动,MCP Server 自动注册到 AI 工具 - **项目无关**:表结构和工具定义不含任何项目硬编码,可迁移到任何 C++ 项目 ## 🚀 快速开始 ### 前置条件 - Python 3.10+ - libclang(与你的 LLVM 版本匹配) - `compile_commands.json`(由 CMake/Bear 生成) ### 1. 安装 git clone https://github.com/your-org/cpp-semantic-graph.git cd cpp-semantic-graph # 创建虚拟环境 python3 -m venv .venv source .venv/bin/activate # 安装依赖 pip install -r requirements.txt ### 2. 准备 compile_commands.json 如果你的项目用 CMake 构建: cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ... 如果没有 CMake,用 [Bear](https://github.com/rizsotto/Bear) 拦截编译命令: bear -- make ### 3. 编写配置文件 创建 `cpp_semantic_graph.yaml`(这是唯一需要改的文件): project: name: "your_project" compile_commands: "/path/to/your/project/compile_commands.json" # 源码范围 — 决定哪些代码算"项目代码" source_paths: - "src" - "include" # 生成代码路径(如 ARA COM src-gen、protobuf) generated_paths: - "src-gen" # 完全忽略的路径 exclude_paths: - "thirdparty" - "build" - "test/mock" # libclang 路径(按你的系统调整) libclang_path: "/usr/lib/llvm-18/lib/libclang.so.1" parse_options: skip_function_bodies: false # false 才能提取调用关系 max_workers: 4 # 并行解析进程数 ### 4. 全量解析 # 1. 停掉 MCP Server(必须!) pkill -f "run_server.py" # 2. 全量解析 python3 -m cpp_semantic_graph full-parse \ --config cpp_semantic_graph.yaml \ --db semantic_graph_full.db # 3. 重新启动 MCP Server(解析完成后) 解析完成后,数据库包含: - **节点**:类、结构体、函数(含签名、命名空间、文件位置) - **边**:继承、调用、override、belongs_to、类型别名(type_alias)、using 声明(using_decl)、友元(friend_of)等关系(模板实例化边 `instantiates` 因 libclang AST 形态暂未启用,见 [复杂场景说明](#-复杂场景说明)) - **include 依赖**:翻译单元间的 include 关系图 - **文档关联**:文档切片 ↔ 代码实体(可选) ### 5. 启动 MCP Server # 设置数据库路径 export CPP_GRAPH_DB=/path/to/semantic_graph_full.db # 启动 MCP Server(stdio 传输) python3 -m cpp_semantic_graph.mcp_server.server ### 6. 注册到 AI 工具 #### Claude Code 编辑 `~/.claude.json`,在 `mcpServers` 中添加: { "mcpServers": { "cpp-semantic-graph": { "type": "stdio", "command": "python3", "args": ["/absolute/path/to/cpp-semantic-graph/mcp_server/run_server.py"], "env": { "CPP_GRAPH_DB": "/absolute/path/to/semantic_graph_full.db" } } } } #### Cursor 编辑 `.cursor/mcp.json`: { "mcpServers": { "cpp-semantic-graph": { "command": "python3", "args": ["/absolute/path/to/cpp-semantic-graph/mcp_server/run_server.py"], "env": { "CPP_GRAPH_DB": "/absolute/path/to/semantic_graph_full.db" } } } } #### Windsurf / 其他 MCP 客户端 配置方式类似,参考各工具的 MCP 文档。核心参数: - **command**: `python3` - **args**: `["/path/to/mcp_server/run_server.py"]` - **env.CPP_GRAPH_DB**: 数据库绝对路径 ## 🛠️ 9 个 MCP 工具 | # | 工具名 | 用途 | 典型场景 | |---|--------|------|---------| | 1 | `cpp_search_class` | 按类名搜索类定义 | "SocUpdate 类在哪定义?" | | 2 | `cpp_search_function` | 按函数名搜索函数定义 | "PerformUpgrade 的签名是什么?" | | 3 | `cpp_get_inheritance` | 查询类的继承关系 | "BasePeriUpdate 有哪些子类?" | | 4 | `cpp_get_callers` | 查询谁调用了指定函数 | "谁调用了 GetSocBootChain?" | | 5 | `cpp_get_callees` | 查询指定函数调用了谁 | "PerformUpgrade 内部调用了什么?" | | 6 | `cpp_get_overrides` | 查询虚函数的所有重写 | "PerformUpgrade 有哪些 override?" | | 7 | `cpp_get_file_symbols` | 查询文件内的所有符号 | "soc_update.cpp 里有什么?" | | 8 | `cpp_traverse_graph` | 多跳遍历图谱 | "修改 SocUpdate 会影响什么?" | | 9 | `cpp_search_docs` | 搜索项目文档 | "OTA 升级流程的设计文档" | ### 工具详情 #### `cpp_search_class(name, exact=False)` 按类名搜索 C++ 类定义。支持模糊匹配。 cpp_search_class("SocUpdate") → ## 搜索结果:类 "SocUpdate"(1 个) ### update::SocUpdate - 文件: soc_update.h:15-120 #### `cpp_search_function(name, class_name="")` 按函数名搜索函数定义。可限定所属类名。 cpp_search_function("PerformUpgrade", class_name="SocUpdate") → ## 搜索结果:函数 "PerformUpgrade"(1 个) ### SocUpdate::PerformUpgrade [virtual, override] - 签名: void PerformUpgrade() override - 文件: soc_update.cpp:45 #### `cpp_get_inheritance(class_name, direction="down", depth=1)` 查询类的继承关系。`direction="down"` 查子类,`"up"` 查父类。`depth=-1` 递归全部。 cpp_get_inheritance("BasePeriUpdate", direction="down", depth=-1) → ## BasePeriUpdate 的子类(4 条) - update::SocUpdate --public--> BasePeriUpdate - update::McuUpdate --public--> BasePeriUpdate - ... #### `cpp_get_callers(function_name, class_name="")` 查询谁调用了指定函数(影响面分析)。 cpp_get_callers("GetSocBootChain") → ## 调用 "GetSocBootChain" 的代码(3 个) ### OtaManager::CheckBootChain - 文件: ota_manager.cpp:128 - 调用类型: calls_direct #### `cpp_get_callees(function_name, class_name="")` 查询指定函数调用了谁(调用链分析)。 cpp_get_callees("PerformUpgrade", class_name="SocUpdate") → ## "PerformUpgrade" 调用的代码(8 个) ... #### `cpp_get_overrides(function_name, class_name)` 查询虚函数的所有重写实现。`class_name` 为声明该虚函数的基类名(必填)。 cpp_get_overrides("PerformUpgrade", class_name="BasePeriUpdate") → ## "PerformUpgrade" 的重写实现(4 个) ### update::SocUpdate::PerformUpgrade - 签名: void PerformUpgrade() override - 文件: soc_update.cpp:45 - 重写基类: BasePeriUpdate #### `cpp_get_file_symbols(file_path)` 查询文件内的所有类和函数符号。`file_path` 支持部分匹配。 cpp_get_file_symbols("soc_update.h") → ## 文件符号:soc_update.h(共 12 个) ### 类/结构体(2 个) 1. ### [class] update::SocUpdate ### 函数(10 个) ... #### `cpp_traverse_graph(start, relation_types=None, direction="outgoing", depth=3, max_results=50)` 多跳遍历图谱,最灵活的查询。沿指定关系类型遍历关联节点。 常用关系类型:`inherits_public`, `inherits_protected`, `overrides`, `belongs_to`, `calls_direct`, `calls_virtual`, `calls_callback`, `doc_describes_code`, `code_refers_to_doc` cpp_traverse_graph("SocUpdate", depth=2, max_results=30) → ## 遍历结果:从 "SocUpdate" 出发(18 个节点) 深度: 2, 遍历边数: 22 ### 关联节点 - [class] update::SocUpdate (soc_update.h) - [class] update::BasePeriUpdate (base_peri_update.h) - [function] update::SocUpdate::PerformUpgrade (soc_update.cpp) ... #### `cpp_search_docs(keyword, tag="", max_results=10, min_confidence=0.0)` 搜索项目文档,返回文档切片 + 关联代码。 cpp_search_docs("升级", tag="架构设计") → ## 文档搜索:"升级"(3 个结果) ### OTA 完整升级流程 - 文件: docs/OTA_flow/OTA_COMPLETE_FLOW.md - 字数: 2450 - 标签: 架构设计, OTA 关联代码: - [class] BasePeriUpdate confidence=0.92 - [class] SocUpdate confidence=0.88 ## 📖 CLI 用法 除了 MCP 工具,还提供 CLI 直接查询: # 搜索类 python3 -m cpp_semantic_graph search-class "SocUpdate" # 查继承 python3 -m cpp_semantic_graph inheritance "BasePeriUpdate" --direction down --depth -1 # 搜索函数 python3 -m cpp_semantic_graph search-func "PerformUpgrade" # 查文件符号 python3 -m cpp_semantic_graph file-symbols "soc_update.cpp" # 查 include 依赖 python3 -m cpp_semantic_graph include "base_peri_update.h" --mode all # 数据库统计 python3 -m cpp_semantic_graph stats ### 增量更新 代码修改后,增量更新只重解析受影响的翻译单元: # 基于 git diff(默认 HEAD~1) python3 -m cpp_semantic_graph incremental --base HEAD~1 # 手动指定文件 python3 -m cpp_semantic_graph incremental --files soc_update.cpp,base_peri_update.h # 仅检测不执行 python3 -m cpp_semantic_graph incremental --files soc_update.cpp --dry-run # 跳过文档关联重建(更快) python3 -m cpp_semantic_graph incremental --files soc_update.cpp --skip-associations ## 📐 架构 ┌─────────────────────────────────────────────────┐ │ AI 工具层 │ │ Claude Code / Cursor / Windsurf / 其他 MCP 客户端 │ └────────────────────┬────────────────────────────┘ │ MCP 协议 (stdio) ┌────────────────────▼────────────────────────────┐ │ MCP Server (9 工具) │ │ FastMCP + Lazy Init DB 连接 + Markdown 格式化 │ └────────────────────┬────────────────────────────┘ │ Python API ┌────────────────────▼────────────────────────────┐ │ 查询层 (query/) │ │ GraphQuery │ CallQuery │ PolymorphismQuery │ │ TraverseQuery │ DocQuery │ IncludeQuery │ └────────────────────┬────────────────────────────┘ │ ┌────────────────────▼────────────────────────────┐ │ 数据层 (db/) │ │ SQLite + 9 索引 + CASCADE 约束 │ │ node │ edge │ include_dep │ parse_status │ └─────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────┐ │ 解析层 (parser/) │ │ AST Visitor (libclang) │ CompileDB │ Config │ │ ChangeDetector │ ImpactAnalyzer │ └─────────────────────────────────────────────────┘ ### 核心数据模型 **节点(node 表)**:类、结构体、函数,含命名空间、文件位置、签名等 **边(edge 表)**:节点间关系,方向约定: - `inherits`: from=子类 → to=父类 - `calls`: from=调用方 → to=被调用方 - `belongs_to`: from=函数 → to=所属类 - `overrides`: from=派生类函数 → to=基类函数 **include_dep 表**:翻译单元的 include 依赖,增量更新的核心依据 ## 🧩 复杂场景说明(模板/别名/友元) | 特性 | 关系边 | 状态 | 说明 | |------|--------|------|------| | 类型别名 `using Alias = T` | `type_alias` | ✅ 已启用 | 别名节点入库 + 边关联目标;目标来自外部库时边可能悬空丢弃,别名节点仍保留 `target_type` 元信息 | | using 声明 `using B::func` | `using_decl` | ✅ 已启用 | 子类函数 → 基类函数;本项目源码无常规 using 声明,仅 1 处 literal operator 未提取 | | 友元 `friend class F` | `friend_of` | ✅ 已启用 | friend → 宿主类;本项目源码无 friend 声明,0 条边符合预期 | | 模板实例化 | `instantiates` | ⏸️ 暂未启用 | libclang 不为模板特化产生独立 CLASS_DECL 节点(特化名仅出现在 CONSTRUCTOR/TYPE_REF 的 spelling 中),`walk_preorder` 找不到含 `<` 的类声明,提取无产出。提取器代码保留,待改用 LibTooling 或基于 TYPE_REF 重建时启用 | ## 🔄 增量更新机制 1. ChangeDetector ──→ 检测文件变更(git diff / 手动指定) 2. ImpactAnalyzer ──→ 分析影响范围(.h → 递归 includer) 3. 删除旧数据 ──→ 删出边(不删共享节点)+ include_dep + parse_status 4. 重新解析 ──→ SemanticExtractor.parse() × 受影响 TU 5. upsert 新数据 ──→ 节点更新/边去重 6. 清理残留节点 ──→ 删除文件中已消失的函数/类 7. 重建文档关联 ──→ content_scan(可选 embedding) **删除策略核心**:只删出边(from_id 在该文件的边),保留入边;节点用 upsert 更新。这保证了头文件中共享的类/函数节点不会被误删。 | 场景 | 受影响 TU | 更新耗时 | |------|----------|---------| | 单个 .cpp 变更 | 1 个 | ~11s | | 单个 .h 变更 | 递归 includer | 取决于 TU 数(7 TU ~76s) | | 幂等性(二次执行) | 不变 | 边数稳定不变 ✅ | ## 📚 文档融合 将项目文档(Markdown)与代码实体双向关联,让 AI 搜索文档时自动定位相关代码。 **本项目已配置文档融合**:58 个文档 → 546 个切片 → 1,756 条关联边(doc_describes_code + code_refers_to_doc)。`cpp_search_docs` 可直接使用。 ### 配置 创建 `config/doc_config.yaml`: doc_dirs: - "docs/" exclude_patterns: - "*.html" - "*/build/*" # 按目录自动打标签 tag_rules: - path_pattern: "architecture/**" tags: ["架构设计"] - path_pattern: "api/**" tags: ["接口规约"] section_split: min_level: 2 # 按 ## 切片 min_word_count: 20 # 少于 20 字的切片合并 # 手动精准关联(不侵入文档原文) manual_links: - doc: "architecture/OTA_FLOW.md" heading: "升级流程" code: - "BasePeriUpdate" - "SocUpdate" - "PerformUpgrade" ### Embedding 关联(可选) 安装 `sentence-transformers` 后,可基于语义相似度自动关联文档与代码: pip install sentence-transformers 默认使用 `all-MiniLM-L6-v2` 模型。中文项目建议换 `bge-small-zh-v1.5` 或 `multilingual-e5-small`。 ## 🧪 验证 全量解析后可运行正确性验证(与 clangd 交叉比对): python3 -m cpp_semantic_graph full-parse \ --config cpp_semantic_graph.yaml \ --validate \ --baseline validation/clangd_baseline.json ## 📋 依赖 ### 核心(必装) | 包 | 版本 | 用途 | |----|------|------| | `clang` | ≥18 | libclang Python 绑定,AST 解析 | | `PyYAML` | ≥6.0 | 配置文件解析 | | `mcp` | ≥1.0 | MCP 协议实现(FastMCP) | ### 文档融合(可选) | 包 | 版本 | 用途 | |----|------|------| | `sentence-transformers` | ≥2.0 | 文档-代码语义关联 | | `torch` | ≥2.0 | sentence-transformers 依赖 | ### 安装 # 核心依赖 pip install clang PyYAML mcp # 文档融合(可选) pip install sentence-transformers 或使用 requirements.txt: pip install -r requirements.txt # 核心 pip install -r requirements-docs.txt # 文档融合(可选) ## 🗂️ 项目结构 cpp_semantic_graph/ ├── __init__.py # 包声明 ├── __main__.py # python -m 入口 ├── cli.py # CLI 工具(search/inheritance/incremental/...) ├── pipeline.py # 全量解析流水线 ├── incremental_updater.py # 增量更新编排器 │ ├── parser/ # 解析层 │ ├── ast_visitor.py # AST 提取器(libclang) │ ├── config.py # 项目配置加载 │ ├── compile_db.py # compile_commands.json 解析 │ ├── change_detector.py # 文件变更检测(git diff) │ ├── impact_analyzer.py # 影响范围分析 │ ├── doc_parser.py # 文档解析器 │ ├── doc_association.py # 文档-代码关联 │ ├── association_ingester.py # 关联边入库 │ └── models.py # 数据模型 │ ├── query/ # 查询层 │ ├── graph_query.py # 类/函数/文件符号查询 │ ├── call_query.py # 调用关系查询 │ ├── polymorphism_query.py # 多态体系查询 │ ├── traverse.py # 多跳遍历查询 │ ├── doc_query.py # 文档融合查询 │ ├── include_query.py # include 依赖查询 │ ├── architecture_query.py # 架构概览查询 │ └── fusion_query.py # 融合查询 │ ├── db/ # 数据层 │ ├── graph_db.py # SQLite 操作 │ ├── importer.py # JSON→SQLite 导入 │ ├── schema.sql # 建表+索引 │ └── relation_types.py # 关系类型枚举 │ ├── mcp_server/ # MCP Server │ ├── server.py # FastMCP Server + 9 工具 │ └── run_server.py # 启动脚本 │ ├── validation/ # 正确性验证 │ ├── accuracy_validator.py # 精度验证器 │ └── clangd_baseline.py # clangd 基线 │ ├── config/ # 配置模板 │ ├── doc_config.yaml # 文档配置示例 │ └── template_whitelist.yaml # 模板白名单 │ └── cpp_semantic_graph.yaml # 项目配置(用户编写) ## ❓ FAQ ### Q: 需要什么版本的 LLVM/libclang? 需要与编译项目时使用的 LLVM 版本匹配。检查方法: # 查看 clang 版本 clang --version # 对应的 libclang 路径 ls /usr/lib/llvm-*/lib/libclang.so* 在配置文件中指定 `libclang_path`。 ### Q: compile_commands.json 怎么生成? - **CMake 项目**:`cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ...` - **Make 项目**:`bear -- make` - **Ninja 项目**:`bear -- ninja` - **Bazel 项目**:使用 [bazel-compile-commands](https://github.com/kiron1/bazel-compile-commands) ### Q: 增量更新安全吗? 是的。删除策略只删出边(from_id 在该文件的边),不删节点。共享头文件中的类/函数节点用 upsert 更新,不会被误删。极端情况(如重命名类)建议全量重建。 ### Q: 支持哪些 AI 工具? 所有支持 MCP 协议的 AI 工具:Claude Code、Cursor、Windsurf、Continue 等。MCP Server 使用 stdio 传输,这是最广泛支持的传输方式。 ### Q: 数据库有多大? 典型 C++ 项目(~100 个翻译单元):约 1500 节点 / 5000 边 / 20000 include 关系,SQLite 文件约 5-10 MB。含文档融合时节点数和边数翻倍,DB 约 5-15 MB。 ### Q: 和 clangd 有什么区别? | | cpp-semantic-graph | clangd | |---|---|---| | 数据存储 | 离线 SQLite 图谱 | 实时 AST | | 查询范围 | 跨文件、跨模块 | 单文件 + 索引 | | 调用链 | 完整调用图 + 多跳遍历 | 单跳引用 | | 文档关联 | 支持 | 不支持 | | 增量更新 | 基于 include 依赖图 | 实时 | | 适合场景 | 架构理解、影响面分析 | 实时编辑、签名查看 | **两者互补**:日常编辑用 clangd,架构理解和影响面分析用 cpp-semantic-graph。 ## 📄 License MIT License ## 📋 测试报告 | 报告 | 说明 | |------|------| | [TEST_REPORT.md](tests/TEST_REPORT.md) | 综合测试报告(功能/准确性/效率/Bug修复) | | [TEST_CASES.md](tests/TEST_CASES.md) | 具体测试用例表(62 条,98.4% 通过) | | [TEST_THREE_LAYERS.md](tests/TEST_THREE_LAYERS.md) | 三层测试(问题→工具调用→代码验证,25 条真实问题) | | [TEST_DOC_FUSION.md](tests/TEST_DOC_FUSION.md) | 文档融合专项测试(27 条,89% 通过) | | [PROJECT_EVALUATION.md](tests/PROJECT_EVALUATION.md) | 项目整体评估(六维评分+对比+结论) |
标签:AI编程助手, C++, MCP协议, SOC Prime, 云安全监控, 代码知识图谱, 开发工具, 数据擦除, 逆向工具, 静态分析