auto-coder 0.1.316__py3-none-any.whl → 0.1.318__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.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/METADATA +2 -2
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/RECORD +41 -20
- autocoder/auto_coder_runner.py +1 -2
- autocoder/common/__init__.py +3 -0
- autocoder/common/auto_coder_lang.py +24 -0
- autocoder/common/code_auto_merge_editblock.py +2 -42
- autocoder/common/git_utils.py +2 -2
- autocoder/common/token_cost_caculate.py +103 -42
- autocoder/common/v2/__init__.py +0 -0
- autocoder/common/v2/code_auto_generate.py +199 -0
- autocoder/common/v2/code_auto_generate_diff.py +361 -0
- autocoder/common/v2/code_auto_generate_editblock.py +380 -0
- autocoder/common/v2/code_auto_generate_strict_diff.py +269 -0
- autocoder/common/v2/code_auto_merge.py +211 -0
- autocoder/common/v2/code_auto_merge_diff.py +354 -0
- autocoder/common/v2/code_auto_merge_editblock.py +523 -0
- autocoder/common/v2/code_auto_merge_strict_diff.py +259 -0
- autocoder/common/v2/code_diff_manager.py +266 -0
- autocoder/common/v2/code_editblock_manager.py +282 -0
- autocoder/common/v2/code_manager.py +238 -0
- autocoder/common/v2/code_strict_diff_manager.py +241 -0
- autocoder/dispacher/actions/action.py +16 -0
- autocoder/dispacher/actions/plugins/action_regex_project.py +6 -0
- autocoder/events/event_manager_singleton.py +2 -2
- autocoder/helper/__init__.py +0 -0
- autocoder/helper/project_creator.py +570 -0
- autocoder/linters/linter_factory.py +44 -25
- autocoder/linters/models.py +220 -0
- autocoder/linters/python_linter.py +1 -7
- autocoder/linters/reactjs_linter.py +580 -0
- autocoder/linters/shadow_linter.py +390 -0
- autocoder/linters/vue_linter.py +576 -0
- autocoder/memory/active_context_manager.py +0 -4
- autocoder/memory/active_package.py +12 -12
- autocoder/shadows/__init__.py +0 -0
- autocoder/shadows/shadow_manager.py +235 -0
- autocoder/version.py +1 -1
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"""
|
|
2
|
+
用于对影子文件进行代码检查并将结果映射回项目路径的模块。
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import time
|
|
7
|
+
from typing import Dict, List, Any, Optional, Tuple
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
from autocoder.linters.linter_factory import LinterFactory
|
|
11
|
+
from autocoder.shadows.shadow_manager import ShadowManager
|
|
12
|
+
from autocoder.linters.models import (
|
|
13
|
+
LintIssue,
|
|
14
|
+
FileLintResult,
|
|
15
|
+
ProjectLintResult,
|
|
16
|
+
IssuePosition,
|
|
17
|
+
IssueSeverity
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
class ShadowLinter:
|
|
21
|
+
"""
|
|
22
|
+
用于对ShadowManager管理的文件进行代码检查并将结果转换回项目路径的类。
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, shadow_manager: ShadowManager, verbose: bool = False):
|
|
26
|
+
"""
|
|
27
|
+
使用ShadowManager实例初始化。
|
|
28
|
+
|
|
29
|
+
参数:
|
|
30
|
+
shadow_manager (ShadowManager): 用于管理文件路径映射的实例
|
|
31
|
+
verbose (bool): 是否启用详细输出
|
|
32
|
+
"""
|
|
33
|
+
self.shadow_manager = shadow_manager
|
|
34
|
+
self.verbose = verbose
|
|
35
|
+
|
|
36
|
+
def lint_shadow_file(self, shadow_path: str, fix: bool = False) -> FileLintResult:
|
|
37
|
+
"""
|
|
38
|
+
对单个影子文件进行代码检查并将结果中的路径转换为项目路径。
|
|
39
|
+
|
|
40
|
+
参数:
|
|
41
|
+
shadow_path (str): 影子文件的路径
|
|
42
|
+
fix (bool): 是否自动修复问题
|
|
43
|
+
|
|
44
|
+
返回:
|
|
45
|
+
FileLintResult: 包含项目路径的代码检查结果
|
|
46
|
+
"""
|
|
47
|
+
# 检查路径是否为影子路径
|
|
48
|
+
if not self.shadow_manager.is_shadow_path(shadow_path):
|
|
49
|
+
raise ValueError(f"不是影子路径: {shadow_path}")
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
# 获取此影子文件的项目路径
|
|
53
|
+
project_path = self.shadow_manager.from_shadow_path(shadow_path)
|
|
54
|
+
|
|
55
|
+
# 记录开始时间以计算执行时间
|
|
56
|
+
start_time = time.time()
|
|
57
|
+
|
|
58
|
+
# 对影子文件运行代码检查
|
|
59
|
+
raw_lint_result = LinterFactory.lint_file(shadow_path, fix=fix, verbose=self.verbose)
|
|
60
|
+
|
|
61
|
+
# 如果lint过程返回None,创建一个空的结果对象,而不是直接返回None
|
|
62
|
+
if raw_lint_result is None:
|
|
63
|
+
language = self._detect_language(shadow_path)
|
|
64
|
+
return FileLintResult(
|
|
65
|
+
file_path=project_path,
|
|
66
|
+
success=False,
|
|
67
|
+
language=language,
|
|
68
|
+
issues=[], # 空问题列表
|
|
69
|
+
error=None,
|
|
70
|
+
error_count=0,
|
|
71
|
+
warning_count=0,
|
|
72
|
+
info_count=0
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# 计算执行时间(毫秒)
|
|
76
|
+
execution_time_ms = int((time.time() - start_time) * 1000)
|
|
77
|
+
raw_lint_result['execution_time_ms'] = execution_time_ms
|
|
78
|
+
|
|
79
|
+
# 将原始结果转换为Pydantic模型
|
|
80
|
+
return self._convert_raw_lint_result(raw_lint_result, shadow_path, project_path)
|
|
81
|
+
except Exception as e:
|
|
82
|
+
if self.verbose:
|
|
83
|
+
print(f"检查 {shadow_path} 时出错: {str(e)}")
|
|
84
|
+
|
|
85
|
+
project_path = self.shadow_manager.from_shadow_path(shadow_path)
|
|
86
|
+
language = self._detect_language(shadow_path)
|
|
87
|
+
return FileLintResult(
|
|
88
|
+
file_path=project_path,
|
|
89
|
+
success=False,
|
|
90
|
+
language=language,
|
|
91
|
+
error=str(e),
|
|
92
|
+
issues=[], # 添加空问题列表
|
|
93
|
+
error_count=0,
|
|
94
|
+
warning_count=0,
|
|
95
|
+
info_count=0
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def lint_all_shadow_files(self, fix: bool = False) -> ProjectLintResult:
|
|
99
|
+
"""
|
|
100
|
+
对影子目录中的所有文件进行代码检查并返回包含项目路径的结果。
|
|
101
|
+
|
|
102
|
+
参数:
|
|
103
|
+
fix (bool): 是否自动修复问题
|
|
104
|
+
|
|
105
|
+
返回:
|
|
106
|
+
ProjectLintResult: 所有文件的汇总代码检查结果
|
|
107
|
+
"""
|
|
108
|
+
shadow_files = self._get_all_shadow_files()
|
|
109
|
+
file_results = {}
|
|
110
|
+
total_files = len(shadow_files)
|
|
111
|
+
files_with_issues = 0
|
|
112
|
+
total_issues = 0
|
|
113
|
+
total_errors = 0
|
|
114
|
+
total_warnings = 0
|
|
115
|
+
total_infos = 0
|
|
116
|
+
fixed_issues_count = 0
|
|
117
|
+
|
|
118
|
+
# 处理每个影子文件
|
|
119
|
+
for shadow_path in shadow_files:
|
|
120
|
+
try:
|
|
121
|
+
file_result = self.lint_shadow_file(shadow_path, fix=fix)
|
|
122
|
+
# lint_shadow_file现在总是返回有效的FileLintResult,不再需要检查None
|
|
123
|
+
project_path = self.shadow_manager.from_shadow_path(shadow_path)
|
|
124
|
+
|
|
125
|
+
file_results[project_path] = file_result
|
|
126
|
+
|
|
127
|
+
# 更新统计数据
|
|
128
|
+
if file_result.success:
|
|
129
|
+
issue_count = len(file_result.issues)
|
|
130
|
+
if issue_count > 0:
|
|
131
|
+
files_with_issues += 1
|
|
132
|
+
total_issues += issue_count
|
|
133
|
+
total_errors += file_result.error_count
|
|
134
|
+
total_warnings += file_result.warning_count
|
|
135
|
+
total_infos += file_result.info_count
|
|
136
|
+
|
|
137
|
+
if file_result.fixed_issues_count:
|
|
138
|
+
fixed_issues_count += file_result.fixed_issues_count
|
|
139
|
+
except Exception as e:
|
|
140
|
+
if self.verbose:
|
|
141
|
+
import traceback
|
|
142
|
+
traceback.print_exc()
|
|
143
|
+
print(f"处理 {shadow_path} 时出错: {str(e)}")
|
|
144
|
+
|
|
145
|
+
# 加载的是影子文件,但是要转换成项目的路径
|
|
146
|
+
project_path = self.shadow_manager.from_shadow_path(shadow_path)
|
|
147
|
+
language = self._detect_language(shadow_path)
|
|
148
|
+
file_results[project_path] = FileLintResult(
|
|
149
|
+
file_path=project_path,
|
|
150
|
+
success=False,
|
|
151
|
+
language=language,
|
|
152
|
+
error=str(e),
|
|
153
|
+
issues=[],
|
|
154
|
+
error_count=0,
|
|
155
|
+
warning_count=0,
|
|
156
|
+
info_count=0
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# 创建项目结果
|
|
160
|
+
return ProjectLintResult(
|
|
161
|
+
project_path=self.shadow_manager.source_dir,
|
|
162
|
+
file_results=file_results,
|
|
163
|
+
total_files=total_files,
|
|
164
|
+
files_with_issues=files_with_issues,
|
|
165
|
+
total_issues=total_issues,
|
|
166
|
+
total_errors=total_errors,
|
|
167
|
+
total_warnings=total_warnings,
|
|
168
|
+
total_infos=total_infos,
|
|
169
|
+
fixed_issues_count=fixed_issues_count if fix else None
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
def lint_shadow_dir(self, shadow_dir: str, fix: bool = False) -> ProjectLintResult:
|
|
173
|
+
"""
|
|
174
|
+
对特定影子目录中的所有文件进行代码检查。
|
|
175
|
+
|
|
176
|
+
参数:
|
|
177
|
+
shadow_dir (str): 影子目录的路径
|
|
178
|
+
fix (bool): 是否自动修复问题
|
|
179
|
+
|
|
180
|
+
返回:
|
|
181
|
+
ProjectLintResult: 目录中所有文件的汇总代码检查结果
|
|
182
|
+
"""
|
|
183
|
+
if not self.shadow_manager.is_shadow_path(shadow_dir):
|
|
184
|
+
raise ValueError(f"不是影子路径: {shadow_dir}")
|
|
185
|
+
|
|
186
|
+
shadow_files = self._get_files_in_dir(shadow_dir)
|
|
187
|
+
file_results = {}
|
|
188
|
+
total_files = len(shadow_files)
|
|
189
|
+
files_with_issues = 0
|
|
190
|
+
total_issues = 0
|
|
191
|
+
total_errors = 0
|
|
192
|
+
total_warnings = 0
|
|
193
|
+
total_infos = 0
|
|
194
|
+
fixed_issues_count = 0
|
|
195
|
+
|
|
196
|
+
for shadow_path in shadow_files:
|
|
197
|
+
try:
|
|
198
|
+
file_result = self.lint_shadow_file(shadow_path, fix=fix)
|
|
199
|
+
# lint_shadow_file现在总是返回有效的FileLintResult,不再需要检查None
|
|
200
|
+
project_path = self.shadow_manager.from_shadow_path(shadow_path)
|
|
201
|
+
|
|
202
|
+
file_results[project_path] = file_result
|
|
203
|
+
|
|
204
|
+
# 更新统计数据
|
|
205
|
+
if file_result.success:
|
|
206
|
+
issue_count = len(file_result.issues)
|
|
207
|
+
if issue_count > 0:
|
|
208
|
+
files_with_issues += 1
|
|
209
|
+
total_issues += issue_count
|
|
210
|
+
total_errors += file_result.error_count
|
|
211
|
+
total_warnings += file_result.warning_count
|
|
212
|
+
total_infos += file_result.info_count
|
|
213
|
+
|
|
214
|
+
if file_result.fixed_issues_count:
|
|
215
|
+
fixed_issues_count += file_result.fixed_issues_count
|
|
216
|
+
except Exception as e:
|
|
217
|
+
if self.verbose:
|
|
218
|
+
print(f"处理 {shadow_path} 时出错: {str(e)}")
|
|
219
|
+
|
|
220
|
+
project_path = self.shadow_manager.from_shadow_path(shadow_path)
|
|
221
|
+
language = self._detect_language(shadow_path)
|
|
222
|
+
file_results[project_path] = FileLintResult(
|
|
223
|
+
file_path=project_path,
|
|
224
|
+
success=False,
|
|
225
|
+
language=language,
|
|
226
|
+
error=str(e),
|
|
227
|
+
issues=[],
|
|
228
|
+
error_count=0,
|
|
229
|
+
warning_count=0,
|
|
230
|
+
info_count=0
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# 创建项目结果
|
|
234
|
+
project_path = self.shadow_manager.from_shadow_path(shadow_dir)
|
|
235
|
+
return ProjectLintResult(
|
|
236
|
+
project_path=project_path,
|
|
237
|
+
file_results=file_results,
|
|
238
|
+
total_files=total_files,
|
|
239
|
+
files_with_issues=files_with_issues,
|
|
240
|
+
total_issues=total_issues,
|
|
241
|
+
total_errors=total_errors,
|
|
242
|
+
total_warnings=total_warnings,
|
|
243
|
+
total_infos=total_infos,
|
|
244
|
+
fixed_issues_count=fixed_issues_count if fix else None
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
def _get_all_shadow_files(self) -> List[str]:
|
|
248
|
+
"""
|
|
249
|
+
获取影子目录中的所有文件。
|
|
250
|
+
|
|
251
|
+
返回:
|
|
252
|
+
List[str]: 影子文件的绝对路径列表
|
|
253
|
+
"""
|
|
254
|
+
all_files = []
|
|
255
|
+
|
|
256
|
+
for root, _, files in os.walk(self.shadow_manager.shadows_dir):
|
|
257
|
+
for file in files:
|
|
258
|
+
# 跳过隐藏文件和目录
|
|
259
|
+
if file.startswith('.'):
|
|
260
|
+
continue
|
|
261
|
+
|
|
262
|
+
file_path = os.path.join(root, file)
|
|
263
|
+
all_files.append(file_path)
|
|
264
|
+
|
|
265
|
+
return all_files
|
|
266
|
+
|
|
267
|
+
def _get_files_in_dir(self, directory: str) -> List[str]:
|
|
268
|
+
"""
|
|
269
|
+
获取目录及其子目录中的所有文件。
|
|
270
|
+
|
|
271
|
+
参数:
|
|
272
|
+
directory (str): 目录路径
|
|
273
|
+
|
|
274
|
+
返回:
|
|
275
|
+
List[str]: 绝对文件路径列表
|
|
276
|
+
"""
|
|
277
|
+
all_files = []
|
|
278
|
+
|
|
279
|
+
for root, _, files in os.walk(directory):
|
|
280
|
+
for file in files:
|
|
281
|
+
# 跳过隐藏文件
|
|
282
|
+
if file.startswith('.'):
|
|
283
|
+
continue
|
|
284
|
+
|
|
285
|
+
file_path = os.path.join(root, file)
|
|
286
|
+
all_files.append(file_path)
|
|
287
|
+
|
|
288
|
+
return all_files
|
|
289
|
+
|
|
290
|
+
def _detect_language(self, file_path: str) -> str:
|
|
291
|
+
"""
|
|
292
|
+
根据文件扩展名检测文件的语言。
|
|
293
|
+
|
|
294
|
+
参数:
|
|
295
|
+
file_path (str): 文件路径
|
|
296
|
+
|
|
297
|
+
返回:
|
|
298
|
+
str: 检测到的语言或"unknown"
|
|
299
|
+
"""
|
|
300
|
+
try:
|
|
301
|
+
language = LinterFactory._detect_language_from_file(file_path)
|
|
302
|
+
# 确保返回值是字符串
|
|
303
|
+
return language if isinstance(language, str) else "unknown"
|
|
304
|
+
except ValueError:
|
|
305
|
+
# 如果语言检测失败,返回默认值
|
|
306
|
+
return "unknown"
|
|
307
|
+
except Exception:
|
|
308
|
+
# 捕获所有其他异常并返回默认值
|
|
309
|
+
return "unknown"
|
|
310
|
+
|
|
311
|
+
def _convert_raw_lint_result(self, raw_result: Dict[str, Any], shadow_path: str, project_path: str) -> FileLintResult:
|
|
312
|
+
"""
|
|
313
|
+
将原始的linter输出转换为FileLintResult Pydantic模型。
|
|
314
|
+
|
|
315
|
+
参数:
|
|
316
|
+
raw_result (Dict[str, Any]): Linter的原始输出
|
|
317
|
+
shadow_path (str): 影子文件的路径
|
|
318
|
+
project_path (str): 项目文件的路径
|
|
319
|
+
|
|
320
|
+
返回:
|
|
321
|
+
FileLintResult: 标准化的lint结果模型
|
|
322
|
+
"""
|
|
323
|
+
# 提取语言信息
|
|
324
|
+
language = raw_result.get('language')
|
|
325
|
+
if not isinstance(language, str):
|
|
326
|
+
language = self._detect_language(shadow_path)
|
|
327
|
+
|
|
328
|
+
# 初始化计数器
|
|
329
|
+
error_count = 0
|
|
330
|
+
warning_count = 0
|
|
331
|
+
info_count = 0
|
|
332
|
+
|
|
333
|
+
# 处理问题
|
|
334
|
+
issues = []
|
|
335
|
+
raw_issues = raw_result.get('issues', [])
|
|
336
|
+
|
|
337
|
+
for raw_issue in raw_issues:
|
|
338
|
+
# 确定严重性
|
|
339
|
+
severity_str = raw_issue.get('severity', 'error').lower()
|
|
340
|
+
if severity_str in ('error', 'critical', 'fatal'):
|
|
341
|
+
severity = IssueSeverity.ERROR
|
|
342
|
+
error_count += 1
|
|
343
|
+
|
|
344
|
+
# 提取位置信息
|
|
345
|
+
line = raw_issue.get('line', 1)
|
|
346
|
+
column = raw_issue.get('column')
|
|
347
|
+
end_line = raw_issue.get('end_line')
|
|
348
|
+
end_column = raw_issue.get('end_column')
|
|
349
|
+
|
|
350
|
+
position = IssuePosition(
|
|
351
|
+
line=line,
|
|
352
|
+
column=column,
|
|
353
|
+
end_line=end_line,
|
|
354
|
+
end_column=end_column
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
# 创建问题
|
|
358
|
+
issue = LintIssue(
|
|
359
|
+
code=raw_issue.get('code', ''),
|
|
360
|
+
message=raw_issue.get('message', '未知问题'),
|
|
361
|
+
severity=severity,
|
|
362
|
+
position=position,
|
|
363
|
+
file_path=project_path, # 使用项目路径而不是影子路径
|
|
364
|
+
rule_name=raw_issue.get('rule_name'),
|
|
365
|
+
source=raw_issue.get('source'),
|
|
366
|
+
fix_available=raw_issue.get('fix_available', False),
|
|
367
|
+
fix_description=raw_issue.get('fix_description')
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
issues.append(issue)
|
|
371
|
+
elif severity_str in ('warning', 'warn'):
|
|
372
|
+
severity = IssueSeverity.WARNING
|
|
373
|
+
warning_count += 1
|
|
374
|
+
else:
|
|
375
|
+
severity = IssueSeverity.INFO
|
|
376
|
+
info_count += 1
|
|
377
|
+
|
|
378
|
+
# 创建文件结果
|
|
379
|
+
return FileLintResult(
|
|
380
|
+
file_path=project_path,
|
|
381
|
+
success=raw_result.get('success', True),
|
|
382
|
+
language=language,
|
|
383
|
+
issues=issues,
|
|
384
|
+
error=raw_result.get('error'),
|
|
385
|
+
warning_count=warning_count,
|
|
386
|
+
error_count=error_count,
|
|
387
|
+
info_count=info_count,
|
|
388
|
+
execution_time_ms=raw_result.get('execution_time_ms'),
|
|
389
|
+
fixed_issues_count=raw_result.get('fixed_issues_count')
|
|
390
|
+
)
|