From fd49f74723826df935bc3a6301a0f41d6bda701a Mon Sep 17 00:00:00 2001 From: Nikolai Obedin Date: Tue, 6 Nov 2018 15:04:31 +0100 Subject: [PATCH] Fix isNotRecurringNestStruct function Currently, the function does not use its refTypeName parameter; instead it checks that the 1st structure in the structures stack does not repeat. Recursion, however, can be indirect. Consider the following example: type Foo struct { Bar Bar } type Bar struct { Foo Foo } type Baz struct { Foo Foo } In the example generator will crash with stack overflow while trying to generate spec for Baz when there is no spec for Foo and Bar generated yet. The fix is to check that refTypeName does not repeat in the structures stack. --- parser.go | 8 ++------ parser_test.go | 11 +++++++++++ testdata/simple/api/api.go | 5 +++++ testdata/simple/web/handler.go | 4 ++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/parser.go b/parser.go index 2e9b11a63..de2f0954d 100644 --- a/parser.go +++ b/parser.go @@ -378,12 +378,8 @@ var structStacks []string // isNotRecurringNestStruct check if a structure that is not a not repeating func isNotRecurringNestStruct(refTypeName string, structStacks []string) bool { - if len(structStacks) <= 0 { - return true - } - startStruct := structStacks[0] - for _, v := range structStacks[1:] { - if startStruct == v { + for _, v := range structStacks { + if refTypeName == v { return false } } diff --git a/parser_test.go b/parser_test.go index fdd6a2b12..5b6f978d0 100644 --- a/parser_test.go +++ b/parser_test.go @@ -483,6 +483,17 @@ func TestParseSimpleApi(t *testing.T) { } } }, + "web.IndirectRecursiveTest": { + "type": "object", + "properties": { + "Tags": { + "type": "array", + "items": { + "$ref": "#/definitions/web.Tag" + } + } + } + }, "web.Pet": { "type": "object", "required": [ diff --git a/testdata/simple/api/api.go b/testdata/simple/api/api.go index 382807ec5..c9ca86d2e 100644 --- a/testdata/simple/api/api.go +++ b/testdata/simple/api/api.go @@ -69,6 +69,11 @@ func Pet2() { } +// @Summary Use IndirectRecursiveTest +// @Success 200 {object} web.IndirectRecursiveTest +func IndirectRecursiveTest() { +} + type Pet3 struct { ID int `json:"id"` } diff --git a/testdata/simple/web/handler.go b/testdata/simple/web/handler.go index 0977bc08f..a726cd989 100644 --- a/testdata/simple/web/handler.go +++ b/testdata/simple/web/handler.go @@ -48,6 +48,10 @@ type Pet2 struct { DeletedAt *time.Time `json:"deleted_at"` } +type IndirectRecursiveTest struct { + Tags []Tag +} + type APIError struct { ErrorCode int ErrorMessage string