From f251cf0bce23093b76044ed5bf7eb354437e6177 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 13:59:15 +0200 Subject: [PATCH 01/27] fix x-logo vendor extension --- parser.go | 10 +++++++++- parser_test.go | 7 ++++++- testdata/main.go | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index f1364cab0..f58bac752 100644 --- a/parser.go +++ b/parser.go @@ -102,6 +102,9 @@ func New(options ...func(*Parser)) *Parser { Contact: &spec.ContactInfo{}, License: &spec.License{}, }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{}, + }, }, Paths: &spec.Paths{ Paths: make(map[string]spec.PathItem), @@ -358,7 +361,12 @@ func (parser *Parser) ParseGeneralAPIInfo(mainAPIFile string) error { if err := json.Unmarshal([]byte(split[1]), &valueJSON); err != nil { return fmt.Errorf("annotation %s need a valid json value", attribute) } - parser.swagger.AddExtension(extensionName, valueJSON) + + if strings.Contains(extensionName, "logo") { + parser.swagger.Info.Extensions.Add(extensionName, valueJSON) + } else { + parser.swagger.AddExtension(extensionName, valueJSON) + } } } } diff --git a/parser_test.go b/parser_test.go index e3802782b..fc240c9ce 100644 --- a/parser_test.go +++ b/parser_test.go @@ -37,7 +37,12 @@ func TestParser_ParseGeneralApiInfo(t *testing.T) { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" }, - "version": "1.0" + "version": "1.0", + "x-logo": { + "altText": "Petstore logo", + "backgroundColor": "#FFFFFF", + "url": "https://redocly.github.io/redoc/petstore-logo.png" + } }, "host": "petstore.swagger.io", "basePath": "/v2", diff --git a/testdata/main.go b/testdata/main.go index f6ef4e21f..310645ad2 100644 --- a/testdata/main.go +++ b/testdata/main.go @@ -45,5 +45,6 @@ package main // @x-google-endpoints [{"name":"name.endpoints.environment.cloud.goog","allowCors":true}] // @x-google-marks "marks values" +// @x-logo {"url":"https://redocly.github.io/redoc/petstore-logo.png", "altText": "Petstore logo", "backgroundColor": "#FFFFFF"} func main() {} From 6fc3823b42b374f83a6f8aa48b4f5851375a134a Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:01:21 +0200 Subject: [PATCH 02/27] parse x-codeSamples from files --- cmd/swag/main.go | 28 +++++++---- gen/gen.go | 3 ++ operation.go | 73 +++++++++++++++++++++++++++-- operation_test.go | 28 +++++++++++ testdata/code_examples/api/api1.go | 13 +++++ testdata/code_examples/example.json | 4 ++ testdata/code_examples/main.go | 8 ++++ 7 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 testdata/code_examples/api/api1.go create mode 100644 testdata/code_examples/example.json create mode 100644 testdata/code_examples/main.go diff --git a/cmd/swag/main.go b/cmd/swag/main.go index 31403e012..fecadc46a 100644 --- a/cmd/swag/main.go +++ b/cmd/swag/main.go @@ -19,6 +19,7 @@ const ( parseVendorFlag = "parseVendor" parseDependencyFlag = "parseDependency" markdownFilesFlag = "markdownFiles" + codeExampleFilesFlag = "codeExampleFiles" parseInternal = "parseInternal" generatedTimeFlag = "generatedTime" ) @@ -66,6 +67,12 @@ var initFlags = []cli.Flag{ Value: "", Usage: "Parse folder containing markdown files to use as description, disabled by default", }, + &cli.StringFlag{ + Name: codeExampleFilesFlag, + Aliases: []string{"cef"}, + Value: "", + Usage: "Parse folder containing code example files to use for the x-codeSamples extension, disabled by default", + }, &cli.BoolFlag{ Name: "parseInternal", Usage: "Parse go files in internal packages, disabled by default", @@ -86,16 +93,17 @@ func initAction(c *cli.Context) error { } return gen.New().Build(&gen.Config{ - SearchDir: c.String(searchDirFlag), - Excludes: c.String(excludeFlag), - MainAPIFile: c.String(generalInfoFlag), - PropNamingStrategy: strategy, - OutputDir: c.String(outputFlag), - ParseVendor: c.Bool(parseVendorFlag), - ParseDependency: c.Bool(parseDependencyFlag), - MarkdownFilesDir: c.String(markdownFilesFlag), - ParseInternal: c.Bool(parseInternal), - GeneratedTime: c.Bool(generatedTimeFlag), + SearchDir: c.String(searchDirFlag), + Excludes: c.String(excludeFlag), + MainAPIFile: c.String(generalInfoFlag), + PropNamingStrategy: strategy, + OutputDir: c.String(outputFlag), + ParseVendor: c.Bool(parseVendorFlag), + ParseDependency: c.Bool(parseDependencyFlag), + MarkdownFilesDir: c.String(markdownFilesFlag), + ParseInternal: c.Bool(parseInternal), + GeneratedTime: c.Bool(generatedTimeFlag), + CodeExampleFilesDir: c.String(codeExampleFilesFlag), }) } diff --git a/gen/gen.go b/gen/gen.go index d51b42246..d2c373197 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -65,6 +65,9 @@ type Config struct { // GeneratedTime whether swag should generate the timestamp at the top of docs.go GeneratedTime bool + + // CodeExampleFilesDir used to find code example files, which can be used for x-codeSamples + CodeExampleFilesDir string } // Build builds swagger json file for given searchDir and mainAPIFile. Returns json diff --git a/operation.go b/operation.go index ba8b68546..8bb8fb131 100644 --- a/operation.go +++ b/operation.go @@ -6,8 +6,10 @@ import ( "go/ast" goparser "go/parser" "go/token" + "io/ioutil" "net/http" "os" + "path/filepath" "regexp" "sort" "strconv" @@ -24,7 +26,8 @@ type Operation struct { Path string spec.Operation - parser *Parser + parser *Parser + codeExampleFilesDir string } var mimeTypeAliases = map[string]string{ @@ -46,17 +49,34 @@ var mimeTypePattern = regexp.MustCompile("^[^/]+/[^/]+$") // NewOperation creates a new Operation with default properties. // map[int]Response -func NewOperation(parser *Parser) *Operation { +func NewOperation(parser *Parser, options ...func(*Operation)) *Operation { if parser == nil { parser = New() } - return &Operation{ + + result := &Operation{ parser: parser, HTTPMethod: "get", Operation: spec.Operation{ OperationProps: spec.OperationProps{}, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{}, + }, }, } + + for _, option := range options { + option(result) + } + + return result +} + +// SetCodeExampleFilesDirectory sets the directory to search for codeExamples +func SetCodeExampleFilesDirectory(directoryPath string) func(*Operation) { + return func(o *Operation) { + o.codeExampleFilesDir = directoryPath + } } // ParseComment parses comment for given comment string and returns error if error occurs. @@ -101,13 +121,30 @@ func (operation *Operation) ParseComment(comment string, astFile *ast.File) erro err = operation.ParseSecurityComment(lineRemainder) case "@deprecated": operation.Deprecate() + case "@x-codesamples": + err = operation.ParseCodeSample(attribute, commentLine, lineRemainder) default: err = operation.ParseMetadata(attribute, lowerAttribute, lineRemainder) } - return err } +// ParseDescriptionComment godoc +func (operation *Operation) ParseCodeSample(attribute, commentLine, lineRemainder string) error { + if lineRemainder == "file" { + data, err := getCodeExampleForSummary(operation.Summary, operation.codeExampleFilesDir) + if err != nil { + return err + } + + operation.Extensions["x-codeSamples"] = string(data) + return nil + } + + // Fallback into existing logic + return operation.ParseMetadata(attribute, strings.ToLower(attribute), lineRemainder) +} + // ParseDescriptionComment godoc func (operation *Operation) ParseDescriptionComment(lineRemainder string) { if operation.Description == "" { @@ -847,3 +884,31 @@ func createParameter(paramType, description, paramName, schemaType string, requi } return parameter } + +func getCodeExampleForSummary(summaryName string, dirPath string) ([]byte, error) { + filesInfos, err := ioutil.ReadDir(dirPath) + if err != nil { + return nil, err + } + + for _, fileInfo := range filesInfos { + if fileInfo.IsDir() { + continue + } + fileName := fileInfo.Name() + + if !strings.Contains(fileName, ".json") { + continue + } + + if strings.Contains(fileName, summaryName) { + fullPath := filepath.Join(dirPath, fileName) + commentInfo, err := ioutil.ReadFile(fullPath) + if err != nil { + return nil, fmt.Errorf("Failed to read code example file %s error: %s ", fullPath, err) + } + return commentInfo, nil + } + } + return nil, fmt.Errorf("Unable to find code example file for tag %s in the given directory", summaryName) +} diff --git a/operation_test.go b/operation_test.go index 184a9a25f..0fc6c4440 100644 --- a/operation_test.go +++ b/operation_test.go @@ -1479,3 +1479,31 @@ func TestParseExtentions(t *testing.T) { assert.Equal(t, expected, string(b)) } } + +func TestParseCodeSamples(t *testing.T) { + t.Run("Find sample by file", func(t *testing.T) { + comment := `@x-codeSamples file` + operation := NewOperation(nil, SetCodeExampleFilesDirectory("testdata/code_examples")) + operation.Summary = "example" + + err := operation.ParseComment(comment, nil) + assert.NoError(t, err, "no error should be thrown") + + b, _ := json.MarshalIndent(operation, "", " ") + + expected := `{ + "summary": "example", + "x-codeSamples": "{\n \"lang\": \"JavaScript\",\n \"source\": \"console.log('Hello World');\"\n}" +}` + assert.Equal(t, expected, string(b)) + }) + + t.Run("Example file not found", func(t *testing.T) { + comment := `@x-codeSamples file` + operation := NewOperation(nil, SetCodeExampleFilesDirectory("testdata/code_examples")) + operation.Summary = "exampel" + + err := operation.ParseComment(comment, nil) + assert.Error(t, err, "error was expected, as file does not exist") + }) +} diff --git a/testdata/code_examples/api/api1.go b/testdata/code_examples/api/api1.go new file mode 100644 index 000000000..4bbd5512f --- /dev/null +++ b/testdata/code_examples/api/api1.go @@ -0,0 +1,13 @@ +package api + +import ( + _ "github.com/swaggo/swag/testdata/conflict_name/model" + "net/http" +) + +// @Description Check if Health of service it's OK! +// @Router /health [get] +// @x-codeSamples file +func Get1(w http.ResponseWriter, r *http.Request) { + +} diff --git a/testdata/code_examples/example.json b/testdata/code_examples/example.json new file mode 100644 index 000000000..26e1cef56 --- /dev/null +++ b/testdata/code_examples/example.json @@ -0,0 +1,4 @@ +{ + "lang": "JavaScript", + "source": "console.log('Hello World');" +} \ No newline at end of file diff --git a/testdata/code_examples/main.go b/testdata/code_examples/main.go new file mode 100644 index 000000000..476d5baa2 --- /dev/null +++ b/testdata/code_examples/main.go @@ -0,0 +1,8 @@ +package main + +// @title Swag test +// @version 1.0 +// @description test for conflict name +func main() { + +} From d3b7a3fd45591d273fdaf7b9599380a302bdabe0 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:03:59 +0200 Subject: [PATCH 03/27] update swag init -h section in readme --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index af54694cc..87e020c69 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,18 @@ USAGE: swag init [command options] [arguments...] OPTIONS: - --generalInfo value, -g value Go file path in which 'swagger general API Info' is written (default: "main.go") - --dir value, -d value Directory you want to parse (default: "./") - --exclude value Exclude directoies and files, comma separated - --propertyStrategy value, -p value Property Naming Strategy like snakecase,camelcase,pascalcase (default: "camelcase") - --output value, -o value Output directory for all the generated files(swagger.json, swagger.yaml and doc.go) (default: "./docs") - --parseVendor Parse go files in 'vendor' folder, disabled by default - --parseDependency Parse go files in outside dependency folder, disabled by default - --parseInternal Parse go files in internal packages, disabled by default + --generalInfo value, -g value Go file path in which 'swagger general API Info' is written (default: "main.go") + --dir value, -d value Directory you want to parse (default: "./") + --exclude value exclude directories and files when searching, comma separated + --propertyStrategy value, -p value Property Naming Strategy like snakecase,camelcase,pascalcase (default: "camelcase") + --output value, -o value Output directory for all the generated files(swagger.json, swagger.yaml and doc.go) (default: "./docs") + --parseVendor Parse go files in 'vendor' folder, disabled by default (default: false) + --parseDependency Parse go files in outside dependency folder, disabled by default (default: false) + --markdownFiles value, --md value Parse folder containing markdown files to use as description, disabled by default + --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, true by default (default: false) + --help, -h show help (default: false) ``` ## Supported Web Frameworks From 52df97f66fe636b0360a66e439473ffdeeb5077d Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:08:08 +0200 Subject: [PATCH 04/27] add atreugo to list of supported web frameworks --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 87e020c69..8a5455cee 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ OPTIONS: - [net/http](https://github.com/swaggo/http-swagger) - [flamingo](https://github.com/i-love-flamingo/swagger) - [fiber](https://github.com/arsmn/fiber-swagger) +- [atreugo](https://github.com/Nerzal/atreugo-swagger) ## How to use it with Gin From 12fe7500eda340182a22c458186318c6237d1717 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:12:02 +0200 Subject: [PATCH 05/27] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8a5455cee..da7d3b5cb 100644 --- a/README.md +++ b/README.md @@ -379,6 +379,7 @@ When a short string in your documentation is insufficient, or you need images, c | header | Header in response that separated by spaces. `return code`,`{param type}`,`data type`,`comment` | | router | Path definition that separated by spaces. `path`,`[httpMethod]` | | x-name | The extension key, must be start by x- and take only json value. | +| x-codeSample | Optional Markdown usage. take `file` as parameter. | | deprecated | Mark endpoint as deprecated. | From 690e4ed516b1faf18e29ea63a3f6828e7f13ac74 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:25:16 +0200 Subject: [PATCH 06/27] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da7d3b5cb..29725205c 100644 --- a/README.md +++ b/README.md @@ -379,7 +379,7 @@ When a short string in your documentation is insufficient, or you need images, c | header | Header in response that separated by spaces. `return code`,`{param type}`,`data type`,`comment` | | router | Path definition that separated by spaces. `path`,`[httpMethod]` | | x-name | The extension key, must be start by x- and take only json value. | -| x-codeSample | Optional Markdown usage. take `file` as parameter. | +| x-codeSample | Optional Markdown usage. take `file` as parameter. This will then search for a file named like the summary in the given folder. | | deprecated | Mark endpoint as deprecated. | From b28be34b8fc266ec253069c133f4c7cd6fb95fdd Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 13:59:15 +0200 Subject: [PATCH 07/27] fix x-logo vendor extension --- parser.go | 10 +++++++++- parser_test.go | 7 ++++++- testdata/main.go | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index f1364cab0..f58bac752 100644 --- a/parser.go +++ b/parser.go @@ -102,6 +102,9 @@ func New(options ...func(*Parser)) *Parser { Contact: &spec.ContactInfo{}, License: &spec.License{}, }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{}, + }, }, Paths: &spec.Paths{ Paths: make(map[string]spec.PathItem), @@ -358,7 +361,12 @@ func (parser *Parser) ParseGeneralAPIInfo(mainAPIFile string) error { if err := json.Unmarshal([]byte(split[1]), &valueJSON); err != nil { return fmt.Errorf("annotation %s need a valid json value", attribute) } - parser.swagger.AddExtension(extensionName, valueJSON) + + if strings.Contains(extensionName, "logo") { + parser.swagger.Info.Extensions.Add(extensionName, valueJSON) + } else { + parser.swagger.AddExtension(extensionName, valueJSON) + } } } } diff --git a/parser_test.go b/parser_test.go index e3802782b..fc240c9ce 100644 --- a/parser_test.go +++ b/parser_test.go @@ -37,7 +37,12 @@ func TestParser_ParseGeneralApiInfo(t *testing.T) { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" }, - "version": "1.0" + "version": "1.0", + "x-logo": { + "altText": "Petstore logo", + "backgroundColor": "#FFFFFF", + "url": "https://redocly.github.io/redoc/petstore-logo.png" + } }, "host": "petstore.swagger.io", "basePath": "/v2", diff --git a/testdata/main.go b/testdata/main.go index f6ef4e21f..310645ad2 100644 --- a/testdata/main.go +++ b/testdata/main.go @@ -45,5 +45,6 @@ package main // @x-google-endpoints [{"name":"name.endpoints.environment.cloud.goog","allowCors":true}] // @x-google-marks "marks values" +// @x-logo {"url":"https://redocly.github.io/redoc/petstore-logo.png", "altText": "Petstore logo", "backgroundColor": "#FFFFFF"} func main() {} From 0fbd5fdfb6d08d1f6abc06295bbf0642f1b91dc3 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:01:21 +0200 Subject: [PATCH 08/27] parse x-codeSamples from files --- cmd/swag/main.go | 28 +++++++---- gen/gen.go | 3 ++ operation.go | 73 +++++++++++++++++++++++++++-- operation_test.go | 28 +++++++++++ testdata/code_examples/api/api1.go | 13 +++++ testdata/code_examples/example.json | 4 ++ testdata/code_examples/main.go | 8 ++++ 7 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 testdata/code_examples/api/api1.go create mode 100644 testdata/code_examples/example.json create mode 100644 testdata/code_examples/main.go diff --git a/cmd/swag/main.go b/cmd/swag/main.go index 31403e012..fecadc46a 100644 --- a/cmd/swag/main.go +++ b/cmd/swag/main.go @@ -19,6 +19,7 @@ const ( parseVendorFlag = "parseVendor" parseDependencyFlag = "parseDependency" markdownFilesFlag = "markdownFiles" + codeExampleFilesFlag = "codeExampleFiles" parseInternal = "parseInternal" generatedTimeFlag = "generatedTime" ) @@ -66,6 +67,12 @@ var initFlags = []cli.Flag{ Value: "", Usage: "Parse folder containing markdown files to use as description, disabled by default", }, + &cli.StringFlag{ + Name: codeExampleFilesFlag, + Aliases: []string{"cef"}, + Value: "", + Usage: "Parse folder containing code example files to use for the x-codeSamples extension, disabled by default", + }, &cli.BoolFlag{ Name: "parseInternal", Usage: "Parse go files in internal packages, disabled by default", @@ -86,16 +93,17 @@ func initAction(c *cli.Context) error { } return gen.New().Build(&gen.Config{ - SearchDir: c.String(searchDirFlag), - Excludes: c.String(excludeFlag), - MainAPIFile: c.String(generalInfoFlag), - PropNamingStrategy: strategy, - OutputDir: c.String(outputFlag), - ParseVendor: c.Bool(parseVendorFlag), - ParseDependency: c.Bool(parseDependencyFlag), - MarkdownFilesDir: c.String(markdownFilesFlag), - ParseInternal: c.Bool(parseInternal), - GeneratedTime: c.Bool(generatedTimeFlag), + SearchDir: c.String(searchDirFlag), + Excludes: c.String(excludeFlag), + MainAPIFile: c.String(generalInfoFlag), + PropNamingStrategy: strategy, + OutputDir: c.String(outputFlag), + ParseVendor: c.Bool(parseVendorFlag), + ParseDependency: c.Bool(parseDependencyFlag), + MarkdownFilesDir: c.String(markdownFilesFlag), + ParseInternal: c.Bool(parseInternal), + GeneratedTime: c.Bool(generatedTimeFlag), + CodeExampleFilesDir: c.String(codeExampleFilesFlag), }) } diff --git a/gen/gen.go b/gen/gen.go index d51b42246..d2c373197 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -65,6 +65,9 @@ type Config struct { // GeneratedTime whether swag should generate the timestamp at the top of docs.go GeneratedTime bool + + // CodeExampleFilesDir used to find code example files, which can be used for x-codeSamples + CodeExampleFilesDir string } // Build builds swagger json file for given searchDir and mainAPIFile. Returns json diff --git a/operation.go b/operation.go index e66cf480e..76aaa3e91 100644 --- a/operation.go +++ b/operation.go @@ -6,8 +6,10 @@ import ( "go/ast" goparser "go/parser" "go/token" + "io/ioutil" "net/http" "os" + "path/filepath" "regexp" "sort" "strconv" @@ -24,7 +26,8 @@ type Operation struct { Path string spec.Operation - parser *Parser + parser *Parser + codeExampleFilesDir string } var mimeTypeAliases = map[string]string{ @@ -46,17 +49,34 @@ var mimeTypePattern = regexp.MustCompile("^[^/]+/[^/]+$") // NewOperation creates a new Operation with default properties. // map[int]Response -func NewOperation(parser *Parser) *Operation { +func NewOperation(parser *Parser, options ...func(*Operation)) *Operation { if parser == nil { parser = New() } - return &Operation{ + + result := &Operation{ parser: parser, HTTPMethod: "get", Operation: spec.Operation{ OperationProps: spec.OperationProps{}, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{}, + }, }, } + + for _, option := range options { + option(result) + } + + return result +} + +// SetCodeExampleFilesDirectory sets the directory to search for codeExamples +func SetCodeExampleFilesDirectory(directoryPath string) func(*Operation) { + return func(o *Operation) { + o.codeExampleFilesDir = directoryPath + } } // ParseComment parses comment for given comment string and returns error if error occurs. @@ -101,13 +121,30 @@ func (operation *Operation) ParseComment(comment string, astFile *ast.File) erro err = operation.ParseSecurityComment(lineRemainder) case "@deprecated": operation.Deprecate() + case "@x-codesamples": + err = operation.ParseCodeSample(attribute, commentLine, lineRemainder) default: err = operation.ParseMetadata(attribute, lowerAttribute, lineRemainder) } - return err } +// ParseDescriptionComment godoc +func (operation *Operation) ParseCodeSample(attribute, commentLine, lineRemainder string) error { + if lineRemainder == "file" { + data, err := getCodeExampleForSummary(operation.Summary, operation.codeExampleFilesDir) + if err != nil { + return err + } + + operation.Extensions["x-codeSamples"] = string(data) + return nil + } + + // Fallback into existing logic + return operation.ParseMetadata(attribute, strings.ToLower(attribute), lineRemainder) +} + // ParseDescriptionComment godoc func (operation *Operation) ParseDescriptionComment(lineRemainder string) { if operation.Description == "" { @@ -847,3 +884,31 @@ func createParameter(paramType, description, paramName, schemaType string, requi } return parameter } + +func getCodeExampleForSummary(summaryName string, dirPath string) ([]byte, error) { + filesInfos, err := ioutil.ReadDir(dirPath) + if err != nil { + return nil, err + } + + for _, fileInfo := range filesInfos { + if fileInfo.IsDir() { + continue + } + fileName := fileInfo.Name() + + if !strings.Contains(fileName, ".json") { + continue + } + + if strings.Contains(fileName, summaryName) { + fullPath := filepath.Join(dirPath, fileName) + commentInfo, err := ioutil.ReadFile(fullPath) + if err != nil { + return nil, fmt.Errorf("Failed to read code example file %s error: %s ", fullPath, err) + } + return commentInfo, nil + } + } + return nil, fmt.Errorf("Unable to find code example file for tag %s in the given directory", summaryName) +} diff --git a/operation_test.go b/operation_test.go index da2c1f06d..804c3b7bf 100644 --- a/operation_test.go +++ b/operation_test.go @@ -1485,3 +1485,31 @@ func TestParseExtentions(t *testing.T) { assert.Equal(t, expected, string(b)) } } + +func TestParseCodeSamples(t *testing.T) { + t.Run("Find sample by file", func(t *testing.T) { + comment := `@x-codeSamples file` + operation := NewOperation(nil, SetCodeExampleFilesDirectory("testdata/code_examples")) + operation.Summary = "example" + + err := operation.ParseComment(comment, nil) + assert.NoError(t, err, "no error should be thrown") + + b, _ := json.MarshalIndent(operation, "", " ") + + expected := `{ + "summary": "example", + "x-codeSamples": "{\n \"lang\": \"JavaScript\",\n \"source\": \"console.log('Hello World');\"\n}" +}` + assert.Equal(t, expected, string(b)) + }) + + t.Run("Example file not found", func(t *testing.T) { + comment := `@x-codeSamples file` + operation := NewOperation(nil, SetCodeExampleFilesDirectory("testdata/code_examples")) + operation.Summary = "exampel" + + err := operation.ParseComment(comment, nil) + assert.Error(t, err, "error was expected, as file does not exist") + }) +} diff --git a/testdata/code_examples/api/api1.go b/testdata/code_examples/api/api1.go new file mode 100644 index 000000000..4bbd5512f --- /dev/null +++ b/testdata/code_examples/api/api1.go @@ -0,0 +1,13 @@ +package api + +import ( + _ "github.com/swaggo/swag/testdata/conflict_name/model" + "net/http" +) + +// @Description Check if Health of service it's OK! +// @Router /health [get] +// @x-codeSamples file +func Get1(w http.ResponseWriter, r *http.Request) { + +} diff --git a/testdata/code_examples/example.json b/testdata/code_examples/example.json new file mode 100644 index 000000000..26e1cef56 --- /dev/null +++ b/testdata/code_examples/example.json @@ -0,0 +1,4 @@ +{ + "lang": "JavaScript", + "source": "console.log('Hello World');" +} \ No newline at end of file diff --git a/testdata/code_examples/main.go b/testdata/code_examples/main.go new file mode 100644 index 000000000..476d5baa2 --- /dev/null +++ b/testdata/code_examples/main.go @@ -0,0 +1,8 @@ +package main + +// @title Swag test +// @version 1.0 +// @description test for conflict name +func main() { + +} From 277826ee7d1dec5fb505570fc9e6f64f9def1a88 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:03:59 +0200 Subject: [PATCH 09/27] update swag init -h section in readme --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 861c13deb..63c79e293 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,18 @@ USAGE: swag init [command options] [arguments...] OPTIONS: - --generalInfo value, -g value Go file path in which 'swagger general API Info' is written (default: "main.go") - --dir value, -d value Directory you want to parse (default: "./") - --exclude value Exclude directoies and files, comma separated - --propertyStrategy value, -p value Property Naming Strategy like snakecase,camelcase,pascalcase (default: "camelcase") - --output value, -o value Output directory for all the generated files(swagger.json, swagger.yaml and doc.go) (default: "./docs") - --parseVendor Parse go files in 'vendor' folder, disabled by default - --parseDependency Parse go files in outside dependency folder, disabled by default - --parseInternal Parse go files in internal packages, disabled by default + --generalInfo value, -g value Go file path in which 'swagger general API Info' is written (default: "main.go") + --dir value, -d value Directory you want to parse (default: "./") + --exclude value exclude directories and files when searching, comma separated + --propertyStrategy value, -p value Property Naming Strategy like snakecase,camelcase,pascalcase (default: "camelcase") + --output value, -o value Output directory for all the generated files(swagger.json, swagger.yaml and doc.go) (default: "./docs") + --parseVendor Parse go files in 'vendor' folder, disabled by default (default: false) + --parseDependency Parse go files in outside dependency folder, disabled by default (default: false) + --markdownFiles value, --md value Parse folder containing markdown files to use as description, disabled by default + --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, true by default (default: false) + --help, -h show help (default: false) ``` ## Supported Web Frameworks From b30fdae43ff8fb112b9d4e1b722e3deb9cde060e Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:08:08 +0200 Subject: [PATCH 10/27] add atreugo to list of supported web frameworks --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 63c79e293..590d7099d 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ OPTIONS: - [net/http](https://github.com/swaggo/http-swagger) - [flamingo](https://github.com/i-love-flamingo/swagger) - [fiber](https://github.com/arsmn/fiber-swagger) +- [atreugo](https://github.com/Nerzal/atreugo-swagger) ## How to use it with Gin From e4e06c695988b911ee468e14f398a63380d20206 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:12:02 +0200 Subject: [PATCH 11/27] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 590d7099d..26984f842 100644 --- a/README.md +++ b/README.md @@ -379,6 +379,7 @@ When a short string in your documentation is insufficient, or you need images, c | header | Header in response that separated by spaces. `return code`,`{param type}`,`data type`,`comment` | | router | Path definition that separated by spaces. `path`,`[httpMethod]` | | x-name | The extension key, must be start by x- and take only json value. | +| x-codeSample | Optional Markdown usage. take `file` as parameter. | | deprecated | Mark endpoint as deprecated. | From 7675b2ace6fed757ca5d16bef350d9ea09ba3ca0 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Fri, 24 Jul 2020 15:25:16 +0200 Subject: [PATCH 12/27] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26984f842..9bde68ead 100644 --- a/README.md +++ b/README.md @@ -379,7 +379,7 @@ When a short string in your documentation is insufficient, or you need images, c | header | Header in response that separated by spaces. `return code`,`{param type}`,`data type`,`comment` | | router | Path definition that separated by spaces. `path`,`[httpMethod]` | | x-name | The extension key, must be start by x- and take only json value. | -| x-codeSample | Optional Markdown usage. take `file` as parameter. | +| x-codeSample | Optional Markdown usage. take `file` as parameter. This will then search for a file named like the summary in the given folder. | | deprecated | Mark endpoint as deprecated. | From f08813c7f3ea499f0f92d0c530fceccd08cef3d7 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 4 Aug 2020 12:02:36 +0200 Subject: [PATCH 13/27] fix linter errors --- example/markdown/api/api.go | 6 +++--- operation.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/markdown/api/api.go b/example/markdown/api/api.go index 2bc900e27..db115f7d3 100644 --- a/example/markdown/api/api.go +++ b/example/markdown/api/api.go @@ -7,7 +7,7 @@ import ( // User example type User struct { - Id int64 + ID int64 Email string Password string } @@ -15,8 +15,8 @@ type User struct { // UsersCollection example type UsersCollection []User -// APIError example -type APIError struct { +// Error example +type Error struct { ErrorCode int ErrorMessage string CreatedAt time.Time diff --git a/operation.go b/operation.go index 76aaa3e91..a65c4abc0 100644 --- a/operation.go +++ b/operation.go @@ -129,7 +129,7 @@ func (operation *Operation) ParseComment(comment string, astFile *ast.File) erro return err } -// ParseDescriptionComment godoc +// ParseCodeSample godoc func (operation *Operation) ParseCodeSample(attribute, commentLine, lineRemainder string) error { if lineRemainder == "file" { data, err := getCodeExampleForSummary(operation.Summary, operation.codeExampleFilesDir) From cc26054f303c3792560fb06808acfa9e1584cdaf Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 4 Aug 2020 12:05:30 +0200 Subject: [PATCH 14/27] fix errors introduced by auto merge --- operation.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/operation.go b/operation.go index 330af0601..a65c4abc0 100644 --- a/operation.go +++ b/operation.go @@ -145,22 +145,6 @@ func (operation *Operation) ParseCodeSample(attribute, commentLine, lineRemainde return operation.ParseMetadata(attribute, strings.ToLower(attribute), lineRemainder) } -// ParseDescriptionComment godoc -func (operation *Operation) ParseCodeSample(attribute, commentLine, lineRemainder string) error { - if lineRemainder == "file" { - data, err := getCodeExampleForSummary(operation.Summary, operation.codeExampleFilesDir) - if err != nil { - return err - } - - operation.Extensions["x-codeSamples"] = string(data) - return nil - } - - // Fallback into existing logic - return operation.ParseMetadata(attribute, strings.ToLower(attribute), lineRemainder) -} - // ParseDescriptionComment godoc func (operation *Operation) ParseDescriptionComment(lineRemainder string) { if operation.Description == "" { From 45fd0d5ecd2472fdbcde3face644e2af859dfc8f Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 11 Aug 2020 12:36:41 +0200 Subject: [PATCH 15/27] go fmt'd --- cmd/swag/main.go | 2 +- gen/gen.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/swag/main.go b/cmd/swag/main.go index fab4fa020..bf055035f 100644 --- a/cmd/swag/main.go +++ b/cmd/swag/main.go @@ -110,7 +110,7 @@ func initAction(c *cli.Context) error { ParseInternal: c.Bool(parseInternal), GeneratedTime: c.Bool(generatedTimeFlag), CodeExampleFilesDir: c.String(codeExampleFilesFlag), - ParseDepth: c.Int(parseDepthFlag), + ParseDepth: c.Int(parseDepthFlag), }) } diff --git a/gen/gen.go b/gen/gen.go index aec1821e8..90f48dccf 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -68,7 +68,7 @@ type Config struct { // CodeExampleFilesDir used to find code example files, which can be used for x-codeSamples CodeExampleFilesDir string - + // ParseDepth dependency parse depth ParseDepth int } From 9480b7b8a257d823b8010d6b81726ad5ce64e444 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 11 Aug 2020 12:40:05 +0200 Subject: [PATCH 16/27] fix merge errors --- cmd/swag/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/swag/main.go b/cmd/swag/main.go index bf055035f..39ff9f81d 100644 --- a/cmd/swag/main.go +++ b/cmd/swag/main.go @@ -107,7 +107,7 @@ func initAction(c *cli.Context) error { ParseVendor: c.Bool(parseVendorFlag), ParseDependency: c.Bool(parseDependencyFlag), MarkdownFilesDir: c.String(markdownFilesFlag), - ParseInternal: c.Bool(parseInternal), + ParseInternal: c.Bool(parseInternalFlag), GeneratedTime: c.Bool(generatedTimeFlag), CodeExampleFilesDir: c.String(codeExampleFilesFlag), ParseDepth: c.Int(parseDepthFlag), From 280d30af491badcddd328f4ea6f66e1b4ac76a9d Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 12 Aug 2020 16:45:12 +0200 Subject: [PATCH 17/27] fix merge errors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9bde68ead..fbe1bc5d9 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,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, true by default (default: false) + --parseDepth Dependency parse depth (default: 100) --help, -h show help (default: false) ``` From 84a3d81c3e548cb6fff378fb09d05cb9fa18e4eb Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 12 Aug 2020 16:51:09 +0200 Subject: [PATCH 18/27] setCodeExampleDirectory when instanciating a NewOperation --- gen/gen.go | 3 ++- parser.go | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/gen/gen.go b/gen/gen.go index 90f48dccf..291517485 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -81,7 +81,8 @@ func (g *Gen) Build(config *Config) error { log.Println("Generate swagger docs....") p := swag.New(swag.SetMarkdownFileDirectory(config.MarkdownFilesDir), - swag.SetExcludedDirsAndFiles(config.Excludes)) + swag.SetExcludedDirsAndFiles(config.Excludes), + swag.SetCodeExamplesDirectory(config.CodeExampleFilesDir)) p.PropNamingStrategy = config.PropNamingStrategy p.ParseVendor = config.ParseVendor p.ParseDependency = config.ParseDependency diff --git a/parser.go b/parser.go index 30b627cfe..d6d0c4370 100644 --- a/parser.go +++ b/parser.go @@ -85,6 +85,9 @@ type Parser struct { // markdownFileDir holds the path to the folder, where markdown files are stored markdownFileDir string + // codeExampleFilesDir holds path to the folder, where code example files are stored + codeExampleFilesDir string + // collectionFormatInQuery set the default collectionFormat otherwise then 'csv' for array in query params collectionFormatInQuery string @@ -134,6 +137,13 @@ func SetMarkdownFileDirectory(directoryPath string) func(*Parser) { } } +// SetCodeExampleFilesDirectory sets the directory to search for code example files +func SetCodeExamplesDirectory(directoryPath string) func(*Parser) { + return func(p *Parser) { + p.codeExampleFilesDir = directoryPath + } +} + // SetExcludedDirsAndFiles sets directories and files to be excluded when searching func SetExcludedDirsAndFiles(excludes string) func(*Parser) { return func(p *Parser) { @@ -529,7 +539,7 @@ func (parser *Parser) ParseRouterAPIInfo(fileName string, astFile *ast.File) err switch astDeclaration := astDescription.(type) { case *ast.FuncDecl: if astDeclaration.Doc != nil && astDeclaration.Doc.List != nil { - operation := NewOperation(parser) //for per 'function' comment, create a new 'Operation' object + operation := NewOperation(parser, SetCodeExampleFilesDirectory(parser.codeExampleFilesDir)) //for per 'function' comment, create a new 'Operation' object for _, comment := range astDeclaration.Doc.List { if err := operation.ParseComment(comment.Text, astFile); err != nil { return fmt.Errorf("ParseComment error in file %s :%+v", fileName, err) From 0fc262a400a42158b9efab96e781dee1e2358535 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 12 Aug 2020 17:04:13 +0200 Subject: [PATCH 19/27] fix lint error --- parser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser.go b/parser.go index d6d0c4370..a26862956 100644 --- a/parser.go +++ b/parser.go @@ -137,7 +137,7 @@ func SetMarkdownFileDirectory(directoryPath string) func(*Parser) { } } -// SetCodeExampleFilesDirectory sets the directory to search for code example files +// SetCodeExamplesDirectory sets the directory to search for code example files func SetCodeExamplesDirectory(directoryPath string) func(*Parser) { return func(p *Parser) { p.codeExampleFilesDir = directoryPath From b7843ef661228f2599e0e86e321c6a0fdd5db36e Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Thu, 20 Aug 2020 17:45:42 +0200 Subject: [PATCH 20/27] fix linter warning and update dependencies --- example/celler/controller/examples.go | 1 - go.mod | 12 ++-- go.sum | 79 ++++++++++++++++++++------- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/example/celler/controller/examples.go b/example/celler/controller/examples.go index f31dae040..bb4dcc285 100644 --- a/example/celler/controller/examples.go +++ b/example/celler/controller/examples.go @@ -22,7 +22,6 @@ import ( // @Router /examples/ping [get] func (c *Controller) PingExample(ctx *gin.Context) { ctx.String(http.StatusOK, "pong") - return } // CalcExample godoc diff --git a/go.mod b/go.mod index de8aa6334..e308edb7a 100644 --- a/go.mod +++ b/go.mod @@ -4,16 +4,14 @@ require ( github.com/KyleBanks/depth v1.2.1 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 github.com/ghodss/yaml v1.0.0 - github.com/gin-gonic/gin v1.4.0 - github.com/go-openapi/jsonreference v0.19.3 - github.com/go-openapi/spec v0.19.4 + github.com/gin-gonic/gin v1.6.3 + github.com/go-openapi/spec v0.19.9 github.com/satori/go.uuid v1.2.0 - github.com/shopspring/decimal v1.2.0 - github.com/stretchr/testify v1.4.0 + github.com/stretchr/testify v1.6.1 github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 github.com/swaggo/gin-swagger v1.2.0 - github.com/urfave/cli/v2 v2.1.1 - golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 + github.com/urfave/cli/v2 v2.2.0 + golang.org/x/tools v0.0.0-20200820010801-b793a1359eac ) go 1.13 diff --git a/go.sum b/go.sum index caf9bc08c..23708f997 100644 --- a/go.sum +++ b/go.sum @@ -25,38 +25,51 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.0 h1:BqWKpV1dFd+AuiKlgtddwVIFQsuMpxfBDBHGfM2yNpk= github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg= +github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/spec v0.19.0 h1:A4SZ6IWh3lnjH0rG0Z5lkxazMGBECtrZcbyYQi+64k4= github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo= -github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.9 h1:9z9cbFuZJ7AcvOHKIY+f6Aevb4vObNDkTEyoMfO7rAc= +github.com/go-openapi/spec v0.19.9/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28= github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -66,8 +79,12 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -77,17 +94,16 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM= github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E= github.com/swaggo/gin-swagger v1.2.0 h1:YskZXEiv51fjOMTsXrOetAjrMDfFaXD79PEoQBOe2W0= @@ -96,15 +112,23 @@ github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+t github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.5-pre h1:jyJKFOSEbdOc2HODrf2qcCkYOdq7zzXqA9bhW5oV4fM= github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.5-pre h1:5YV9PsFAN+ndcCtTM7s60no7nY7eTG3LPtxhSwuxzCs= github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -112,28 +136,40 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190611141213-3f473d35a33a h1:+KkCgOMgnKSgenxTBoiwkMqTiouMIy/3o8RLdmSbGoY= golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae h1:xiXzMMEQdQcric9hXtr1QU98MHunKK7OTtsoU6bYWs4= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b h1:/mJ+GKieZA6hFDQGdWZrjj4AXPl5ylY+5HusG80roy0= golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 h1:QjA/9ArTfVTLfEhClDCG7SGrZkZixxWpwNCDiwJfh88= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac h1:DugppSxw0LSF8lcjaODPJZoDzq0ElTGskTst3ZaBkHI= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -144,3 +180,8 @@ gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/R gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 9f47519dc40525ea5fe3977ca29f756327458c2f Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Thu, 20 Aug 2020 17:51:14 +0200 Subject: [PATCH 21/27] add some error checks in tests --- go.mod | 1 + go.sum | 2 ++ parser_test.go | 19 ++++++++++++++----- schema.go | 3 ++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e308edb7a..b2f3f2b09 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/gin-gonic/gin v1.6.3 github.com/go-openapi/spec v0.19.9 github.com/satori/go.uuid v1.2.0 + github.com/shopspring/decimal v1.2.0 github.com/stretchr/testify v1.6.1 github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 github.com/swaggo/gin-swagger v1.2.0 diff --git a/go.sum b/go.sum index 23708f997..702b322dc 100644 --- a/go.sum +++ b/go.sum @@ -94,6 +94,8 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/parser_test.go b/parser_test.go index 167a97d55..ee5fbfcb0 100644 --- a/parser_test.go +++ b/parser_test.go @@ -268,8 +268,9 @@ func TestParser_ParseType(t *testing.T) { err := p.getAllGoFileInfo("testdata", searchDir) assert.NoError(t, err) - p.packages.ParseTypes() + _, err = p.packages.ParseTypes() + assert.NoError(t, err) assert.NotNil(t, p.packages.uniqueDefinitions["api.Pet3"]) assert.NotNil(t, p.packages.uniqueDefinitions["web.Pet"]) assert.NotNil(t, p.packages.uniqueDefinitions["web.Pet2"]) @@ -1690,7 +1691,8 @@ type ResponseWrapper struct { assert.NoError(t, err) parser.packages.CollectAstFile("rest", "rest/rest.go", f2) - parser.packages.ParseTypes() + _, err = parser.packages.ParseTypes() + assert.NoError(t, err) err = parser.ParseRouterAPIInfo("", f) assert.NoError(t, err) @@ -1875,7 +1877,8 @@ func Test(){ p := New() p.packages.CollectAstFile("api", "api/api.go", f) - p.packages.ParseTypes() + _, err = p.packages.ParseTypes() + assert.NoError(t, err) err = p.ParseRouterAPIInfo("", f) assert.NoError(t, err) @@ -2274,7 +2277,10 @@ func Fun() { p := New() p.packages.CollectAstFile("api", "api/api.go", f) - p.packages.ParseTypes() + + _, err = p.packages.ParseTypes() + assert.NoError(t, err) + err = p.ParseRouterAPIInfo("", f) assert.NoError(t, err) @@ -2307,7 +2313,9 @@ func Fun() { p := New() p.packages.CollectAstFile("api", "api/api.go", f) - p.packages.ParseTypes() + _, err = p.packages.ParseTypes() + assert.NoError(t, err) + err = p.ParseRouterAPIInfo("", f) assert.NoError(t, err) @@ -2319,6 +2327,7 @@ func Fun() { _, ok = p.swagger.Definitions["Student"] assert.True(t, ok) path, ok := p.swagger.Paths.Paths["/test"] + assert.True(t, ok) assert.Equal(t, "#/definitions/Teacher", path.Get.Parameters[0].Schema.Ref.String()) ref = path.Get.Responses.ResponsesProps.StatusCodeResponses[200].ResponseProps.Schema.Ref assert.Equal(t, "#/definitions/Teacher", ref.String()) diff --git a/schema.go b/schema.go index d43e322f0..0b8bdef37 100644 --- a/schema.go +++ b/schema.go @@ -3,9 +3,10 @@ package swag import ( "errors" "fmt" - "github.com/go-openapi/spec" "go/ast" "strings" + + "github.com/go-openapi/spec" ) const ( From a9260b1f26aa275b602ec04cf1c0e28bcddbb18a Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Mon, 24 Aug 2020 20:52:29 +0200 Subject: [PATCH 22/27] vendor extensions won't be saved with toLower names anymore --- operation.go | 3 ++- operation_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/operation.go b/operation.go index 3d6edae55..50e241ece 100644 --- a/operation.go +++ b/operation.go @@ -166,7 +166,8 @@ func (operation *Operation) ParseMetadata(attribute, lowerAttribute, lineRemaind if err := json.Unmarshal([]byte(lineRemainder), &valueJSON); err != nil { return fmt.Errorf("annotation %s need a valid json value", attribute) } - operation.Operation.AddExtension(attribute[1:], valueJSON) // Trim "@" at head + + operation.Extensions[attribute[1:]] = valueJSON // don't use the method provided by spec lib, cause it will call toLower() on attribute names, which is wrongy } return nil } diff --git a/operation_test.go b/operation_test.go index 804c3b7bf..912739856 100644 --- a/operation_test.go +++ b/operation_test.go @@ -1484,6 +1484,31 @@ func TestParseExtentions(t *testing.T) { b, _ := json.MarshalIndent(operation, "", " ") assert.Equal(t, expected, string(b)) } + + // Test x-tagGroups + { + comment := `@x-tagGroups [{"name":"Natural Persons","tags":["Person","PersonRisk","PersonDocuments"]}]` + operation := NewOperation(nil) + + err := operation.ParseComment(comment, nil) + assert.NoError(t, err) + + expected := `{ + "x-tagGroups": [ + { + "name": "Natural Persons", + "tags": [ + "Person", + "PersonRisk", + "PersonDocuments" + ] + } + ] +}` + + b, _ := json.MarshalIndent(operation, "", " ") + assert.Equal(t, expected, string(b)) + } } func TestParseCodeSamples(t *testing.T) { From e1ecc4d1f67ac22a3b7827a2f85f6c0a14e0c05d Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Mon, 24 Aug 2020 21:02:13 +0200 Subject: [PATCH 23/27] validate json when loading code samples from file --- operation.go | 8 +++++++- operation_test.go | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/operation.go b/operation.go index 50e241ece..b159e481b 100644 --- a/operation.go +++ b/operation.go @@ -137,7 +137,13 @@ func (operation *Operation) ParseCodeSample(attribute, commentLine, lineRemainde return err } - operation.Extensions["x-codeSamples"] = string(data) + var valueJSON interface{} + if err := json.Unmarshal(data, &valueJSON); err != nil { + return fmt.Errorf("annotation %s need a valid json value", attribute) + } + + operation.Extensions[attribute[1:]] = valueJSON // don't use the method provided by spec lib, cause it will call toLower() on attribute names, which is wrongy + return nil } diff --git a/operation_test.go b/operation_test.go index 912739856..e6105c2f1 100644 --- a/operation_test.go +++ b/operation_test.go @@ -1524,7 +1524,10 @@ func TestParseCodeSamples(t *testing.T) { expected := `{ "summary": "example", - "x-codeSamples": "{\n \"lang\": \"JavaScript\",\n \"source\": \"console.log('Hello World');\"\n}" + "x-codeSamples": { + "lang": "JavaScript", + "source": "console.log('Hello World');" + } }` assert.Equal(t, expected, string(b)) }) From 2118dec7bbd6ccac6996104c2b9705cf7d0e0d01 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Mon, 24 Aug 2020 21:07:47 +0200 Subject: [PATCH 24/27] remove unused method --- parser.go | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/parser.go b/parser.go index a26862956..c2eaffe72 100644 --- a/parser.go +++ b/parser.go @@ -833,34 +833,6 @@ type structField struct { extensions map[string]interface{} } -func (sf *structField) toStandardSchema() *spec.Schema { - required := make([]string, 0) - if sf.isRequired { - required = append(required, sf.name) - } - return &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{sf.schemaType}, - Description: sf.desc, - Format: sf.formatType, - Required: required, - Maximum: sf.maximum, - Minimum: sf.minimum, - MaxLength: sf.maxLength, - MinLength: sf.minLength, - Enum: sf.enums, - Default: sf.defaultValue, - }, - SwaggerSchemaProps: spec.SwaggerSchemaProps{ - Example: sf.exampleValue, - ReadOnly: sf.readOnly, - }, - VendorExtensible: spec.VendorExtensible{ - Extensions: sf.extensions, - }, - } -} - func (parser *Parser) parseStructField(file *ast.File, field *ast.Field) (map[string]spec.Schema, []string, error) { if field.Names == nil { typeName, err := getFieldType(field.Type) From 519d4845a952e5ab9cc88074003b1b8c5e41e850 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Mon, 24 Aug 2020 21:18:13 +0200 Subject: [PATCH 25/27] add negative test for markdown files to make codecov happy --- parser_test.go | 9 +++++++++ testdata/tags/main.go | 2 +- testdata/tags2/apes.md | 3 +++ testdata/tags2/api.md | 5 +++++ testdata/tags2/main.go | 12 ++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 testdata/tags2/apes.md create mode 100644 testdata/tags2/api.md create mode 100644 testdata/tags2/main.go diff --git a/parser_test.go b/parser_test.go index ee5fbfcb0..eae717aec 100644 --- a/parser_test.go +++ b/parser_test.go @@ -2154,6 +2154,15 @@ func TestApiParseTag(t *testing.T) { } } +func TestApiParseTag_NonExistendTag(t *testing.T) { + searchDir := "testdata/tags" + mainAPIFile := "main.go" + p := New(SetMarkdownFileDirectory(searchDir)) + p.PropNamingStrategy = PascalCase + err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth) + assert.Error(t, err) +} + func TestParseTagMarkdownDescription(t *testing.T) { searchDir := "testdata/tags" mainAPIFile := "main.go" diff --git a/testdata/tags/main.go b/testdata/tags/main.go index 381d545f9..d2d776058 100644 --- a/testdata/tags/main.go +++ b/testdata/tags/main.go @@ -7,6 +7,6 @@ package main // @tag.description Cats are the devil // @tag.docs.url https://google.de // @tag.docs.description google is super useful to find out that cats are evil! -// @tag.name apes +// @tag.name nonexistend // @tag.description.markdown func main() {} diff --git a/testdata/tags2/apes.md b/testdata/tags2/apes.md new file mode 100644 index 000000000..5e6434d9f --- /dev/null +++ b/testdata/tags2/apes.md @@ -0,0 +1,3 @@ +## Apes + +Apes are very cool! \ No newline at end of file diff --git a/testdata/tags2/api.md b/testdata/tags2/api.md new file mode 100644 index 000000000..94c5bda83 --- /dev/null +++ b/testdata/tags2/api.md @@ -0,0 +1,5 @@ +## CoolApi Title + +### Cool API SubTitle + +We love markdown! \ No newline at end of file diff --git a/testdata/tags2/main.go b/testdata/tags2/main.go new file mode 100644 index 000000000..381d545f9 --- /dev/null +++ b/testdata/tags2/main.go @@ -0,0 +1,12 @@ +package main + +// @description.markdown +// @tag.name dogs +// @tag.description Dogs are cool +// @tag.name cats +// @tag.description Cats are the devil +// @tag.docs.url https://google.de +// @tag.docs.description google is super useful to find out that cats are evil! +// @tag.name apes +// @tag.description.markdown +func main() {} From 69abb5ac62ca0266787d44ab9693d72ffc8795a1 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Sat, 29 Aug 2020 18:54:06 +0200 Subject: [PATCH 26/27] fix tests --- parser_test.go | 2 +- testdata/tags/cats.md | 3 +++ testdata/tags/main.go | 4 ++-- testdata/tags_nonexistend_tag/apes.md | 3 +++ testdata/tags_nonexistend_tag/api.md | 5 +++++ testdata/tags_nonexistend_tag/main.go | 11 +++++++++++ 6 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 testdata/tags/cats.md create mode 100644 testdata/tags_nonexistend_tag/apes.md create mode 100644 testdata/tags_nonexistend_tag/api.md create mode 100644 testdata/tags_nonexistend_tag/main.go diff --git a/parser_test.go b/parser_test.go index 3c7006baa..7f94e80d4 100644 --- a/parser_test.go +++ b/parser_test.go @@ -2155,7 +2155,7 @@ func TestApiParseTag(t *testing.T) { } func TestApiParseTag_NonExistendTag(t *testing.T) { - searchDir := "testdata/tags" + searchDir := "testdata/tags_nonexistend_tag" mainAPIFile := "main.go" p := New(SetMarkdownFileDirectory(searchDir)) p.PropNamingStrategy = PascalCase diff --git a/testdata/tags/cats.md b/testdata/tags/cats.md new file mode 100644 index 000000000..1fcfb09b0 --- /dev/null +++ b/testdata/tags/cats.md @@ -0,0 +1,3 @@ +## Cats + +Cats are also very cool! \ No newline at end of file diff --git a/testdata/tags/main.go b/testdata/tags/main.go index d2d776058..d1507ebe0 100644 --- a/testdata/tags/main.go +++ b/testdata/tags/main.go @@ -7,6 +7,6 @@ package main // @tag.description Cats are the devil // @tag.docs.url https://google.de // @tag.docs.description google is super useful to find out that cats are evil! -// @tag.name nonexistend -// @tag.description.markdown +// @tag.name apes +// @tag.description Apes are also cool func main() {} diff --git a/testdata/tags_nonexistend_tag/apes.md b/testdata/tags_nonexistend_tag/apes.md new file mode 100644 index 000000000..5e6434d9f --- /dev/null +++ b/testdata/tags_nonexistend_tag/apes.md @@ -0,0 +1,3 @@ +## Apes + +Apes are very cool! \ No newline at end of file diff --git a/testdata/tags_nonexistend_tag/api.md b/testdata/tags_nonexistend_tag/api.md new file mode 100644 index 000000000..94c5bda83 --- /dev/null +++ b/testdata/tags_nonexistend_tag/api.md @@ -0,0 +1,5 @@ +## CoolApi Title + +### Cool API SubTitle + +We love markdown! \ No newline at end of file diff --git a/testdata/tags_nonexistend_tag/main.go b/testdata/tags_nonexistend_tag/main.go new file mode 100644 index 000000000..5e8b6191b --- /dev/null +++ b/testdata/tags_nonexistend_tag/main.go @@ -0,0 +1,11 @@ +package main + +// @description.markdown +// @tag.name dogs +// @tag.description Dogs are cool +// @tag.name cats +// @tag.description Cats are the devil +// @tag.docs.url https://google.de +// @tag.docs.description google is super useful to find out that cats are evil! +// @tag.description.markdown +func main() {} From 0d45116ede1a9d1b49c459017e86be53ff4564d1 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Sun, 4 Oct 2020 19:52:54 +0200 Subject: [PATCH 27/27] go mod tidied --- go.mod | 1 - go.sum | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0bf8092ee..7007b4061 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/gin-gonic/gin v1.6.3 github.com/go-openapi/spec v0.19.9 github.com/gofrs/uuid v3.3.0+incompatible - github.com/shopspring/decimal v1.2.0 github.com/stretchr/testify v1.6.1 github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 github.com/swaggo/gin-swagger v1.2.0 diff --git a/go.sum b/go.sum index e53073260..8ce1d4877 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -92,8 +94,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=