codegraph-py 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codegraph/__init__.py +12 -0
- codegraph/__main__.py +6 -0
- codegraph/cli.py +911 -0
- codegraph/codegraph.py +618 -0
- codegraph/context/__init__.py +216 -0
- codegraph/db/__init__.py +11 -0
- codegraph/db/connection.py +163 -0
- codegraph/db/queries.py +752 -0
- codegraph/db/schema.sql +151 -0
- codegraph/directory.py +160 -0
- codegraph/errors.py +101 -0
- codegraph/extraction/__init__.py +956 -0
- codegraph/extraction/languages/__init__.py +64 -0
- codegraph/extraction/languages/base.py +132 -0
- codegraph/extraction/languages/c_cfg.py +53 -0
- codegraph/extraction/languages/cpp_cfg.py +60 -0
- codegraph/extraction/languages/dart_cfg.py +53 -0
- codegraph/extraction/languages/go_cfg.py +70 -0
- codegraph/extraction/languages/java_cfg.py +62 -0
- codegraph/extraction/languages/javascript_cfg.py +84 -0
- codegraph/extraction/languages/kotlin_cfg.py +52 -0
- codegraph/extraction/languages/lua_cfg.py +65 -0
- codegraph/extraction/languages/python_cfg.py +75 -0
- codegraph/extraction/languages/ruby_cfg.py +48 -0
- codegraph/extraction/languages/rust_cfg.py +68 -0
- codegraph/extraction/languages/scala_cfg.py +59 -0
- codegraph/extraction/languages/swift_cfg.py +64 -0
- codegraph/extraction/languages/typescript_cfg.py +89 -0
- codegraph/extraction/tree_sitter_extractor.py +689 -0
- codegraph/graph/__init__.py +685 -0
- codegraph/installer/__init__.py +6 -0
- codegraph/mcp/__init__.py +668 -0
- codegraph/project_config.py +191 -0
- codegraph/resolution/__init__.py +337 -0
- codegraph/search/__init__.py +653 -0
- codegraph/sync/__init__.py +204 -0
- codegraph/types.py +334 -0
- codegraph/ui/__init__.py +11 -0
- codegraph/utils.py +218 -0
- codegraph_py-1.0.0.dist-info/METADATA +238 -0
- codegraph_py-1.0.0.dist-info/RECORD +44 -0
- codegraph_py-1.0.0.dist-info/WHEEL +5 -0
- codegraph_py-1.0.0.dist-info/entry_points.txt +2 -0
- codegraph_py-1.0.0.dist-info/top_level.txt +1 -0
codegraph/utils.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CodeGraph Utilities
|
|
3
|
+
|
|
4
|
+
Shared utility functions and classes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import hashlib
|
|
10
|
+
import os
|
|
11
|
+
import threading
|
|
12
|
+
import time
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Callable, Iterator, List, Optional, TypeVar
|
|
15
|
+
|
|
16
|
+
T = TypeVar('T')
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# =============================================================================
|
|
20
|
+
# Hashing
|
|
21
|
+
# =============================================================================
|
|
22
|
+
|
|
23
|
+
def sha256_hash(content: str) -> str:
|
|
24
|
+
"""Calculate SHA256 hash of string content."""
|
|
25
|
+
return hashlib.sha256(content.encode('utf-8')).hexdigest()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def sha256_file(filepath: str) -> str:
|
|
29
|
+
"""Calculate SHA256 hash of a file."""
|
|
30
|
+
h = hashlib.sha256()
|
|
31
|
+
with open(filepath, 'rb') as f:
|
|
32
|
+
for chunk in iter(lambda: f.read(65536), b''):
|
|
33
|
+
h.update(chunk)
|
|
34
|
+
return h.hexdigest()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# =============================================================================
|
|
38
|
+
# Path Utilities
|
|
39
|
+
# =============================================================================
|
|
40
|
+
|
|
41
|
+
def normalize_path(p: str) -> str:
|
|
42
|
+
"""Normalize path separators to forward slashes."""
|
|
43
|
+
return p.replace('\\', '/')
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def is_subpath(child: str, parent: str) -> bool:
|
|
47
|
+
"""Check if child path is under parent path."""
|
|
48
|
+
child = os.path.normpath(os.path.abspath(child))
|
|
49
|
+
parent = os.path.normpath(os.path.abspath(parent))
|
|
50
|
+
if child == parent:
|
|
51
|
+
return True
|
|
52
|
+
# Add trailing separator to parent to avoid partial matches
|
|
53
|
+
parent = parent.rstrip(os.sep) + os.sep
|
|
54
|
+
return child.startswith(parent)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def validate_path_within_root(path: str, root: str) -> bool:
|
|
58
|
+
"""Validate that a path is within the project root (no traversal)."""
|
|
59
|
+
abs_path = os.path.normpath(os.path.abspath(path))
|
|
60
|
+
abs_root = os.path.normpath(os.path.abspath(root))
|
|
61
|
+
return abs_path.startswith(abs_root + os.sep) or abs_path == abs_root
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# =============================================================================
|
|
65
|
+
# Mutex (Async-friendly via threading)
|
|
66
|
+
# =============================================================================
|
|
67
|
+
|
|
68
|
+
class Mutex:
|
|
69
|
+
"""A simple mutex for preventing concurrent operations within a process."""
|
|
70
|
+
|
|
71
|
+
def __init__(self):
|
|
72
|
+
self._lock = threading.Lock()
|
|
73
|
+
self._owner = None
|
|
74
|
+
|
|
75
|
+
def acquire(self, blocking: bool = True) -> bool:
|
|
76
|
+
"""Acquire the mutex."""
|
|
77
|
+
return self._lock.acquire(blocking=blocking)
|
|
78
|
+
|
|
79
|
+
def release(self) -> None:
|
|
80
|
+
"""Release the mutex."""
|
|
81
|
+
if self._lock.locked():
|
|
82
|
+
self._lock.release()
|
|
83
|
+
|
|
84
|
+
def __enter__(self):
|
|
85
|
+
self._lock.acquire()
|
|
86
|
+
return self
|
|
87
|
+
|
|
88
|
+
def __exit__(self, *args):
|
|
89
|
+
self._lock.release()
|
|
90
|
+
|
|
91
|
+
async def with_lock(self, func: Callable[..., T]) -> T:
|
|
92
|
+
"""Execute a function while holding the lock."""
|
|
93
|
+
with self._lock:
|
|
94
|
+
return func()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# =============================================================================
|
|
98
|
+
# File Lock (cross-process)
|
|
99
|
+
# =============================================================================
|
|
100
|
+
|
|
101
|
+
class FileLock:
|
|
102
|
+
"""Cross-process file lock using a lock file."""
|
|
103
|
+
|
|
104
|
+
def __init__(self, lock_path: str, timeout: float = 10.0):
|
|
105
|
+
self.lock_path = lock_path
|
|
106
|
+
self.timeout = timeout
|
|
107
|
+
self._fd = None
|
|
108
|
+
|
|
109
|
+
def acquire(self) -> bool:
|
|
110
|
+
"""Acquire the file lock. Returns True if successful."""
|
|
111
|
+
import fcntl
|
|
112
|
+
deadline = time.time() + self.timeout
|
|
113
|
+
while time.time() < deadline:
|
|
114
|
+
try:
|
|
115
|
+
self._fd = os.open(self.lock_path, os.O_CREAT | os.O_RDWR, 0o644)
|
|
116
|
+
fcntl.flock(self._fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
117
|
+
return True
|
|
118
|
+
except (IOError, OSError):
|
|
119
|
+
if self._fd:
|
|
120
|
+
os.close(self._fd)
|
|
121
|
+
self._fd = None
|
|
122
|
+
time.sleep(0.1)
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
def release(self) -> None:
|
|
126
|
+
"""Release the file lock."""
|
|
127
|
+
if self._fd is not None:
|
|
128
|
+
try:
|
|
129
|
+
import fcntl
|
|
130
|
+
fcntl.flock(self._fd, fcntl.LOCK_UN)
|
|
131
|
+
os.close(self._fd)
|
|
132
|
+
except (IOError, OSError):
|
|
133
|
+
pass
|
|
134
|
+
finally:
|
|
135
|
+
self._fd = None
|
|
136
|
+
try:
|
|
137
|
+
os.unlink(self.lock_path)
|
|
138
|
+
except OSError:
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
def __enter__(self):
|
|
142
|
+
self.acquire()
|
|
143
|
+
return self
|
|
144
|
+
|
|
145
|
+
def __exit__(self, *args):
|
|
146
|
+
self.release()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# =============================================================================
|
|
150
|
+
# Batch Processing
|
|
151
|
+
# =============================================================================
|
|
152
|
+
|
|
153
|
+
def process_in_batches(items: List[T], batch_size: int) -> Iterator[List[T]]:
|
|
154
|
+
"""Yield successive batches from items."""
|
|
155
|
+
for i in range(0, len(items), batch_size):
|
|
156
|
+
yield items[i:i + batch_size]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# =============================================================================
|
|
160
|
+
# Debounce / Throttle
|
|
161
|
+
# =============================================================================
|
|
162
|
+
|
|
163
|
+
class Debouncer:
|
|
164
|
+
"""Debounce calls to a function."""
|
|
165
|
+
|
|
166
|
+
def __init__(self, delay_ms: float = 2000):
|
|
167
|
+
self.delay = delay_ms / 1000.0
|
|
168
|
+
self._timer: Optional[threading.Timer] = None
|
|
169
|
+
self._last_call: float = 0
|
|
170
|
+
|
|
171
|
+
def call(self, func: Callable, *args, **kwargs) -> None:
|
|
172
|
+
"""Call function after debounce delay."""
|
|
173
|
+
if self._timer:
|
|
174
|
+
self._timer.cancel()
|
|
175
|
+
self._timer = threading.Timer(self.delay, func, args, kwargs)
|
|
176
|
+
self._timer.daemon = True
|
|
177
|
+
self._timer.start()
|
|
178
|
+
|
|
179
|
+
def cancel(self) -> None:
|
|
180
|
+
"""Cancel pending call."""
|
|
181
|
+
if self._timer:
|
|
182
|
+
self._timer.cancel()
|
|
183
|
+
self._timer = None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
# =============================================================================
|
|
187
|
+
# Generated File Detection
|
|
188
|
+
# =============================================================================
|
|
189
|
+
|
|
190
|
+
_GENERATED_PATTERNS = [
|
|
191
|
+
'.pb.', '_pb2.py', '_pb2_grpc.py',
|
|
192
|
+
'.grpc.', '.gen.', '_gen.',
|
|
193
|
+
'.generated.', '_generated.',
|
|
194
|
+
'grpc_', 'proto_',
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def is_generated_file(filepath: str) -> bool:
|
|
199
|
+
"""Check if a file appears to be generated."""
|
|
200
|
+
name = os.path.basename(filepath).lower()
|
|
201
|
+
for pattern in _GENERATED_PATTERNS:
|
|
202
|
+
if pattern in name:
|
|
203
|
+
return True
|
|
204
|
+
return False
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# =============================================================================
|
|
208
|
+
# Config Leaf Languages
|
|
209
|
+
# =============================================================================
|
|
210
|
+
|
|
211
|
+
CONFIG_LEAF_LANGUAGES = frozenset({
|
|
212
|
+
'terraform', 'yaml', 'properties', 'nix', 'solidity',
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def is_config_leaf_node(node_kind: str, node_language: str) -> bool:
|
|
217
|
+
"""Check if a node is a config-leaf (no meaningful children to recurse)."""
|
|
218
|
+
return node_language in CONFIG_LEAF_LANGUAGES
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codegraph-py
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Supercharge AI coding agents with semantic code intelligence — surgical context, fewer tool calls, faster answers. 100% local.
|
|
5
|
+
Author-email: mading <martin98@bu.edu>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/martin98-afk/codegraph-py
|
|
8
|
+
Project-URL: Source, https://github.com/martin98-afk/codegraph-py
|
|
9
|
+
Project-URL: Issues, https://github.com/martin98-afk/codegraph-py/issues
|
|
10
|
+
Keywords: code-intelligence,knowledge-graph,static-analysis,mcp,ai-agent,tree-sitter
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
Requires-Dist: click>=8.0
|
|
26
|
+
Provides-Extra: ts
|
|
27
|
+
Requires-Dist: tree-sitter>=0.21; extra == "ts"
|
|
28
|
+
Requires-Dist: tree-sitter-python>=0.21; extra == "ts"
|
|
29
|
+
Requires-Dist: tree-sitter-javascript>=0.21; extra == "ts"
|
|
30
|
+
Requires-Dist: tree-sitter-typescript>=0.21; extra == "ts"
|
|
31
|
+
Requires-Dist: tree-sitter-java>=0.21; extra == "ts"
|
|
32
|
+
Requires-Dist: tree-sitter-go>=0.21; extra == "ts"
|
|
33
|
+
Requires-Dist: tree-sitter-rust>=0.21; extra == "ts"
|
|
34
|
+
Provides-Extra: watch
|
|
35
|
+
Requires-Dist: watchfiles>=0.20.0; extra == "watch"
|
|
36
|
+
Provides-Extra: all
|
|
37
|
+
Requires-Dist: codegraph-py[ts,watch]; extra == "all"
|
|
38
|
+
|
|
39
|
+
# codegraph-py
|
|
40
|
+
|
|
41
|
+
**Python 版 CodeGraph** — 基于知识图谱的语义代码智能引擎,为 AI 编程助手提供精准的代码上下文。
|
|
42
|
+
|
|
43
|
+
> 对代码库建立预索引的知识图谱。AI Agent 直接查询图结构而非逐文件扫描 —— 精准上下文、更少工具调用、更快回答。
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 特性
|
|
48
|
+
|
|
49
|
+
- 🔍 **多语言 AST 解析** — 基于 tree-sitter 的符号级解析(Python/JS/TS/Go/Java/Rust,更多开发中)
|
|
50
|
+
- 🧠 **知识图谱** — 函数、类、方法、接口之间的包含、调用、继承关系全量索引
|
|
51
|
+
- ⚡ **FTS5 全文搜索** — 毫秒级符号查找,支持 camelCase / snake_case 分词
|
|
52
|
+
- 🔗 **调用链分析** — `callers` / `callees` / `impact` 精准定位影响范围
|
|
53
|
+
- 🏗 **增量同步** — 仅索引变更文件,监听文件系统变更
|
|
54
|
+
- 🛠 **MCP 服务器** — 8 个工具,直接对接 Claude/Cursor 等 AI Agent
|
|
55
|
+
- 🚀 **SQLite WAL 模式** — 256MB 内存映射 I/O,批量 checkpoint,生产级性能
|
|
56
|
+
|
|
57
|
+
## 快速开始
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# 安装
|
|
61
|
+
pip install codegraph-py
|
|
62
|
+
|
|
63
|
+
# 在项目目录初始化索引
|
|
64
|
+
cd your-project
|
|
65
|
+
codegraph init
|
|
66
|
+
|
|
67
|
+
# 搜索符号
|
|
68
|
+
codegraph query "calculateTotal"
|
|
69
|
+
|
|
70
|
+
# 探索代码上下文
|
|
71
|
+
codegraph explore "How does authentication work?"
|
|
72
|
+
|
|
73
|
+
# 查看索引状态
|
|
74
|
+
codegraph status
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## CLI 命令
|
|
78
|
+
|
|
79
|
+
| 命令 | 描述 |
|
|
80
|
+
|------|------|
|
|
81
|
+
| `init [path]` | 初始化并建立索引 |
|
|
82
|
+
| `uninit [path]` | 移除 CodeGraph 索引 |
|
|
83
|
+
| `index [path]` | 重建完整索引 |
|
|
84
|
+
| `sync [path]` | 增量同步变更 |
|
|
85
|
+
| `status [path]` | 显示索引统计 |
|
|
86
|
+
| `query <search>` | 全文搜索符号 |
|
|
87
|
+
| `explore <query>` | 探索代码(符号源码 + 调用路径) |
|
|
88
|
+
| `node <name>` | 查看符号详细信息 |
|
|
89
|
+
| `files` | 列出索引文件及符号统计 |
|
|
90
|
+
| `callers <symbol>` | 查找调用者 |
|
|
91
|
+
| `callees <symbol>` | 查找被调用者 |
|
|
92
|
+
| `impact <symbol>` | 影响范围分析 |
|
|
93
|
+
| `affected [files]` | 查找受影响的测试文件 |
|
|
94
|
+
| `serve [path]` | 启动 MCP 服务器 |
|
|
95
|
+
| `unlock [path]` | 移除陈旧锁文件 |
|
|
96
|
+
| `install` | CLI 集成指南 |
|
|
97
|
+
|
|
98
|
+
## Python API
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from codegraph import CodeGraph
|
|
102
|
+
|
|
103
|
+
# 初始化或打开项目
|
|
104
|
+
cg = CodeGraph.init_sync('/path/to/project')
|
|
105
|
+
|
|
106
|
+
# 全量索引
|
|
107
|
+
result = cg.index_all()
|
|
108
|
+
print(f"Indexed {result.files_indexed} files, {result.nodes_created} nodes")
|
|
109
|
+
|
|
110
|
+
# 搜索符号
|
|
111
|
+
results = cg.search_nodes("calculateTotal")
|
|
112
|
+
for r in results:
|
|
113
|
+
print(f"{r.node.kind}: {r.node.name} ({r.node.file_path}:{r.node.start_line})")
|
|
114
|
+
|
|
115
|
+
# 调用链分析
|
|
116
|
+
callers = cg.get_callers(node.id)
|
|
117
|
+
callees = cg.get_callees(node.id)
|
|
118
|
+
|
|
119
|
+
# 影响分析
|
|
120
|
+
impact = cg.get_impact_radius(node.id)
|
|
121
|
+
print(f"{len(impact.nodes)} symbols affected by change")
|
|
122
|
+
|
|
123
|
+
# 统计信息
|
|
124
|
+
stats = cg.get_stats()
|
|
125
|
+
print(f"Files: {stats.file_count}, Nodes: {stats.node_count}")
|
|
126
|
+
|
|
127
|
+
# 关闭连接
|
|
128
|
+
cg.close()
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## MCP 服务器
|
|
132
|
+
|
|
133
|
+
启动 MCP 服务器供 AI Agent 集成:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
codegraph serve
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
暴露的 MCP 工具:
|
|
140
|
+
|
|
141
|
+
| 工具 | 功能 |
|
|
142
|
+
|------|------|
|
|
143
|
+
| `codegraph_explore` | 主探索工具 — 自然语言查询符号和上下文 |
|
|
144
|
+
| `codegraph_node` | 获取符号或文件的源码 |
|
|
145
|
+
| `codegraph_search` | 快速符号搜索 |
|
|
146
|
+
| `codegraph_callers` | 查找函数调用者 |
|
|
147
|
+
| `codegraph_callees` | 查找函数被调用者 |
|
|
148
|
+
| `codegraph_impact` | 影响范围分析 |
|
|
149
|
+
| `codegraph_status` | 索引健康检查 |
|
|
150
|
+
| `codegraph_files` | 列出索引文件 |
|
|
151
|
+
|
|
152
|
+
## 工作原理
|
|
153
|
+
|
|
154
|
+
1. **`codegraph init`** 在项目根创建 `.codegraph/` 目录(含 SQLite 数据库 + `.gitignore`)
|
|
155
|
+
2. **索引阶段** 扫描源文件,用 tree-sitter 解析 AST,提取符号(函数、类、方法、接口等),存入节点和边
|
|
156
|
+
3. **FTS5 全文索引** 支持毫秒级符号搜索,智能分词 camelCase / snake_case
|
|
157
|
+
4. **图遍历引擎** 沿边(调用、包含、继承等)查找调用链和影响范围
|
|
158
|
+
5. **增量同步** 通过文件 mtime 对比实现,仅处理变更文件
|
|
159
|
+
6. **MCP 服务器** 基于 JSON-RPC 2.0 stdio 协议,8 个工具直连 AI Agent
|
|
160
|
+
|
|
161
|
+
## 技术栈
|
|
162
|
+
|
|
163
|
+
| 组件 | 技术 |
|
|
164
|
+
|------|------|
|
|
165
|
+
| 数据库 | SQLite (WAL + mmap + FTS5) |
|
|
166
|
+
| AST 解析 | tree-sitter (Python/JS/TS/Go/Java/Rust) |
|
|
167
|
+
| CLI | Click |
|
|
168
|
+
| MCP | JSON-RPC 2.0 over stdio |
|
|
169
|
+
| 文件监控 | watchfiles(可选) |
|
|
170
|
+
|
|
171
|
+
## 性能
|
|
172
|
+
|
|
173
|
+
在 **原版 CodeGraph TypeScript 项目**(329 个源文件)上的压测结果:
|
|
174
|
+
|
|
175
|
+
| 指标 | 数据 |
|
|
176
|
+
|------|------|
|
|
177
|
+
| 索引文件数 | 329 |
|
|
178
|
+
| 提取节点数 | 2,349(1,069 函数 + 699 方法 + 153 接口 + 60 类 + 39 类型别名) |
|
|
179
|
+
| 索引耗时 | **3.7 秒** |
|
|
180
|
+
| 数据库 PRAGMA | WAL + 256MB mmap + 64MB cache + NORMAL sync |
|
|
181
|
+
|
|
182
|
+
## 支持的语言
|
|
183
|
+
|
|
184
|
+
### tree-sitter 完整 AST 解析
|
|
185
|
+
- Python ✅
|
|
186
|
+
- JavaScript / JSX ✅
|
|
187
|
+
- TypeScript / TSX ✅
|
|
188
|
+
- Go ✅
|
|
189
|
+
- Java ✅
|
|
190
|
+
- Rust ✅
|
|
191
|
+
|
|
192
|
+
### 更多语言(文件级别跟踪,AST 解析即将支持)
|
|
193
|
+
- C/C++, C#, PHP, Ruby, Swift, Kotlin, Dart, Scala, Lua, Objective-C, R, Solidity, Terraform, 等 50+ 种
|
|
194
|
+
|
|
195
|
+
## 安装
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# 基础安装
|
|
199
|
+
pip install codegraph-py
|
|
200
|
+
|
|
201
|
+
# 带 tree-sitter 多语言支持
|
|
202
|
+
pip install "codegraph-py[ts]"
|
|
203
|
+
|
|
204
|
+
# 带文件监控
|
|
205
|
+
pip install "codegraph-py[watch]"
|
|
206
|
+
|
|
207
|
+
# 全功能
|
|
208
|
+
pip install "codegraph-py[all]"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## 项目结构
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
codegraph/
|
|
215
|
+
├── codegraph/
|
|
216
|
+
│ ├── cli.py # 16 个 CLI 命令
|
|
217
|
+
│ ├── codegraph.py # 核心 CodeGraph 类
|
|
218
|
+
│ ├── types.py # 类型定义
|
|
219
|
+
│ ├── db/ # SQLite 数据库层
|
|
220
|
+
│ │ ├── connection.py # 连接管理 + PRAGMA 优化
|
|
221
|
+
│ │ ├── queries.py # 查询构建器
|
|
222
|
+
│ │ └── schema.sql # 数据库 schema
|
|
223
|
+
│ ├── extraction/ # 代码解析引擎
|
|
224
|
+
│ │ ├── tree_sitter_extractor.py # tree-sitter 核心提取器
|
|
225
|
+
│ │ └── languages/ # 语言配置(6 种)
|
|
226
|
+
│ ├── graph/ # 图遍历引擎
|
|
227
|
+
│ ├── search/ # FTS5 全文搜索
|
|
228
|
+
│ ├── mcp/ # MCP 服务器
|
|
229
|
+
│ ├── sync/ # 文件同步/监控
|
|
230
|
+
│ └── resolution/ # 引用解析
|
|
231
|
+
├── tests/
|
|
232
|
+
│ └── test_codegraph.py # 11 个单元测试
|
|
233
|
+
└── pyproject.toml
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## 许可证
|
|
237
|
+
|
|
238
|
+
MIT — 基于原版 [CodeGraph](https://github.com/colbymchenry/codegraph) TypeScript 项目。
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
codegraph/__init__.py,sha256=Qkd-AU1AJ6sYtHtWnlWZD8WGUycr_F0twWO7ZguJDVk,285
|
|
2
|
+
codegraph/__main__.py,sha256=CU1tC_q6j0dvOAONsWUSBfVtbpVEsLmt8Jj358sbGjg,136
|
|
3
|
+
codegraph/cli.py,sha256=b8GZ_C5f7g2vmtIWlBa9DRQqkZ2m8cZtjRMNjnRfvEw,31967
|
|
4
|
+
codegraph/codegraph.py,sha256=B_Vvc1OeqA5LB4hGdNol5k_gJz0io3eOZy8L6NPpm4Q,23109
|
|
5
|
+
codegraph/directory.py,sha256=N-6LiwqDnvD87ms9SEPpeukXRuZWpgIT0-juQRBxgG4,5136
|
|
6
|
+
codegraph/errors.py,sha256=70lFoLu-BW4VLR39O0fsqRStG4IgwUSCxVkWvLPlYTA,2861
|
|
7
|
+
codegraph/project_config.py,sha256=14tBQ66vPi44wVxJF3Suasy0xrHfCQYuHokEIh0sbfU,6117
|
|
8
|
+
codegraph/types.py,sha256=hxTqcqEu-nnhaSuZGQvgm50NZlSFuzBYLmExBWwYzHU,9637
|
|
9
|
+
codegraph/utils.py,sha256=OkgKpYUI1VWchfxmBstObjpkSU3JT0fHbrQzgU6aTUQ,6998
|
|
10
|
+
codegraph/context/__init__.py,sha256=TCU36JORIUL2XyUbxhAk3E89uU2mErCP6pji13Sasp4,7871
|
|
11
|
+
codegraph/db/__init__.py,sha256=geWlUD7spD1kYC638ON5V2jPRmtt6s1_lcR5vVEvUls,302
|
|
12
|
+
codegraph/db/connection.py,sha256=xG6XSt5SWugWlePqpMP3paAgwCO_4Fva-GYPac0esww,5670
|
|
13
|
+
codegraph/db/queries.py,sha256=-_a-5Bu9rfnuT5Cy_mKoOXJDpcICwLPWAsmUo7UO9Oc,29425
|
|
14
|
+
codegraph/db/schema.sql,sha256=4yJFQytPksbu0cvx92_xVyrxDYfoV2Um86kofQ7EoBU,5508
|
|
15
|
+
codegraph/extraction/__init__.py,sha256=EHJfbFhww0zmTZ-i7TLY_QioE1O9TY7Zny8equ1h0uk,31451
|
|
16
|
+
codegraph/extraction/tree_sitter_extractor.py,sha256=4tDqaSs5enxdN_WtCvmHAf8H70WAOffR9m1Tmuts9iI,25217
|
|
17
|
+
codegraph/extraction/languages/__init__.py,sha256=9OTdDdAxRwkvaFoF_lkMJ0zEvDiMK0vNoQAvjDcnPII,2175
|
|
18
|
+
codegraph/extraction/languages/base.py,sha256=huH08ABk_d3zRlp2zVQ4NxO3R75fWYZJqGZYsOS2Ubw,4747
|
|
19
|
+
codegraph/extraction/languages/c_cfg.py,sha256=vU8f04Ohvvoy1WYtiGVwZJQ6VCPecW54WYrZ6jy_APQ,2049
|
|
20
|
+
codegraph/extraction/languages/cpp_cfg.py,sha256=Hq70zSi451dKutcaf4PJEtNmuYyat6H8fUK3Ykde7Y4,2621
|
|
21
|
+
codegraph/extraction/languages/dart_cfg.py,sha256=yXaMpTiVUrrRYXXCHjqM1-YNIVfzXrb3_VcT63Ge4ZY,2142
|
|
22
|
+
codegraph/extraction/languages/go_cfg.py,sha256=qaCJrCgBNK31vlb_MSdh4HzSpcZXvm1uiSV769jT1mE,2717
|
|
23
|
+
codegraph/extraction/languages/java_cfg.py,sha256=F3spSAlPu8wqbWktTLA-ntqcSHcIMbg5ybrVticfkkU,2294
|
|
24
|
+
codegraph/extraction/languages/javascript_cfg.py,sha256=QtveWNxjABiBVFOiUuLH5csgECOPjaefSQ1ZAUN6OM8,3040
|
|
25
|
+
codegraph/extraction/languages/kotlin_cfg.py,sha256=cngAu4wRonfvy5kJx3XrB2CJBjyFk3pGvf6xfP1Kpbc,2053
|
|
26
|
+
codegraph/extraction/languages/lua_cfg.py,sha256=nRF9IA9kgAG2PWwyrjAdnRTtGtRION37n5Xz9sv2VQ4,2415
|
|
27
|
+
codegraph/extraction/languages/python_cfg.py,sha256=C4HKjR9mcN_PJGnNYOsKSvewDWgk_BRHRcp4T5yUlJk,2857
|
|
28
|
+
codegraph/extraction/languages/ruby_cfg.py,sha256=etSpVnq43zuszqyWsUjnGzzTl7XBUy-_Jo4qX_mH-_0,1724
|
|
29
|
+
codegraph/extraction/languages/rust_cfg.py,sha256=JUxwXFH8l62VVRc7TBxLLf6xmkziip4ToPVjmIdCFto,2566
|
|
30
|
+
codegraph/extraction/languages/scala_cfg.py,sha256=biL-Q-B_2bIaFyzcH2V3RbFV57BUCC4bPSgvcAFng5A,2284
|
|
31
|
+
codegraph/extraction/languages/swift_cfg.py,sha256=VE2Wm1HOttZOZ1XpbM8ePwDjlXEmTN7pH3vekzxCGvs,2497
|
|
32
|
+
codegraph/extraction/languages/typescript_cfg.py,sha256=IlSQ7AXC8gPUengePZlS0R3J9JpI02wc--IrO_HphFw,3331
|
|
33
|
+
codegraph/graph/__init__.py,sha256=EoZIK_EqcnOWSkZhTjspchB82TK_zjkmfsHSG_Oi8xg,23129
|
|
34
|
+
codegraph/installer/__init__.py,sha256=0S058PkGTZrzyC0ZLFnWbCmsyeGBEiI6swdYINlyhm0,240
|
|
35
|
+
codegraph/mcp/__init__.py,sha256=o4AQEeC7dnkKt7ZTgodklVofJ3B_bdsBG48vZvgcdy4,25729
|
|
36
|
+
codegraph/resolution/__init__.py,sha256=VfDWWeFvYTNgJG1Mb3HW6vfbGafMGLEN97wKjnFliTc,13167
|
|
37
|
+
codegraph/search/__init__.py,sha256=ZLghOTL2MWiwa0tQMKsjP0ARvALCVK0tvnowXR1DZK4,22109
|
|
38
|
+
codegraph/sync/__init__.py,sha256=n6Voj1neoSQPCwdvECoOzTFhCfN2zeHA1sPmJyUixww,6558
|
|
39
|
+
codegraph/ui/__init__.py,sha256=tCi-_FJ7-MLPwmRt02dadMlJ3iy3QR26o1fgFc1DsUI,229
|
|
40
|
+
codegraph_py-1.0.0.dist-info/METADATA,sha256=H7RzzsItDz9T5vgP8MMOZjzna4Dew_biogE-ckYI_pY,8393
|
|
41
|
+
codegraph_py-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
42
|
+
codegraph_py-1.0.0.dist-info/entry_points.txt,sha256=3f2dJK7oR3dBzP21qRk_KuQa6Li8MVbVXeKcx3UjQ6c,49
|
|
43
|
+
codegraph_py-1.0.0.dist-info/top_level.txt,sha256=RqBj9sPbifZTb9aeHtnbxTgKJvfHIQdmYE1Brv8Wdkg,10
|
|
44
|
+
codegraph_py-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
codegraph
|