Skip to content

Commit

Permalink
improve code quality (#1047)
Browse files Browse the repository at this point in the history
  • Loading branch information
ubogdan committed Nov 10, 2021
1 parent 5237c6d commit 9b23c9e
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 210 deletions.
4 changes: 2 additions & 2 deletions cmd/swag/main.go
Expand Up @@ -46,8 +46,8 @@ var initFlags = []cli.Flag{
&cli.StringFlag{
Name: propertyStrategyFlag,
Aliases: []string{"p"},
Value: "camelcase",
Usage: "Property Naming Strategy like snakecase,camelcase,pascalcase",
Value: swag.CamelCase,
Usage: "Property Naming Strategy like " + swag.SnakeCase + "," + swag.CamelCase + "," + swag.PascalCase,
},
&cli.StringFlag{
Name: outputFlag,
Expand Down
63 changes: 31 additions & 32 deletions field_parser.go
Expand Up @@ -130,19 +130,19 @@ type structField struct {
schemaType string
arrayType string
formatType string
readOnly bool
exampleValue interface{}
maximum *float64
minimum *float64
multipleOf *float64
maxLength *int64
minLength *int64
maxItems *int64
minItems *int64
unique bool
enums []interface{}
exampleValue interface{}
defaultValue interface{}
extensions map[string]interface{}
enums []interface{}
readOnly bool
unique bool
}

func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
Expand All @@ -163,7 +163,10 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {

structField := &structField{
schemaType: types[0],
formatType: ps.tag.Get("format"),
readOnly: ps.tag.Get("readonly") == "true",
}

if len(types) > 1 && (types[0] == ARRAY || types[0] == OBJECT) {
structField.arrayType = types[1]
}
Expand All @@ -189,14 +192,12 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
structField.exampleValue = example
}
}
formatTag := ps.tag.Get("format")
if formatTag != "" {
structField.formatType = formatTag
}

bindingTag := ps.tag.Get("binding")
if bindingTag != "" {
ps.parseValidTags(bindingTag, structField)
}

validateTag := ps.tag.Get("validate")
if validateTag != "" {
ps.parseValidTags(validateTag, structField)
Expand All @@ -211,13 +212,14 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
structField.extensions[parts[0]] = parts[1]
} else {
if len(parts[0]) > 0 && string(parts[0][0]) == "!" {
structField.extensions[string(parts[0][1:])] = false
structField.extensions[parts[0][1:]] = false
} else {
structField.extensions[parts[0]] = true
}
}
}
}

enumsTag := ps.tag.Get("enums")
if enumsTag != "" {
enumType := structField.schemaType
Expand All @@ -233,6 +235,7 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
structField.enums = append(structField.enums, value)
}
}

defaultTag := ps.tag.Get("default")
if defaultTag != "" {
value, err := defineType(structField.schemaType, defaultTag)
Expand Down Expand Up @@ -267,6 +270,7 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
structField.multipleOf = multipleOf
}
}

if structField.schemaType == STRING || structField.arrayType == STRING {
maxLength, err := getIntTag(ps.tag, "maxLength")
if err != nil {
Expand All @@ -284,10 +288,6 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
structField.minLength = minLength
}
}
readOnly := ps.tag.Get("readonly")
if readOnly != "" {
structField.readOnly = readOnly == "true"
}

