diff --git a/parser.go b/parser.go index 7f0639edb..cf3a7a4b8 100644 --- a/parser.go +++ b/parser.go @@ -867,7 +867,7 @@ func (parser *Parser) parseAnonymousField(pkgName string, field *ast.Field) (map } func (parser *Parser) parseField(field *ast.Field) (*structField, error) { - prop := getPropertyName(field, parser) + prop := getPropertyName(field.Type, parser) if len(prop.ArrayType) == 0 { CheckSchemaType(prop.SchemaType) } else { diff --git a/property.go b/property.go index e845d5fc9..5d1b38558 100644 --- a/property.go +++ b/property.go @@ -66,77 +66,63 @@ func parseFieldSelectorExpr(astTypeSelectorExpr *ast.SelectorExpr, parser *Parse // getPropertyName returns the string value for the given field if it exists, otherwise it panics. // allowedValues: array, boolean, integer, null, number, object, string -func getPropertyName(field *ast.Field, parser *Parser) propertyName { - if astTypeSelectorExpr, ok := field.Type.(*ast.SelectorExpr); ok { +func getPropertyName(expr ast.Expr, parser *Parser) propertyName { + if astTypeSelectorExpr, ok := expr.(*ast.SelectorExpr); ok { return parseFieldSelectorExpr(astTypeSelectorExpr, parser, newProperty) } // check if it is a custom type - typeName := fmt.Sprintf("%v", field.Type) + typeName := fmt.Sprintf("%v", expr) if actualPrimitiveType, isCustomType := parser.CustomPrimitiveTypes[typeName]; isCustomType { return propertyName{SchemaType: actualPrimitiveType, ArrayType: actualPrimitiveType} } - if astTypeIdent, ok := field.Type.(*ast.Ident); ok { + if astTypeIdent, ok := expr.(*ast.Ident); ok { name := astTypeIdent.Name schemeType := TransToValidSchemeType(name) return propertyName{SchemaType: schemeType, ArrayType: schemeType} } - if ptr, ok := field.Type.(*ast.StarExpr); ok { - if astTypeSelectorExpr, ok := ptr.X.(*ast.SelectorExpr); ok { - return parseFieldSelectorExpr(astTypeSelectorExpr, parser, newProperty) - } - // TODO support custom pointer type? - if _, ok := ptr.X.(*ast.MapType); ok { // if map - //TODO support map - return propertyName{SchemaType: "object", ArrayType: "object"} - } - if _, ok := ptr.X.(*ast.StructType); ok { // if struct - return propertyName{SchemaType: "object", ArrayType: "object"} - } - if astTypeIdent, ok := ptr.X.(*ast.Ident); ok { - name := astTypeIdent.Name - schemeType := TransToValidSchemeType(name) - return propertyName{SchemaType: schemeType, ArrayType: schemeType} - } - if astTypeArray, ok := ptr.X.(*ast.ArrayType); ok { // if array - if astTypeArrayExpr, ok := astTypeArray.Elt.(*ast.SelectorExpr); ok { - return parseFieldSelectorExpr(astTypeArrayExpr, parser, newArrayProperty) - } - if astTypeArrayIdent, ok := astTypeArray.Elt.(*ast.Ident); ok { - name := TransToValidSchemeType(astTypeArrayIdent.Name) - return propertyName{SchemaType: "array", ArrayType: name} - } - } + + if ptr, ok := expr.(*ast.StarExpr); ok { + return getPropertyName(ptr.X, parser) } - if astTypeArray, ok := field.Type.(*ast.ArrayType); ok { // if array - if astTypeArrayExpr, ok := astTypeArray.Elt.(*ast.SelectorExpr); ok { - return parseFieldSelectorExpr(astTypeArrayExpr, parser, newArrayProperty) - } - if astTypeArrayExpr, ok := astTypeArray.Elt.(*ast.StarExpr); ok { - if astTypeArraySel, ok := astTypeArrayExpr.X.(*ast.SelectorExpr); ok { - return parseFieldSelectorExpr(astTypeArraySel, parser, newArrayProperty) - } - if astTypeArrayIdent, ok := astTypeArrayExpr.X.(*ast.Ident); ok { - name := TransToValidSchemeType(astTypeArrayIdent.Name) - return propertyName{SchemaType: "array", ArrayType: name} - } - } - itemTypeName := TransToValidSchemeType(fmt.Sprintf("%s", astTypeArray.Elt)) - if actualPrimitiveType, isCustomType := parser.CustomPrimitiveTypes[itemTypeName]; isCustomType { - itemTypeName = actualPrimitiveType - } - return propertyName{SchemaType: "array", ArrayType: itemTypeName} + + if astTypeArray, ok := expr.(*ast.ArrayType); ok { // if array + return getArrayPropertyName(astTypeArray, parser) } - if _, ok := field.Type.(*ast.MapType); ok { // if map + + if _, ok := expr.(*ast.MapType); ok { // if map //TODO: support map return propertyName{SchemaType: "object", ArrayType: "object"} } - if _, ok := field.Type.(*ast.StructType); ok { // if struct + + if _, ok := expr.(*ast.StructType); ok { // if struct return propertyName{SchemaType: "object", ArrayType: "object"} } - if _, ok := field.Type.(*ast.InterfaceType); ok { // if interface{} + + if _, ok := expr.(*ast.InterfaceType); ok { // if interface{} return propertyName{SchemaType: "object", ArrayType: "object"} } - panic("not supported" + fmt.Sprint(field.Type)) + + panic("not supported" + fmt.Sprint(expr)) +} + +func getArrayPropertyName(astTypeArray *ast.ArrayType, parser *Parser) propertyName { + if astTypeArrayExpr, ok := astTypeArray.Elt.(*ast.SelectorExpr); ok { + return parseFieldSelectorExpr(astTypeArrayExpr, parser, newArrayProperty) + } + if astTypeArrayExpr, ok := astTypeArray.Elt.(*ast.StarExpr); ok { + if astTypeArraySel, ok := astTypeArrayExpr.X.(*ast.SelectorExpr); ok { + return parseFieldSelectorExpr(astTypeArraySel, parser, newArrayProperty) + } + if astTypeArrayIdent, ok := astTypeArrayExpr.X.(*ast.Ident); ok { + name := TransToValidSchemeType(astTypeArrayIdent.Name) + return propertyName{SchemaType: "array", ArrayType: name} + } + } + itemTypeName := TransToValidSchemeType(fmt.Sprintf("%s", astTypeArray.Elt)) + if actualPrimitiveType, isCustomType := parser.CustomPrimitiveTypes[itemTypeName]; isCustomType { + itemTypeName = actualPrimitiveType + } + return propertyName{SchemaType: "array", ArrayType: itemTypeName} } diff --git a/property_test.go b/property_test.go index 7c1a670b4..24fe90252 100644 --- a/property_test.go +++ b/property_test.go @@ -8,18 +8,16 @@ import ( ) func TestGetPropertyNameSelectorExpr(t *testing.T) { - input := &ast.Field{ - Type: &ast.SelectorExpr{ - X: &ast.Ident{ - NamePos: 1136, - Name: "time", - Obj: (*ast.Object)(nil), - }, - Sel: &ast.Ident{ - NamePos: 1141, - Name: "Time", - Obj: (*ast.Object)(nil), - }, + input := &ast.SelectorExpr{ + X: &ast.Ident{ + NamePos: 1136, + Name: "time", + Obj: (*ast.Object)(nil), + }, + Sel: &ast.Ident{ + NamePos: 1141, + Name: "Time", + Obj: (*ast.Object)(nil), }, } expected := propertyName{ @@ -31,18 +29,16 @@ func TestGetPropertyNameSelectorExpr(t *testing.T) { } func TestGetPropertyNameIdentObjectId(t *testing.T) { - input := &ast.Field{ - Type: &ast.SelectorExpr{ - X: &ast.Ident{ - NamePos: 1136, - Name: "hoge", - Obj: (*ast.Object)(nil), - }, - Sel: &ast.Ident{ - NamePos: 1141, - Name: "ObjectId", - Obj: (*ast.Object)(nil), - }, + input := &ast.SelectorExpr{ + X: &ast.Ident{ + NamePos: 1136, + Name: "hoge", + Obj: (*ast.Object)(nil), + }, + Sel: &ast.Ident{ + NamePos: 1141, + Name: "ObjectId", + Obj: (*ast.Object)(nil), }, } expected := propertyName{ @@ -54,18 +50,16 @@ func TestGetPropertyNameIdentObjectId(t *testing.T) { } func TestGetPropertyNameIdentUUID(t *testing.T) { - input := &ast.Field{ - Type: &ast.SelectorExpr{ - X: &ast.Ident{ - NamePos: 1136, - Name: "hoge", - Obj: (*ast.Object)(nil), - }, - Sel: &ast.Ident{ - NamePos: 1141, - Name: "uuid", - Obj: (*ast.Object)(nil), - }, + input := &ast.SelectorExpr{ + X: &ast.Ident{ + NamePos: 1136, + Name: "hoge", + Obj: (*ast.Object)(nil), + }, + Sel: &ast.Ident{ + NamePos: 1141, + Name: "uuid", + Obj: (*ast.Object)(nil), }, } expected := propertyName{ @@ -77,18 +71,16 @@ func TestGetPropertyNameIdentUUID(t *testing.T) { } func TestGetPropertyNameIdentDecimal(t *testing.T) { - input := &ast.Field{ - Type: &ast.SelectorExpr{ - X: &ast.Ident{ - NamePos: 1136, - Name: "hoge", - Obj: (*ast.Object)(nil), - }, - Sel: &ast.Ident{ - NamePos: 1141, - Name: "Decimal", - Obj: (*ast.Object)(nil), - }, + input := &ast.SelectorExpr{ + X: &ast.Ident{ + NamePos: 1136, + Name: "hoge", + Obj: (*ast.Object)(nil), + }, + Sel: &ast.Ident{ + NamePos: 1141, + Name: "Decimal", + Obj: (*ast.Object)(nil), }, } expected := propertyName{ @@ -100,18 +92,16 @@ func TestGetPropertyNameIdentDecimal(t *testing.T) { } func TestGetPropertyNameIdentTime(t *testing.T) { - input := &ast.Field{ - Type: &ast.SelectorExpr{ - X: &ast.Ident{ - NamePos: 1136, - Name: "hoge", - Obj: (*ast.Object)(nil), - }, - Sel: &ast.Ident{ - NamePos: 1141, - Name: "Time", - Obj: (*ast.Object)(nil), - }, + input := &ast.SelectorExpr{ + X: &ast.Ident{ + NamePos: 1136, + Name: "hoge", + Obj: (*ast.Object)(nil), + }, + Sel: &ast.Ident{ + NamePos: 1141, + Name: "Time", + Obj: (*ast.Object)(nil), }, } expected := propertyName{ @@ -123,14 +113,12 @@ func TestGetPropertyNameIdentTime(t *testing.T) { } func TestGetPropertyNameStarExprIdent(t *testing.T) { - input := &ast.Field{ - Type: &ast.StarExpr{ - Star: 1026, - X: &ast.Ident{ - NamePos: 1027, - Name: "string", - Obj: (*ast.Object)(nil), - }, + input := &ast.StarExpr{ + Star: 1026, + X: &ast.Ident{ + NamePos: 1027, + Name: "string", + Obj: (*ast.Object)(nil), }, } expected := propertyName{ @@ -142,21 +130,19 @@ func TestGetPropertyNameStarExprIdent(t *testing.T) { } func TestGetPropertyNameStarExprMap(t *testing.T) { - input := &ast.Field{ - Type: &ast.StarExpr{ - Star: 1026, - X: &ast.MapType{ - Map: 1027, - Key: &ast.Ident{ - NamePos: 1034, - Name: "string", - Obj: (*ast.Object)(nil), - }, - Value: &ast.Ident{ - NamePos: 1041, - Name: "string", - Obj: (*ast.Object)(nil), - }, + input := &ast.StarExpr{ + Star: 1026, + X: &ast.MapType{ + Map: 1027, + Key: &ast.Ident{ + NamePos: 1034, + Name: "string", + Obj: (*ast.Object)(nil), + }, + Value: &ast.Ident{ + NamePos: 1041, + Name: "string", + Obj: (*ast.Object)(nil), }, }, } @@ -169,16 +155,14 @@ func TestGetPropertyNameStarExprMap(t *testing.T) { } func TestGetPropertyNameArrayStarExpr(t *testing.T) { - input := &ast.Field{ - Type: &ast.ArrayType{ - Lbrack: 465, - Len: nil, - Elt: &ast.StarExpr{ - X: &ast.Ident{ - NamePos: 467, - Name: "string", - Obj: (*ast.Object)(nil), - }, + input := &ast.ArrayType{ + Lbrack: 465, + Len: nil, + Elt: &ast.StarExpr{ + X: &ast.Ident{ + NamePos: 467, + Name: "string", + Obj: (*ast.Object)(nil), }, }, } @@ -191,22 +175,20 @@ func TestGetPropertyNameArrayStarExpr(t *testing.T) { } func TestGetPropertyNameArrayStarExprSelector(t *testing.T) { - input := &ast.Field{ - Type: &ast.ArrayType{ - Lbrack: 1111, - Len: nil, - Elt: &ast.StarExpr{ - X: &ast.SelectorExpr{ - X: &ast.Ident{ - NamePos: 1136, - Name: "hoge", - Obj: (*ast.Object)(nil), - }, - Sel: &ast.Ident{ - NamePos: 1141, - Name: "ObjectId", - Obj: (*ast.Object)(nil), - }, + input := &ast.ArrayType{ + Lbrack: 1111, + Len: nil, + Elt: &ast.StarExpr{ + X: &ast.SelectorExpr{ + X: &ast.Ident{ + NamePos: 1136, + Name: "hoge", + Obj: (*ast.Object)(nil), + }, + Sel: &ast.Ident{ + NamePos: 1141, + Name: "ObjectId", + Obj: (*ast.Object)(nil), }, }, }, @@ -220,14 +202,12 @@ func TestGetPropertyNameArrayStarExprSelector(t *testing.T) { } func TestGetPropertyNameMap(t *testing.T) { - input := &ast.Field{ - Type: &ast.MapType{ - Key: &ast.Ident{ - Name: "string", - }, - Value: &ast.Ident{ - Name: "string", - }, + input := &ast.MapType{ + Key: &ast.Ident{ + Name: "string", + }, + Value: &ast.Ident{ + Name: "string", }, } expected := propertyName{ @@ -239,9 +219,7 @@ func TestGetPropertyNameMap(t *testing.T) { } func TestGetPropertyNameStruct(t *testing.T) { - input := &ast.Field{ - Type: &ast.StructType{}, - } + input := &ast.StructType{} expected := propertyName{ "object", "object", @@ -251,9 +229,7 @@ func TestGetPropertyNameStruct(t *testing.T) { } func TestGetPropertyNameInterface(t *testing.T) { - input := &ast.Field{ - Type: &ast.InterfaceType{}, - } + input := &ast.InterfaceType{} expected := propertyName{ "object", "object",