From 5bd794dcaf089d5729d990defd0f96bd6d0b6feb Mon Sep 17 00:00:00 2001 From: "andrey.lukin" Date: Mon, 18 Apr 2022 11:22:58 +0300 Subject: [PATCH 1/6] Added defaultRequired flag --- cmd/swag/main.go | 6 ++++++ field_parser.go | 12 +++++++++--- field_parser_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ gen/gen.go | 4 ++++ parser.go | 3 +++ 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/cmd/swag/main.go b/cmd/swag/main.go index 0a18900f0..5e5f28da1 100644 --- a/cmd/swag/main.go +++ b/cmd/swag/main.go @@ -26,6 +26,7 @@ const ( codeExampleFilesFlag = "codeExampleFiles" parseInternalFlag = "parseInternal" generatedTimeFlag = "generatedTime" + defaultRequiredFlag = "defaultRequired" parseDepthFlag = "parseDepth" instanceNameFlag = "instanceName" overridesFileFlag = "overridesFile" @@ -100,6 +101,10 @@ var initFlags = []cli.Flag{ Value: 100, Usage: "Dependency parse depth", }, + &cli.BoolFlag{ + Name: defaultRequiredFlag, + Usage: "Set validation required for all fields by default", + }, &cli.StringFlag{ Name: instanceNameFlag, Value: "", @@ -138,6 +143,7 @@ func initAction(c *cli.Context) error { MarkdownFilesDir: c.String(markdownFilesFlag), ParseInternal: c.Bool(parseInternalFlag), GeneratedTime: c.Bool(generatedTimeFlag), + DefaultRequired: c.Bool(defaultRequiredFlag), CodeExampleFilesDir: c.String(codeExampleFilesFlag), ParseDepth: c.Int(parseDepthFlag), InstanceName: c.String(instanceNameFlag), diff --git a/field_parser.go b/field_parser.go index b5cf26242..a8a8dc27b 100644 --- a/field_parser.go +++ b/field_parser.go @@ -439,8 +439,11 @@ func (ps *tagBaseFieldParser) IsRequired() (bool, error) { bindingTag := ps.tag.Get(bindingTag) if bindingTag != "" { for _, val := range strings.Split(bindingTag, ",") { - if val == "required" { + switch val { + case "required": return true, nil + case "optional": + return false, nil } } } @@ -448,13 +451,16 @@ func (ps *tagBaseFieldParser) IsRequired() (bool, error) { validateTag := ps.tag.Get(validateTag) if validateTag != "" { for _, val := range strings.Split(validateTag, ",") { - if val == "required" { + switch val { + case "required": return true, nil + case "optional": + return false, nil } } } - return false, nil + return ps.p.DefaultRequired, nil } func (ps *tagBaseFieldParser) parseValidTags(validTag string, sf *structField) { diff --git a/field_parser_test.go b/field_parser_test.go index 1b0e1d639..c66cf4db5 100644 --- a/field_parser_test.go +++ b/field_parser_test.go @@ -82,6 +82,47 @@ func TestDefaultFieldParser(t *testing.T) { assert.Equal(t, true, got) }) + t.Run("Default required tag", func(t *testing.T) { + t.Parallel() + + got, err := newTagBaseFieldParser( + &Parser{ + DefaultRequired: true, + }, + &ast.Field{Tag: &ast.BasicLit{ + Value: `json:"test"`, + }}, + ).IsRequired() + assert.NoError(t, err) + assert.True(t, got) + }) + + t.Run("Optional tag", func(t *testing.T) { + t.Parallel() + + got, err := newTagBaseFieldParser( + &Parser{ + DefaultRequired: true, + }, + &ast.Field{Tag: &ast.BasicLit{ + Value: `json:"test" binding:"optional"`, + }}, + ).IsRequired() + assert.NoError(t, err) + assert.False(t, got) + + got, err = newTagBaseFieldParser( + &Parser{ + DefaultRequired: true, + }, + &ast.Field{Tag: &ast.BasicLit{ + Value: `json:"test" validate:"optional"`, + }}, + ).IsRequired() + assert.NoError(t, err) + assert.False(t, got) + }) + t.Run("Extensions tag", func(t *testing.T) { t.Parallel() diff --git a/gen/gen.go b/gen/gen.go index e8655d94e..0b3d0096d 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -105,6 +105,9 @@ type Config struct { // GeneratedTime whether swag should generate the timestamp at the top of docs.go GeneratedTime bool + // DefaultRequired set validation required for all fields by default + DefaultRequired bool + // OverridesFile defines global type overrides. OverridesFile string } @@ -151,6 +154,7 @@ func (g *Gen) Build(config *Config) error { p.ParseVendor = config.ParseVendor p.ParseDependency = config.ParseDependency p.ParseInternal = config.ParseInternal + p.DefaultRequired = config.DefaultRequired if err := p.ParseAPIMultiSearchDir(searchDirs, config.MainAPIFile, config.ParseDepth); err != nil { return err diff --git a/parser.go b/parser.go index 387151aba..5605c5bb4 100644 --- a/parser.go +++ b/parser.go @@ -117,6 +117,9 @@ type Parser struct { // Strict whether swag should error or warn when it detects cases which are most likely user errors Strict bool + // DefaultRequired set validation required for all fields by default + DefaultRequired bool + // structStack stores full names of the structures that were already parsed or are being parsed now structStack []*TypeSpecDef From 642a0edc439b2a88d5f40811d76dbbe1b5d5e49e Mon Sep 17 00:00:00 2001 From: "andrey.lukin" Date: Mon, 18 Apr 2022 11:36:34 +0300 Subject: [PATCH 2/6] Updated readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8774db7a4..2ab939060 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ OPTIONS: --codeExampleFiles value, --cef value Parse folder containing code example files to use for the x-codeSamples extension, disabled by default --parseInternal Parse go files in internal packages, disabled by default (default: false) --generatedTime Generate timestamp at the top of docs.go, disabled by default (default: false) + --defaultRequired Set validation required for all fields by default (default: false) --parseDepth value Dependency parse depth (default: 100) --instanceName value This parameter can be used to name different swagger document instances. It is optional. --overridesFile value File to read global type overrides from. (default: ".swaggo") @@ -487,7 +488,7 @@ type Foo struct { Field Name | Type | Description ---|:---:|--- -validate | `string` | Determines the validation for the parameter. Possible values are: `required`. +validate | `string` | Determines the validation for the parameter. Possible values are: `required,optional`. default | * | Declares the value of the parameter that the server will use if none is provided, for example a "count" to control the number of results per page might default to 100 if not supplied by the client in the request. (Note: "default" has no meaning for required parameters.) See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. Unlike JSON Schema this value MUST conform to the defined [`type`](#parameterType) for this parameter. maximum | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.2. minimum | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.3. From 6e7cd89a2317bb78fb725ae4894dabf52598d839 Mon Sep 17 00:00:00 2001 From: "andrey.lukin" Date: Mon, 18 Apr 2022 11:41:31 +0300 Subject: [PATCH 3/6] Updated go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index bcd3d2e65..160d184a7 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/swaggo/swag +module github.com/AndreyAndreevich/swag go 1.18 From c972235c97598d7c20ed88088efae583adf6a511 Mon Sep 17 00:00:00 2001 From: "andrey.lukin" Date: Mon, 18 Apr 2022 11:45:12 +0300 Subject: [PATCH 4/6] Updated go.mod --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 160d184a7..bcd3d2e65 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/AndreyAndreevich/swag +module github.com/swaggo/swag go 1.18 diff --git a/go.sum b/go.sum index 8cf267760..b8e8e1c28 100644 --- a/go.sum +++ b/go.sum @@ -60,6 +60,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI= +github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= From 95dd05f13d569e0352ed251bc1ce13a8ed30fe3b Mon Sep 17 00:00:00 2001 From: "andrey.lukin" Date: Sun, 12 Jun 2022 20:37:35 +0400 Subject: [PATCH 5/6] Updated sum --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 65bcf10f1..f2c35bf10 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI= -github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= From c65a4a2258ccc834d96021cf2d71b4d500127118 Mon Sep 17 00:00:00 2001 From: "andrey.lukin" Date: Sun, 12 Jun 2022 20:42:57 +0400 Subject: [PATCH 6/6] Fixed review --- README.md | 2 +- cmd/swag/main.go | 40 ++++++++++++++++++++-------------------- field_parser.go | 2 +- field_parser_test.go | 6 +++--- gen/gen.go | 6 +++--- parser.go | 4 ++-- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 183a57596..065c93a76 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ OPTIONS: --codeExampleFiles value, --cef value Parse folder containing code example files to use for the x-codeSamples extension, disabled by default --parseInternal Parse go files in internal packages, disabled by default (default: false) --generatedTime Generate timestamp at the top of docs.go, disabled by default (default: false) - --defaultRequired Set validation required for all fields by default (default: false) + --requiredByDefault Set validation required for all fields by default (default: false) --parseDepth value Dependency parse depth (default: 100) --instanceName value This parameter can be used to name different swagger document instances. It is optional. --overridesFile value File to read global type overrides from. (default: ".swaggo") diff --git a/cmd/swag/main.go b/cmd/swag/main.go index 2190438ce..b6805c786 100644 --- a/cmd/swag/main.go +++ b/cmd/swag/main.go @@ -15,24 +15,24 @@ import ( ) const ( - searchDirFlag = "dir" - excludeFlag = "exclude" - generalInfoFlag = "generalInfo" - propertyStrategyFlag = "propertyStrategy" - outputFlag = "output" - outputTypesFlag = "outputTypes" - parseVendorFlag = "parseVendor" - parseDependencyFlag = "parseDependency" - markdownFilesFlag = "markdownFiles" - codeExampleFilesFlag = "codeExampleFiles" - parseInternalFlag = "parseInternal" - generatedTimeFlag = "generatedTime" - defaultRequiredFlag = "defaultRequired" - parseDepthFlag = "parseDepth" - instanceNameFlag = "instanceName" - overridesFileFlag = "overridesFile" - parseGoListFlag = "parseGoList" - quietFlag = "quiet" + searchDirFlag = "dir" + excludeFlag = "exclude" + generalInfoFlag = "generalInfo" + propertyStrategyFlag = "propertyStrategy" + outputFlag = "output" + outputTypesFlag = "outputTypes" + parseVendorFlag = "parseVendor" + parseDependencyFlag = "parseDependency" + markdownFilesFlag = "markdownFiles" + codeExampleFilesFlag = "codeExampleFiles" + parseInternalFlag = "parseInternal" + generatedTimeFlag = "generatedTime" + requiredByDefaultFlag = "requiredByDefault" + parseDepthFlag = "parseDepth" + instanceNameFlag = "instanceName" + overridesFileFlag = "overridesFile" + parseGoListFlag = "parseGoList" + quietFlag = "quiet" ) var initFlags = []cli.Flag{ @@ -110,7 +110,7 @@ var initFlags = []cli.Flag{ Usage: "Dependency parse depth", }, &cli.BoolFlag{ - Name: defaultRequiredFlag, + Name: requiredByDefaultFlag, Usage: "Set validation required for all fields by default", }, &cli.StringFlag{ @@ -160,7 +160,7 @@ func initAction(ctx *cli.Context) error { MarkdownFilesDir: ctx.String(markdownFilesFlag), ParseInternal: ctx.Bool(parseInternalFlag), GeneratedTime: ctx.Bool(generatedTimeFlag), - DefaultRequired: ctx.Bool(defaultRequiredFlag), + RequiredByDefault: ctx.Bool(requiredByDefaultFlag), CodeExampleFilesDir: ctx.String(codeExampleFilesFlag), ParseDepth: ctx.Int(parseDepthFlag), InstanceName: ctx.String(instanceNameFlag), diff --git a/field_parser.go b/field_parser.go index 3b5f9a23f..ce1ef4bf5 100644 --- a/field_parser.go +++ b/field_parser.go @@ -494,7 +494,7 @@ func (ps *tagBaseFieldParser) IsRequired() (bool, error) { } } - return ps.p.DefaultRequired, nil + return ps.p.RequiredByDefault, nil } func parseValidTags(validTag string, sf *structField) { diff --git a/field_parser_test.go b/field_parser_test.go index e83381ad8..a7487c03d 100644 --- a/field_parser_test.go +++ b/field_parser_test.go @@ -87,7 +87,7 @@ func TestDefaultFieldParser(t *testing.T) { got, err := newTagBaseFieldParser( &Parser{ - DefaultRequired: true, + RequiredByDefault: true, }, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test"`, @@ -102,7 +102,7 @@ func TestDefaultFieldParser(t *testing.T) { got, err := newTagBaseFieldParser( &Parser{ - DefaultRequired: true, + RequiredByDefault: true, }, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" binding:"optional"`, @@ -113,7 +113,7 @@ func TestDefaultFieldParser(t *testing.T) { got, err = newTagBaseFieldParser( &Parser{ - DefaultRequired: true, + RequiredByDefault: true, }, &ast.Field{Tag: &ast.BasicLit{ Value: `json:"test" validate:"optional"`, diff --git a/gen/gen.go b/gen/gen.go index 65c5d2631..b85290b4f 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -105,8 +105,8 @@ type Config struct { // GeneratedTime whether swag should generate the timestamp at the top of docs.go GeneratedTime bool - // DefaultRequired set validation required for all fields by default - DefaultRequired bool + // RequiredByDefault set validation required for all fields by default + RequiredByDefault bool // OverridesFile defines global type overrides. OverridesFile string @@ -162,7 +162,7 @@ func (g *Gen) Build(config *Config) error { p.ParseVendor = config.ParseVendor p.ParseDependency = config.ParseDependency p.ParseInternal = config.ParseInternal - p.DefaultRequired = config.DefaultRequired + p.RequiredByDefault = config.RequiredByDefault if err := p.ParseAPIMultiSearchDir(searchDirs, config.MainAPIFile, config.ParseDepth); err != nil { return err diff --git a/parser.go b/parser.go index f8fb9b1d7..ae0046579 100644 --- a/parser.go +++ b/parser.go @@ -130,8 +130,8 @@ type Parser struct { // Strict whether swag should error or warn when it detects cases which are most likely user errors Strict bool - // DefaultRequired set validation required for all fields by default - DefaultRequired bool + // RequiredByDefault set validation required for all fields by default + RequiredByDefault bool // structStack stores full names of the structures that were already parsed or are being parsed now structStack []*TypeSpecDef