From dfce6c8f6af1f3e5d048310aebf08479d8ba13f3 Mon Sep 17 00:00:00 2001 From: sdghchj Date: Tue, 13 Dec 2022 01:01:12 +0800 Subject: [PATCH] parse self-nested generic struct (#1420) --- generics.go | 5 +- generics_test.go | 2 + testdata/generics_nested/api/api.go | 10 ++ testdata/generics_nested/expected.json | 37 ++++++++ testdata/generics_nested/web/handler.go | 5 + testdata/generics_property/expected.json | 115 ++++++++++++----------- 6 files changed, 118 insertions(+), 56 deletions(-) diff --git a/generics.go b/generics.go index 652f4a8d0..1f8301b5b 100644 --- a/generics.go +++ b/generics.go @@ -95,13 +95,14 @@ func (pkgDefs *PackagesDefinitions) parametrizeGenericType(file *ast.File, origi NamePos: original.TypeSpec.Name.NamePos, Obj: original.TypeSpec.Name.Obj, }, - Type: pkgDefs.resolveGenericType(original.File, original.TypeSpec.Type, genericParamTypeDefs), Doc: original.TypeSpec.Doc, Assign: original.TypeSpec.Assign, }, } pkgDefs.uniqueDefinitions[name] = parametrizedTypeSpec + parametrizedTypeSpec.TypeSpec.Type = pkgDefs.resolveGenericType(original.File, original.TypeSpec.Type, genericParamTypeDefs) + return parametrizedTypeSpec } @@ -184,7 +185,7 @@ func (pkgDefs *PackagesDefinitions) resolveGenericType(file *ast.File, expr ast. fullGenericName, _ := getGenericFieldType(file, expr, genericParamTypeDefs) typeDef := pkgDefs.FindTypeSpec(fullGenericName, file) if typeDef != nil { - return typeDef.TypeSpec.Type + return typeDef.TypeSpec.Name } case *ast.StructType: newStructTypeDef := &ast.StructType{ diff --git a/generics_test.go b/generics_test.go index 48dde59a9..9eb51c09f 100644 --- a/generics_test.go +++ b/generics_test.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "go/ast" + "io/fs" "os" "path/filepath" "testing" @@ -84,6 +85,7 @@ func TestParseGenericsProperty(t *testing.T) { err = p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth) assert.NoError(t, err) b, err := json.MarshalIndent(p.swagger, "", " ") + os.WriteFile(searchDir+"/expected.json", b, fs.ModePerm) assert.NoError(t, err) assert.Equal(t, string(expected), string(b)) } diff --git a/testdata/generics_nested/api/api.go b/testdata/generics_nested/api/api.go index 76bc06b13..19c215ee6 100644 --- a/testdata/generics_nested/api/api.go +++ b/testdata/generics_nested/api/api.go @@ -38,3 +38,13 @@ func GetPosts(w http.ResponseWriter, r *http.Request) { func GetPostArray(w http.ResponseWriter, r *http.Request) { _ = web.GenericNestedResponse[types.Post]{} } + +// @Summary List Posts +// @Description Get All of the Posts +// @Accept json +// @Produce json +// @Success 200 {object} web.GenericNodeThree[string] +// @Router /posts-self-nested-struct/ [get] +func GetPostSelfNestStruct(w http.ResponseWriter, r *http.Request) { + +} diff --git a/testdata/generics_nested/expected.json b/testdata/generics_nested/expected.json index 850fc5ae4..51b53a1c5 100644 --- a/testdata/generics_nested/expected.json +++ b/testdata/generics_nested/expected.json @@ -130,6 +130,26 @@ } } } + }, + "/posts-self-nested-struct/": { + "get": { + "description": "Get All of the Posts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "List Posts", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/web.GenericNodeThree-string" + } + } + } + } } }, "definitions": { @@ -580,6 +600,23 @@ "type": "string" } } + }, + "web.GenericNodeThree-string": { + "type": "object", + "properties": { + "current": { + "type": "array", + "items": { + "type": "string" + } + }, + "next": { + "type": "array", + "items": { + "$ref": "#/definitions/web.GenericNodeThree-string" + } + } + } } } } \ No newline at end of file diff --git a/testdata/generics_nested/web/handler.go b/testdata/generics_nested/web/handler.go index 9d53e91d4..02f07121f 100644 --- a/testdata/generics_nested/web/handler.go +++ b/testdata/generics_nested/web/handler.go @@ -62,3 +62,8 @@ type APIError struct { ErrorCtx string // Error `context` tick comment CreatedAt time.Time // Error time } + +type GenericNodeThree[T any] struct { + CurrentData []T `json:"current"` + Next []*GenericNodeThree[T] `json:"next"` +} diff --git a/testdata/generics_property/expected.json b/testdata/generics_property/expected.json index e0880258f..490909ee0 100644 --- a/testdata/generics_property/expected.json +++ b/testdata/generics_property/expected.json @@ -184,15 +184,7 @@ } }, "value4": { - "type": "object", - "properties": { - "subValue1": { - "$ref": "#/definitions/api.Person" - }, - "subValue2": { - "type": "string" - } - } + "$ref": "#/definitions/types.SubField1-api_Person-string" } } }, @@ -221,15 +213,7 @@ } }, "value4": { - "type": "object", - "properties": { - "subValue1": { - "$ref": "#/definitions/api.Person" - }, - "subValue2": { - "type": "string" - } - } + "$ref": "#/definitions/types.SubField1-api_Person-string" } } }, @@ -258,15 +242,7 @@ } }, "value4": { - "type": "object", - "properties": { - "subValue1": { - "$ref": "#/definitions/types.Post" - }, - "subValue2": { - "type": "string" - } - } + "$ref": "#/definitions/types.SubField1-types_Post-string" } } }, @@ -286,15 +262,7 @@ } }, "value4": { - "type": "object", - "properties": { - "subValue1": { - "type": "string" - }, - "subValue2": { - "type": "string" - } - } + "$ref": "#/definitions/types.SubField1-string-string" } } }, @@ -314,15 +282,7 @@ } }, "value4": { - "type": "object", - "properties": { - "subValue1": { - "$ref": "#/definitions/types.Field-api_Person" - }, - "subValue2": { - "type": "string" - } - } + "$ref": "#/definitions/types.SubField1-types_Field-api_Person-string" } } }, @@ -342,15 +302,7 @@ } }, "value4": { - "type": "object", - "properties": { - "subValue1": { - "$ref": "#/definitions/types.Field-string" - }, - "subValue2": { - "type": "string" - } - } + "$ref": "#/definitions/types.SubField1-types_Field-string-string" } } }, @@ -385,6 +337,61 @@ } } }, + "types.SubField1-api_Person-string": { + "type": "object", + "properties": { + "subValue1": { + "$ref": "#/definitions/api.Person" + }, + "subValue2": { + "type": "string" + } + } + }, + "types.SubField1-string-string": { + "type": "object", + "properties": { + "subValue1": { + "type": "string" + }, + "subValue2": { + "type": "string" + } + } + }, + "types.SubField1-types_Field-api_Person-string": { + "type": "object", + "properties": { + "subValue1": { + "$ref": "#/definitions/types.Field-api_Person" + }, + "subValue2": { + "type": "string" + } + } + }, + "types.SubField1-types_Field-string-string": { + "type": "object", + "properties": { + "subValue1": { + "$ref": "#/definitions/types.Field-string" + }, + "subValue2": { + "type": "string" + } + } + }, + "types.SubField1-types_Post-string": { + "type": "object", + "properties": { + "subValue1": { + "$ref": "#/definitions/types.Post" + }, + "subValue2": { + "type": "string" + } + } + }, "web.PostResponse": { "type": "object", "properties": {