feat: add swag tool

This commit is contained in:
Rogee
2024-12-25 16:18:41 +08:00
parent 2f2feb35c2
commit 77e36d5aaf
16 changed files with 76 additions and 54 deletions

12
.vscode/launch.json vendored
View File

@@ -15,6 +15,18 @@
"init", "init",
"/projects/tt", "/projects/tt",
] ]
},
{
"name": "Gen_Route",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}",
"args": [
"gen",
"route",
"/projects/learn/go-demo",
]
} }
] ]
} }

View File

@@ -136,8 +136,7 @@ func ParseFile(file string) []RouteDefinition {
} }
if strings.HasPrefix(line, "@Bind") { if strings.HasPrefix(line, "@Bind") {
//@Bind name query key() table() model() //@Bind name [uri|query|path|body|header|cookie] [key()] [table()] [model()]
//@Bind name query
bindParams = append(bindParams, parseRouteBind(line)) bindParams = append(bindParams, parseRouteBind(line))
} }
} }

View File

@@ -85,7 +85,7 @@ func (ps *tagBaseFieldParser) FieldNames() ([]string, error) {
return nil, nil return nil, nil
} }
} }
var names = make([]string, 0, len(ps.field.Names)) names := make([]string, 0, len(ps.field.Names))
for _, name := range ps.field.Names { for _, name := range ps.field.Names {
switch ps.p.PropNamingStrategy { switch ps.p.PropNamingStrategy {
case SnakeCase: case SnakeCase:
@@ -247,7 +247,7 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
} }
if IsRefSchema(schema) { if IsRefSchema(schema) {
var newSchema = spec.Schema{} newSchema := spec.Schema{}
err := ps.complementSchema(&newSchema, types) err := ps.complementSchema(&newSchema, types)
if err != nil { if err != nil {
return err return err
@@ -658,9 +658,11 @@ const (
// These code copy from // These code copy from
// https://github.com/go-playground/validator/blob/d4271985b44b735c6f76abc7a06532ee997f9476/baked_in.go#L207 // https://github.com/go-playground/validator/blob/d4271985b44b735c6f76abc7a06532ee997f9476/baked_in.go#L207
// ---. // ---.
var oneofValsCache = map[string][]string{} var (
var oneofValsCacheRWLock = sync.RWMutex{} oneofValsCache = map[string][]string{}
var splitParamsRegex = regexp.MustCompile(`'[^']*'|\S+`) oneofValsCacheRWLock = sync.RWMutex{}
splitParamsRegex = regexp.MustCompile(`'[^']*'|\S+`)
)
func parseOneOfParam2(param string) []string { func parseOneOfParam2(param string) []string {
oneofValsCacheRWLock.RLock() oneofValsCacheRWLock.RLock()

View File

@@ -680,7 +680,8 @@ func TestValidTags(t *testing.T) {
Names: []*ast.Ident{{Name: "Test"}}, Names: []*ast.Ident{{Name: "Test"}},
Tag: &ast.BasicLit{ Tag: &ast.BasicLit{
Value: `json:"test" validate:"required,oneof=one two"`, Value: `json:"test" validate:"required,oneof=one two"`,
}}, },
},
).ComplementSchema(&schema) ).ComplementSchema(&schema)
assert.NoError(t, err) assert.NoError(t, err)
assert.Empty(t, schema.Enum) assert.Empty(t, schema.Enum)
@@ -695,7 +696,8 @@ func TestValidTags(t *testing.T) {
Names: []*ast.Ident{{Name: "Test"}}, Names: []*ast.Ident{{Name: "Test"}},
Tag: &ast.BasicLit{ Tag: &ast.BasicLit{
Value: `form:"test[]"`, Value: `form:"test[]"`,
}}, },
},
).FieldNames() ).FieldNames()
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "test", filednames[0]) assert.Equal(t, "test", filednames[0])
@@ -706,7 +708,8 @@ func TestValidTags(t *testing.T) {
Names: []*ast.Ident{{Name: "Test"}}, Names: []*ast.Ident{{Name: "Test"}},
Tag: &ast.BasicLit{ Tag: &ast.BasicLit{
Value: `form:"test"`, Value: `form:"test"`,
}}, },
},
).FieldNames() ).FieldNames()
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "test", filednames[0]) assert.Equal(t, "test", filednames[0])

