You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

158 lines
3.7 KiB

package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"strings"
)
// ControllerCommentChecker Controller注释检查器
type ControllerCommentChecker struct {
errors []string
}
// NewControllerCommentChecker 创建检查器实例
func NewControllerCommentChecker() *ControllerCommentChecker {
return &ControllerCommentChecker{
errors: make([]string, 0),
}
}
// CheckFile 检查单个文件
func (c *ControllerCommentChecker) CheckFile(filePath string) error {
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
if err != nil {
return fmt.Errorf("解析文件失败: %v", err)
}
// 检查是否是Controller文件
if !strings.Contains(filePath, "controller") {
return nil
}
// 遍历AST节点
ast.Inspect(node, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.FuncDecl:
// 检查Controller方法
if c.isControllerMethod(x) {
c.checkMethodComments(x, filePath)
}
}
return true
})
return nil
}
// isControllerMethod 判断是否是Controller方法
func (c *ControllerCommentChecker) isControllerMethod(fn *ast.FuncDecl) bool {
// 检查方法接收者
if fn.Recv == nil || len(fn.Recv.List) == 0 {
return false
}
// 检查接收者类型是否包含Controller
recvType := fn.Recv.List[0].Type
if starExpr, ok := recvType.(*ast.StarExpr); ok {
if ident, ok := starExpr.X.(*ast.Ident); ok {
return strings.Contains(ident.Name, "Controller")
}
}
return false
}
// checkMethodComments 检查方法注释
func (c *ControllerCommentChecker) checkMethodComments(fn *ast.FuncDecl, filePath string) {
if fn.Doc == nil {
c.errors = append(c.errors, fmt.Sprintf("%s:%d 方法 %s 缺少注释", filePath, fn.Pos(), fn.Name.Name))
return
}
commentText := fn.Doc.Text()
requiredTags := []string{"@Summary", "@Description", "@Tags", "@Router"}
for _, tag := range requiredTags {
if !strings.Contains(commentText, tag) {
c.errors = append(c.errors, fmt.Sprintf("%s:%d 方法 %s 缺少 %s 注释", filePath, fn.Pos(), fn.Name.Name, tag))
}
}
// 检查中文描述
if !c.containsChinese(commentText) {
c.errors = append(c.errors, fmt.Sprintf("%s:%d 方法 %s 注释应包含中文描述", filePath, fn.Pos(), fn.Name.Name))
}
}
// containsChinese 检查是否包含中文字符
func (c *ControllerCommentChecker) containsChinese(text string) bool {
for _, r := range text {
if r >= 0x4e00 && r <= 0x9fff {
return true
}
}
return false
}
// CheckDirectory 检查目录下的所有Controller文件
func (c *ControllerCommentChecker) CheckDirectory(dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(path, ".go") {
return c.CheckFile(path)
}
return nil
})
}
// GetErrors 获取检查错误
func (c *ControllerCommentChecker) GetErrors() []string {
return c.errors
}
// PrintReport 打印检查报告
func (c *ControllerCommentChecker) PrintReport() {
if len(c.errors) == 0 {
fmt.Println("✅ 所有Controller方法注释检查通过")
return
}
fmt.Printf("❌ 发现 %d 个注释问题:\n", len(c.errors))
for i, err := range c.errors {
fmt.Printf("%d. %s\n", i+1, err)
}
}
func main() {
if len(os.Args) < 2 {
fmt.Println("用法: go run check_controller_comments.go <controller_directory>")
fmt.Println("示例: go run check_controller_comments.go ./internal/auth/controller")
os.Exit(1)
}
dir := os.Args[1]
checker := NewControllerCommentChecker()
fmt.Printf("🔍 检查目录: %s\n", dir)
if err := checker.CheckDirectory(dir); err != nil {
fmt.Printf("❌ 检查失败: %v\n", err)
os.Exit(1)
}
checker.PrintReport()
if len(checker.GetErrors()) > 0 {
os.Exit(1)
}
}