// perform this after setting everything else (min, max, etc...)
if strings.Contains(jsonTag, ",string") { // @encoding/json: "It applies only to fields of string, floating point, integer, or boolean types."
Expand Down Expand Up @@ -410,13 +410,14 @@ func (ps *tagBaseFieldParser) parseValidTags(validTag string, sf *structField) {
valKey string
valValue string
)
vals := strings.Split(val, "=")
if len(vals) == 1 {
valKey = vals[0]
} else if len(vals) == 2 {
valKey = vals[0]
valValue = vals[1]
} else {
kv := strings.Split(val, "=")
switch len(kv) {
case 1:
valKey = kv[0]
case 2:
valKey = kv[0]
valValue = kv[1]
default:
continue
}
valValue = strings.Replace(strings.Replace(valValue, utf8HexComma, ",", -1), utf8Pipe, "|", -1)
Expand Down Expand Up @@ -464,29 +465,27 @@ func (ps *tagBaseFieldParser) parseValidTags(validTag string, sf *structField) {
}

func checkSchemaTypeAndSetValue(sf *structField, value float64, isMax bool) {
typeSchema := sf.schemaType

if IsNumericType(typeSchema) {
switch sf.schemaType {
case INTEGER, NUMBER:
if isMax {
sf.maximum = &value
} else {
sf.minimum = &value
}
} else if typeSchema == STRING {
case STRING:
intValue := int64(value)
if isMax {
sf.maxLength = &intValue
} else {
sf.minLength = &intValue
}
} else if typeSchema == ARRAY {
case ARRAY:
intValue := int64(value)
if isMax {
sf.maxItems = &intValue
} else {
sf.minItems = &intValue
}
// ps. for simplicity, the max\min value of the array elements is ignored
}
}

Expand All @@ -504,18 +503,18 @@ var splitParamsRegex = regexp.MustCompile(`'[^']*'|\S+`)

func parseOneOfParam2(s string) []string {
oneofValsCacheRWLock.RLock()
vals, ok := oneofValsCache[s]
values, ok := oneofValsCache[s]
oneofValsCacheRWLock.RUnlock()
if !ok {
oneofValsCacheRWLock.Lock()
vals = splitParamsRegex.FindAllString(s, -1)
for i := 0; i < len(vals); i++ {
vals[i] = strings.Replace(vals[i], "'", "", -1)
values = splitParamsRegex.FindAllString(s, -1)
for i := 0; i < len(values); i++ {
values[i] = strings.Replace(values[i], "'", "", -1)
}
oneofValsCache[s] = vals
oneofValsCache[s] = values
oneofValsCacheRWLock.Unlock()
}
return vals
return values
}

// ---
12 changes: 11 additions & 1 deletion field_parser_test.go
Expand Up @@ -279,6 +279,16 @@ func TestDefaultFieldParser(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, true, schema.ReadOnly)
})

t.Run("Invalid tag", func(t *testing.T) {
t.Parallel()

err := newTagBaseFieldParser(
&Parser{},
&ast.Field{Names: []*ast.Ident{{Name: "BasicStruct"}}},
).ComplementSchema(nil)
assert.Error(t, err)
})
}

func TestValidTags(t *testing.T) {
Expand Down Expand Up @@ -441,8 +451,8 @@ func TestValidTags(t *testing.T) {
).ComplementSchema(&schema)
assert.NoError(t, err)
assert.Equal(t, true, schema.UniqueItems)

})

t.Run("All tag", func(t *testing.T) {
t.Parallel()
schema := spec.Schema{}
Expand Down
32 changes: 16 additions & 16 deletions gen/gen.go
Expand Up @@ -48,9 +48,22 @@ type Config struct {
// MainAPIFile the Go file path in which 'swagger general API Info' is written
MainAPIFile string

// PropNamingStrategy represents property naming strategy like snakecase,camelcase,pascalcase
// PropNamingStrategy represents property naming strategy like snake case,camel case,pascal case
PropNamingStrategy string

// MarkdownFilesDir used to find markdown files, which can be used for tag descriptions
MarkdownFilesDir string

// CodeExampleFilesDir used to find code example files, which can be used for x-codeSamples
CodeExampleFilesDir string

// InstanceName is used to get distinct names for different swagger documents in the
// same project. The default value is "swagger".
InstanceName string

// ParseDepth dependency parse depth
ParseDepth int

// ParseVendor whether swag should be parse vendor folder
ParseVendor bool

Expand All @@ -63,21 +76,8 @@ type Config struct {
// Strict whether swag should error or warn when it detects cases which are most likely user errors
Strict bool

// MarkdownFilesDir used to find markdownfiles, which can be used for tag descriptions
MarkdownFilesDir string

// 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

// ParseDepth dependency parse depth
ParseDepth int

// InstanceName is used to get distinct names for different swagger documents in the
// same project. The default value is "swagger".
InstanceName string
}

// Build builds swagger json file for given searchDir and mainAPIFile. Returns json
Expand Down Expand Up @@ -232,16 +232,16 @@ func (g *Gen) writeGoDoc(packageName string, output io.Writer, swagger *spec.Swa
buffer := &bytes.Buffer{}
err = generator.Execute(buffer, struct {
Timestamp time.Time
GeneratedTime bool
Doc string
Host string
PackageName string
BasePath string
Schemes []string
Title string
Description string
Version string
InstanceName string
Schemes []string
GeneratedTime bool
}{
Timestamp: time.Now(),
GeneratedTime: config.GeneratedTime,
Expand Down

0 comments on commit 9b23c9e

Please sign in to comment.