From cf009bd123b49ab6385d4853731dec7fa98e697a Mon Sep 17 00:00:00 2001 From: Fabian Martin Date: Thu, 15 Sep 2022 20:07:56 +0200 Subject: [PATCH] fix: Generics not detected if name does not contain a pkg path - Generic detection moved to own method - prepend pkg path if not provided refs https://github.com/swaggo/swag/issues/1319 --- packages.go | 39 ++++++++++++++-------- testdata/generics_basic/api/api.go | 13 ++++++++ testdata/generics_basic/expected.json | 48 +++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 14 deletions(-) diff --git a/packages.go b/packages.go index 25afe9753..402ee7c89 100644 --- a/packages.go +++ b/packages.go @@ -389,25 +389,17 @@ func (pkgDefs *PackagesDefinitions) FindTypeSpec(typeName string, file *ast.File } } - if strings.Contains(typeName, "[") { - // joinedParts differs from typeName in that it does not contain any type parameters - joinedParts := strings.Join(parts, ".") - for tName, tSpec := range pkgDefs.uniqueDefinitions { - if !strings.Contains(tName, "[") { - continue - } - - if strings.Contains(tName, joinedParts) { - if parametrized := pkgDefs.parametrizeStruct(file, tSpec, typeName, parseDependency); parametrized != nil { - return parametrized - } - } - } + if def := pkgDefs.findGenericTypeSpec(typeName, file, parseDependency); def != nil { + return def } return pkgDefs.findTypeSpec(pkgPath, parts[1]) } + if def := pkgDefs.findGenericTypeSpec(fullTypeName(file.Name.Name, typeName), file, parseDependency); def != nil { + return def + } + typeDef, ok := pkgDefs.uniqueDefinitions[fullTypeName(file.Name.Name, typeName)] if ok { return typeDef @@ -429,3 +421,22 @@ func (pkgDefs *PackagesDefinitions) FindTypeSpec(typeName string, file *ast.File return nil } + +func (pkgDefs *PackagesDefinitions) findGenericTypeSpec(typeName string, file *ast.File, parseDependency bool) *TypeSpecDef { + if strings.Contains(typeName, "[") { + // genericName differs from typeName in that it does not contain any type parameters + genericName := strings.SplitN(typeName, "[", 2)[0] + for tName, tSpec := range pkgDefs.uniqueDefinitions { + if !strings.Contains(tName, "[") { + continue + } + + if strings.Contains(tName, genericName) { + if parametrized := pkgDefs.parametrizeStruct(file, tSpec, typeName, parseDependency); parametrized != nil { + return parametrized + } + } + } + } + return nil +} diff --git a/testdata/generics_basic/api/api.go b/testdata/generics_basic/api/api.go index e42551344..381fe5446 100644 --- a/testdata/generics_basic/api/api.go +++ b/testdata/generics_basic/api/api.go @@ -7,6 +7,17 @@ import ( "github.com/swaggo/swag/testdata/generics_basic/web" ) +type Response[T any, X any] struct { + Data T + Meta X + + Status string +} + +type StringStruct struct { + Data string +} + // @Summary Add a new pet to the store // @Description get string by ID // @Accept json @@ -16,6 +27,8 @@ import ( // @Success 201 {object} web.GenericResponse[types.Hello] // @Success 202 {object} web.GenericResponse[types.Field[string]] // @Success 203 {object} web.GenericResponse[types.Field[int]] +// @Success 204 {object} Response[string, types.Field[int]] +// @Success 205 {object} Response[StringStruct, types.Field[int]] // @Success 222 {object} web.GenericResponseMulti[types.Post, types.Post] // @Failure 400 {object} web.APIError "We need ID!!" // @Failure 404 {object} web.APIError "Can not find ID" diff --git a/testdata/generics_basic/expected.json b/testdata/generics_basic/expected.json index 8f56bf54f..d4933fe9c 100644 --- a/testdata/generics_basic/expected.json +++ b/testdata/generics_basic/expected.json @@ -147,6 +147,18 @@ "$ref": "#/definitions/web.GenericResponse-types_Field_int" } }, + "204": { + "description": "No Content", + "schema": { + "$ref": "#/definitions/api.Response-string-types_Field_int" + } + }, + "205": { + "description": "Reset Content", + "schema": { + "$ref": "#/definitions/api.Response-api_StringStruct-types_Field_int" + } + }, "222": { "description": "", "schema": { @@ -170,6 +182,42 @@ } }, "definitions": { + "api.Response-api_StringStruct-types_Field_int": { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/api.StringStruct" + }, + "meta": { + "$ref": "#/definitions/types.Field-int" + }, + "status": { + "type": "string" + } + } + }, + "api.Response-string-types_Field_int": { + "type": "object", + "properties": { + "data": { + "type": "string" + }, + "meta": { + "$ref": "#/definitions/types.Field-int" + }, + "status": { + "type": "string" + } + } + }, + "api.StringStruct": { + "type": "object", + "properties": { + "data": { + "type": "string" + } + } + }, "types.Field-int": { "type": "object", "properties": {