diff --git a/operation.go b/operation.go index 9f8388a58..c4a7d5727 100644 --- a/operation.go +++ b/operation.go @@ -231,7 +231,12 @@ func (operation *Operation) parseAndExtractionParamAttribute(commentLine, schema } for _, e := range enums { e = strings.TrimSpace(e) - param.Enum = append(param.Enum, defineType(schemaType, e)) + + value, err := defineType(schemaType, e) + if err != nil { + return err + } + param.Enum = append(param.Enum, value) } case "maxinum": attr, err := findAttr(re, commentLine) @@ -264,7 +269,11 @@ func (operation *Operation) parseAndExtractionParamAttribute(commentLine, schema if err != nil { break } - param.Default = defineType(schemaType, attr) + value, err := defineType(schemaType, attr) + if err != nil { + return nil + } + param.Default = value case "maxlength": attr, err := findAttr(re, commentLine) if err != nil { @@ -321,31 +330,31 @@ func findAttrList(re *regexp.Regexp, commentLine string) ([]string, error) { } // defineType enum value define the type (object and array unsupported) -func defineType(schemaType string, value string) interface{} { +func defineType(schemaType string, value string) (interface{}, error) { schemaType = TransToValidSchemeType(schemaType) switch schemaType { case "string": - return value + return value, nil case "number": v, err := strconv.ParseFloat(value, 64) if err != nil { - panic(fmt.Errorf("enum value %s can't convert to %s err: %s", value, schemaType, err)) + return nil, fmt.Errorf("enum value %s can't convert to %s err: %s", value, schemaType, err) } - return v + return v, nil case "integer": v, err := strconv.Atoi(value) if err != nil { - panic(fmt.Errorf("enum value %s can't convert to %s err: %s", value, schemaType, err)) + return nil, fmt.Errorf("enum value %s can't convert to %s err: %s", value, schemaType, err) } - return v + return v, nil case "boolean": v, err := strconv.ParseBool(value) if err != nil { - panic(fmt.Errorf("enum value %s can't convert to %s err: %s", value, schemaType, err)) + return nil, fmt.Errorf("enum value %s can't convert to %s err: %s", value, schemaType, err) } - return v + return v, nil default: - panic(fmt.Errorf("%s is unsupported type in enum value", schemaType)) + return nil, fmt.Errorf("%s is unsupported type in enum value", schemaType) } } diff --git a/parser.go b/parser.go index dc0d21b3b..5370ae030 100644 --- a/parser.go +++ b/parser.go @@ -949,7 +949,10 @@ func (parser *Parser) parseAnonymousField(pkgName string, field *ast.Field) (map } func (parser *Parser) parseField(field *ast.Field) (*structField, error) { - prop := getPropertyName(field.Type, parser) + prop, err := getPropertyName(field.Type, parser) + if err != nil { + return nil, err + } if len(prop.ArrayType) == 0 { CheckSchemaType(prop.SchemaType) } else { @@ -1058,11 +1061,19 @@ func (parser *Parser) parseField(field *ast.Field) (*structField, error) { } for _, e := range strings.Split(enumsTag, ",") { - structField.enums = append(structField.enums, defineType(enumType, e)) + value, err := defineType(enumType, e) + if err != nil { + return nil, err + } + structField.enums = append(structField.enums, value) } } if defaultTag := structTag.Get("default"); defaultTag != "" { - structField.defaultValue = defineType(structField.schemaType, defaultTag) + value, err := defineType(structField.schemaType, defaultTag) + if err != nil { + return nil, err + } + structField.defaultValue = value } if IsNumericType(structField.schemaType) || IsNumericType(structField.arrayType) { diff --git a/parser_test.go b/parser_test.go index 04f7ffdfb..7c2963acb 100644 --- a/parser_test.go +++ b/parser_test.go @@ -2149,9 +2149,7 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) p := New("") err = p.ParseRouterAPIInfo("", f) @@ -2167,11 +2165,11 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) + p := New("") - p.ParseRouterAPIInfo("", f) + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) ps := p.swagger.Paths.Paths @@ -2190,11 +2188,11 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) + p := New("") - p.ParseRouterAPIInfo("", f) + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) ps := p.swagger.Paths.Paths @@ -2213,11 +2211,11 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) p := New("") - p.ParseRouterAPIInfo("", f) + + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) ps := p.swagger.Paths.Paths @@ -2236,11 +2234,11 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) + p := New("") - p.ParseRouterAPIInfo("", f) + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) ps := p.swagger.Paths.Paths @@ -2259,11 +2257,11 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) + p := New("") - p.ParseRouterAPIInfo("", f) + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) ps := p.swagger.Paths.Paths @@ -2282,12 +2280,12 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) p := New("") - p.ParseRouterAPIInfo("", f) + err = p.ParseRouterAPIInfo("", f) + + assert.NoError(t, err) ps := p.swagger.Paths.Paths val, ok := ps["/api/{id}"] @@ -2305,11 +2303,11 @@ func Test(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) + p := New("") - p.ParseRouterAPIInfo("", f) + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) ps := p.swagger.Paths.Paths @@ -2336,11 +2334,11 @@ func Test3(){ } ` f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) - if err != nil { - panic(err) - } + assert.NoError(t, err) + p := New("") - p.ParseRouterAPIInfo("", f) + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) ps := p.swagger.Paths.Paths diff --git a/property.go b/property.go index a3fa5a3d3..bbc2a5982 100644 --- a/property.go +++ b/property.go @@ -62,23 +62,23 @@ func parseFieldSelectorExpr(astTypeSelectorExpr *ast.SelectorExpr, parser *Parse return propertyName{SchemaType: "string", ArrayType: "string"} } -// getPropertyName returns the string value for the given field if it exists, otherwise it panics. +// getPropertyName returns the string value for the given field if it exists // allowedValues: array, boolean, integer, null, number, object, string -func getPropertyName(expr ast.Expr, parser *Parser) propertyName { +func getPropertyName(expr ast.Expr, parser *Parser) (propertyName, error) { if astTypeSelectorExpr, ok := expr.(*ast.SelectorExpr); ok { - return parseFieldSelectorExpr(astTypeSelectorExpr, parser, newProperty) + return parseFieldSelectorExpr(astTypeSelectorExpr, parser, newProperty), nil } // check if it is a custom type typeName := fmt.Sprintf("%v", expr) if actualPrimitiveType, isCustomType := parser.CustomPrimitiveTypes[typeName]; isCustomType { - return propertyName{SchemaType: actualPrimitiveType, ArrayType: actualPrimitiveType} + return propertyName{SchemaType: actualPrimitiveType, ArrayType: actualPrimitiveType}, nil } if astTypeIdent, ok := expr.(*ast.Ident); ok { name := astTypeIdent.Name schemeType := TransToValidSchemeType(name) - return propertyName{SchemaType: schemeType, ArrayType: schemeType} + return propertyName{SchemaType: schemeType, ArrayType: schemeType}, nil } if ptr, ok := expr.(*ast.StarExpr); ok { @@ -86,22 +86,22 @@ func getPropertyName(expr ast.Expr, parser *Parser) propertyName { } if astTypeArray, ok := expr.(*ast.ArrayType); ok { // if array - return getArrayPropertyName(astTypeArray, parser) + return getArrayPropertyName(astTypeArray, parser), nil } if _, ok := expr.(*ast.MapType); ok { // if map - return propertyName{SchemaType: "object", ArrayType: "object"} + return propertyName{SchemaType: "object", ArrayType: "object"}, nil } if _, ok := expr.(*ast.StructType); ok { // if struct - return propertyName{SchemaType: "object", ArrayType: "object"} + return propertyName{SchemaType: "object", ArrayType: "object"}, nil } if _, ok := expr.(*ast.InterfaceType); ok { // if interface{} - return propertyName{SchemaType: "object", ArrayType: "object"} + return propertyName{SchemaType: "object", ArrayType: "object"}, nil } - panic("not supported" + fmt.Sprint(expr)) + return propertyName{}, errors.New("not supported" + fmt.Sprint(expr)) } func getArrayPropertyName(astTypeArray *ast.ArrayType, parser *Parser) propertyName { diff --git a/property_test.go b/property_test.go index 77f75dacc..dc5aed620 100644 --- a/property_test.go +++ b/property_test.go @@ -25,7 +25,9 @@ func TestGetPropertyNameSelectorExpr(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameIdentObjectId(t *testing.T) { @@ -46,7 +48,10 @@ func TestGetPropertyNameIdentObjectId(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameIdentUUID(t *testing.T) { @@ -67,7 +72,10 @@ func TestGetPropertyNameIdentUUID(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameIdentDecimal(t *testing.T) { @@ -88,7 +96,9 @@ func TestGetPropertyNameIdentDecimal(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameIdentTime(t *testing.T) { @@ -109,7 +119,10 @@ func TestGetPropertyNameIdentTime(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, nil)) + + propertyName, err := getPropertyName(input, nil) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameStarExprIdent(t *testing.T) { @@ -126,7 +139,10 @@ func TestGetPropertyNameStarExprIdent(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameStarExprMap(t *testing.T) { @@ -151,7 +167,10 @@ func TestGetPropertyNameStarExprMap(t *testing.T) { "object", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameArrayStarExpr(t *testing.T) { @@ -171,7 +190,9 @@ func TestGetPropertyNameArrayStarExpr(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameArrayStarExprSelector(t *testing.T) { @@ -198,7 +219,10 @@ func TestGetPropertyNameArrayStarExprSelector(t *testing.T) { "string", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameMap(t *testing.T) { @@ -215,7 +239,10 @@ func TestGetPropertyNameMap(t *testing.T) { "object", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameStruct(t *testing.T) { @@ -225,7 +252,10 @@ func TestGetPropertyNameStruct(t *testing.T) { "object", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestGetPropertyNameInterface(t *testing.T) { @@ -235,7 +265,10 @@ func TestGetPropertyNameInterface(t *testing.T) { "object", "", } - assert.Equal(t, expected, getPropertyName(input, New(""))) + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) } func TestParseTag(t *testing.T) { @@ -267,3 +300,4 @@ func TestParseTag(t *testing.T) { t.FailNow() } } + diff --git a/schema.go b/schema.go index 6b799aa78..2ebef1678 100644 --- a/schema.go +++ b/schema.go @@ -2,11 +2,12 @@ package swag import "fmt" -// CheckSchemaType begins panicking if typeName is not a name of primitive type -func CheckSchemaType(typeName string) { +// CheckSchemaType checks if typeName is not a name of primitive type +func CheckSchemaType(typeName string) error { if !IsPrimitiveType(typeName) { - panic(fmt.Errorf("%s is not basic types", typeName)) + return fmt.Errorf("%s is not basic types", typeName) } + return nil } // IsPrimitiveType determine whether the type name is a primitive type diff --git a/schema_test.go b/schema_test.go index 0c07ef3d1..bee29d165 100644 --- a/schema_test.go +++ b/schema_test.go @@ -7,28 +7,14 @@ import ( ) func TestValidDataType(t *testing.T) { - assert.NotPanics(t, func() { - CheckSchemaType("string") - }) - assert.NotPanics(t, func() { - CheckSchemaType("number") - }) - assert.NotPanics(t, func() { - CheckSchemaType("integer") - }) - assert.NotPanics(t, func() { - CheckSchemaType("boolean") - }) - assert.NotPanics(t, func() { - CheckSchemaType("array") - }) - assert.NotPanics(t, func() { - CheckSchemaType("object") - }) + assert.NoError(t, CheckSchemaType("string")) + assert.NoError(t, CheckSchemaType("number")) + assert.NoError(t, CheckSchemaType("integer")) + assert.NoError(t, CheckSchemaType("boolean")) + assert.NoError(t, CheckSchemaType("array")) + assert.NoError(t, CheckSchemaType("object")) - assert.Panics(t, func() { - CheckSchemaType("oops") - }) + assert.Error(t, CheckSchemaType("oops")) } func TestTransToValidSchemeType(t *testing.T) { @@ -40,7 +26,5 @@ func TestTransToValidSchemeType(t *testing.T) { assert.Equal(t, TransToValidSchemeType("string"), "string") // should accept any type, due to user defined types - assert.NotPanics(t, func() { - TransToValidSchemeType("oops") - }) + TransToValidSchemeType("oops") }