diff --git a/field_parser_v3_test.go b/field_parser_v3_test.go index 8b0b80cf4..da544b9b2 100644 --- a/field_parser_v3_test.go +++ b/field_parser_v3_test.go @@ -16,7 +16,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" example:"one"`, }}, @@ -28,7 +27,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" example:""`, }}, @@ -40,7 +38,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"float"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" example:"one"`, }}, @@ -55,7 +52,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" format:"csv"`, }}, @@ -69,7 +65,6 @@ func TestDefaultFieldParserV3(t *testing.T) { got, err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" binding:"required"`, }}, @@ -79,7 +74,6 @@ func TestDefaultFieldParserV3(t *testing.T) { got, err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required"`, }}, @@ -95,7 +89,6 @@ func TestDefaultFieldParserV3(t *testing.T) { &Parser{ RequiredByDefault: true, }, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test"`, }}, @@ -111,7 +104,6 @@ func TestDefaultFieldParserV3(t *testing.T) { &Parser{ RequiredByDefault: true, }, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" binding:"optional"`, }}, @@ -123,7 +115,6 @@ func TestDefaultFieldParserV3(t *testing.T) { &Parser{ RequiredByDefault: true, }, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"optional"`, }}, @@ -140,7 +131,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Extensions = map[string]interface{}{} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" extensions:"x-nullable,x-abc=def,!x-omitempty,x-example=[0, 9],x-example2={çãíœ, (bar=(abc, def)), [0,9]}"`, }}, @@ -160,7 +150,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" enums:"a,b,c"`, }}, @@ -172,7 +161,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"float"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" enums:"a,b,c"`, }}, @@ -189,7 +177,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Enum = []interface{}{} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" enums:"0,1,2" x-enum-varnames:"Daily,Weekly,Monthly"`, }}, @@ -201,7 +188,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"int"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" enums:"0,1,2,3" x-enum-varnames:"Daily,Weekly,Monthly"`, }}, @@ -218,7 +204,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Enum = []interface{}{} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" enums:"0,1,2" x-enum-varnames:"Daily,Weekly,Monthly"`, }}, @@ -235,7 +220,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" default:"pass"`, }}, @@ -247,7 +231,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"float"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" default:"pass"`, }}, @@ -262,7 +245,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"integer"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" maximum:"1"`, }}, @@ -275,7 +257,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"integer"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" maximum:"one"`, }}, @@ -286,7 +267,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"number"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" maximum:"1"`, }}, @@ -299,7 +279,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"number"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" maximum:"one"`, }}, @@ -310,7 +289,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"number"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" multipleOf:"1"`, }}, @@ -323,7 +301,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"number"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" multipleOf:"one"`, }}, @@ -334,7 +311,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"integer"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" minimum:"1"`, }}, @@ -347,7 +323,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"integer"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" minimum:"one"`, }}, @@ -362,7 +337,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" maxLength:"1"`, }}, @@ -375,7 +349,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" maxLength:"one"`, }}, @@ -386,7 +359,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" minLength:"1"`, }}, @@ -399,7 +371,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" minLength:"one"`, }}, @@ -414,7 +385,6 @@ func TestDefaultFieldParserV3(t *testing.T) { schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" readonly:"true"`, }}, @@ -422,24 +392,6 @@ func TestDefaultFieldParserV3(t *testing.T) { assert.NoError(t, err) assert.Equal(t, true, schema.Spec.ReadOnly) }) - - t.Run("OneOf tag", func(t *testing.T) { - t.Parallel() - - schema := spec.NewSchemaSpec() - schema.Spec.Type = []string{ANY} - err := newTagBaseFieldParserV3( - &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, - &ast.Field{Tag: &ast.BasicLit{ - Value: `json:"test" oneOf:"string,float64"`, - }}, - ).ComplementSchema(schema) - assert.NoError(t, err) - assert.Len(t, schema.Spec.OneOf, 2) - assert.Equal(t, spec.NewSingleOrArray("string"), schema.Spec.OneOf[0].Spec.Type) - assert.Equal(t, spec.NewSingleOrArray("number"), schema.Spec.OneOf[1].Spec.Type) - }) } func TestValidTagsV3(t *testing.T) { @@ -450,7 +402,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,max=10,min=1"`, }}, @@ -465,7 +416,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,max=10,gte=1"`, }}, @@ -478,7 +428,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"integer"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,max=10,min=1"`, }}, @@ -497,7 +446,6 @@ func TestValidTagsV3(t *testing.T) { err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,max=10,min=1"`, }}, @@ -509,7 +457,6 @@ func TestValidTagsV3(t *testing.T) { // wrong validate tag will be ignored. err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,max=ten,min=1"`, }}, @@ -526,7 +473,6 @@ func TestValidTagsV3(t *testing.T) { err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,oneof='red book' 'green book'"`, }}, @@ -538,7 +484,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"integer"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,oneof=1 2 3"`, }}, @@ -554,7 +499,6 @@ func TestValidTagsV3(t *testing.T) { err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,oneof=red green yellow"`, }}, @@ -566,7 +510,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,oneof='red green' blue 'c0x2Cc' 'd0x7Cd'"`, }}, @@ -578,7 +521,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,oneof='c0x9Ab' book"`, }}, @@ -590,7 +532,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" binding:"oneof=foo bar" validate:"required,oneof=foo bar" enums:"a,b,c"`, }}, @@ -602,7 +543,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" binding:"oneof=aa bb" validate:"required,oneof=foo bar"`, }}, @@ -620,7 +560,6 @@ func TestValidTagsV3(t *testing.T) { err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,unique"`, }}, @@ -638,7 +577,6 @@ func TestValidTagsV3(t *testing.T) { err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,unique,max=10,min=1,oneof=a0x2Cc 'c0x7Cd book',omitempty,dive,max=1"`, }}, @@ -659,7 +597,6 @@ func TestValidTagsV3(t *testing.T) { err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,oneof=,max=10=90,min=1"`, }}, @@ -675,7 +612,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Items.Schema.Spec.Type = []string{"string"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,max=10,min=one"`, }}, @@ -688,7 +624,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = []string{"integer"} err = newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"required,oneof=one two"`, }}, @@ -706,7 +641,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Items.Schema.Spec.Type = []string{"string"} err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" pattern:"^[a-zA-Z0-9_]*$"`, }}, @@ -722,7 +656,6 @@ func TestValidTagsV3(t *testing.T) { schema.Spec.Type = typeString err := newTagBaseFieldParserV3( &Parser{}, - &ast.File{Name: &ast.Ident{Name: "test"}}, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" pattern:"^[a-zA-Z0-9_]*$"`, }}, diff --git a/field_parserv3.go b/field_parserv3.go index 37a9c646d..733907f4b 100644 --- a/field_parserv3.go +++ b/field_parserv3.go @@ -83,15 +83,13 @@ func (sf *structFieldV3) setMax(valValue string) { type tagBaseFieldParserV3 struct { p *Parser - file *ast.File field *ast.Field tag reflect.StructTag } -func newTagBaseFieldParserV3(p *Parser, file *ast.File, field *ast.Field) FieldParserV3 { +func newTagBaseFieldParserV3(p *Parser, field *ast.Field) FieldParserV3 { fieldParser := tagBaseFieldParserV3{ p: p, - file: file, field: field, tag: "", } @@ -136,10 +134,9 @@ func (ps *tagBaseFieldParserV3) ComplementSchema(schema *spec.RefOrSpec[spec.Sch if err != nil { return err } - if !reflect.ValueOf(newSchema).IsZero() { - newSchema.AllOf = []*spec.RefOrSpec[spec.Schema]{{Spec: schema.Spec}} - *schema = spec.RefOrSpec[spec.Schema]{Spec: &newSchema} - } + // if !reflect.ValueOf(newSchema).IsZero() { + // *schema = *(newSchema.WithAllOf(*schema.Spec)) + // } return nil } @@ -342,19 +339,6 @@ func (ps *tagBaseFieldParserV3) complementSchema(schema *spec.Schema, types []st } } - var oneOfSchemas []*spec.RefOrSpec[spec.Schema] - oneOfTagValue := ps.tag.Get(oneOfTag) - if oneOfTagValue != "" { - oneOfTypes := strings.Split((oneOfTagValue), ",") - for _, oneOfType := range oneOfTypes { - oneOfSchema, err := ps.p.getTypeSchemaV3(oneOfType, ps.file, true) - if err != nil { - return fmt.Errorf("can't find oneOf type %q: %v", oneOfType, err) - } - oneOfSchemas = append(oneOfSchemas, oneOfSchema) - } - } - elemSchema := schema if field.schemaType == ARRAY { @@ -378,7 +362,6 @@ func (ps *tagBaseFieldParserV3) complementSchema(schema *spec.Schema, types []st elemSchema.MinLength = field.minLength elemSchema.Enum = field.enums elemSchema.Pattern = field.pattern - elemSchema.OneOf = oneOfSchemas return nil } diff --git a/go.mod b/go.mod index 0ba74277f..8f6be0f9f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.2 github.com/sv-tools/openapi v0.2.1 - golang.org/x/tools v0.13.0 + golang.org/x/tools v0.8.0 sigs.k8s.io/yaml v1.3.0 ) @@ -30,7 +30,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/urfave/cli/v2 v2.25.1 - golang.org/x/sys v0.12.0 // indirect + golang.org/x/sys v0.7.0 // indirect gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 298a46f74..16966338a 100644 --- a/go.sum +++ b/go.sum @@ -64,11 +64,11 @@ github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/operation.go b/operation.go index 57850f27e..7569ee790 100644 --- a/operation.go +++ b/operation.go @@ -423,7 +423,6 @@ const ( extensionsTag = "extensions" collectionFormatTag = "collectionFormat" patternTag = "pattern" - oneOfTag = "oneOf" ) var regexAttributes = map[string]*regexp.Regexp{ diff --git a/operationv3.go b/operationv3.go index 503ef4653..4737694e1 100644 --- a/operationv3.go +++ b/operationv3.go @@ -5,7 +5,6 @@ import ( "fmt" "go/ast" "log" - "maps" "net/http" "strconv" "strings" @@ -927,15 +926,22 @@ func (o *OperationV3) ParseResponseComment(commentLine string, astFile *ast.File for _, codeStr := range strings.Split(matches[1], ",") { if strings.EqualFold(codeStr, defaultTag) { - codeStr = "" - } else { - code, err := strconv.Atoi(codeStr) - if err != nil { - return fmt.Errorf("can not parse response comment \"%s\"", commentLine) - } - if description == "" { - description = http.StatusText(code) - } + response := o.DefaultResponse() + response.Description = description + + mimeType := "application/json" // TODO: set correct mimeType + setResponseSchema(response, mimeType, schema) + + continue + } + + code, err := strconv.Atoi(codeStr) + if err != nil { + return fmt.Errorf("can not parse response comment \"%s\"", commentLine) + } + + if description == "" { + description = http.StatusText(code) } response := spec.NewResponseSpec() @@ -973,12 +979,15 @@ func (o *OperationV3) ParseEmptyResponseComment(commentLine string) error { for _, codeStr := range strings.Split(matches[1], ",") { if strings.EqualFold(codeStr, defaultTag) { - codeStr = "" - } else { - _, err := strconv.Atoi(codeStr) - if err != nil { - return fmt.Errorf("can not parse response comment \"%s\"", commentLine) - } + response := o.DefaultResponse() + response.Description = description + + continue + } + + _, err := strconv.Atoi(codeStr) + if err != nil { + return fmt.Errorf("can not parse response comment \"%s\"", commentLine) } o.AddResponse(codeStr, newResponseWithDescription(description)) @@ -987,10 +996,21 @@ func (o *OperationV3) ParseEmptyResponseComment(commentLine string) error { return nil } +// DefaultResponse return the default response member pointer. +func (o *OperationV3) DefaultResponse() *spec.Response { + if o.Responses.Spec.Default == nil { + o.Responses.Spec.Default = spec.NewResponseSpec() + o.Responses.Spec.Default.Spec.Spec.Headers = make(map[string]*spec.RefOrSpec[spec.Extendable[spec.Header]]) + } + + if o.Responses.Spec.Default.Spec.Spec.Content == nil { + o.Responses.Spec.Default.Spec.Spec.Content = make(map[string]*spec.Extendable[spec.MediaType]) + } + + return o.Responses.Spec.Default.Spec.Spec +} + // AddResponse add a response for a code. -// If the code is already exist, it will merge with the old one: -// 1. The description will be replaced by the new one if the new one is not empty. -// 2. The content schema will be merged using `oneOf` if the new one is not empty. func (o *OperationV3) AddResponse(code string, response *spec.RefOrSpec[spec.Extendable[spec.Response]]) { if response.Spec.Spec.Headers == nil { response.Spec.Spec.Headers = make(map[string]*spec.RefOrSpec[spec.Extendable[spec.Header]]) @@ -1000,74 +1020,24 @@ func (o *OperationV3) AddResponse(code string, response *spec.RefOrSpec[spec.Ext o.Responses.Spec.Response = make(map[string]*spec.RefOrSpec[spec.Extendable[spec.Response]]) } - res := response - var prev *spec.RefOrSpec[spec.Extendable[spec.Response]] - if code != "" { - prev = o.Responses.Spec.Response[code] - } else { - prev = o.Responses.Spec.Default - } - if prev != nil { // merge into prev - res = prev - if response.Spec.Spec.Description != "" { - prev.Spec.Spec.Description = response.Spec.Spec.Description - } - if len(response.Spec.Spec.Content) > 0 { - // responses should only have one content type - singleKey := "" - for k := range response.Spec.Spec.Content { - singleKey = k - break - } - if prevMediaType := prev.Spec.Spec.Content[singleKey]; prevMediaType == nil { - prev.Spec.Spec.Content = response.Spec.Spec.Content - } else { - newMediaType := response.Spec.Spec.Content[singleKey] - if len(newMediaType.Extensions) > 0 { - if prevMediaType.Extensions == nil { - prevMediaType.Extensions = make(map[string]interface{}) - } - maps.Copy(prevMediaType.Extensions, newMediaType.Extensions) - } - if len(newMediaType.Spec.Examples) > 0 { - if prevMediaType.Spec.Examples == nil { - prevMediaType.Spec.Examples = make(map[string]*spec.RefOrSpec[spec.Extendable[spec.Example]]) - } - maps.Copy(prevMediaType.Spec.Examples, newMediaType.Spec.Examples) - } - if prevSchema := prevMediaType.Spec.Schema; prevSchema.Ref != nil || prevSchema.Spec.OneOf == nil { - oneOfSchema := spec.NewSchemaSpec() - oneOfSchema.Spec.OneOf = []*spec.RefOrSpec[spec.Schema]{prevSchema, newMediaType.Spec.Schema} - prevMediaType.Spec.Schema = oneOfSchema - } else { - prevSchema.Spec.OneOf = append(prevSchema.Spec.OneOf, newMediaType.Spec.Schema) - } - } - } - } - - if code != "" { - o.Responses.Spec.Response[code] = res - } else { - o.Responses.Spec.Default = res - } + o.Responses.Spec.Response[code] = response } // ParseEmptyResponseOnly parse only comment out status code ,eg: @Success 200. func (o *OperationV3) ParseEmptyResponseOnly(commentLine string) error { for _, codeStr := range strings.Split(commentLine, ",") { - var description string if strings.EqualFold(codeStr, defaultTag) { - codeStr = "" - } else { - code, err := strconv.Atoi(codeStr) - if err != nil { - return fmt.Errorf("can not parse response comment \"%s\"", commentLine) - } - description = http.StatusText(code) + _ = o.DefaultResponse() + + continue } - o.AddResponse(codeStr, newResponseWithDescription(description)) + code, err := strconv.Atoi(codeStr) + if err != nil { + return fmt.Errorf("can not parse response comment \"%s\"", commentLine) + } + + o.AddResponse(codeStr, newResponseWithDescription(http.StatusText(code))) } return nil diff --git a/parserv3.go b/parserv3.go index 33aef2c31..d7953e555 100644 --- a/parserv3.go +++ b/parserv3.go @@ -15,8 +15,8 @@ import ( "github.com/sv-tools/openapi/spec" ) -// FieldParserFactoryV3 create FieldParser. -type FieldParserFactoryV3 func(ps *Parser, file *ast.File, field *ast.Field) FieldParserV3 +// FieldParserFactoryV3 func(ps *Parser, field *ast.Field) FieldParserV3 create FieldParser. +type FieldParserFactoryV3 func(ps *Parser, field *ast.Field) FieldParserV3 // FieldParserV3 parse struct field. type FieldParserV3 interface { @@ -903,7 +903,7 @@ func (p *Parser) parseStructFieldV3(file *ast.File, field *ast.Field) (map[strin } } - ps := p.fieldParserFactoryV3(p, file, field) + ps := p.fieldParserFactoryV3(p, field) if ps.ShouldSkip() { return nil, nil, nil diff --git a/parserv3_test.go b/parserv3_test.go index af56f04cd..3123f25f3 100644 --- a/parserv3_test.go +++ b/parserv3_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/sv-tools/openapi/spec" ) func TestOverridesGetTypeSchemaV3(t *testing.T) { @@ -359,6 +358,7 @@ func TestParseSimpleApiV3(t *testing.T) { assert.NoError(t, err) paths := p.openAPI.Paths.Spec.Paths + assert.Equal(t, 15, len(paths)) path := paths["/testapi/get-string-by-int/{some_id}"].Spec.Spec.Get.Spec assert.Equal(t, "get string by ID", path.Description) @@ -372,98 +372,6 @@ func TestParseSimpleApiV3(t *testing.T) { assert.NotNil(t, path) assert.NotNil(t, path.RequestBody) //TODO add asserts - - t.Run("Test parse struct oneOf", func(t *testing.T) { - t.Parallel() - - assert.Contains(t, p.openAPI.Components.Spec.Schemas, "web.OneOfTest") - schema := p.openAPI.Components.Spec.Schemas["web.OneOfTest"].Spec - expected := `{ - "properties": { - "big_int": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - }, - "pet_detail": { - "oneOf": [ - { - "$ref": "#/components/schemas/web.Cat" - }, - { - "$ref": "#/components/schemas/web.Dog" - } - ] - } - }, - "type": "object" -}` - out, err := json.MarshalIndent(schema, "", " ") - assert.NoError(t, err) - assert.Equal(t, expected, string(out)) - - assert.Contains(t, p.openAPI.Components.Spec.Schemas, "web.Cat") - schema = p.openAPI.Components.Spec.Schemas["web.Cat"].Spec - expected = `{ - "properties": { - "age": { - "type": "integer" - }, - "hunts": { - "type": "boolean" - } - }, - "type": "object" -}` - out, err = json.MarshalIndent(schema, "", " ") - assert.NoError(t, err) - assert.Equal(t, expected, string(out)) - - assert.Contains(t, p.openAPI.Components.Spec.Schemas, "web.Dog") - schema = p.openAPI.Components.Spec.Schemas["web.Dog"].Spec - expected = `{ - "properties": { - "bark": { - "type": "boolean" - }, - "breed": { - "enum": [ - "Dingo", - "Husky", - "Retriever", - "Shepherd" - ], - "type": "string" - } - }, - "type": "object" -}` - out, err = json.MarshalIndent(schema, "", " ") - assert.NoError(t, err) - assert.Equal(t, expected, string(out)) - }) - - t.Run("Test parse response oneOf", func(t *testing.T) { - t.Parallel() - - assert.Contains(t, paths, "/pets/{id}") - path := paths["/pets/{id}"] - assert.Contains(t, path.Spec.Spec.Get.Spec.Responses.Spec.Response, "200") - response = path.Spec.Spec.Get.Spec.Responses.Spec.Response["200"] - assert.Equal(t, "Return Cat or Dog", response.Spec.Spec.Description) - mediaType := response.Spec.Spec.Content["application/json"] - rootSchema := mediaType.Spec.Schema.Spec - assert.Equal(t, []*spec.RefOrSpec[spec.Schema]{ - {Ref: &spec.Ref{Ref: "#/components/schemas/web.Cat"}}, - {Ref: &spec.Ref{Ref: "#/components/schemas/web.Dog"}}, - }, rootSchema.OneOf) - - }) } func TestParserParseServers(t *testing.T) { diff --git a/testdata/v3/simple/api/api.go b/testdata/v3/simple/api/api.go index 39ca8bad6..91433b466 100644 --- a/testdata/v3/simple/api/api.go +++ b/testdata/v3/simple/api/api.go @@ -144,19 +144,3 @@ func GetPet6FunctionScopedResponse() { func FormData() { } - -// @Success 200 {object} web.OneOfTest -// @Router /GetOneOfTypes [get] -func GetOneOfTypes() { - -} - -// @Summary Get pet by ID -// @Param id path string true "ID" -// @Success 200 {object} web.Cat -// @Success 200 {object} web.Dog -// @Success 200 "Return Cat or Dog" -// @Router /pets/{id} [get] -func GetPetByID() { - -} diff --git a/testdata/v3/simple/web/handler.go b/testdata/v3/simple/web/handler.go index a8e03ac9d..3afcdd0d1 100644 --- a/testdata/v3/simple/web/handler.go +++ b/testdata/v3/simple/web/handler.go @@ -112,18 +112,3 @@ type Request struct { Password string `json:"password"` RefreshToken string `json:"refresh_token"` } - -type OneOfTest struct { - BigInt any `json:"big_int" oneOf:"string,int64"` - PetDetail any `json:"pet_detail" oneOf:"Cat,Dog"` -} - -type Dog struct { - Bark bool `json:"bark"` - Breed string `json:"breed" enums:"Dingo,Husky,Retriever,Shepherd"` -} - -type Cat struct { - Hunts bool `json:"hunts"` - Age int `json:"age"` -}