本文目录导读:

我来帮你实现一个统一的代码注释风格检测和格式化脚本,这里提供几个不同语言的实现方案:
Python 实现版本(功能最完整)
#!/usr/bin/env python3
"""
代码注释风格统一检查与格式化工具
支持:Python, JavaScript, TypeScript, Java, C/C++
"""
import re
import os
import sys
from pathlib import Path
class CommentStyleChecker:
def __init__(self, config=None):
self.config = config or {
'max_line_length': 80,
'require_space_after_marker': True, # # 后面要有空格
'require_capital_start': True, # 注释首字母大写
'require_period_end': True, # 注释结尾需要句号
'block_comment_style': 'consistent', # 块注释风格:consistent, asterisk, star
}
self.errors = []
def check_line_comment(self, line, line_num, file_path):
"""检查单行注释"""
# Python样式 (#)
if line.strip().startswith('#'):
return self._check_python_line_comment(line, line_num)
# // 样式
elif '//' in line:
return self._check_double_slash_comment(line, line_num)
return True
def _check_python_line_comment(self, line, line_num):
"""检查Python风格注释"""
stripped = line.strip()
if stripped == '#':
return True
# 检查#后面是否有空格
if self.config['require_space_after_marker']:
match = re.match(r'^#(\S)', stripped)
if match:
self.errors.append(f"缺少空格: {line_num}: {stripped}")
return False
# 检查首字母大写
if self.config['require_capital_start']:
content = stripped.lstrip('#').strip()
if content and content[0].islower():
self.errors.append(f"首字母需大写: {line_num}: {stripped}")
return False
# 检查结尾句号
if self.config['require_period_end'] and not stripped.endswith('.'):
# 跳过空注释和URL等
if not any(stripped.endswith(s) for s in [':', ';', ')']):
self.errors.append(f"需要句号结尾: {line_num}: {stripped}")
return False
return True
def _check_double_slash_comment(self, line, line_num):
"""检查//风格注释"""
# 提取注释内容
comment_match = re.search(r'//(.+)$', line)
if not comment_match:
return True
comment = comment_match.group(1)
# 检查//后面是否有空格
if self.config['require_space_after_marker']:
if comment and not comment.startswith(' '):
self.errors.append(f"//后需空格: {line_num}: {line.strip()}")
return False
return True
def check_block_comment(self, content, file_path):
"""检查块注释"""
lines = content.split('\n')
in_block = False
block_start = 0
for i, line in enumerate(lines, 1):
stripped = line.strip()
if not in_block:
if stripped.startswith('/*') or stripped.startswith('"""'):
in_block = True
block_start = i
# 检查开始标记
if not self._check_block_start(stripped):
self.errors.append(f"块注释开始格式: {i}: {stripped}")
else:
if stripped.endswith('*/') or stripped.endswith('"""'):
in_block = False
elif self.config['block_comment_style'] == 'asterisk':
# 中间行需要*对齐
if not stripped.startswith('*') and stripped:
self.errors.append(f"块注释对齐: {i}: {stripped}")
return len(self.errors) == 0
def _check_block_start(self, line):
"""检查块注释开始"""
if line.startswith('/*'):
return True
if line.startswith('"""'):
return True
return False
def auto_fix_line_comment(self, line):
"""自动修复单行注释"""
stripped = line
# 修复Python注释 (#后面加空格)
if line.strip().startswith('#'):
stripped = re.sub(r'^(\s*#)(\S)', r'\1 \2', line)
# 修复//注释 (//后面加空格)
if '//' in line:
stripped = re.sub(r'(//)(\S)', r'\1 \2', stripped)
# 首字母大写
if self.config['require_capital_start']:
if stripped.strip().startswith('#') or '//' in stripped:
# 提取注释内容
if stripped.strip().startswith('#'):
content = stripped.strip().lstrip('#').strip()
if content and content[0].islower():
content = content[0].upper() + content[1:]
# 替换回原位置
indent = len(line) - len(line.lstrip())
stripped = ' ' * indent + '# ' + content + '\n'
return stripped
def format_file(file_path, checker):
"""格式化单个文件"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
except UnicodeDecodeError:
try:
with open(file_path, 'r', encoding='gbk') as f:
content = f.read()
except:
return False
# 检查注释
lines = content.split('\n')
formatted_lines = []
has_changes = False
for i, line in enumerate(lines, 1):
if '#' in line or '//' in line or '/*' in line:
fixed = checker.auto_fix_line_comment(line)
if fixed != line:
has_changes = True
formatted_lines.append(fixed)
else:
formatted_lines.append(line)
else:
formatted_lines.append(line)
if has_changes:
with open(file_path, 'w', encoding='utf-8') as f:
f.write('\n'.join(formatted_lines))
print(f"✅ 已修复: {file_path}")
return True
return False
def main():
"""主函数"""
import argparse
parser = argparse.ArgumentParser(description='统一代码注释风格工具')
parser.add_argument('paths', nargs='+', help='要检查的文件或目录路径')
parser.add_argument('--fix', action='store_true', help='自动修复注释风格')
parser.add_argument('--extensions', nargs='+', default=['.py', '.js', '.ts', '.java', '.c', '.cpp'],
help='要处理的文件扩展名')
args = parser.parse_args()
checker = CommentStyleChecker()
# 收集文件
files = []
for path in args.paths:
p = Path(path)
if p.is_file():
files.append(p)
elif p.is_dir():
for ext in args.extensions:
files.extend(p.rglob(f'*{ext}'))
# 处理文件
total_errors = 0
for file_path in files:
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
except:
continue
# 检查
errors_before = len(checker.errors)
checker.check_line_comment(content, 0, file_path)
checker.check_block_comment(content, file_path)
errors_after = len(checker.errors)
if errors_after > errors_before:
total_errors += (errors_after - errors_before)
print(f"❌ 检查失败: {file_path}")
for error in checker.errors[errors_before:]:
print(f" {error}")
# 修复
if args.fix:
format_file(file_path, checker)
if total_errors == 0:
print("✅ 所有文件注释风格一致!")
else:
print(f"⚠️ 发现 {total_errors} 个注释风格问题")
if not args.fix:
print(" 使用 --fix 参数自动修复")
if __name__ == '__main__':
main()
简单的 Bash 脚本版本
#!/bin/bash
# 统一代码注释风格检查脚本
# 支持 Python, JavaScript, TypeScript
check_comments() {
local file=$1
local errors=0
echo "检查文件: $file"
# 读取文件
while IFS= read -r line; do
line_num=$((line_num + 1))
# 检查 Python 注释 (#)
if [[ $line == *"#"* ]] && [[ ! $line == *"#!"* ]]; then
# 提取注释部分
comment=${line##*#}
if [[ -n $comment ]]; then
# 检查#后面是否有空格
if [[ $comment != " "* ]]; then
echo " ⚠️ 第 $line_num 行: # 后缺少空格"
((errors++))
fi
# 检查注释内容
content=$(echo "$comment" | sed 's/^ *//')
if [[ -n $content ]]; then
# 检查首字母大写
first_char=${content:0:1}
if [[ $first_char =~ [a-z] ]]; then
echo " ⚠️ 第 $line_num 行: 注释首字母需大写"
((errors++))
fi
fi
fi
fi
# 检查 // 注释
if [[ $line == *"//"* ]]; then
if [[ ! $line == *"https://"* ]] && [[ ! $line == *"http://"* ]]; then
echo " ⚠️ 第 $line_num 行: 发现 // 注释"
((errors++))
fi
fi
done < "$file"
return $errors
}
# 主逻辑
if [[ -z $1 ]]; then
echo "用法: $0 <文件或目录>"
echo "示例: $0 ./src"
exit 1
fi
total_errors=0
if [[ -f $1 ]]; then
check_comments "$1"
total_errors=$?
elif [[ -d $1 ]]; then
find "$1" -type f \( -name "*.py" -o -name "*.js" -o -name "*.ts" \) | while read file; do
check_comments "$file"
total_errors=$((total_errors + $?))
done
fi
if [[ $total_errors -eq 0 ]]; then
echo "✅ 所有注释风格一致!"
else
echo "⚠️ 发现 $total_errors 个问题"
fi
使用 pre-commit 钩子(推荐)
创建 .pre-commit-config.yaml 文件:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-merge-conflict
- id: check-yaml
# Python 注释检查
- repo: https://github.com/PyCQA/pydocstyle
rev: 6.3.0
hooks:
- id: pydocstyle
args: ["--convention=google"]
# JavaScript/TypeScript 注释检查
- repo: https://github.com/eslint/eslint
rev: v8.56.0
hooks:
- id: eslint
args: ["--rule", "spaced-comment: [error, always]"]
# 通用注释格式化
- repo: local
hooks:
- id: comment-style
name: comment-style-check
entry: python3 scripts/comment_style.py
language: python
types: [python, javascript, typescript]
args: ["--fix"]
ESLint 配置(JavaScript/TypeScript)
创建 .eslintrc.json:
{
"rules": {
"spaced-comment": ["error", "always", {
"line": {
"markers": ["/", "#"],
"exceptions": ["-", "+", "*"]
},
"block": {
"markers": ["!"],
"exceptions": ["*", "**"],
"balanced": true
}
}],
"capitalized-comments": ["warn", "always", {
"ignoreConsecutiveComments": true,
"ignoreInlineComments": true
}],
"multiline-comment-style": ["warn", "starred-block"]
}
}
使用示例
# 安装依赖 pip install pre-commit npm install -g eslint # 检查注释风格 python3 comment_style.py ./src --extensions .py .js .ts # 自动修复 python3 comment_style.py ./src --fix # 使用 pre-commit pre-commit install pre-commit run --all-files
这个脚本可以根据你的需求定制,主要功能包括:
- 检查注释格式:空格、大小写、标点符号
- 自动修复:一键格式化所有注释
- 多语言支持:Python、JavaScript、TypeScript、Java等
- 集成 pre-commit:提交代码前自动检查
- 灵活配置:通过配置文件自定义规则
你可以根据团队的具体规范调整配置文件中的参数。