View File

@@ -57,7 +57,7 @@ func TestFormat_DefaultExcludes(t *testing.T) {
func TestFormat_ParseError(t *testing.T) { func TestFormat_ParseError(t *testing.T) {
fx := setup(t) fx := setup(t)
os.WriteFile(filepath.Join(fx.basedir, "parse_error.go"), []byte(`package main os.WriteFile(filepath.Join(fx.basedir, "parse_error.go"), []byte(`package main
func invalid() {`), 0644) func invalid() {`), 0o644)
assert.Error(t, New().Build(&Config{SearchDir: fx.basedir})) assert.Error(t, New().Build(&Config{SearchDir: fx.basedir}))
} }
@@ -69,9 +69,9 @@ func TestFormat_ReadError(t *testing.T) {
func TestFormat_WriteError(t *testing.T) { func TestFormat_WriteError(t *testing.T) {
fx := setup(t) fx := setup(t)
os.Chmod(fx.basedir, 0555) os.Chmod(fx.basedir, 0o555)
assert.Error(t, New().Build(&Config{SearchDir: fx.basedir})) assert.Error(t, New().Build(&Config{SearchDir: fx.basedir}))
os.Chmod(fx.basedir, 0755) os.Chmod(fx.basedir, 0o755)
} }
func TestFormat_InvalidSearchDir(t *testing.T) { func TestFormat_InvalidSearchDir(t *testing.T) {
@@ -91,10 +91,10 @@ func setup(t *testing.T) *fixture {
} }
for filename, contents := range testFiles { for filename, contents := range testFiles {
fullpath := filepath.Join(fx.basedir, filepath.Clean(filename)) fullpath := filepath.Join(fx.basedir, filepath.Clean(filename))
if err := os.MkdirAll(filepath.Dir(fullpath), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(fullpath), 0o755); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := os.WriteFile(fullpath, contents, 0644); err != nil { if err := os.WriteFile(fullpath, contents, 0o644); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }

View File

@@ -227,7 +227,6 @@ func Test_AlignAttribute(t *testing.T) {
` `
testFormat(t, "align.go", contents, want) testFormat(t, "align.go", contents, want)
} }
func Test_SyntaxError(t *testing.T) { func Test_SyntaxError(t *testing.T) {

View File

@@ -90,7 +90,7 @@ func (pkgDefs *PackagesDefinitions) getTypeFromGenericParam(genericParam string,
TypeSpec: &ast.TypeSpec{ TypeSpec: &ast.TypeSpec{
Name: ast.NewIdent(string(IgnoreNameOverridePrefix) + "map_" + parts[0] + "_" + typeSpecDef.TypeName()), Name: ast.NewIdent(string(IgnoreNameOverridePrefix) + "map_" + parts[0] + "_" + typeSpecDef.TypeName()),
Type: &ast.MapType{ Type: &ast.MapType{
Key: ast.NewIdent(parts[0]), //assume key is string or integer Key: ast.NewIdent(parts[0]), // assume key is string or integer
Value: expr, Value: expr,
}, },
}, },
@@ -123,7 +123,7 @@ func (pkgDefs *PackagesDefinitions) parametrizeGenericType(file *ast.File, origi
return nil return nil
} }
//generic[x,y any,z any] considered, TODO what if the type is not `any`, but a concrete one, such as `int32|int64` or an certain interface{} // generic[x,y any,z any] considered, TODO what if the type is not `any`, but a concrete one, such as `int32|int64` or an certain interface{}
var formals []formalParamType var formals []formalParamType
for _, field := range original.TypeSpec.TypeParams.List { for _, field := range original.TypeSpec.TypeParams.List {
for _, ident := range field.Names { for _, ident := range field.Names {
@@ -206,7 +206,7 @@ func (pkgDefs *PackagesDefinitions) parametrizeGenericType(file *ast.File, origi
// splitGenericsTypeName splits a generic struct name in his parts // splitGenericsTypeName splits a generic struct name in his parts
func splitGenericsTypeName(fullGenericForm string) (string, []string) { func splitGenericsTypeName(fullGenericForm string) (string, []string) {
//remove all spaces character // remove all spaces character
fullGenericForm = strings.Map(func(r rune) rune { fullGenericForm = strings.Map(func(r rune) rune {
if unicode.IsSpace(r) { if unicode.IsSpace(r) {
return -1 return -1
@@ -254,7 +254,7 @@ func (pkgDefs *PackagesDefinitions) getParametrizedType(genTypeSpec *genericType
} }
} }
//a primitive type name or a type name in current package // a primitive type name or a type name in current package
return &ast.Ident{Name: genTypeSpec.Name} return &ast.Ident{Name: genTypeSpec.Name}
} }

View File

@@ -164,7 +164,8 @@ func TestParametrizeStruct(t *testing.T) {
Name: &ast.Ident{Name: "Field"}, Name: &ast.Ident{Name: "Field"},
TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}}, TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}},
Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}}, Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}},
}}, "test.Field[string, []string]") },
}, "test.Field[string, []string]")
assert.NotNil(t, typeSpec) assert.NotNil(t, typeSpec)
assert.Equal(t, "$test.Field-string-array_string", typeSpec.Name()) assert.Equal(t, "$test.Field-string-array_string", typeSpec.Name())
assert.Equal(t, "test.Field-string-array_string", typeSpec.TypeName()) assert.Equal(t, "test.Field-string-array_string", typeSpec.TypeName())
@@ -177,7 +178,8 @@ func TestParametrizeStruct(t *testing.T) {
Name: &ast.Ident{Name: "Field"}, Name: &ast.Ident{Name: "Field"},
TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}}}, TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}}},
Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}}, Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}},
}}, "test.Field[string, string]") },
}, "test.Field[string, string]")
assert.Nil(t, typeSpec) assert.Nil(t, typeSpec)
// definition contains two type params, but only one is used // definition contains two type params, but only one is used
@@ -188,7 +190,8 @@ func TestParametrizeStruct(t *testing.T) {
Name: &ast.Ident{Name: "Field"}, Name: &ast.Ident{Name: "Field"},
TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}}, TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}},
Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}}, Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}},
}}, "test.Field[string]") },
}, "test.Field[string]")
assert.Nil(t, typeSpec) assert.Nil(t, typeSpec)
// name is not a valid type name // name is not a valid type name
@@ -199,7 +202,8 @@ func TestParametrizeStruct(t *testing.T) {
Name: &ast.Ident{Name: "Field"}, Name: &ast.Ident{Name: "Field"},
TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}}, TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}},
Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}}, Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}},
}}, "test.Field[string") },
}, "test.Field[string")
assert.Nil(t, typeSpec) assert.Nil(t, typeSpec)
typeSpec = pd.parametrizeGenericType( typeSpec = pd.parametrizeGenericType(
@@ -209,7 +213,8 @@ func TestParametrizeStruct(t *testing.T) {
Name: &ast.Ident{Name: "Field"}, Name: &ast.Ident{Name: "Field"},
TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}}, TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}},
Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}}, Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}},
}}, "test.Field[string, [string]") },
}, "test.Field[string, [string]")
assert.Nil(t, typeSpec) assert.Nil(t, typeSpec)
typeSpec = pd.parametrizeGenericType( typeSpec = pd.parametrizeGenericType(
@@ -219,7 +224,8 @@ func TestParametrizeStruct(t *testing.T) {
Name: &ast.Ident{Name: "Field"}, Name: &ast.Ident{Name: "Field"},
TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}}, TypeParams: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "T"}}}, {Names: []*ast.Ident{{Name: "T2"}}}}},
Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}}, Type: &ast.StructType{Struct: 100, Fields: &ast.FieldList{Opening: 101, Closing: 102}},
}}, "test.Field[string, ]string]") },
}, "test.Field[string, ]string]")
assert.Nil(t, typeSpec) assert.Nil(t, typeSpec)
} }

