diff --git a/parser.go b/parser.go index 9db79fa39..9da938a85 100644 --- a/parser.go +++ b/parser.go @@ -1040,6 +1040,31 @@ func matchExtension(extensionToMatch string, comments []*ast.Comment) (match boo return true } +func getFuncDoc(decl any) (*ast.CommentGroup, bool) { + switch astDecl := decl.(type) { + case *ast.FuncDecl: // func name() {} + return astDecl.Doc, true + case *ast.GenDecl: // var name = namePointToFuncDirectlyOrIndirectly + if astDecl.Tok != token.VAR { + return nil, false + } + varSpec, ok := astDecl.Specs[0].(*ast.ValueSpec) + if !ok || len(varSpec.Values) != 1 { + return nil, false + } + _, ok = getFuncDoc(varSpec) + return astDecl.Doc, ok + case *ast.ValueSpec: + value, ok := astDecl.Values[0].(*ast.Ident) + if !ok || value == nil { + return nil, false + } + _, ok = getFuncDoc(value.Obj.Decl) + return astDecl.Doc, ok + } + return nil, false +} + // ParseRouterAPIInfo parses router api info for given astFile. func (parser *Parser) ParseRouterAPIInfo(fileInfo *AstFileInfo) error { if (fileInfo.ParseFlag & ParseOperations) == ParseNone { @@ -1059,10 +1084,10 @@ func (parser *Parser) ParseRouterAPIInfo(fileInfo *AstFileInfo) error { return nil } - for _, astDescription := range fileInfo.File.Decls { - astDeclaration, ok := astDescription.(*ast.FuncDecl) - if ok && astDeclaration.Doc != nil && astDeclaration.Doc.List != nil { - if err := parser.parseRouterAPIInfoComment(astDeclaration.Doc.List, fileInfo); err != nil { + for _, decl := range fileInfo.File.Decls { + funcDoc, ok := getFuncDoc(decl) + if ok && funcDoc != nil && funcDoc.List != nil { + if err := parser.parseRouterAPIInfoComment(funcDoc.List, fileInfo); err != nil { return err } } diff --git a/parser_test.go b/parser_test.go index 1f560366e..f0ca3b9c4 100644 --- a/parser_test.go +++ b/parser_test.go @@ -4388,3 +4388,34 @@ func TestParser_EmbeddedStructAsOtherAliasGoListNested(t *testing.T) { assert.NoError(t, err) assert.Equal(t, string(expected), string(b)) } + +func TestParser_genVarDefinedFuncDoc(t *testing.T) { + t.Parallel() + + src := ` +package main +func f() {} +// @Summary generate var-defined functions' doc +// @Router /test [get] +var Func = f +// @Summary generate indirectly pointing +// @Router /test2 [get] +var Func2 = Func +` + p := New() + err := p.packages.ParseFile("api", "api/api.go", src, ParseAll) + assert.NoError(t, err) + _, _ = p.packages.ParseTypes() + err = p.packages.RangeFiles(p.ParseRouterAPIInfo) + assert.NoError(t, err) + + val, ok := p.swagger.Paths.Paths["/test"] + assert.True(t, ok) + assert.NotNil(t, val.Get) + assert.Equal(t, val.Get.OperationProps.Summary, "generate var-defined functions' doc") + + val2, ok := p.swagger.Paths.Paths["/test2"] + assert.True(t, ok) + assert.NotNil(t, val2.Get) + assert.Equal(t, val2.Get.OperationProps.Summary, "generate indirectly pointing") +}