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
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) |
|
} |
|
}
|
|
|