221 lines
8.0 KiB
Python
Executable File
221 lines
8.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
NAC命名规范自动化检查工具
|
||
|
||
功能:
|
||
1. 检查文档中的协议名称大小写
|
||
2. 检查GNACS编码定义一致性
|
||
3. 检查架构层级命名规范
|
||
4. 生成检查报告
|
||
|
||
使用方法:
|
||
python3 nac_naming_checker.py [目录路径]
|
||
|
||
示例:
|
||
python3 nac_naming_checker.py /home/ubuntu/NAC_Clean_Dev
|
||
"""
|
||
|
||
import os
|
||
import re
|
||
import sys
|
||
from pathlib import Path
|
||
from typing import List, Dict, Tuple
|
||
|
||
class NACNamingChecker:
|
||
def __init__(self, root_dir: str):
|
||
self.root_dir = Path(root_dir)
|
||
self.issues = []
|
||
|
||
# 协议名称规范
|
||
self.protocols = {
|
||
'cbpp': 'CBPP',
|
||
'csnp': 'CSNP',
|
||
'nvm': 'NVM',
|
||
'acc': 'ACC',
|
||
'gnacs': 'GNACS',
|
||
'xtzh': 'XTZH',
|
||
}
|
||
|
||
# GNACS编码规范
|
||
self.gnacs_patterns = {
|
||
'correct': r'GNACSCode\(\[0u8; 6\]\)', # 48位 = 6字节
|
||
'wrong_48': r'GNACSCode\(\[0u8; 48\]\)', # 错误:48字节
|
||
'wrong_24': r'GNACSCode\(\[0u8; 24\]\)', # 错误:24字节
|
||
}
|
||
|
||
def check_markdown_files(self) -> List[Dict]:
|
||
"""检查Markdown文档中的命名规范"""
|
||
print("🔍 检查Markdown文档...")
|
||
|
||
md_files = list(self.root_dir.glob('**/*.md'))
|
||
issues = []
|
||
|
||
for md_file in md_files:
|
||
# 跳过node_modules和target目录
|
||
if 'node_modules' in str(md_file) or 'target' in str(md_file):
|
||
continue
|
||
|
||
try:
|
||
with open(md_file, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
# 检查协议名称大小写
|
||
for lowercase, uppercase in self.protocols.items():
|
||
# 查找小写协议名(排除代码路径)
|
||
pattern = rf'\b{lowercase}\b(?![/\w])'
|
||
matches = re.finditer(pattern, content, re.IGNORECASE)
|
||
|
||
for match in matches:
|
||
matched_text = match.group()
|
||
if matched_text == lowercase and matched_text != uppercase:
|
||
line_num = content[:match.start()].count('\n') + 1
|
||
issues.append({
|
||
'file': str(md_file.relative_to(self.root_dir)),
|
||
'line': line_num,
|
||
'type': 'protocol_naming',
|
||
'found': matched_text,
|
||
'expected': uppercase,
|
||
'message': f'协议名称应使用大写:{matched_text} -> {uppercase}'
|
||
})
|
||
except Exception as e:
|
||
print(f"⚠️ 无法读取文件 {md_file}: {e}")
|
||
|
||
return issues
|
||
|
||
def check_rust_files(self) -> List[Dict]:
|
||
"""检查Rust代码中的命名规范"""
|
||
print("🔍 检查Rust代码...")
|
||
|
||
rs_files = list(self.root_dir.glob('**/*.rs'))
|
||
issues = []
|
||
|
||
for rs_file in rs_files:
|
||
# 跳过target目录
|
||
if 'target' in str(rs_file):
|
||
continue
|
||
|
||
try:
|
||
with open(rs_file, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
# 检查GNACS编码错误用法
|
||
for pattern_name, pattern in self.gnacs_patterns.items():
|
||
if pattern_name.startswith('wrong_'):
|
||
matches = re.finditer(pattern, content)
|
||
for match in matches:
|
||
line_num = content[:match.start()].count('\n') + 1
|
||
issues.append({
|
||
'file': str(rs_file.relative_to(self.root_dir)),
|
||
'line': line_num,
|
||
'type': 'gnacs_encoding',
|
||
'found': match.group(),
|
||
'expected': 'GNACSCode([0u8; 6])',
|
||
'message': f'GNACS编码应使用6字节(48位):{match.group()} -> GNACSCode([0u8; 6])'
|
||
})
|
||
except Exception as e:
|
||
print(f"⚠️ 无法读取文件 {rs_file}: {e}")
|
||
|
||
return issues
|
||
|
||
def generate_report(self, issues: List[Dict]) -> str:
|
||
"""生成检查报告"""
|
||
report = []
|
||
report.append("# NAC命名规范检查报告\n")
|
||
report.append(f"**检查目录**: {self.root_dir}\n")
|
||
report.append(f"**检查时间**: {self._get_timestamp()}\n")
|
||
report.append(f"**发现问题数**: {len(issues)}\n")
|
||
report.append("\n---\n\n")
|
||
|
||
if not issues:
|
||
report.append("✅ **未发现命名规范问题!**\n")
|
||
return ''.join(report)
|
||
|
||
# 按类型分组
|
||
issues_by_type = {}
|
||
for issue in issues:
|
||
issue_type = issue['type']
|
||
if issue_type not in issues_by_type:
|
||
issues_by_type[issue_type] = []
|
||
issues_by_type[issue_type].append(issue)
|
||
|
||
# 生成各类型问题报告
|
||
for issue_type, type_issues in issues_by_type.items():
|
||
report.append(f"## {self._get_type_name(issue_type)}\n\n")
|
||
report.append(f"**问题数量**: {len(type_issues)}\n\n")
|
||
|
||
for i, issue in enumerate(type_issues, 1):
|
||
report.append(f"### 问题 {i}\n\n")
|
||
report.append(f"- **文件**: `{issue['file']}`\n")
|
||
report.append(f"- **行号**: {issue['line']}\n")
|
||
report.append(f"- **发现**: `{issue['found']}`\n")
|
||
report.append(f"- **应为**: `{issue['expected']}`\n")
|
||
report.append(f"- **说明**: {issue['message']}\n\n")
|
||
|
||
return ''.join(report)
|
||
|
||
def _get_type_name(self, issue_type: str) -> str:
|
||
"""获取问题类型的中文名称"""
|
||
type_names = {
|
||
'protocol_naming': '协议名称大小写问题',
|
||
'gnacs_encoding': 'GNACS编码定义问题',
|
||
'architecture_layer': '架构层级命名问题',
|
||
}
|
||
return type_names.get(issue_type, issue_type)
|
||
|
||
def _get_timestamp(self) -> str:
|
||
"""获取当前时间戳"""
|
||
from datetime import datetime
|
||
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||
|
||
def run(self) -> Tuple[List[Dict], str]:
|
||
"""运行检查"""
|
||
print(f"🚀 开始检查NAC命名规范...")
|
||
print(f"📂 检查目录: {self.root_dir}\n")
|
||
|
||
all_issues = []
|
||
|
||
# 检查Markdown文档
|
||
md_issues = self.check_markdown_files()
|
||
all_issues.extend(md_issues)
|
||
print(f" ✅ Markdown文档检查完成,发现 {len(md_issues)} 个问题\n")
|
||
|
||
# 检查Rust代码
|
||
rs_issues = self.check_rust_files()
|
||
all_issues.extend(rs_issues)
|
||
print(f" ✅ Rust代码检查完成,发现 {len(rs_issues)} 个问题\n")
|
||
|
||
# 生成报告
|
||
report = self.generate_report(all_issues)
|
||
|
||
print(f"📊 检查完成,共发现 {len(all_issues)} 个问题")
|
||
|
||
return all_issues, report
|
||
|
||
def main():
|
||
if len(sys.argv) < 2:
|
||
print("使用方法: python3 nac_naming_checker.py [目录路径]")
|
||
print("示例: python3 nac_naming_checker.py /home/ubuntu/NAC_Clean_Dev")
|
||
sys.exit(1)
|
||
|
||
root_dir = sys.argv[1]
|
||
|
||
if not os.path.exists(root_dir):
|
||
print(f"❌ 目录不存在: {root_dir}")
|
||
sys.exit(1)
|
||
|
||
checker = NACNamingChecker(root_dir)
|
||
issues, report = checker.run()
|
||
|
||
# 保存报告
|
||
report_file = Path(root_dir) / 'NAC_Naming_Check_Report.md'
|
||
with open(report_file, 'w', encoding='utf-8') as f:
|
||
f.write(report)
|
||
|
||
print(f"\n📄 报告已保存到: {report_file}")
|
||
|
||
# 返回退出码
|
||
sys.exit(0 if len(issues) == 0 else 1)
|
||
|
||
if __name__ == '__main__':
|
||
main()
|