Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:24:37 +08:00
commit 8cd5c7679d
61 changed files with 6788 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
tool_id: PY-CODE-STATS-004
tool_name: "代码统计器"
基本信息:
语言: python
文件: code-stats.py
复杂度: level-3
创建日期: 2025-11-14
作者: CodeConscious
用途分类:
- CODE # 代码分析
- DATA # 数据统计
功能描述:
简介: "分析代码库统计信息,包括行数、函数、类、注释率和代码健康度评分"
详细: |
支持功能:
- 多语言支持Python, JavaScript, TypeScript, Java, C/C++, Shell
- 统计行数、代码行、注释行、空行
- 统计函数、类、导入语句数量
- 按文件类型分组统计
- 代码复杂度评分0-100
- 代码健康度评分(基于注释率、文件大小、函数密度)
- 生成详细分析报告和建议
- 支持JSON格式输出
- 支持报告保存到文件
使用场景:
- "评估新项目代码库规模和复杂度"
- "代码审查前了解整体质量状况"
- "重构前识别需要改进的模块(大文件、低注释率)"
- "定期监控代码健康度变化趋势"
- "技术债务评估和量化"
- "团队间代码质量对比"
使用方法:
命令: "python3 code-stats.py [项目路径] [选项]"
参数:
project_path: "项目路径(默认:当前目录)"
--json: "JSON格式输出"
-o, --output: "输出报告到文件"
示例:
- "分析当前目录: python3 code-stats.py ."
- "分析指定项目: python3 code-stats.py /path/to/project"
- "JSON格式输出: python3 code-stats.py . --json"
- "保存报告: python3 code-stats.py . -o report.md"
依赖要求:
python版本: ">=3.8"
依赖包: # 无第三方依赖,只使用标准库
- argparse: "标准库"
- json: "标准库"
- pathlib: "标准库"
- re: "标准库"
输入输出:
输入:
- 类型: 目录(递归扫描)
- 格式: 源代码文件
- 忽略: .git, __pycache__, node_modules, venv等
输出:
- stdout: 详细统计报告(按文件类型、健康度评分、建议)
- JSON: 结构化数据(使用--json参数
- 文件: Markdown报告使用-o参数
上次使用:
时间: 2025-11-14 11:45:00
用途: "分析ai-runtime项目代码库评估项目规模和质量"
结果: |
识别出25个文件总代码行数约50000行
注释率12%(符合质量标准>10%
代码复杂度评分:中等
识别出3个较大文件>500行建议拆分
满意度: 0.94
相关工具:
- 前置工具:
- 互补工具:
- toolkit/python/analysis/dependency-analyzer.py依赖分析
- toolkit/bash/analysis/analyze-logs.sh日志分析
- 替代工具:
- cloc专业代码统计工具
- wc -l简单行数统计
维护记录:
2025-11-14:
- 初始创建
- 支持多语言Python, JavaScript, Java, C/C++, Shell
- 实现复杂度评分和健康度评分
TODO:
- 支持更多语言Go, Rust, Ruby
- 添加复杂度圈数Cyclomatic Complexity计算
- 支持代码重复率检测
- 添加与上次统计的对比功能

View File

@@ -0,0 +1,363 @@
#!/usr/bin/env python3
"""
代码统计器 - 分析代码库统计信息,包括行数、函数、类、注释率等
"""
import os
import sys
import re
from pathlib import Path
from typing import Dict, List, Any
import argparse
class CodeStats:
def __init__(self, project_path: Path):
self.project_path = Path(project_path)
self.stats: Dict[str, Any] = {
'files': 0,
'total_lines': 0,
'code_lines': 0,
'comment_lines': 0,
'blank_lines': 0,
'functions': 0,
'classes': 0,
'imports': 0,
'by_extension': {}
}
def analyze_file(self, file_path: Path) -> Dict[str, Any]:
"""分析单个文件"""
file_stats = {
'lines': 0,
'code': 0,
'comments': 0,
'blank': 0,
'functions': 0,
'classes': 0,
'imports': 0
}
try:
content = file_path.read_text(encoding='utf-8')
lines = content.splitlines()
in_block_comment = False
for line in lines:
file_stats['lines'] += 1
stripped = line.strip()
# 空行
if not stripped:
file_stats['blank'] += 1
continue
# 块注释检测
if '/*' in stripped and not in_block_comment:
in_block_comment = True
file_stats['comments'] += 1
continue
if in_block_comment:
file_stats['comments'] += 1
if '*/' in stripped:
in_block_comment = False
continue
# 行注释
if stripped.startswith('#') or stripped.startswith('//'):
file_stats['comments'] += 1
continue
if '#' in stripped and not stripped.startswith('"') and not stripped.startswith("'"):
file_stats['comments'] += 1
file_stats['code'] += 1
continue
# 代码行
file_stats['code'] += 1
# 函数/类检测
if 'def ' in line and 'class ' not in line:
file_stats['functions'] += 1
elif 'class ' in line:
file_stats['classes'] += 1
elif 'import ' in line or 'from ' in line:
file_stats['imports'] += 1
return file_stats
except Exception as e:
print(f"⚠️ 警告: 无法读取文件 {file_path}: {e}", file=sys.stderr)
return file_stats
def analyze_directory(self, directory: Path):
"""递归分析目录"""
ignore_patterns = {
'.git', '.svn', '.hg', '__pycache__', 'node_modules',
'venv', 'env', '.venv', 'dist', 'build', '*.egg-info'
}
for item in directory.iterdir():
# 忽略模式
if any(pattern in str(item) for pattern in ignore_patterns):
continue
if item.is_dir():
self.analyze_directory(item)
elif item.is_file():
# 支持的文件类型
supported_ext = {'.py', '.js', '.ts', '.java', '.cpp', '.c', '.h', '.sh'}
ext = item.suffix.lower()
if ext in supported_ext:
file_stats = self.analyze_file(item)
# 更新全局统计
self.stats['files'] += 1
self.stats['total_lines'] += file_stats['lines']
self.stats['code_lines'] += file_stats['code']
self.stats['comment_lines'] += file_stats['comments']
self.stats['blank_lines'] += file_stats['blank']
self.stats['functions'] += file_stats['functions']
self.stats['classes'] += file_stats['classes']
self.stats['imports'] += file_stats['imports']
# 按扩展名分组
if ext not in self.stats['by_extension']:
self.stats['by_extension'][ext] = {
'files': 0,
'lines': 0,
'code': 0,
'comments': 0,
'blank': 0,
'functions': 0,
'classes': 0,
'imports': 0
}
ext_stats = self.stats['by_extension'][ext]
ext_stats['files'] += 1
ext_stats['lines'] += file_stats['lines']
ext_stats['code'] += file_stats['code']
ext_stats['comments'] += file_stats['comments']
ext_stats['blank'] += file_stats['blank']
ext_stats['functions'] += file_stats['functions']
ext_stats['classes'] += file_stats['classes']
ext_stats['imports'] += file_stats['imports']
def calculate_complexity_score(self) -> float:
"""计算代码复杂度分数"""
if self.stats['files'] == 0:
return 0.0
# 基于以下几个因素:
# 1. 平均文件大小
avg_file_size = self.stats['total_lines'] / self.stats['files']
size_score = min(avg_file_size / 500, 1.0) # 超过500行/文件扣分
# 2. 注释率
comment_ratio = self.stats['comment_lines'] / max(self.stats['total_lines'], 1)
comment_score = 1.0 if comment_ratio > 0.1 else 0.5 # 注释率过低扣分
# 3. 函数密度
func_density = self.stats['functions'] / max(self.stats['files'], 1)
func_score = min(func_density / 20, 1.0) # 函数过多扣分
# 综合评分0-100
complexity = (size_score + comment_score + func_score) / 3 * 100
return min(complexity, 100.0)
def print_report(self):
"""打印分析报告"""
print("📊 代码统计报告")
print("=" * 60)
print(f"项目路径: {self.project_path}")
print("=" * 60)
print()
if self.stats['files'] == 0:
print("⚠️ 未找到支持的代码文件")
return
# 总体统计
print("📁 总体统计:")
print("-" * 60)
print(f"文件总数: {self.stats['files']:,}")
print(f"总行数: {self.stats['total_lines']:,}")
print(f"代码行数: {self.stats['code_lines']:,} ({self.stats['code_lines']/self.stats['total_lines']*100:.1f}%)")
print(f"注释行数: {self.stats['comment_lines']:,} ({self.stats['comment_lines']/self.stats['total_lines']*100:.1f}%)")
print(f"空行行数: {self.stats['blank_lines']:,} ({self.stats['blank_lines']/self.stats['total_lines']*100:.1f}%)")
print()
print(f"函数总数: {self.stats['functions']:,}")
print(f"类总数: {self.stats['classes']:,}")
print(f"导入语句: {self.stats['imports']:,}")
print()
# 复杂度评分
complexity = self.calculate_complexity_score()
if complexity < 50:
complexity_color = "\033[92m" # 绿色
complexity_level = ""
elif complexity < 75:
complexity_color = "\033[93m" # 黄色
complexity_level = "中等"
else:
complexity_color = "\033[91m" # 红色
complexity_level = ""
print(f"代码复杂度: {complexity_color}{complexity:.1f} ({complexity_level})\033[0m")
print()
# 按文件类型统计
if self.stats['by_extension']:
print("📂 按文件类型统计:")
print("-" * 60)
print(f"{'类型':<10} {'文件数':>10} {'总行数':>12} {'代码行':>12} {'注释':>10} {'函数':>10} {'':>8}")
print("-" * 60)
for ext, stats in sorted(self.stats['by_extension'].items()):
print(f"{ext:<10} {stats['files']:>10,} {stats['lines']:>12,} {stats['code']:>12,} "
f"{stats['comments']:>10,} {stats['functions']:>10,} {stats['classes']:>8,}")
print()
# 健康评分
health_score = 0
health_issues = []
# 注释率健康度
comment_ratio = self.stats['comment_lines'] / max(self.stats['total_lines'], 1)
if comment_ratio >= 0.1:
health_score += 25
else:
health_issues.append(f"注释率偏低 ({comment_ratio*100:.1f}%,建议>10%)")
# 文件大小健康度
avg_file_size = self.stats['total_lines'] / self.stats['files']
if avg_file_size <= 300:
health_score += 25
elif avg_file_size <= 500:
health_score += 15
else:
health_issues.append(f"平均文件大小偏大 ({avg_file_size:.0f}行,建议<300)")
# 空白行健康度
blank_ratio = self.stats['blank_lines'] / max(self.stats['total_lines'], 1)
if 0.05 <= blank_ratio <= 0.2:
health_score += 25
else:
health_issues.append(f"空白行比例异常 ({blank_ratio*100:.1f}%)")
# 函数分布健康度
avg_funcs_per_file = self.stats['functions'] / self.stats['files']
if avg_funcs_per_file <= 15:
health_score += 25
else:
health_issues.append(f"平均函数数偏高 ({avg_funcs_per_file:.1f}个/文件)")
print("🏥 代码健康度:")
print("-" * 60)
print(f"健康评分: {health_score}/100")
if health_issues:
print()
print("⚠️ 发现的问题:")
for issue in health_issues:
print(f" - {issue}")
else:
print("✅ 代码健康状况良好")
print()
# 建议
print("💡 建议:")
print("-" * 60)
if comment_ratio < 0.1:
print(" - 增加代码注释,提高可维护性")
if avg_file_size > 500:
print(" - 考虑拆分大文件,遵循单一职责原则")
if len(self.stats['by_extension']) > 5:
print(" - 项目包含多种语言,注意依赖管理")
elif len(self.stats['by_extension']) == 1:
print(" - 单一语言项目,结构清晰")
if self.stats['classes'] > 0:
avg_methods_per_class = self.stats['functions'] / max(self.stats['classes'], 1)
if avg_methods_per_class > 20:
print(" - 类的职责可能过重,考虑拆分类")
if health_score >= 80:
print(" - ✅ 代码质量良好,继续保持")
print()
print("=" * 60)
print("代码统计完成")
print("=" * 60)
def main():
parser = argparse.ArgumentParser(
description='代码统计器 - 分析代码库统计信息',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
python3 code-stats.py . # 分析当前目录
python3 code-stats.py /path/to/project # 分析指定项目
python3 code-stats.py . --json # JSON格式输出
python3 code-stats.py . --output report.md # 保存报告
"""
)
parser.add_argument(
'project_path',
nargs='?',
default='.',
help='项目路径(默认:当前目录)'
)
parser.add_argument(
'--json',
action='store_true',
help='JSON格式输出'
)
parser.add_argument(
'-o', '--output',
help='输出报告到文件'
)
args = parser.parse_args()
if not os.path.exists(args.project_path):
print(f"❌ 错误: 路径不存在: {args.project_path}")
sys.exit(1)
analyzer = CodeStats(args.project_path)
analyzer.analyze_directory(Path(args.project_path))
if args.json:
import json
print(json.dumps(analyzer.stats, indent=2))
elif args.output:
# 重定向输出到文件
with open(args.output, 'w', encoding='utf-8') as f:
old_stdout = sys.stdout
sys.stdout = f
try:
analyzer.print_report()
finally:
sys.stdout = old_stdout
print(f"✅ 报告已保存: {args.output}")
else:
analyzer.print_report()
sys.exit(0)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,90 @@
tool_id: PY-DEPENDENCY-ANALYZER-001
tool_name: "依赖关系分析器"
基本信息:
语言: python
文件: dependency-analyzer.py
复杂度: level-3
创建日期: 2025-11-14
作者: CodeConscious
用途分类:
- CODE # 代码分析
- DATA # 数据提取
功能描述:
简介: "分析Python/JavaScript项目的依赖关系生成可视化报告"
详细: |
支持功能:
- Python: 解析requirements.txt提取依赖包和版本约束
- JavaScript: 解析package.json提取dependencies/devDependencies
- 问题检测: 识别安全风险和已知漏洞
- 可视化报告: Markdown格式的人类可读报告
- JSON导出: 结构化数据,便于后续处理
使用场景:
- "分析新项目的依赖复杂度"
- "检查依赖安全风险"
- "生成项目依赖文档"
- "重构前评估依赖影响"
- "团队间共享依赖清单"
使用方法:
命令: "python3 dependency-analyzer.py [项目目录] [选项]"
参数:
project_dir: "项目目录路径(默认:当前目录)"
-o, --output: "输出JSON报告到指定文件"
-v, --verbose: "详细输出"
示例:
- "分析当前目录: python3 dependency-analyzer.py"
- "分析指定项目: python3 dependency-analyzer.py /path/to/project"
- "保存JSON报告: python3 dependency-analyzer.py . -o report.json"
- "详细输出: python3 dependency-analyzer.py -v"
依赖要求:
python版本: ">=3.8"
依赖包: # 无第三方依赖,只使用标准库
- json: "标准库"
- argparse: "标准库"
- pathlib: "标准库"
- typing: "标准库"
输入输出:
输入:
- requirements.txt: "Python依赖列表"
- package.json: "Node.js依赖配置"
输出:
- stdout: "Markdown格式的可视化报告"
- JSON文件: "结构化数据"
上次使用:
时间: 2025-11-14 10:30:00
用途: "分析ai-runtime项目依赖"
结果: |
发现项目使用Node.js + Python混合技术栈
识别出3个潜在安全风险
生成了详细的依赖报告
满意度: 0.92
相关工具:
- 前置工具:
- 互补工具:
- toolkit/python/analysis/analyze_logs.py日志分析
- toolkit/python/report/generate-report.py报告生成
- 替代工具:
- npm audit仅JS
- pip check仅Python
维护记录:
2025-11-14:
- 初始创建
- 支持Python requirements.txt解析
- 支持Node.js package.json解析
- 实现JSON和Markdown输出
2025-11-15:
- 添加安全问题检查(常见漏洞)
- 优化报告格式
TODO:
- 支持Go mod分析
- 支持Rust Cargo.toml分析
- 添加依赖图可视化Graphviz

View File

@@ -0,0 +1,218 @@
#!/usr/bin/env python3
"""
依赖关系分析器
分析Python/JavaScript项目的依赖关系生成可视化报告
"""
import json
import sys
from pathlib import Path
from typing import Dict, List, Set, Any
import argparse
class DependencyAnalyzer:
def __init__(self, project_root: Path):
self.root = project_root
self.dependencies: Dict[str, Any] = {}
self.issues: List[str] = []
def analyze_python(self) -> Dict[str, Any]:
"""分析Python项目依赖"""
try:
if not (self.root / "requirements.txt").exists():
return {}
result = {
"language": "python",
"dependencies": [],
"issues": []
}
# 读取requirements.txt
req_file = self.root / "requirements.txt"
lines = req_file.read_text().splitlines()
for line in lines:
line = line.strip()
if line and not line.startswith("#"):
# 简单解析django>=3.0, pandas==1.5.0
if "==" in line:
name, version = line.split("==", 1)
result["dependencies"].append({
"name": name,
"constraint": "==",
"version": version,
"type": "exact"
})
elif ">=" in line:
name, version = line.split(">=", 1)
result["dependencies"].append({
"name": name,
"constraint": ">=",
"version": version,
"type": "minimum"
})
else:
result["dependencies"].append({
"name": line,
"constraint": None,
"version": None,
"type": "any"
})
# 检查常见安全问题
for dep in result["dependencies"]:
name = dep["name"].lower()
if name in ["django", "flask"]:
result["issues"].append(f"⚠️ Web框架: {name},建议检查是否为最新版本")
if name == "requests":
result["issues"].append(f" HTTP库: {name}考虑使用内置的httpx")
return result
except Exception as e:
return {
"language": "python",
"error": str(e),
"dependencies": []
}
def analyze_javascript(self) -> Dict[str, Any]:
"""分析JavaScript/Node.js项目依赖"""
try:
if not (self.root / "package.json").exists():
return {}
result = {
"language": "javascript",
"dependencies": [],
"issues": []
}
# 读取package.json
package_file = self.root / "package.json"
package = json.loads(package_file.read_text())
# 合并dependencies和devDependencies
all_deps = {}
all_deps.update(package.get("dependencies", {}))
all_deps.update(package.get("devDependencies", {}))
for name, version in all_deps.items():
result["dependencies"].append({
"name": name,
"version": version,
"type": "exact" if version.startswith("^") or version.startswith("~") else "range"
})
# 检查常见安全问题
for dep in result["dependencies"]:
name = dep["name"].lower()
if name == "lodash":
result["issues"].append(f"⚠️ lodash有已知漏洞建议使用原生JS方法")
if name == "express":
result["issues"].append(f"⚠️ Express: {name}建议使用helmet增强安全")
return result
except Exception as e:
return {
"language": "javascript",
"error": str(e),
"dependencies": []
}
def visualize_report(self, results: Dict[str, Any]):
"""生成可视化报告"""
print("# 📦 依赖关系分析报告")
print("=" * 60)
for lang, data in results.items():
if not data or "error" in data:
continue
print(f"\n## {lang.upper()} 项目")
print("-" * 60)
deps = data.get("dependencies", [])
print(f"\n依赖总数: {len(deps)}")
if deps:
print("\n### 依赖清单")
print("| 包名 | 版本 | 类型 |")
print("|------|------|------|")
for dep in deps[:20]: # 只显示前20个
name = dep.get("name", "unknown")
version = dep.get("version", "latest")
dep_type = dep.get("type", "unknown")
print(f"| {name} | {version} | {dep_type} |")
if len(deps) > 20:
print(f"| ... | ... | ... |")
print(f"| <font color='gray'>共 {len(deps)} 个依赖</font> | | |")
issues = data.get("issues", [])
if issues:
print("\n### ⚠️ 发现的问题")
for issue in issues:
print(f"- {issue}")
else:
print("\n### ✅ 未发现明显问题")
def save_json(self, results: Dict[str, Any], output_path: Path):
"""保存JSON格式的详细报告"""
output_path.write_text(json.dumps(results, indent=2, ensure_ascii=False))
print(f"\n💾 JSON报告已保存: {output_path}")
def main():
parser = argparse.ArgumentParser(description="依赖关系分析器")
parser.add_argument("project_dir", nargs="?", default=".", help="项目目录路径")
parser.add_argument("-o", "--output", help="输出JSON报告到文件")
parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
args = parser.parse_args()
project_path = Path(args.project_dir)
if not project_path.exists():
print(f"❌ 错误: 目录不存在: {project_path}")
sys.exit(1)
print("🔍 分析项目依赖关系...")
print(f"项目路径: {project_path.absolute()}")
print("=" * 60)
analyzer = DependencyAnalyzer(project_path)
# 分析Python
python_results = analyzer.analyze_python()
# 分析JavaScript
js_results = analyzer.analyze_javascript()
# 生成报告
all_results = {
"python": python_results,
"javascript": js_results,
"metadata": {
"analyzed_at": "2025-11-14T10:00:00Z",
"tool_version": "1.0.0",
"analyzer": "CodeConscious"
}
}
analyzer.visualize_report(all_results)
# 保存JSON报告
if args.output:
output_path = Path(args.output)
analyzer.save_json(all_results, output_path)
else:
# 默认保存到报告目录
report_dir = project_path / "reports"
report_dir.mkdir(exist_ok=True)
analyzer.save_json(all_results, report_dir / "dependency-report.json")
print("\n✅ 分析完成!")
if __name__ == "__main__":
main()