View File

@@ -598,7 +598,7 @@ func setCollectionFormatParam(param *spec.Parameter, name, schemaType, attr, com
return fmt.Errorf("%s is attribute to set to an array. comment=%s got=%s", name, commentLine, schemaType) return fmt.Errorf("%s is attribute to set to an array. comment=%s got=%s", name, commentLine, schemaType)
} }
func setDefault(param *spec.Parameter, schemaType string, value string) error { func setDefault(param *spec.Parameter, schemaType, value string) error {
val, err := defineType(schemaType, value) val, err := defineType(schemaType, value)
if err != nil { if err != nil {
return nil // Don't set a default value if it's not valid return nil // Don't set a default value if it's not valid
@@ -609,7 +609,7 @@ func setDefault(param *spec.Parameter, schemaType string, value string) error {
return nil return nil
} }
func setSchemaExample(param *spec.Parameter, schemaType string, value string) error { func setSchemaExample(param *spec.Parameter, schemaType, value string) error {
val, err := defineType(schemaType, value) val, err := defineType(schemaType, value)
if err != nil { if err != nil {
return nil // Don't set a example value if it's not valid return nil // Don't set a example value if it's not valid
@@ -630,7 +630,7 @@ func setSchemaExample(param *spec.Parameter, schemaType string, value string) er
return nil return nil
} }
func setExample(param *spec.Parameter, schemaType string, value string) error { func setExample(param *spec.Parameter, schemaType, value string) error {
val, err := defineType(schemaType, value) val, err := defineType(schemaType, value)
if err != nil { if err != nil {
return nil // Don't set a example value if it's not valid return nil // Don't set a example value if it's not valid
@@ -642,7 +642,7 @@ func setExample(param *spec.Parameter, schemaType string, value string) error {
} }
// defineType enum value define the type (object and array unsupported). // defineType enum value define the type (object and array unsupported).
func defineType(schemaType string, value string) (v interface{}, err error) { func defineType(schemaType, value string) (v interface{}, err error) {
schemaType = TransToValidSchemeType(schemaType) schemaType = TransToValidSchemeType(schemaType)
switch schemaType { switch schemaType {
@@ -1187,7 +1187,7 @@ func (operation *Operation) AddResponse(code int, response *spec.Response) {
} }
// createParameter returns swagger spec.Parameter for given paramType, description, paramName, schemaType, required. // createParameter returns swagger spec.Parameter for given paramType, description, paramName, schemaType, required.
func createParameter(paramType, description, paramName, objectType, schemaType string, format string, required bool, enums []interface{}, collectionFormat string) spec.Parameter { func createParameter(paramType, description, paramName, objectType, schemaType, format string, required bool, enums []interface{}, collectionFormat string) spec.Parameter {
// //five possible parameter types. query, path, body, header, form // //five possible parameter types. query, path, body, header, form
result := spec.Parameter{ result := spec.Parameter{
ParamProps: spec.ParamProps{ ParamProps: spec.ParamProps{
@@ -1223,7 +1223,7 @@ func createParameter(paramType, description, paramName, objectType, schemaType s
return result return result
} }
func getCodeExampleForSummary(summaryName string, dirPath string) ([]byte, error) { func getCodeExampleForSummary(summaryName, dirPath string) ([]byte, error) {
dirEntries, err := os.ReadDir(dirPath) dirEntries, err := os.ReadDir(dirPath)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -100,16 +100,16 @@ func (pkg *PackageDefinitions) evaluateConstValue(file *ast.File, iota int, expr
valueExpr.Value = strings.Replace(valueExpr.Value, "_", "", -1) valueExpr.Value = strings.Replace(valueExpr.Value, "_", "", -1)
} }
if len(valueExpr.Value) >= 2 && valueExpr.Value[0] == '0' { if len(valueExpr.Value) >= 2 && valueExpr.Value[0] == '0' {
var start, base = 2, 8 start, base := 2, 8
switch valueExpr.Value[1] { switch valueExpr.Value[1] {
case 'x', 'X': case 'x', 'X':
//hex // hex
base = 16 base = 16
case 'b', 'B': case 'b', 'B':
//binary // binary
base = 2 base = 2
default: default:
//octet // octet
start = 1 start = 1
} }
if x, err := strconv.ParseInt(valueExpr.Value[start:], base, 64); err == nil { if x, err := strconv.ParseInt(valueExpr.Value[start:], base, 64); err == nil {
@@ -121,7 +121,7 @@ func (pkg *PackageDefinitions) evaluateConstValue(file *ast.File, iota int, expr
} }
} }
//a basic literal integer is int type in default, or must have an explicit converting type in front // a basic literal integer is int type in default, or must have an explicit converting type in front
if x, err := strconv.ParseInt(valueExpr.Value, 10, 64); err == nil { if x, err := strconv.ParseInt(valueExpr.Value, 10, 64); err == nil {
return int(x), nil return int(x), nil
} else if x, err := strconv.ParseUint(valueExpr.Value, 10, 64); err == nil { } else if x, err := strconv.ParseUint(valueExpr.Value, 10, 64); err == nil {
@@ -153,7 +153,7 @@ func (pkg *PackageDefinitions) evaluateConstValue(file *ast.File, iota int, expr
case *ast.ParenExpr: case *ast.ParenExpr:
return pkg.evaluateConstValue(file, iota, valueExpr.X, globalEvaluator, recursiveStack) return pkg.evaluateConstValue(file, iota, valueExpr.X, globalEvaluator, recursiveStack)
case *ast.CallExpr: case *ast.CallExpr:
//data conversion // data conversion
if len(valueExpr.Args) != 1 { if len(valueExpr.Args) != 1 {
return nil, nil return nil, nil
} }

View File

@@ -272,7 +272,6 @@ func (pkgDefs *PackagesDefinitions) parseFunctionScopedTypesFromFile(astFile *as
} }
} }
} }
} }
} }
} }
@@ -420,7 +419,7 @@ func (pkgDefs *PackagesDefinitions) removeAllNotUniqueTypes() {
} }
} }
func (pkgDefs *PackagesDefinitions) findTypeSpec(pkgPath string, typeName string) *TypeSpecDef { func (pkgDefs *PackagesDefinitions) findTypeSpec(pkgPath, typeName string) *TypeSpecDef {
if pkgDefs.packages == nil { if pkgDefs.packages == nil {
return nil return nil
} }

View File

@@ -367,7 +367,7 @@ func ParseUsingGoList(enabled bool) func(parser *Parser) {
} }
// ParseAPI parses general api info for given searchDir and mainAPIFile. // ParseAPI parses general api info for given searchDir and mainAPIFile.
func (parser *Parser) ParseAPI(searchDir string, mainAPIFile string, parseDepth int) error { func (parser *Parser) ParseAPI(searchDir, mainAPIFile string, parseDepth int) error {
return parser.ParseAPIMultiSearchDir([]string{searchDir}, mainAPIFile, parseDepth) return parser.ParseAPIMultiSearchDir([]string{searchDir}, mainAPIFile, parseDepth)
} }
@@ -902,7 +902,7 @@ func isGeneralAPIComment(comments []string) bool {
return true return true
} }
func getMarkdownForTag(tagName string, dirPath string) ([]byte, error) { func getMarkdownForTag(tagName, dirPath string) ([]byte, error) {
if tagName == "" { if tagName == "" {
// this happens when parsing the @description.markdown attribute // this happens when parsing the @description.markdown attribute
// it will be called properly another time with tagName="api" // it will be called properly another time with tagName="api"
@@ -970,7 +970,6 @@ func getTagsFromComment(comment string) (tags []string) {
} }
} }
return return
} }
func (parser *Parser) matchTag(tag string) bool { func (parser *Parser) matchTag(tag string) bool {
@@ -1342,8 +1341,8 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef) (*Schema, error)
if len(typeSpecDef.Enums) > 0 { if len(typeSpecDef.Enums) > 0 {
var varnames []string var varnames []string
var enumComments = make(map[string]string) enumComments := make(map[string]string)
var enumDescriptions = make([]string, 0, len(typeSpecDef.Enums)) enumDescriptions := make([]string, 0, len(typeSpecDef.Enums))
for _, value := range typeSpecDef.Enums { for _, value := range typeSpecDef.Enums {
definition.Enum = append(definition.Enum, value.Value) definition.Enum = append(definition.Enum, value.Value)
varnames = append(varnames, value.key) varnames = append(varnames, value.key)
@@ -1409,8 +1408,7 @@ func (parser *Parser) fillDefinitionDescription(definition *spec.Schema, file *a
if typeSpec.Name != nil { if typeSpec.Name != nil {
typeName = typeSpec.Name.Name typeName = typeSpec.Name.Name
} }
definition.Description, err = definition.Description, err = parser.extractDeclarationDescription(typeName, typeSpec.Doc, typeSpec.Comment, generalDeclaration.Doc)
parser.extractDeclarationDescription(typeName, typeSpec.Doc, typeSpec.Comment, generalDeclaration.Doc)
if err != nil { if err != nil {
return return
} }

View File

@@ -3,6 +3,7 @@ package swag
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/go-openapi/spec" "github.com/go-openapi/spec"
) )
@@ -184,7 +185,7 @@ func IsComplexSchema(schema *spec.Schema) bool {
return true return true
} }
//Object included, such as Object or []Object // Object included, such as Object or []Object
for _, st := range schema.Type { for _, st := range schema.Type {
if st == OBJECT { if st == OBJECT {
return true return true
@@ -254,7 +255,7 @@ func BuildCustomSchema(types []string) (*spec.Schema, error) {
} }
// MergeSchema merge schemas // MergeSchema merge schemas
func MergeSchema(dst *spec.Schema, src *spec.Schema) *spec.Schema { func MergeSchema(dst, src *spec.Schema) *spec.Schema {
if len(src.Type) > 0 { if len(src.Type) > 0 {
dst.Type = src.Type dst.Type = src.Type
} }

View File

@@ -33,7 +33,7 @@ func (i *Spec) ReadDoc() string {
}, },
"escape": func(v interface{}) string { "escape": func(v interface{}) string {
// escape tabs // escape tabs
var str = strings.ReplaceAll(v.(string), "\t", "\\t") str := strings.ReplaceAll(v.(string), "\t", "\\t")
// replace " with \", and if that results in \\", replace that with \\\" // replace " with \", and if that results in \\", replace that with \\\"
str = strings.ReplaceAll(str, "\"", "\\\"") str = strings.ReplaceAll(str, "\"", "\\\"")

View File

@@ -106,7 +106,7 @@ func (t *TypeSpecDef) SetSchemaName() {
// AstFileInfo information of an ast.File. // AstFileInfo information of an ast.File.
type AstFileInfo struct { type AstFileInfo struct {
//FileSet the FileSet object which is used to parse this go source file // FileSet the FileSet object which is used to parse this go source file
FileSet *token.FileSet FileSet *token.FileSet
// File ast.File // File ast.File

View File

@@ -1,8 +1,9 @@
package swag package swag
import ( import (
"github.com/stretchr/testify/assert"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestFieldsByAnySpace(t *testing.T) { func TestFieldsByAnySpace(t *testing.T) {
@@ -15,14 +16,16 @@ func TestFieldsByAnySpace(t *testing.T) {
args args args args
want []string want []string
}{ }{
{"test1", {
"test1",
args{ args{
" aa bb cc dd ff", " aa bb cc dd ff",
2, 2,
}, },
[]string{"aa", "bb\tcc dd \t\tff"}, []string{"aa", "bb\tcc dd \t\tff"},
}, },
{"test2", {
"test2",
args{ args{
` aa "bb cc dd ff"`, ` aa "bb cc dd ff"`,
2, 2,