From cf3856c24ca74a71f4e453db5ea178b336473066 Mon Sep 17 00:00:00 2001 From: tdakkota Date: Tue, 12 Mar 2024 05:59:36 +0300 Subject: [PATCH] fix(gen): re-use parameter type --- gen/gen_parameters.go | 35 +++++++++++++++++++++++++++++++---- gen/genctx.go | 14 ++++++++++++++ gen/tstorage.go | 33 +++++++++++++++++++++++++++------ 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/gen/gen_parameters.go b/gen/gen_parameters.go index 3dfe5e9c9..6604ad678 100644 --- a/gen/gen_parameters.go +++ b/gen/gen_parameters.go @@ -99,14 +99,41 @@ func (g *Generator) generateParameters(ctx *genctx, opName string, params []*ope return result, nil } -func (g *Generator) generateParameter(ctx *genctx, opName string, p *openapi.Parameter) (*ir.Parameter, error) { +func (g *Generator) generateParameter(ctx *genctx, opName string, p *openapi.Parameter) (ret *ir.Parameter, rerr error) { if err := isSupportedParamStyle(p); err != nil { return nil, err } - paramTypeName, err := pascal(opName, p.Name) - if err != nil { - return nil, errors.Wrapf(err, "parameter type name: %q", p.Name) + var paramTypeName string + if ref := p.Ref; !ref.IsZero() { + if p, ok := ctx.lookupParameter(ref); ok { + return p, nil + } + + n, err := pascal(cleanRef(ref)) + if err != nil { + return nil, errors.Wrapf(err, "parameter type name: %q", ref) + } + paramTypeName = n + + defer func() { + if rerr != nil { + return + } + + if err := ctx.saveParameter(ref, ret); err != nil { + rerr = err + ret = nil + } + }() + } + + if paramTypeName == "" { + var err error + paramTypeName, err = pascal(opName, p.Name) + if err != nil { + return nil, errors.Wrapf(err, "parameter type name: %q", p.Name) + } } generate := func(ctx *genctx, sch *jsonschema.Schema) (*ir.Type, error) { diff --git a/gen/genctx.go b/gen/genctx.go index 39fb21018..c4d27cbb6 100644 --- a/gen/genctx.go +++ b/gen/genctx.go @@ -38,6 +38,10 @@ func (g *genctx) saveWType(parent, ref jsonschema.Ref, t *ir.Type) error { return g.local.saveWType(parent, ref, t) } +func (g *genctx) saveParameter(ref jsonschema.Ref, r *ir.Parameter) error { + return g.local.saveParameter(ref, r) +} + func (g *genctx) lookupResponse(ref jsonschema.Ref) (*ir.Response, bool) { if r, ok := g.global.responses[ref]; ok { return r, true @@ -58,3 +62,13 @@ func (g *genctx) lookupWType(parent, ref jsonschema.Ref) (*ir.Type, bool) { } return nil, false } + +func (g *genctx) lookupParameter(ref jsonschema.Ref) (*ir.Parameter, bool) { + if r, ok := g.global.parameters[ref]; ok { + return r, true + } + if r, ok := g.local.parameters[ref]; ok { + return r, true + } + return nil, false +} diff --git a/gen/tstorage.go b/gen/tstorage.go index 77b478b67..533374300 100644 --- a/gen/tstorage.go +++ b/gen/tstorage.go @@ -33,8 +33,9 @@ type tstorage struct { // in the map because // the type is anonymous. // - types map[string]*ir.Type // Key: type name - responses map[jsonschema.Ref]*ir.Response // Key: ref + types map[string]*ir.Type // Key: type name + responses map[jsonschema.Ref]*ir.Response // Key: ref + parameters map[jsonschema.Ref]*ir.Parameter // Key: ref // wtypes stores references to wrapped types: // * [T]StatusCode @@ -45,10 +46,11 @@ type tstorage struct { func newTStorage() *tstorage { return &tstorage{ - refs: map[schemaKey]*ir.Type{}, - types: map[string]*ir.Type{}, - responses: map[jsonschema.Ref]*ir.Response{}, - wtypes: map[[2]jsonschema.Ref]*ir.Type{}, + refs: map[schemaKey]*ir.Type{}, + types: map[string]*ir.Type{}, + responses: map[jsonschema.Ref]*ir.Response{}, + parameters: map[jsonschema.Ref]*ir.Parameter{}, + wtypes: map[[2]jsonschema.Ref]*ir.Type{}, } } @@ -120,6 +122,15 @@ func (s *tstorage) saveWType(parent, ref jsonschema.Ref, t *ir.Type) error { return nil } +func (s *tstorage) saveParameter(ref jsonschema.Ref, p *ir.Parameter) error { + if _, ok := s.parameters[ref]; ok { + return errors.Errorf("reference conflict: %q", ref) + } + + s.parameters[ref] = p + return nil +} + func sameBase(t, tt *ir.Type) bool { if t.GenericOf != nil { t = t.GenericOf @@ -182,6 +193,12 @@ func (s *tstorage) merge(other *tstorage) error { } } + for ref := range other.parameters { + if _, ok := s.parameters[ref]; ok { + return errors.Errorf("parameter reference conflict: %q", ref) + } + } + // Merge types. for ref, t := range other.refs { s.refs[ref] = t @@ -200,5 +217,9 @@ func (s *tstorage) merge(other *tstorage) error { s.wtypes[name] = t } + for name, t := range other.parameters { + s.parameters[name] = t + } + return nil }