diff --git a/README.md b/README.md index 1fd76932c..ff2de0dba 100644 --- a/README.md +++ b/README.md @@ -616,6 +616,9 @@ type Account struct { ### Description of struct ```go +// Account model info +// @Description User account information +// @Description with user id and username type Account struct { // ID this is userid ID int `json:"id"` @@ -623,6 +626,27 @@ type Account struct { } ``` +[#708](https://github.com/swaggo/swag/issues/708) The parser handles only struct comments starting with `@Description` attribute. +But it writes all struct field comments as is. + +So, generated swagger doc as follows: +```json +"Account": { + "type":"object", + "description": "User account information with user id and username" + "properties": { + "id": { + "type": "integer", + "description": "ID this is userid" + }, + "name": { + "type":"string", + "description": "This is Name" + } + } +} +``` + ### Use swaggertype tag to supported custom type [#201](https://github.com/swaggo/swag/issues/201#issuecomment-475479409) diff --git a/parser.go b/parser.go index f4195feba..387151aba 100644 --- a/parser.go +++ b/parser.go @@ -954,6 +954,10 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef) (*Schema, error) return nil, err } + if definition.Description == "" { + fillDefinitionDescription(definition, typeSpecDef.File, typeSpecDef) + } + s := Schema{ Name: refTypeName, PkgPath: typeSpecDef.PkgPath, @@ -978,6 +982,56 @@ func fullTypeName(pkgName, typeName string) string { return typeName } +// fillDefinitionDescription additionally fills fields in definition (spec.Schema) +// TODO: If .go file contains many types, it may work for a long time +func fillDefinitionDescription(definition *spec.Schema, file *ast.File, typeSpecDef *TypeSpecDef) { + for _, astDeclaration := range file.Decls { + generalDeclaration, ok := astDeclaration.(*ast.GenDecl) + if !ok || generalDeclaration.Tok != token.TYPE { + continue + } + + for _, astSpec := range generalDeclaration.Specs { + typeSpec, ok := astSpec.(*ast.TypeSpec) + if !ok || typeSpec != typeSpecDef.TypeSpec { + continue + } + + definition.Description = + extractDeclarationDescription(typeSpec.Doc, typeSpec.Comment, generalDeclaration.Doc) + } + } +} + +// extractDeclarationDescription gets first description +// from attribute descriptionAttr in commentGroups (ast.CommentGroup) +func extractDeclarationDescription(commentGroups ...*ast.CommentGroup) string { + var description string + + for _, commentGroup := range commentGroups { + if commentGroup == nil { + continue + } + + isHandlingDescription := false + for _, comment := range commentGroup.List { + commentText := strings.TrimSpace(strings.TrimLeft(comment.Text, "/")) + attribute := strings.Split(commentText, " ")[0] + if strings.ToLower(attribute) != descriptionAttr { + if !isHandlingDescription { + continue + } + break + } + + isHandlingDescription = true + description += " " + strings.TrimSpace(commentText[len(attribute):]) + } + } + + return strings.TrimLeft(description, " ") +} + // parseTypeExpr parses given type expression that corresponds to the type under // given name and package, and returns swagger schema for it. func (parser *Parser) parseTypeExpr(file *ast.File, typeExpr ast.Expr, ref bool) (*spec.Schema, error) { diff --git a/parser_test.go b/parser_test.go index 1506acb19..5282f8e88 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1800,6 +1800,7 @@ func TestParseStructComment(t *testing.T) { }, "definitions": { "web.APIError": { + "description": "API error with information about it", "type": "object", "properties": { "createdAt": { diff --git a/testdata/struct_comment/web/handler.go b/testdata/struct_comment/web/handler.go index 49674dae3..60293353a 100644 --- a/testdata/struct_comment/web/handler.go +++ b/testdata/struct_comment/web/handler.go @@ -15,6 +15,10 @@ type Post struct { } `json:"data"` } +// APIError +// @Description API error +// @Description with information about it +// Other some summary type APIError struct { // Error an Api error Error string // Error this is Line comment