开发code-quality

This commit is contained in:
2026-01-30 00:42:33 +08:00
parent f95b5f5b13
commit 3367268ace
14 changed files with 1636 additions and 0 deletions
+175
View File
@@ -0,0 +1,175 @@
#!/usr/bin/env python3
"""
代码分析器
扫描代码文件,检测常见问题
"""
import json
import sys
import os
import re
from pathlib import Path
def analyze_file(file_path):
"""分析单个代码文件"""
issues = []
try:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
lines = content.split('\n')
# 检测模式
patterns = {
'TODO': r'TODO|FIXME|XXX|HACK',
'empty_function': r'def\s+\w+\s*\([^)]*\)\s*:\s*(pass|#\s*.*|.{0})',
'empty_method': r'(def|async\s+def)\s+\w+\s*\([^)]*\)\s*:\s*(pass|.{0})',
'commented_code': r'^\s*#.*=[^#\n]|^\s*#.*\([^)]*\)',
'placeholder': r'(NotImplementedError|raise\s+NotImplemented|pass\s*#.*placeholder)',
'debug_print': r'print\([^)]*\)|console\.log\([^)]*\)',
}
for line_num, line in enumerate(lines, 1):
for issue_type, pattern in patterns.items():
if re.search(pattern, line, re.IGNORECASE):
issues.append({
'type': issue_type,
'line': line_num,
'content': line.strip(),
'file': str(file_path)
})
except Exception as e:
issues.append({
'type': 'read_error',
'message': str(e),
'file': str(file_path)
})
return issues
def detect_project_changes(project_root):
"""检测项目中的代码变更"""
import subprocess
try:
# 获取 Git 变更的文件
result = subprocess.run(
['git', 'diff', '--name-only', 'HEAD'],
cwd=project_root,
capture_output=True,
text=True,
timeout=5
)
if result.returncode == 0:
changed_files = result.stdout.strip().split('\n')
changed_files = [f for f in changed_files if f]
# 过滤代码文件
code_extensions = {'.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.go', '.rs', '.c', '.cpp', '.h'}
code_files = [
Path(project_root) / f
for f in changed_files
if Path(f).suffix.lower() in code_extensions
]
return code_files
except Exception:
pass
# 如果 Git 不可用,扫描所有代码文件
code_extensions = {'.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.go', '.rs', '.c', '.cpp', '.h'}
project_path = Path(project_root)
code_files = []
for ext in code_extensions:
code_files.extend(project_path.rglob(f'*{ext}'))
return code_files
def analyze_code_quality(project_root):
"""分析代码质量"""
all_issues = {
'todo': [],
'empty_functions': [],
'commented_code': [],
'placeholders': [],
'debug_statements': [],
'other': []
}
# 获取需要分析的文件
files_to_analyze = detect_project_changes(project_root)
for file_path in files_to_analyze:
if not file_path.exists():
continue
issues = analyze_file(file_path)
for issue in issues:
issue_type = issue['type']
if issue_type == 'TODO':
all_issues['todo'].append(issue)
elif 'empty' in issue_type:
all_issues['empty_functions'].append(issue)
elif issue_type == 'commented_code':
all_issues['commented_code'].append(issue)
elif issue_type == 'placeholder':
all_issues['placeholders'].append(issue)
elif issue_type == 'debug_print':
all_issues['debug_statements'].append(issue)
else:
all_issues['other'].append(issue)
return all_issues
def calculate_completeness_score(issues):
"""计算完整度评分"""
total_issues = sum(len(v) for v in issues.values())
# 严重问题权重
critical_issues = len(issues['empty_functions']) + len(issues['placeholders'])
minor_issues = len(issues['todo']) + len(issues['commented_code']) + len(issues['debug_statements'])
# 计算分数(0-100)
score = 100 - (critical_issues * 15) - (minor_issues * 5)
return max(0, min(100, score))
def main():
"""主函数"""
# 从命令行参数或 stdin 获取项目路径
if len(sys.argv) > 1:
project_root = sys.argv[1]
else:
project_root = os.getcwd()
# 执行分析
issues = analyze_code_quality(project_root)
score = calculate_completeness_score(issues)
# 输出结果
result = {
'score': score,
'issues': issues,
'total_issues': sum(len(v) for v in issues.values()),
'summary': {
'todo_count': len(issues['todo']),
'empty_functions_count': len(issues['empty_functions']),
'commented_code_count': len(issues['commented_code']),
'placeholder_count': len(issues['placeholders']),
'debug_statements_count': len(issues['debug_statements'])
}
}
print(json.dumps(result, ensure_ascii=False, indent=2))
if __name__ == '__main__':
main()