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.
 
 
 
 
 
 

199 lines
5.3 KiB

package service
import (
"bufio"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
)
// SwaggerInfo Swagger注释信息
type SwaggerInfo struct {
Summary string
Description string
Tags string
Router string
Method string
}
// SwaggerParser Swagger注释解析器
type SwaggerParser struct {
swaggerMap map[string]SwaggerInfo
}
// NewSwaggerParser 创建Swagger解析器
func NewSwaggerParser() *SwaggerParser {
parser := &SwaggerParser{
swaggerMap: make(map[string]SwaggerInfo),
}
fmt.Println("🔧 SwaggerParser创建成功")
return parser
}
// ParseControllerDirectory 解析Controller目录下的所有文件
func (sp *SwaggerParser) ParseControllerDirectory(dir string) error {
fmt.Printf("🔍 开始解析Controller目录: %s\n", dir)
fileCount := 0
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Printf("❌ 访问文件失败: %s, 错误: %v\n", path, err)
return err
}
if !info.IsDir() && strings.HasSuffix(path, ".go") {
fmt.Printf("📄 解析文件: %s\n", path)
fileCount++
return sp.parseControllerFile(path)
}
return nil
})
fmt.Printf("📊 解析完成,共处理 %d 个Go文件\n", fileCount)
fmt.Printf("📋 解析到的Swagger信息数量: %d\n", len(sp.swaggerMap))
return err
}
// parseControllerFile 解析单个Controller文件
func (sp *SwaggerParser) parseControllerFile(filePath string) error {
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
var currentComment []string
for scanner.Scan() {
line := scanner.Text()
// 检查是否是注释行
if strings.HasPrefix(strings.TrimSpace(line), "//") {
currentComment = append(currentComment, line)
} else {
// 如果不是注释行,处理之前收集的注释
if len(currentComment) > 0 {
swaggerInfo := sp.extractSwaggerInfo(currentComment)
if swaggerInfo.Router != "" {
// 使用Router路径作为key
key := fmt.Sprintf("%s %s", swaggerInfo.Method, swaggerInfo.Router)
sp.swaggerMap[key] = swaggerInfo
}
currentComment = nil
}
}
}
return scanner.Err()
}
// extractSwaggerInfo 从注释中提取Swagger信息
func (sp *SwaggerParser) extractSwaggerInfo(comments []string) SwaggerInfo {
info := SwaggerInfo{}
for _, comment := range comments {
comment = strings.TrimSpace(comment)
// 提取@Summary
if strings.HasPrefix(comment, "// @Summary") {
info.Summary = strings.TrimSpace(strings.TrimPrefix(comment, "// @Summary"))
}
// 提取@Description
if strings.HasPrefix(comment, "// @Description") {
info.Description = strings.TrimSpace(strings.TrimPrefix(comment, "// @Description"))
}
// 提取@Tags
if strings.HasPrefix(comment, "// @Tags") {
info.Tags = strings.TrimSpace(strings.TrimPrefix(comment, "// @Tags"))
}
// 提取@Router
if strings.HasPrefix(comment, "// @Router") {
routerLine := strings.TrimSpace(strings.TrimPrefix(comment, "// @Router"))
// 解析格式:/path [method]
parts := strings.Fields(routerLine)
if len(parts) >= 2 {
info.Router = parts[0]
// 提取HTTP方法
if len(parts) > 1 {
methodPart := parts[1]
if strings.HasPrefix(methodPart, "[") && strings.HasSuffix(methodPart, "]") {
info.Method = strings.ToUpper(strings.Trim(methodPart, "[]"))
}
}
}
}
}
return info
}
// GetSummary 根据路径和方法获取Summary
func (sp *SwaggerParser) GetSummary(method, path string) string {
// 尝试精确匹配
key := fmt.Sprintf("%s %s", strings.ToUpper(method), path)
if info, exists := sp.swaggerMap[key]; exists {
return info.Summary
}
// 尝试匹配不带/api前缀的路径
if strings.HasPrefix(path, "/api/") {
pathWithoutAPI := strings.TrimPrefix(path, "/api")
keyWithoutAPI := fmt.Sprintf("%s %s", strings.ToUpper(method), pathWithoutAPI)
if info, exists := sp.swaggerMap[keyWithoutAPI]; exists {
return info.Summary
}
}
// 尝试模糊匹配(处理路径参数)
for swaggerKey, info := range sp.swaggerMap {
if sp.matchRoute(swaggerKey, fmt.Sprintf("%s %s", strings.ToUpper(method), path)) {
return info.Summary
}
}
// 尝试匹配转换后的路径(将:var转换为{var})
convertedPath := sp.convertPathFormat(path)
if convertedPath != path {
convertedKey := fmt.Sprintf("%s %s", strings.ToUpper(method), convertedPath)
if info, exists := sp.swaggerMap[convertedKey]; exists {
return info.Summary
}
}
return ""
}
// convertPathFormat 转换路径格式:将:var格式改为{var}格式
func (sp *SwaggerParser) convertPathFormat(path string) string {
re := regexp.MustCompile(`:([a-zA-Z0-9_]+)`)
return re.ReplaceAllString(path, "{$1}")
}
// matchRoute 匹配路由(处理路径参数)
func (sp *SwaggerParser) matchRoute(pattern, route string) bool {
// 将路径参数转换为正则表达式
// 例如:/users/:id -> /users/[^/]+
patternRegex := regexp.MustCompile(`:[a-zA-Z0-9_]+`)
regexPattern := patternRegex.ReplaceAllString(pattern, `[^/]+`)
// 创建正则表达式
re, err := regexp.Compile("^" + regexPattern + "$")
if err != nil {
return false
}
return re.MatchString(route)
}
// GetAllSwaggerInfo 获取所有Swagger信息
func (sp *SwaggerParser) GetAllSwaggerInfo() map[string]SwaggerInfo {
return sp.swaggerMap
}