vite-plugin-ai-code-review 1.0.3 → 1.0.4
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.
- package/dist/index.js +203 -168
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +138 -129
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import { ChatOpenAI } from '@langchain/openai';
|
|
2
|
-
import { SystemMessage, HumanMessage } from '@langchain/core/messages';
|
|
3
|
-
import crypto from 'crypto';
|
|
4
|
-
import { execSync } from 'child_process';
|
|
5
|
-
import fs2 from 'fs';
|
|
6
|
-
import path2 from 'path';
|
|
7
|
-
|
|
8
1
|
// src/reviewer.ts
|
|
2
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
3
|
+
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
4
|
+
import crypto from "crypto";
|
|
9
5
|
var CodeReviewer = class {
|
|
10
6
|
constructor(options) {
|
|
11
7
|
this.llm = null;
|
|
@@ -42,7 +38,7 @@ var CodeReviewer = class {
|
|
|
42
38
|
}
|
|
43
39
|
return issues;
|
|
44
40
|
} catch (error) {
|
|
45
|
-
console.error(
|
|
41
|
+
console.error(`❌ 审查失败: ${error.message}`);
|
|
46
42
|
return [];
|
|
47
43
|
}
|
|
48
44
|
}
|
|
@@ -73,63 +69,63 @@ var CodeReviewer = class {
|
|
|
73
69
|
*/
|
|
74
70
|
buildSystemPrompt() {
|
|
75
71
|
const { level, rules } = this.options;
|
|
76
|
-
let prompt =
|
|
72
|
+
let prompt = `你是一个专业的代码审查专家。请审查代码并识别问题。
|
|
77
73
|
|
|
78
|
-
|
|
74
|
+
审查级别: ${level}
|
|
79
75
|
`;
|
|
80
76
|
if (rules.security !== "off") {
|
|
81
77
|
prompt += `
|
|
82
|
-
|
|
83
|
-
- XSS
|
|
84
|
-
- SQL
|
|
85
|
-
- eval()
|
|
86
|
-
-
|
|
87
|
-
-
|
|
78
|
+
🔒 安全问题 (${rules.security}):
|
|
79
|
+
- XSS 漏洞
|
|
80
|
+
- SQL 注入
|
|
81
|
+
- eval() 使用
|
|
82
|
+
- 敏感信息泄露
|
|
83
|
+
- 不安全的依赖`;
|
|
88
84
|
}
|
|
89
85
|
if (rules.performance !== "off") {
|
|
90
86
|
prompt += `
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
87
|
+
⚡ 性能问题 (${rules.performance}):
|
|
88
|
+
- 大循环
|
|
89
|
+
- 内存泄漏
|
|
90
|
+
- 重复计算
|
|
91
|
+
- 不必要的渲染
|
|
92
|
+
- 阻塞操作`;
|
|
97
93
|
}
|
|
98
94
|
if (rules.style !== "off") {
|
|
99
95
|
prompt += `
|
|
100
|
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
96
|
+
📝 代码规范 (${rules.style}):
|
|
97
|
+
- 命名规范
|
|
98
|
+
- 代码复杂度
|
|
99
|
+
- 重复代码
|
|
100
|
+
- 注释完整性`;
|
|
105
101
|
}
|
|
106
102
|
if (rules.bestPractice !== "off") {
|
|
107
103
|
prompt += `
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
104
|
+
🎨 最佳实践 (${rules.bestPractice}):
|
|
105
|
+
- 错误处理
|
|
106
|
+
- 类型安全
|
|
107
|
+
- 组件设计
|
|
108
|
+
- 状态管理`;
|
|
113
109
|
}
|
|
114
110
|
prompt += `
|
|
115
111
|
|
|
116
|
-
|
|
112
|
+
返回 JSON 格式:
|
|
117
113
|
{
|
|
118
114
|
"issues": [
|
|
119
115
|
{
|
|
120
|
-
"line": 10, //
|
|
116
|
+
"line": 10, // 必须是准确的行号!
|
|
121
117
|
"category": "security",
|
|
122
118
|
"severity": "error",
|
|
123
|
-
"message": "
|
|
124
|
-
"suggestion": "
|
|
119
|
+
"message": "使用了 eval(),存在安全风险",
|
|
120
|
+
"suggestion": "使用 JSON.parse() 或其他安全方法"
|
|
125
121
|
}
|
|
126
122
|
]
|
|
127
123
|
}
|
|
128
124
|
|
|
129
|
-
|
|
130
|
-
1. line
|
|
131
|
-
2.
|
|
132
|
-
3.
|
|
125
|
+
**重要提示**:
|
|
126
|
+
1. line 字段必须是准确的行号,与代码中的行号一致
|
|
127
|
+
2. 如果代码带有行号前缀(如 "10: const x = 1"),请提取正确的行号
|
|
128
|
+
3. 只返回 JSON,不要其他解释`;
|
|
133
129
|
return new SystemMessage(prompt);
|
|
134
130
|
}
|
|
135
131
|
/**
|
|
@@ -141,19 +137,19 @@ var CodeReviewer = class {
|
|
|
141
137
|
const lines = code.split("\n");
|
|
142
138
|
const codeWithLineNumbers = lines.map((line, index) => `${index + 1}: ${line}`).join("\n");
|
|
143
139
|
return new HumanMessage(`
|
|
144
|
-
|
|
140
|
+
请审查以下 ${language} 代码:
|
|
145
141
|
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
文件: ${filePath}
|
|
143
|
+
总行数: ${lines.length}
|
|
148
144
|
|
|
149
|
-
|
|
145
|
+
代码(带行号):
|
|
150
146
|
\`\`\`${language}
|
|
151
147
|
${codeWithLineNumbers}
|
|
152
148
|
\`\`\`
|
|
153
149
|
|
|
154
|
-
|
|
150
|
+
**重要**:请返回准确的行号!行号必须与上面代码中的行号一致。
|
|
155
151
|
|
|
156
|
-
|
|
152
|
+
请返回 JSON 格式的问题列表。
|
|
157
153
|
`);
|
|
158
154
|
}
|
|
159
155
|
/**
|
|
@@ -168,7 +164,7 @@ ${codeWithLineNumbers}
|
|
|
168
164
|
line: issue.line,
|
|
169
165
|
category: issue.category || "best-practice",
|
|
170
166
|
severity: issue.severity || "info",
|
|
171
|
-
message: issue.message || "
|
|
167
|
+
message: issue.message || "未知问题",
|
|
172
168
|
suggestion: issue.suggestion,
|
|
173
169
|
code: issue.code
|
|
174
170
|
})).filter((issue) => {
|
|
@@ -216,6 +212,11 @@ ${codeWithLineNumbers}
|
|
|
216
212
|
};
|
|
217
213
|
}
|
|
218
214
|
};
|
|
215
|
+
|
|
216
|
+
// src/git-utils.ts
|
|
217
|
+
import { execSync } from "child_process";
|
|
218
|
+
import fs from "fs";
|
|
219
|
+
import path from "path";
|
|
219
220
|
var GitUtils = class {
|
|
220
221
|
/**
|
|
221
222
|
* 获取 Git 变更的文件列表
|
|
@@ -224,29 +225,29 @@ var GitUtils = class {
|
|
|
224
225
|
async getChangedFiles() {
|
|
225
226
|
try {
|
|
226
227
|
if (!this.isGitRepository()) {
|
|
227
|
-
console.warn("
|
|
228
|
+
console.warn("⚠️ 不在 Git 仓库中,无法获取变更文件");
|
|
228
229
|
return [];
|
|
229
230
|
}
|
|
230
|
-
console.log(
|
|
231
|
+
console.log(`🔍 [Git] 对比策略: HEAD~1 vs HEAD`);
|
|
231
232
|
const changedFiles = this.getCommitDiffFiles();
|
|
232
|
-
console.log(
|
|
233
|
+
console.log(`🔍 [Git] 检测到 ${changedFiles.length} 个变更文件`);
|
|
233
234
|
changedFiles.forEach((f) => console.log(` - ${f}`));
|
|
234
235
|
const existingFiles = changedFiles.map((file) => {
|
|
235
236
|
const cleanFile = file.replace(/^[^/]+\//, "");
|
|
236
237
|
return cleanFile;
|
|
237
238
|
}).filter((file) => {
|
|
238
|
-
const fullPath =
|
|
239
|
-
const exists =
|
|
239
|
+
const fullPath = path.resolve(process.cwd(), file);
|
|
240
|
+
const exists = fs.existsSync(fullPath);
|
|
240
241
|
if (!exists) {
|
|
241
|
-
console.log(`
|
|
242
|
+
console.log(` ⚠️ 文件不存在: ${fullPath}`);
|
|
242
243
|
}
|
|
243
244
|
return exists;
|
|
244
245
|
});
|
|
245
|
-
console.log(
|
|
246
|
-
existingFiles.forEach((f) => console.log(`
|
|
246
|
+
console.log(`🔍 [Git] 过滤后文件: ${existingFiles.length} 个`);
|
|
247
|
+
existingFiles.forEach((f) => console.log(` ✓ ${f}`));
|
|
247
248
|
return existingFiles;
|
|
248
249
|
} catch (error) {
|
|
249
|
-
console.warn(
|
|
250
|
+
console.warn(`⚠️ 获取 Git 变更文件失败: ${error.message}`);
|
|
250
251
|
return [];
|
|
251
252
|
}
|
|
252
253
|
}
|
|
@@ -277,10 +278,10 @@ var GitUtils = class {
|
|
|
277
278
|
if (files.length > 0) {
|
|
278
279
|
return files;
|
|
279
280
|
}
|
|
280
|
-
console.log(`
|
|
281
|
+
console.log(` ℹ️ 没有上一次提交,获取当前提交的所有文件`);
|
|
281
282
|
return this.getLastCommitFiles();
|
|
282
283
|
} catch (error) {
|
|
283
|
-
console.log(`
|
|
284
|
+
console.log(` ℹ️ 无法对比提交,尝试获取未提交的变更`);
|
|
284
285
|
return this.getUncommittedFiles();
|
|
285
286
|
}
|
|
286
287
|
}
|
|
@@ -370,6 +371,10 @@ var GitUtils = class {
|
|
|
370
371
|
}
|
|
371
372
|
}
|
|
372
373
|
};
|
|
374
|
+
|
|
375
|
+
// src/reporter.ts
|
|
376
|
+
import fs2 from "fs";
|
|
377
|
+
import path2 from "path";
|
|
373
378
|
var Reporter = class {
|
|
374
379
|
constructor(options = {}) {
|
|
375
380
|
this.options = options;
|
|
@@ -395,23 +400,23 @@ var Reporter = class {
|
|
|
395
400
|
* 生成控制台报告
|
|
396
401
|
*/
|
|
397
402
|
generateConsoleReport(issues) {
|
|
398
|
-
console.log("\n
|
|
399
|
-
console.log("
|
|
400
|
-
console.log("
|
|
403
|
+
console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
404
|
+
console.log("📊 代码审查报告");
|
|
405
|
+
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
|
401
406
|
const errors = issues.filter((i) => i.severity === "error");
|
|
402
407
|
const warnings = issues.filter((i) => i.severity === "warn");
|
|
403
408
|
const infos = issues.filter((i) => i.severity === "info");
|
|
404
|
-
console.log(
|
|
405
|
-
console.log(
|
|
406
|
-
console.log(
|
|
407
|
-
console.log(
|
|
409
|
+
console.log(`❌ 错误: ${errors.length}`);
|
|
410
|
+
console.log(`⚠️ 警告: ${warnings.length}`);
|
|
411
|
+
console.log(`ℹ️ 信息: ${infos.length}`);
|
|
412
|
+
console.log(`📝 总计: ${issues.length}
|
|
408
413
|
`);
|
|
409
414
|
const byCategory = this.groupByCategory(issues);
|
|
410
|
-
console.log("
|
|
415
|
+
console.log("📋 问题分类:");
|
|
411
416
|
Object.entries(byCategory).forEach(([category, count]) => {
|
|
412
417
|
console.log(` ${this.getCategoryIcon(category)} ${category}: ${count}`);
|
|
413
418
|
});
|
|
414
|
-
console.log("\n
|
|
419
|
+
console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
|
415
420
|
}
|
|
416
421
|
/**
|
|
417
422
|
* 生成 HTML 报告
|
|
@@ -423,7 +428,7 @@ var Reporter = class {
|
|
|
423
428
|
<head>
|
|
424
429
|
<meta charset="UTF-8">
|
|
425
430
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
426
|
-
<title
|
|
431
|
+
<title>代码审查报告</title>
|
|
427
432
|
<style>
|
|
428
433
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
429
434
|
body {
|
|
@@ -576,7 +581,7 @@ var Reporter = class {
|
|
|
576
581
|
line-height: 1.6;
|
|
577
582
|
}
|
|
578
583
|
.issue-suggestion::before {
|
|
579
|
-
content: "
|
|
584
|
+
content: "💡 建议: ";
|
|
580
585
|
font-weight: bold;
|
|
581
586
|
color: #2e7d32;
|
|
582
587
|
font-size: 16px;
|
|
@@ -611,27 +616,27 @@ var Reporter = class {
|
|
|
611
616
|
<body>
|
|
612
617
|
<div class="container">
|
|
613
618
|
<div class="header">
|
|
614
|
-
<h1
|
|
615
|
-
<div class="time"
|
|
619
|
+
<h1>🔍 代码审查报告</h1>
|
|
620
|
+
<div class="time">生成时间: ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN")}</div>
|
|
616
621
|
</div>
|
|
617
622
|
|
|
618
623
|
<div class="content">
|
|
619
624
|
<div class="summary">
|
|
620
625
|
<div class="summary-card error">
|
|
621
626
|
<h2>${issues.filter((i) => i.severity === "error").length}</h2>
|
|
622
|
-
<p
|
|
627
|
+
<p>错误</p>
|
|
623
628
|
</div>
|
|
624
629
|
<div class="summary-card warn">
|
|
625
630
|
<h2>${issues.filter((i) => i.severity === "warn").length}</h2>
|
|
626
|
-
<p
|
|
631
|
+
<p>警告</p>
|
|
627
632
|
</div>
|
|
628
633
|
<div class="summary-card info">
|
|
629
634
|
<h2>${issues.filter((i) => i.severity === "info").length}</h2>
|
|
630
|
-
<p
|
|
635
|
+
<p>信息</p>
|
|
631
636
|
</div>
|
|
632
637
|
</div>
|
|
633
638
|
|
|
634
|
-
<div class="section-title"
|
|
639
|
+
<div class="section-title">📊 问题分类统计</div>
|
|
635
640
|
<div class="category-stats">
|
|
636
641
|
${Object.entries(this.groupByCategory(issues)).map(
|
|
637
642
|
([category, count]) => `<div class="category-tag">${this.getCategoryIcon(
|
|
@@ -640,7 +645,7 @@ var Reporter = class {
|
|
|
640
645
|
).join("")}
|
|
641
646
|
</div>
|
|
642
647
|
|
|
643
|
-
<div class="section-title"
|
|
648
|
+
<div class="section-title">📋 问题详情</div>
|
|
644
649
|
${issues.map(
|
|
645
650
|
(issue) => `
|
|
646
651
|
<div class="issue">
|
|
@@ -648,7 +653,7 @@ var Reporter = class {
|
|
|
648
653
|
<span class="issue-badge ${issue.severity}">${issue.severity.toUpperCase()}</span>
|
|
649
654
|
<span class="issue-category">${issue.category}</span>
|
|
650
655
|
<span class="issue-file">${issue.file}</span>
|
|
651
|
-
${issue.line ? `<span class="issue-line"
|
|
656
|
+
${issue.line ? `<span class="issue-line">行 ${issue.line}</span>` : ""}
|
|
652
657
|
</div>
|
|
653
658
|
<div class="issue-message">${issue.message}</div>
|
|
654
659
|
${issue.suggestion ? `<div class="issue-suggestion">${issue.suggestion}</div>` : ""}
|
|
@@ -671,7 +676,7 @@ var Reporter = class {
|
|
|
671
676
|
}
|
|
672
677
|
const reportPath = path2.join(reportsDir, "code-review-report.html");
|
|
673
678
|
fs2.writeFileSync(reportPath, html, "utf-8");
|
|
674
|
-
console.log(
|
|
679
|
+
console.log(`📄 HTML 报告已生成: ${reportPath}
|
|
675
680
|
`);
|
|
676
681
|
}
|
|
677
682
|
/**
|
|
@@ -681,33 +686,33 @@ var Reporter = class {
|
|
|
681
686
|
const errors = issues.filter((i) => i.severity === "error");
|
|
682
687
|
const warnings = issues.filter((i) => i.severity === "warn");
|
|
683
688
|
const infos = issues.filter((i) => i.severity === "info");
|
|
684
|
-
let markdown = `#
|
|
689
|
+
let markdown = `# 🔍 代码审查报告
|
|
685
690
|
|
|
686
|
-
|
|
691
|
+
生成时间: ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN")}
|
|
687
692
|
|
|
688
|
-
##
|
|
693
|
+
## 📊 概览
|
|
689
694
|
|
|
690
|
-
|
|
|
695
|
+
| 类型 | 数量 |
|
|
691
696
|
|------|------|
|
|
692
|
-
|
|
|
693
|
-
|
|
|
694
|
-
|
|
|
695
|
-
|
|
|
697
|
+
| ❌ 错误 | ${errors.length} |
|
|
698
|
+
| ⚠️ 警告 | ${warnings.length} |
|
|
699
|
+
| ℹ️ 信息 | ${infos.length} |
|
|
700
|
+
| 📝 总计 | ${issues.length} |
|
|
696
701
|
|
|
697
|
-
##
|
|
702
|
+
## 📋 问题详情
|
|
698
703
|
|
|
699
704
|
`;
|
|
700
705
|
issues.forEach((issue, index) => {
|
|
701
706
|
const icon = this.getSeverityIcon(issue.severity);
|
|
702
707
|
markdown += `### ${index + 1}. ${icon} ${issue.category}
|
|
703
708
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
709
|
+
**文件**: \`${issue.file}${issue.line ? `:${issue.line}` : ""}\`
|
|
710
|
+
**严重程度**: ${issue.severity}
|
|
711
|
+
**问题**: ${issue.message}
|
|
707
712
|
|
|
708
713
|
`;
|
|
709
714
|
if (issue.suggestion) {
|
|
710
|
-
markdown +=
|
|
715
|
+
markdown += `💡 **建议**: ${issue.suggestion}
|
|
711
716
|
|
|
712
717
|
`;
|
|
713
718
|
}
|
|
@@ -719,7 +724,7 @@ var Reporter = class {
|
|
|
719
724
|
}
|
|
720
725
|
const reportPath = path2.join(reportsDir, "code-review-report.md");
|
|
721
726
|
fs2.writeFileSync(reportPath, markdown, "utf-8");
|
|
722
|
-
console.log(
|
|
727
|
+
console.log(`📄 Markdown 报告已生成: ${reportPath}
|
|
723
728
|
`);
|
|
724
729
|
}
|
|
725
730
|
/**
|
|
@@ -742,7 +747,7 @@ var Reporter = class {
|
|
|
742
747
|
}
|
|
743
748
|
const reportPath = path2.join(reportsDir, "code-review-report.json");
|
|
744
749
|
fs2.writeFileSync(reportPath, JSON.stringify(report, null, 2), "utf-8");
|
|
745
|
-
console.log(
|
|
750
|
+
console.log(`📄 JSON 报告已生成: ${reportPath}
|
|
746
751
|
`);
|
|
747
752
|
}
|
|
748
753
|
/**
|
|
@@ -760,12 +765,12 @@ var Reporter = class {
|
|
|
760
765
|
*/
|
|
761
766
|
getCategoryIcon(category) {
|
|
762
767
|
const icons = {
|
|
763
|
-
security: "
|
|
764
|
-
performance: "
|
|
765
|
-
style: "
|
|
766
|
-
"best-practice": "
|
|
768
|
+
security: "🔒",
|
|
769
|
+
performance: "⚡",
|
|
770
|
+
style: "📝",
|
|
771
|
+
"best-practice": "🎨"
|
|
767
772
|
};
|
|
768
|
-
return icons[category] || "
|
|
773
|
+
return icons[category] || "📋";
|
|
769
774
|
}
|
|
770
775
|
/**
|
|
771
776
|
* 获取严重程度图标
|
|
@@ -773,13 +778,13 @@ var Reporter = class {
|
|
|
773
778
|
getSeverityIcon(severity) {
|
|
774
779
|
switch (severity) {
|
|
775
780
|
case "error":
|
|
776
|
-
return "
|
|
781
|
+
return "❌";
|
|
777
782
|
case "warn":
|
|
778
|
-
return "
|
|
783
|
+
return "⚠️";
|
|
779
784
|
case "info":
|
|
780
|
-
return "
|
|
785
|
+
return "ℹ️";
|
|
781
786
|
default:
|
|
782
|
-
return "
|
|
787
|
+
return "📝";
|
|
783
788
|
}
|
|
784
789
|
}
|
|
785
790
|
};
|
|
@@ -834,20 +839,20 @@ function vitePluginAICodeReview(options = {}) {
|
|
|
834
839
|
name: "vite-plugin-ai-code-review",
|
|
835
840
|
enforce: "post",
|
|
836
841
|
configResolved(config) {
|
|
837
|
-
console.log("\n
|
|
838
|
-
console.log(
|
|
839
|
-
console.log(
|
|
840
|
-
console.log(
|
|
842
|
+
console.log("\n🔍 AI Code Review 已启动...");
|
|
843
|
+
console.log(`📂 审查模式: ${mode}`);
|
|
844
|
+
console.log(`📊 审查级别: ${level}`);
|
|
845
|
+
console.log(`🔑 API Key: ${apiKey ? "已配置" : "未配置"}
|
|
841
846
|
`);
|
|
842
847
|
},
|
|
843
848
|
async buildStart() {
|
|
844
849
|
if (!apiKey) {
|
|
845
|
-
console.warn("
|
|
850
|
+
console.warn("⚠️ 未配置 API Key,跳过代码审查");
|
|
846
851
|
return;
|
|
847
852
|
}
|
|
848
853
|
if (mode === "changed") {
|
|
849
854
|
filesToReview = await gitUtils.getChangedFiles();
|
|
850
|
-
console.log(
|
|
855
|
+
console.log(`🔍 [Git] 检测到 ${filesToReview.length} 个变更文件`);
|
|
851
856
|
filesToReview.forEach((f) => console.log(` - ${f}`));
|
|
852
857
|
} else if (mode === "manual") {
|
|
853
858
|
filesToReview = files;
|
|
@@ -858,16 +863,16 @@ function vitePluginAICodeReview(options = {}) {
|
|
|
858
863
|
(file) => shouldReview(file, include, exclude)
|
|
859
864
|
);
|
|
860
865
|
if (mode !== "all" && filesToReview.length > 0) {
|
|
861
|
-
console.log(
|
|
866
|
+
console.log(`📝 过滤后需要审查 ${filesToReview.length} 个文件
|
|
862
867
|
`);
|
|
863
868
|
for (const file of filesToReview) {
|
|
864
869
|
try {
|
|
865
|
-
const fs3 = await import(
|
|
866
|
-
const path3 = await import(
|
|
870
|
+
const fs3 = await import("fs");
|
|
871
|
+
const path3 = await import("path");
|
|
867
872
|
const fullPath = path3.resolve(process.cwd(), file);
|
|
868
873
|
if (fs3.existsSync(fullPath)) {
|
|
869
874
|
const code = fs3.readFileSync(fullPath, "utf-8");
|
|
870
|
-
console.log(
|
|
875
|
+
console.log(`🔍 [审查] ${file}`);
|
|
871
876
|
const issues = await reviewer.review(code, file);
|
|
872
877
|
if (issues.length > 0) {
|
|
873
878
|
allIssues.push(...issues);
|
|
@@ -879,22 +884,22 @@ function vitePluginAICodeReview(options = {}) {
|
|
|
879
884
|
);
|
|
880
885
|
console.log(` ${issue.message}`);
|
|
881
886
|
if (issue.suggestion) {
|
|
882
|
-
console.log(`
|
|
887
|
+
console.log(` 💡 ${issue.suggestion}`);
|
|
883
888
|
}
|
|
884
889
|
});
|
|
885
890
|
console.log("");
|
|
886
891
|
}
|
|
887
892
|
} else {
|
|
888
|
-
console.log(
|
|
893
|
+
console.log(`✅ 未发现问题
|
|
889
894
|
`);
|
|
890
895
|
}
|
|
891
896
|
}
|
|
892
897
|
} catch (error) {
|
|
893
|
-
console.warn(
|
|
898
|
+
console.warn(`⚠️ 审查失败 ${file}: ${error.message}`);
|
|
894
899
|
}
|
|
895
900
|
}
|
|
896
901
|
} else if (mode !== "all") {
|
|
897
|
-
console.log(
|
|
902
|
+
console.log(`📝 没有需要审查的文件
|
|
898
903
|
`);
|
|
899
904
|
}
|
|
900
905
|
},
|
|
@@ -909,8 +914,8 @@ function vitePluginAICodeReview(options = {}) {
|
|
|
909
914
|
return null;
|
|
910
915
|
}
|
|
911
916
|
try {
|
|
912
|
-
console.log(
|
|
913
|
-
const fs3 = await import(
|
|
917
|
+
console.log(`🔍 [审查] ${id}`);
|
|
918
|
+
const fs3 = await import("fs");
|
|
914
919
|
let sourceCode = code;
|
|
915
920
|
if (fs3.existsSync(id)) {
|
|
916
921
|
sourceCode = fs3.readFileSync(id, "utf-8");
|
|
@@ -926,27 +931,27 @@ function vitePluginAICodeReview(options = {}) {
|
|
|
926
931
|
);
|
|
927
932
|
console.log(` ${issue.message}`);
|
|
928
933
|
if (issue.suggestion) {
|
|
929
|
-
console.log(`
|
|
934
|
+
console.log(` 💡 ${issue.suggestion}`);
|
|
930
935
|
}
|
|
931
936
|
});
|
|
932
937
|
console.log("");
|
|
933
938
|
}
|
|
934
939
|
}
|
|
935
940
|
} catch (error) {
|
|
936
|
-
console.warn(
|
|
941
|
+
console.warn(`⚠️ 审查失败 ${id}: ${error.message}`);
|
|
937
942
|
}
|
|
938
943
|
return null;
|
|
939
944
|
},
|
|
940
945
|
async buildEnd() {
|
|
941
946
|
if (allIssues.length === 0) {
|
|
942
|
-
console.log("
|
|
947
|
+
console.log("✨ 代码审查完成,未发现问题\n");
|
|
943
948
|
return;
|
|
944
949
|
}
|
|
945
950
|
await reporter.generate(allIssues);
|
|
946
951
|
if (output.failOnError) {
|
|
947
952
|
const errors = allIssues.filter((i) => i.severity === "error");
|
|
948
953
|
if (errors.length > 0) {
|
|
949
|
-
throw new Error(
|
|
954
|
+
throw new Error(`代码审查发现 ${errors.length} 个错误`);
|
|
950
955
|
}
|
|
951
956
|
}
|
|
952
957
|
}
|
|
@@ -977,17 +982,21 @@ function matchPattern(filePath, pattern) {
|
|
|
977
982
|
function getSeverityIcon(severity) {
|
|
978
983
|
switch (severity) {
|
|
979
984
|
case "error":
|
|
980
|
-
return "
|
|
985
|
+
return "❌";
|
|
981
986
|
case "warn":
|
|
982
|
-
return "
|
|
987
|
+
return "⚠️";
|
|
983
988
|
case "info":
|
|
984
|
-
return "
|
|
989
|
+
return "ℹ️";
|
|
985
990
|
default:
|
|
986
|
-
return "
|
|
991
|
+
return "📝";
|
|
987
992
|
}
|
|
988
993
|
}
|
|
989
994
|
var index_default = vitePluginAICodeReview;
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
995
|
+
export {
|
|
996
|
+
CodeReviewer,
|
|
997
|
+
GitUtils,
|
|
998
|
+
Reporter,
|
|
999
|
+
index_default as default,
|
|
1000
|
+
vitePluginAICodeReview
|
|
1001
|
+
};
|
|
993
1002
|
//# sourceMappingURL=index.mjs.map
|