This repository has been archived on 2026-03-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
AIMisc/code-quality-system/hooks/code-analyzer.py
T
2026-01-30 00:42:33 +08:00

176 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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()