From 63511a0526584a2208855cf5997b276c747bfa5e Mon Sep 17 00:00:00 2001 From: tdakkota Date: Mon, 19 Feb 2024 20:10:54 +0300 Subject: [PATCH 1/2] fix(gen): use response ref as key for wrapped type lookup --- gen/gen_responses.go | 11 +++++++---- gen/genctx.go | 11 ++++++----- gen/tstorage.go | 11 ++++++----- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/gen/gen_responses.go b/gen/gen_responses.go index cf6418a7e..9f6a0124b 100644 --- a/gen/gen_responses.go +++ b/gen/gen_responses.go @@ -7,6 +7,7 @@ import ( "github.com/ogen-go/ogen/gen/ir" "github.com/ogen-go/ogen/internal/xmaps" + "github.com/ogen-go/ogen/jsonschema" "github.com/ogen-go/ogen/openapi" ) @@ -211,7 +212,7 @@ func (g *Generator) responseToIR( }, } } - t, err := wrapResponseType(ctx, name, media.Type, headers, withStatusCode) + t, err := wrapResponseType(ctx, name, resp.Ref, media.Type, headers, withStatusCode) if err != nil { return nil, errors.Wrapf(err, "content: %q: wrap response type", contentType) } @@ -234,6 +235,7 @@ func (g *Generator) responseToIR( func wrapResponseType( ctx *genctx, name string, + respRef jsonschema.Ref, t *ir.Type, headers map[string]*ir.Parameter, withStatusCode bool, @@ -243,7 +245,7 @@ func wrapResponseType( } if schema := t.Schema; schema != nil && !schema.Ref.IsZero() { - if t, ok := ctx.lookupWType(schema.Ref); ok { + if t, ok := ctx.lookupWType(respRef, schema.Ref); ok { return t, nil } @@ -252,7 +254,7 @@ func wrapResponseType( return } - if err := ctx.saveWType(schema.Ref, ret); err != nil { + if err := ctx.saveWType(respRef, schema.Ref, ret); err != nil { rerr = err ret = nil } @@ -270,7 +272,8 @@ func wrapResponseType( }() } - if t.Name != "" { + // Prefer response name to schema name in case of wrapping. + if respRef.IsZero() && t.Name != "" { name = t.Name } diff --git a/gen/genctx.go b/gen/genctx.go index 46b0fb7aa..39fb21018 100644 --- a/gen/genctx.go +++ b/gen/genctx.go @@ -34,8 +34,8 @@ func (g *genctx) saveResponse(ref jsonschema.Ref, r *ir.Response) error { return g.local.saveResponse(ref, r) } -func (g *genctx) saveWType(ref jsonschema.Ref, t *ir.Type) error { - return g.local.saveWType(ref, t) +func (g *genctx) saveWType(parent, ref jsonschema.Ref, t *ir.Type) error { + return g.local.saveWType(parent, ref, t) } func (g *genctx) lookupResponse(ref jsonschema.Ref) (*ir.Response, bool) { @@ -48,11 +48,12 @@ func (g *genctx) lookupResponse(ref jsonschema.Ref) (*ir.Response, bool) { return nil, false } -func (g *genctx) lookupWType(ref jsonschema.Ref) (*ir.Type, bool) { - if t, ok := g.global.wtypes[ref]; ok { +func (g *genctx) lookupWType(parent, ref jsonschema.Ref) (*ir.Type, bool) { + key := [2]jsonschema.Ref{parent, ref} + if t, ok := g.global.wtypes[key]; ok { return t, true } - if t, ok := g.local.wtypes[ref]; ok { + if t, ok := g.local.wtypes[key]; ok { return t, true } return nil, false diff --git a/gen/tstorage.go b/gen/tstorage.go index 49a9e7a07..77b478b67 100644 --- a/gen/tstorage.go +++ b/gen/tstorage.go @@ -40,7 +40,7 @@ type tstorage struct { // * [T]StatusCode // * [T]Headers // * [T]StatusCodeWithHeaders - wtypes map[jsonschema.Ref]*ir.Type // Key: ref + wtypes map[[2]jsonschema.Ref]*ir.Type // Key: parent ref + ref } func newTStorage() *tstorage { @@ -48,7 +48,7 @@ func newTStorage() *tstorage { refs: map[schemaKey]*ir.Type{}, types: map[string]*ir.Type{}, responses: map[jsonschema.Ref]*ir.Response{}, - wtypes: map[jsonschema.Ref]*ir.Type{}, + wtypes: map[[2]jsonschema.Ref]*ir.Type{}, } } @@ -106,15 +106,16 @@ func (s *tstorage) saveResponse(ref jsonschema.Ref, r *ir.Response) error { return nil } -func (s *tstorage) saveWType(ref jsonschema.Ref, t *ir.Type) error { - if _, ok := s.wtypes[ref]; ok { +func (s *tstorage) saveWType(parent, ref jsonschema.Ref, t *ir.Type) error { + key := [2]jsonschema.Ref{parent, ref} + if _, ok := s.wtypes[key]; ok { return errors.Errorf("reference conflict: %q", ref) } if _, ok := s.types[t.Name]; ok { return errors.Errorf("reference %q type name conflict: %q", ref, t.Name) } - s.wtypes[ref] = t + s.wtypes[key] = t s.types[t.Name] = t return nil } From 6383038c18ba1115a3e96c041d81c0f883a9a187 Mon Sep 17 00:00:00 2001 From: tdakkota Date: Mon, 19 Feb 2024 20:11:31 +0300 Subject: [PATCH 2/2] test: add regression test spec --- _testdata/positive/issue1182.yaml | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 _testdata/positive/issue1182.yaml diff --git a/_testdata/positive/issue1182.yaml b/_testdata/positive/issue1182.yaml new file mode 100644 index 000000000..536d2cbc1 --- /dev/null +++ b/_testdata/positive/issue1182.yaml @@ -0,0 +1,66 @@ +openapi: 3.0.1 +info: + title: "REST API" + version: 0.0.1 + +servers: + - url: "http://localhost:8888" + +paths: + /api/auth: + post: + operationId: auth + tags: + - auth + responses: + "200": + $ref: "#/components/responses/AuthOk" + /api/alive: + get: + operationId: alive + tags: + - system + responses: + "200": + $ref: "#/components/responses/Alive" + +components: + headers: + setCookie: + required: true + schema: + type: string + accessControlAllowCredentials: + required: false + schema: + type: string + + schemas: + Ok: + type: object + required: + - ok + properties: + ok: + type: boolean + example: true + + responses: + AuthOk: + description: "Ok" + headers: + Set-Cookie: + $ref: "#/components/headers/setCookie" + content: + application/json: + schema: + $ref: "#/components/schemas/Ok" + Alive: + description: "Alive" + headers: + Access-Control-Allow-Credentials: + $ref: "#/components/headers/accessControlAllowCredentials" + content: + application/json: + schema: + $ref: "#/components/schemas/Ok"