vcode-analysis 0.2.0__tar.gz → 0.4.0__tar.gz
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.
- {vcode_analysis-0.2.0/vcode_analysis.egg-info → vcode_analysis-0.4.0}/PKG-INFO +67 -18
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/README.md +66 -17
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/analyzers/__init__.py +3 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/analyzers/architecture.py +11 -1
- vcode_analysis-0.4.0/analyzers/code_review.py +307 -0
- vcode_analysis-0.4.0/analyzers/context_builder.py +420 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/analyzers/security.py +12 -1
- vcode_analysis-0.4.0/cli.py +1190 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/core/analyzer.py +46 -13
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/docs/USER_MANUAL.md +39 -24
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/pyproject.toml +8 -1
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0/vcode_analysis.egg-info}/PKG-INFO +67 -18
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/vcode_analysis.egg-info/SOURCES.txt +2 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/vcode_analysis.egg-info/top_level.txt +1 -0
- vcode_analysis-0.2.0/analyzers/code_review.py +0 -150
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/LICENSE +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/MANIFEST.in +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/analyzers/directory.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/analyzers/documentation.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/core/__init__.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/core/config.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/core/git_handler.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/core/ignore.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/core/llm_client.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/docs/design/c-parser-design.md +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/docs/design/code-analysis-tool.md +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/docs/design/kotlin-parser-design.md +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/__init__.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/c/__init__.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/c/ast_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/c/models.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/c/patterns.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/c/regex_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/c_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/java_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/javascript_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/kotlin/__init__.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/kotlin/ast_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/kotlin/models.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/kotlin/patterns.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/kotlin/regex_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/kotlin_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/python_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/parsers/typescript_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/requirements.txt +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/setup.cfg +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/tests/test_batch_operations.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/tests/test_c_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/tests/test_kotlin_parser.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/tests/test_security_rules.py +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/vcode_analysis.egg-info/dependency_links.txt +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/vcode_analysis.egg-info/entry_points.txt +0 -0
- {vcode_analysis-0.2.0 → vcode_analysis-0.4.0}/vcode_analysis.egg-info/requires.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vcode-analysis
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: 基于大模型的智能代码分析工具,支持代码审查、文档生成、架构分析和安全扫描
|
|
5
5
|
Author-email: Wellchang <2483808264@qq.com>
|
|
6
6
|
License: MIT
|
|
@@ -40,7 +40,8 @@ Dynamic: license-file
|
|
|
40
40
|
|
|
41
41
|
# Code Analysis - 智能代码分析工具
|
|
42
42
|
|
|
43
|
-
[](https://pypi.org/project/vcode-analysis/)
|
|
44
|
+
[](https://www.python.org/downloads/)
|
|
44
45
|
[](https://opensource.org/licenses/MIT)
|
|
45
46
|
|
|
46
47
|
基于私有化部署大模型的智能代码分析工具,支持代码审查、文档生成、架构分析和安全扫描。
|
|
@@ -53,6 +54,7 @@ Dynamic: license-file
|
|
|
53
54
|
| 📝 **文档生成** | 自动生成模块文档、API 文档 |
|
|
54
55
|
| 🏗️ **架构分析** | 分析项目结构、依赖关系、代码度量 |
|
|
55
56
|
| 🔒 **安全扫描** | 检测常见安全漏洞和风险代码 |
|
|
57
|
+
| ⚡ **并发分析** | 支持多线程并发分析,默认 5 个线程 |
|
|
56
58
|
| 📦 **批量操作** | 批量克隆、批量 Git 操作、多仓库管理 |
|
|
57
59
|
| 📂 **目录分析** | 扫描项目结构、识别技术栈 |
|
|
58
60
|
| 🌐 **多语言支持** | Python, Java, Kotlin, C, JavaScript, TypeScript 等 |
|
|
@@ -62,20 +64,32 @@ Dynamic: license-file
|
|
|
62
64
|
|
|
63
65
|
### 安装
|
|
64
66
|
|
|
67
|
+
**方式一:从 PyPI 安装(推荐)**
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# 基础安装
|
|
71
|
+
pip install vcode-analysis
|
|
72
|
+
|
|
73
|
+
# 安装额外解析器支持
|
|
74
|
+
pip install vcode-analysis[parsers]
|
|
75
|
+
|
|
76
|
+
# 安装所有可选依赖
|
|
77
|
+
pip install vcode-analysis[parsers,rich]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**方式二:从源码安装**
|
|
81
|
+
|
|
65
82
|
```bash
|
|
66
|
-
# 克隆项目
|
|
67
83
|
git clone https://gitcode.com/wellchang/code-analysis.git
|
|
68
84
|
cd code-analysis
|
|
69
|
-
|
|
70
|
-
# 安装依赖
|
|
71
|
-
pip install httpx docopt pyyaml
|
|
85
|
+
pip install -e .
|
|
72
86
|
```
|
|
73
87
|
|
|
74
88
|
### 配置
|
|
75
89
|
|
|
76
90
|
```bash
|
|
77
91
|
# 初始化配置文件
|
|
78
|
-
|
|
92
|
+
vcode-analysis config --init
|
|
79
93
|
|
|
80
94
|
# 编辑配置文件
|
|
81
95
|
# ~/.code-analysis/config.yaml
|
|
@@ -84,17 +98,20 @@ python cli.py config --init
|
|
|
84
98
|
### 使用
|
|
85
99
|
|
|
86
100
|
```bash
|
|
87
|
-
#
|
|
88
|
-
|
|
101
|
+
# 代码审查(结果自动保存到 result/目录名_review_时间戳.md)
|
|
102
|
+
vcode-analysis review ./src
|
|
89
103
|
|
|
90
104
|
# 架构分析
|
|
91
|
-
|
|
105
|
+
vcode-analysis arch ./src
|
|
92
106
|
|
|
93
107
|
# 安全扫描
|
|
94
|
-
|
|
108
|
+
vcode-analysis security ./src --deep
|
|
109
|
+
|
|
110
|
+
# 使用 10 个并发线程加速分析
|
|
111
|
+
vcode-analysis review ./src --workers 10
|
|
95
112
|
|
|
96
113
|
# 目录扫描
|
|
97
|
-
|
|
114
|
+
vcode-analysis scan-dir ./project
|
|
98
115
|
```
|
|
99
116
|
|
|
100
117
|
## 📖 命令概览
|
|
@@ -161,28 +178,37 @@ code-analysis/
|
|
|
161
178
|
### 代码审查
|
|
162
179
|
|
|
163
180
|
```bash
|
|
164
|
-
#
|
|
165
|
-
|
|
181
|
+
# 审查整个项目(结果保存到 result/src_review_20260320_120000.md)
|
|
182
|
+
vcode-analysis review ./src
|
|
183
|
+
|
|
184
|
+
# 使用 10 个线程加速分析
|
|
185
|
+
vcode-analysis review ./src --workers 10
|
|
186
|
+
|
|
187
|
+
# 自定义输出路径
|
|
188
|
+
vcode-analysis review ./src --output custom_report.md
|
|
166
189
|
|
|
167
190
|
# 审查最新提交
|
|
168
|
-
|
|
191
|
+
vcode-analysis review-commit HEAD
|
|
169
192
|
```
|
|
170
193
|
|
|
171
194
|
### 安全扫描
|
|
172
195
|
|
|
173
196
|
```bash
|
|
174
197
|
# 深度安全扫描
|
|
175
|
-
|
|
198
|
+
vcode-analysis security ./src --deep
|
|
199
|
+
|
|
200
|
+
# 快速扫描
|
|
201
|
+
vcode-analysis security ./src
|
|
176
202
|
```
|
|
177
203
|
|
|
178
204
|
### 批量操作
|
|
179
205
|
|
|
180
206
|
```bash
|
|
181
207
|
# 批量克隆(从文件读取 URL 列表)
|
|
182
|
-
|
|
208
|
+
vcode-analysis batch-clone repos.txt ./projects --parallel
|
|
183
209
|
|
|
184
210
|
# 查看多仓库状态
|
|
185
|
-
|
|
211
|
+
vcode-analysis git-status ~/projects
|
|
186
212
|
```
|
|
187
213
|
|
|
188
214
|
## ⚙️ 配置示例
|
|
@@ -242,11 +268,34 @@ parser = CASTParser()
|
|
|
242
268
|
result = parser.parse_file('main.c', mode='fast')
|
|
243
269
|
```
|
|
244
270
|
|
|
271
|
+
## 📦 发布到 PyPI
|
|
272
|
+
|
|
273
|
+
### 发布新版本
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# 安装发布工具
|
|
277
|
+
pip install build twine
|
|
278
|
+
|
|
279
|
+
# 构建包
|
|
280
|
+
python -m build
|
|
281
|
+
|
|
282
|
+
# 上传到 PyPI
|
|
283
|
+
twine upload dist/*
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 发布到 TestPyPI(测试)
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# 上传到 TestPyPI
|
|
290
|
+
twine upload --repository testpypi dist/*
|
|
291
|
+
```
|
|
292
|
+
|
|
245
293
|
## 📄 许可证
|
|
246
294
|
|
|
247
295
|
[MIT License](LICENSE)
|
|
248
296
|
|
|
249
297
|
## 🔗 链接
|
|
250
298
|
|
|
299
|
+
- [PyPI 包地址](https://pypi.org/project/vcode-analysis/)
|
|
251
300
|
- [项目主页](https://gitcode.com/wellchang/code-analysis)
|
|
252
301
|
- [问题反馈](https://gitcode.com/wellchang/code-analysis/issues)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Code Analysis - 智能代码分析工具
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/vcode-analysis/)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
4
5
|
[](https://opensource.org/licenses/MIT)
|
|
5
6
|
|
|
6
7
|
基于私有化部署大模型的智能代码分析工具,支持代码审查、文档生成、架构分析和安全扫描。
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
| 📝 **文档生成** | 自动生成模块文档、API 文档 |
|
|
14
15
|
| 🏗️ **架构分析** | 分析项目结构、依赖关系、代码度量 |
|
|
15
16
|
| 🔒 **安全扫描** | 检测常见安全漏洞和风险代码 |
|
|
17
|
+
| ⚡ **并发分析** | 支持多线程并发分析,默认 5 个线程 |
|
|
16
18
|
| 📦 **批量操作** | 批量克隆、批量 Git 操作、多仓库管理 |
|
|
17
19
|
| 📂 **目录分析** | 扫描项目结构、识别技术栈 |
|
|
18
20
|
| 🌐 **多语言支持** | Python, Java, Kotlin, C, JavaScript, TypeScript 等 |
|
|
@@ -22,20 +24,32 @@
|
|
|
22
24
|
|
|
23
25
|
### 安装
|
|
24
26
|
|
|
27
|
+
**方式一:从 PyPI 安装(推荐)**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 基础安装
|
|
31
|
+
pip install vcode-analysis
|
|
32
|
+
|
|
33
|
+
# 安装额外解析器支持
|
|
34
|
+
pip install vcode-analysis[parsers]
|
|
35
|
+
|
|
36
|
+
# 安装所有可选依赖
|
|
37
|
+
pip install vcode-analysis[parsers,rich]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**方式二:从源码安装**
|
|
41
|
+
|
|
25
42
|
```bash
|
|
26
|
-
# 克隆项目
|
|
27
43
|
git clone https://gitcode.com/wellchang/code-analysis.git
|
|
28
44
|
cd code-analysis
|
|
29
|
-
|
|
30
|
-
# 安装依赖
|
|
31
|
-
pip install httpx docopt pyyaml
|
|
45
|
+
pip install -e .
|
|
32
46
|
```
|
|
33
47
|
|
|
34
48
|
### 配置
|
|
35
49
|
|
|
36
50
|
```bash
|
|
37
51
|
# 初始化配置文件
|
|
38
|
-
|
|
52
|
+
vcode-analysis config --init
|
|
39
53
|
|
|
40
54
|
# 编辑配置文件
|
|
41
55
|
# ~/.code-analysis/config.yaml
|
|
@@ -44,17 +58,20 @@ python cli.py config --init
|
|
|
44
58
|
### 使用
|
|
45
59
|
|
|
46
60
|
```bash
|
|
47
|
-
#
|
|
48
|
-
|
|
61
|
+
# 代码审查(结果自动保存到 result/目录名_review_时间戳.md)
|
|
62
|
+
vcode-analysis review ./src
|
|
49
63
|
|
|
50
64
|
# 架构分析
|
|
51
|
-
|
|
65
|
+
vcode-analysis arch ./src
|
|
52
66
|
|
|
53
67
|
# 安全扫描
|
|
54
|
-
|
|
68
|
+
vcode-analysis security ./src --deep
|
|
69
|
+
|
|
70
|
+
# 使用 10 个并发线程加速分析
|
|
71
|
+
vcode-analysis review ./src --workers 10
|
|
55
72
|
|
|
56
73
|
# 目录扫描
|
|
57
|
-
|
|
74
|
+
vcode-analysis scan-dir ./project
|
|
58
75
|
```
|
|
59
76
|
|
|
60
77
|
## 📖 命令概览
|
|
@@ -121,28 +138,37 @@ code-analysis/
|
|
|
121
138
|
### 代码审查
|
|
122
139
|
|
|
123
140
|
```bash
|
|
124
|
-
#
|
|
125
|
-
|
|
141
|
+
# 审查整个项目(结果保存到 result/src_review_20260320_120000.md)
|
|
142
|
+
vcode-analysis review ./src
|
|
143
|
+
|
|
144
|
+
# 使用 10 个线程加速分析
|
|
145
|
+
vcode-analysis review ./src --workers 10
|
|
146
|
+
|
|
147
|
+
# 自定义输出路径
|
|
148
|
+
vcode-analysis review ./src --output custom_report.md
|
|
126
149
|
|
|
127
150
|
# 审查最新提交
|
|
128
|
-
|
|
151
|
+
vcode-analysis review-commit HEAD
|
|
129
152
|
```
|
|
130
153
|
|
|
131
154
|
### 安全扫描
|
|
132
155
|
|
|
133
156
|
```bash
|
|
134
157
|
# 深度安全扫描
|
|
135
|
-
|
|
158
|
+
vcode-analysis security ./src --deep
|
|
159
|
+
|
|
160
|
+
# 快速扫描
|
|
161
|
+
vcode-analysis security ./src
|
|
136
162
|
```
|
|
137
163
|
|
|
138
164
|
### 批量操作
|
|
139
165
|
|
|
140
166
|
```bash
|
|
141
167
|
# 批量克隆(从文件读取 URL 列表)
|
|
142
|
-
|
|
168
|
+
vcode-analysis batch-clone repos.txt ./projects --parallel
|
|
143
169
|
|
|
144
170
|
# 查看多仓库状态
|
|
145
|
-
|
|
171
|
+
vcode-analysis git-status ~/projects
|
|
146
172
|
```
|
|
147
173
|
|
|
148
174
|
## ⚙️ 配置示例
|
|
@@ -202,11 +228,34 @@ parser = CASTParser()
|
|
|
202
228
|
result = parser.parse_file('main.c', mode='fast')
|
|
203
229
|
```
|
|
204
230
|
|
|
231
|
+
## 📦 发布到 PyPI
|
|
232
|
+
|
|
233
|
+
### 发布新版本
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# 安装发布工具
|
|
237
|
+
pip install build twine
|
|
238
|
+
|
|
239
|
+
# 构建包
|
|
240
|
+
python -m build
|
|
241
|
+
|
|
242
|
+
# 上传到 PyPI
|
|
243
|
+
twine upload dist/*
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 发布到 TestPyPI(测试)
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# 上传到 TestPyPI
|
|
250
|
+
twine upload --repository testpypi dist/*
|
|
251
|
+
```
|
|
252
|
+
|
|
205
253
|
## 📄 许可证
|
|
206
254
|
|
|
207
255
|
[MIT License](LICENSE)
|
|
208
256
|
|
|
209
257
|
## 🔗 链接
|
|
210
258
|
|
|
259
|
+
- [PyPI 包地址](https://pypi.org/project/vcode-analysis/)
|
|
211
260
|
- [项目主页](https://gitcode.com/wellchang/code-analysis)
|
|
212
261
|
- [问题反馈](https://gitcode.com/wellchang/code-analysis/issues)
|
|
@@ -5,6 +5,7 @@ from .documentation import DocumentationAnalyzer, DocumentationResult
|
|
|
5
5
|
from .architecture import ArchitectureAnalyzer, ArchitectureResult, ModuleInfo, DependencyInfo
|
|
6
6
|
from .security import SecurityAnalyzer, SecurityResult, SecurityIssue
|
|
7
7
|
from .directory import DirectoryAnalyzer, DirectoryAnalysisResult, ProjectInfo
|
|
8
|
+
from .context_builder import ContextBuilder, AnalysisContext
|
|
8
9
|
|
|
9
10
|
__all__ = [
|
|
10
11
|
"CodeReviewAnalyzer",
|
|
@@ -21,4 +22,6 @@ __all__ = [
|
|
|
21
22
|
"DirectoryAnalyzer",
|
|
22
23
|
"DirectoryAnalysisResult",
|
|
23
24
|
"ProjectInfo",
|
|
25
|
+
"ContextBuilder",
|
|
26
|
+
"AnalysisContext",
|
|
24
27
|
]
|
|
@@ -166,6 +166,16 @@ class ArchitectureAnalyzer:
|
|
|
166
166
|
self.modules: list[ModuleInfo] = []
|
|
167
167
|
self.dependencies: list[DependencyInfo] = []
|
|
168
168
|
|
|
169
|
+
def _count_lines(self, content: str) -> int:
|
|
170
|
+
"""准确计算代码行数"""
|
|
171
|
+
if not content:
|
|
172
|
+
return 0
|
|
173
|
+
# 如果以换行符结尾,换行符数量就是行数
|
|
174
|
+
# 否则,行数 = 换行符数量 + 1
|
|
175
|
+
if content.endswith('\n'):
|
|
176
|
+
return content.count('\n')
|
|
177
|
+
return content.count('\n') + 1
|
|
178
|
+
|
|
169
179
|
def _detect_imports(self, content: str, language: str, file_path: str = "") -> list[str]:
|
|
170
180
|
"""检测文件中的导入语句"""
|
|
171
181
|
imports = []
|
|
@@ -349,7 +359,7 @@ class ArchitectureAnalyzer:
|
|
|
349
359
|
language=file_info.language,
|
|
350
360
|
imports=imports,
|
|
351
361
|
exports=[], # TODO: 实现导出检测
|
|
352
|
-
lines=
|
|
362
|
+
lines=self._count_lines(content),
|
|
353
363
|
classes=structures.get("classes", 0),
|
|
354
364
|
functions=structures.get("functions", 0),
|
|
355
365
|
)
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"""代码审查分析器"""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Optional, TYPE_CHECKING
|
|
5
|
+
from core.analyzer import Analyzer, FileInfo, AnalysisResult
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .context_builder import AnalysisContext
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class CodeReviewResult:
|
|
13
|
+
"""代码审查结果"""
|
|
14
|
+
file_path: str
|
|
15
|
+
score: int # 1-10, 0 表示分析失败
|
|
16
|
+
issues: list[dict]
|
|
17
|
+
suggestions: list[str]
|
|
18
|
+
summary: str
|
|
19
|
+
success: bool = True
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _add_line_numbers(content: str) -> str:
|
|
23
|
+
"""给代码添加行号前缀,方便 LLM 准确定位问题"""
|
|
24
|
+
lines = content.split('\n')
|
|
25
|
+
max_width = len(str(len(lines)))
|
|
26
|
+
numbered_lines = [f"{i+1:>{max_width}}| {line}" for i, line in enumerate(lines)]
|
|
27
|
+
return '\n'.join(numbered_lines)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# 代码审查提示词模板
|
|
31
|
+
CODE_REVIEW_PROMPT = """请审查以下 {language} 代码:
|
|
32
|
+
|
|
33
|
+
文件: {file_path}
|
|
34
|
+
|
|
35
|
+
```{language}
|
|
36
|
+
{content}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
请进行代码审查,必须严格按照以下 JSON 格式输出,不要输出任何其他内容:
|
|
40
|
+
|
|
41
|
+
{{"score": 评分1-10, "issues": [{{"type": "问题类型", "severity": "high/medium/low", "line": 行号, "description": "问题描述"}}], "suggestions": ["改进建议"], "summary": "代码评价总结"}}"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# 带上下文的代码审查提示词模板
|
|
45
|
+
CODE_REVIEW_PROMPT_V2 = """请审查以下 {language} 代码:
|
|
46
|
+
|
|
47
|
+
文件: {file_path}
|
|
48
|
+
|
|
49
|
+
{context_section}
|
|
50
|
+
|
|
51
|
+
## 当前文件代码
|
|
52
|
+
```{language}
|
|
53
|
+
{content}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
请进行代码审查,必须严格按照以下 JSON 格式输出,不要输出任何其他内容:
|
|
57
|
+
|
|
58
|
+
{{"score": 评分1-10, "issues": [{{"type": "问题类型", "severity": "high/medium/low", "line": 行号, "description": "问题描述", "context": "相关上下文说明(可选)"}}], "suggestions": ["改进建议"], "summary": "代码评价总结", "cross_file_issues": ["跨文件问题(可选)"]}}"""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
COMMIT_REVIEW_PROMPT = """你是一位代码审查专家。请审查以下 Git 提交的变更。
|
|
62
|
+
|
|
63
|
+
提交信息: {commit_message}
|
|
64
|
+
作者: {author}
|
|
65
|
+
|
|
66
|
+
变更内容:
|
|
67
|
+
{diff}
|
|
68
|
+
|
|
69
|
+
请分析:
|
|
70
|
+
1. 变更的目的和影响
|
|
71
|
+
2. 潜在的问题或风险
|
|
72
|
+
3. 代码风格和最佳实践
|
|
73
|
+
4. 改进建议
|
|
74
|
+
|
|
75
|
+
以 Markdown 格式输出审查报告。"""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class CodeReviewAnalyzer:
|
|
79
|
+
"""代码审查分析器"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, analyzer: Analyzer):
|
|
82
|
+
self.analyzer = analyzer
|
|
83
|
+
|
|
84
|
+
def review_file(self, file_info: FileInfo) -> CodeReviewResult:
|
|
85
|
+
"""审查单个文件"""
|
|
86
|
+
try:
|
|
87
|
+
# 读取文件内容并添加行号
|
|
88
|
+
content = self.analyzer.read_file_content(file_info)
|
|
89
|
+
numbered_content = _add_line_numbers(content)
|
|
90
|
+
|
|
91
|
+
# 构建提示词
|
|
92
|
+
prompt = CODE_REVIEW_PROMPT.format(
|
|
93
|
+
file_path=file_info.relative_path,
|
|
94
|
+
language=file_info.language,
|
|
95
|
+
content=numbered_content,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# 调用 LLM
|
|
99
|
+
response = self.analyzer.llm.simple_chat(prompt)
|
|
100
|
+
|
|
101
|
+
result = AnalysisResult(
|
|
102
|
+
file_path=file_info.relative_path,
|
|
103
|
+
analyzer="code_review",
|
|
104
|
+
success=True,
|
|
105
|
+
content=response,
|
|
106
|
+
)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
result = AnalysisResult(
|
|
109
|
+
file_path=file_info.relative_path,
|
|
110
|
+
analyzer="code_review",
|
|
111
|
+
success=False,
|
|
112
|
+
content="",
|
|
113
|
+
errors=[str(e)],
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
if not result.success:
|
|
117
|
+
return CodeReviewResult(
|
|
118
|
+
file_path=file_info.relative_path,
|
|
119
|
+
score=0,
|
|
120
|
+
issues=[{"type": "error", "severity": "high", "description": result.errors[0]}],
|
|
121
|
+
suggestions=[],
|
|
122
|
+
summary="分析失败",
|
|
123
|
+
success=False,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# 解析 JSON 结果
|
|
127
|
+
import json
|
|
128
|
+
try:
|
|
129
|
+
# 尝试从 markdown 代码块中提取 JSON
|
|
130
|
+
content = result.content
|
|
131
|
+
if "```json" in content:
|
|
132
|
+
content = content.split("```json")[1].split("```")[0]
|
|
133
|
+
elif "```" in content:
|
|
134
|
+
content = content.split("```")[1].split("```")[0]
|
|
135
|
+
|
|
136
|
+
data = json.loads(content.strip())
|
|
137
|
+
return CodeReviewResult(
|
|
138
|
+
file_path=file_info.relative_path,
|
|
139
|
+
score=data.get("score", 0),
|
|
140
|
+
issues=data.get("issues", []),
|
|
141
|
+
suggestions=data.get("suggestions", []),
|
|
142
|
+
summary=data.get("summary", ""),
|
|
143
|
+
)
|
|
144
|
+
except json.JSONDecodeError:
|
|
145
|
+
# 如果解析失败,返回原始内容作为总结
|
|
146
|
+
return CodeReviewResult(
|
|
147
|
+
file_path=file_info.relative_path,
|
|
148
|
+
score=0,
|
|
149
|
+
issues=[],
|
|
150
|
+
suggestions=[],
|
|
151
|
+
summary=result.content,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def review_commit(self, commit_hash: str) -> AnalysisResult:
|
|
155
|
+
"""审查指定提交"""
|
|
156
|
+
git = self.analyzer.git
|
|
157
|
+
if not git:
|
|
158
|
+
return AnalysisResult(
|
|
159
|
+
file_path="",
|
|
160
|
+
analyzer="code_review",
|
|
161
|
+
success=False,
|
|
162
|
+
content="",
|
|
163
|
+
errors=["目标路径不是有效的 Git 仓库"],
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
commit_info = git.get_commit_info(commit_hash)
|
|
167
|
+
diffs = git.get_commit_diff(commit_hash)
|
|
168
|
+
|
|
169
|
+
# 构建差异内容
|
|
170
|
+
diff_content = ""
|
|
171
|
+
for diff in diffs:
|
|
172
|
+
diff_content += f"\n### {diff.file_path}\n"
|
|
173
|
+
diff_content += f"状态: {diff.status} (+{diff.additions}/-{diff.deletions})\n"
|
|
174
|
+
diff_content += f"```diff\n{diff.diff}\n```\n"
|
|
175
|
+
|
|
176
|
+
prompt = COMMIT_REVIEW_PROMPT.format(
|
|
177
|
+
commit_message=commit_info.message,
|
|
178
|
+
author=commit_info.author,
|
|
179
|
+
diff=diff_content,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
response = self.analyzer.llm.simple_chat(prompt)
|
|
183
|
+
|
|
184
|
+
return AnalysisResult(
|
|
185
|
+
file_path=commit_hash,
|
|
186
|
+
analyzer="code_review",
|
|
187
|
+
success=True,
|
|
188
|
+
content=response,
|
|
189
|
+
metadata={
|
|
190
|
+
"commit_hash": commit_hash,
|
|
191
|
+
"author": commit_info.author,
|
|
192
|
+
"date": commit_info.date.isoformat(),
|
|
193
|
+
"files_changed": commit_info.files_changed,
|
|
194
|
+
},
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
def review_files(self, file_infos: list[FileInfo]) -> list[CodeReviewResult]:
|
|
198
|
+
"""审查多个文件"""
|
|
199
|
+
results = []
|
|
200
|
+
for file_info in file_infos:
|
|
201
|
+
result = self.review_file(file_info)
|
|
202
|
+
results.append(result)
|
|
203
|
+
return results
|
|
204
|
+
|
|
205
|
+
def review_file_with_context(
|
|
206
|
+
self,
|
|
207
|
+
file_info: FileInfo,
|
|
208
|
+
context: "AnalysisContext",
|
|
209
|
+
context_builder=None
|
|
210
|
+
) -> CodeReviewResult:
|
|
211
|
+
"""带上下文的文件审查
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
file_info: 文件信息
|
|
215
|
+
context: 分析上下文
|
|
216
|
+
context_builder: 上下文构建器(用于格式化)
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
审查结果
|
|
220
|
+
"""
|
|
221
|
+
try:
|
|
222
|
+
# 读取文件内容并添加行号
|
|
223
|
+
content = self.analyzer.read_file_content(file_info)
|
|
224
|
+
numbered_content = _add_line_numbers(content)
|
|
225
|
+
|
|
226
|
+
# 构建上下文部分
|
|
227
|
+
context_section = ""
|
|
228
|
+
if context_builder:
|
|
229
|
+
context_section = context_builder.format_context_for_prompt(
|
|
230
|
+
file_info.relative_path, context
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# 构建提示词
|
|
234
|
+
prompt = CODE_REVIEW_PROMPT_V2.format(
|
|
235
|
+
file_path=file_info.relative_path,
|
|
236
|
+
language=file_info.language,
|
|
237
|
+
context_section=context_section,
|
|
238
|
+
content=numbered_content,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# 调用 LLM
|
|
242
|
+
response = self.analyzer.llm.simple_chat(prompt)
|
|
243
|
+
|
|
244
|
+
result = AnalysisResult(
|
|
245
|
+
file_path=file_info.relative_path,
|
|
246
|
+
analyzer="code_review",
|
|
247
|
+
success=True,
|
|
248
|
+
content=response,
|
|
249
|
+
)
|
|
250
|
+
except Exception as e:
|
|
251
|
+
result = AnalysisResult(
|
|
252
|
+
file_path=file_info.relative_path,
|
|
253
|
+
analyzer="code_review",
|
|
254
|
+
success=False,
|
|
255
|
+
content="",
|
|
256
|
+
errors=[str(e)],
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
if not result.success:
|
|
260
|
+
return CodeReviewResult(
|
|
261
|
+
file_path=file_info.relative_path,
|
|
262
|
+
score=0,
|
|
263
|
+
issues=[{"type": "error", "severity": "high", "description": result.errors[0]}],
|
|
264
|
+
suggestions=[],
|
|
265
|
+
summary="分析失败",
|
|
266
|
+
success=False,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# 解析 JSON 结果
|
|
270
|
+
import json
|
|
271
|
+
try:
|
|
272
|
+
# 尝试从 markdown 代码块中提取 JSON
|
|
273
|
+
content = result.content
|
|
274
|
+
if "```json" in content:
|
|
275
|
+
content = content.split("```json")[1].split("```")[0]
|
|
276
|
+
elif "```" in content:
|
|
277
|
+
content = content.split("```")[1].split("```")[0]
|
|
278
|
+
|
|
279
|
+
data = json.loads(content.strip())
|
|
280
|
+
|
|
281
|
+
# 提取跨文件问题并添加到 issues
|
|
282
|
+
issues = data.get("issues", [])
|
|
283
|
+
cross_file = data.get("cross_file_issues", [])
|
|
284
|
+
if cross_file:
|
|
285
|
+
for cf_issue in cross_file:
|
|
286
|
+
issues.append({
|
|
287
|
+
"type": "cross_file",
|
|
288
|
+
"severity": "medium",
|
|
289
|
+
"description": cf_issue,
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
return CodeReviewResult(
|
|
293
|
+
file_path=file_info.relative_path,
|
|
294
|
+
score=data.get("score", 0),
|
|
295
|
+
issues=issues,
|
|
296
|
+
suggestions=data.get("suggestions", []),
|
|
297
|
+
summary=data.get("summary", ""),
|
|
298
|
+
)
|
|
299
|
+
except json.JSONDecodeError:
|
|
300
|
+
# 如果解析失败,返回原始内容作为总结
|
|
301
|
+
return CodeReviewResult(
|
|
302
|
+
file_path=file_info.relative_path,
|
|
303
|
+
score=0,
|
|
304
|
+
issues=[],
|
|
305
|
+
suggestions=[],
|
|
306
|
+
summary=result.content,
|
|
307
|
+
)
|