Skip to content

Commit

Permalink
fix: Generic Fields does not handle Arrays in the .swaggo file (#1322)
Browse files Browse the repository at this point in the history
* fix: Generic Fields does not handle Arrays in the .swaggo file

- Detect array type and transform schema into spec.ArrayProperty if needed

fixes #1318, #1320

* refactor: use existing code to parse new type definition

- use methods from Operation to get schema
- methods parseObjectSchema and parseCombinedObjectSchema disconnected from struct
  • Loading branch information
FabianMartin committed Sep 15, 2022
1 parent bc895ed commit b8f53da
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 16 deletions.
5 changes: 3 additions & 2 deletions generics_test.go
Expand Up @@ -31,8 +31,9 @@ func TestParseGenericsBasic(t *testing.T) {

p := New()
p.Overrides = map[string]string{
"types.Field[string]": "string",
"types.DoubleField[string,string]": "string",
"types.Field[string]": "string",
"types.DoubleField[string,string]": "[]string",
"types.TrippleField[string,string]": "[][]string",
}

err = p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth)
Expand Down
20 changes: 12 additions & 8 deletions operation.go
Expand Up @@ -824,6 +824,10 @@ var responsePattern = regexp.MustCompile(`^([\w,]+)\s+([\w{}]+)\s+([\w\-.\\{}=,\
var combinedPattern = regexp.MustCompile(`^([\w\-./\[\]]+){(.*)}$`)

func (operation *Operation) parseObjectSchema(refType string, astFile *ast.File) (*spec.Schema, error) {
return parseObjectSchema(operation.parser, refType, astFile)
}

func parseObjectSchema(parser *Parser, refType string, astFile *ast.File) (*spec.Schema, error) {
switch {
case refType == NIL:
return nil, nil
Expand All @@ -838,7 +842,7 @@ func (operation *Operation) parseObjectSchema(refType string, astFile *ast.File)
case IsPrimitiveType(refType):
return PrimitiveSchema(refType), nil
case strings.HasPrefix(refType, "[]"):
schema, err := operation.parseObjectSchema(refType[2:], astFile)
schema, err := parseObjectSchema(parser, refType[2:], astFile)
if err != nil {
return nil, err
}
Expand All @@ -856,17 +860,17 @@ func (operation *Operation) parseObjectSchema(refType string, astFile *ast.File)
return spec.MapProperty(nil), nil
}

schema, err := operation.parseObjectSchema(refType, astFile)
schema, err := parseObjectSchema(parser, refType, astFile)
if err != nil {
return nil, err
}

return spec.MapProperty(schema), nil
case strings.Contains(refType, "{"):
return operation.parseCombinedObjectSchema(refType, astFile)
return parseCombinedObjectSchema(parser, refType, astFile)
default:
if operation.parser != nil { // checking refType has existing in 'TypeDefinitions'
schema, err := operation.parser.getTypeSchema(refType, astFile, true)
if parser != nil { // checking refType has existing in 'TypeDefinitions'
schema, err := parser.getTypeSchema(refType, astFile, true)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -896,13 +900,13 @@ func parseFields(s string) []string {
})
}

func (operation *Operation) parseCombinedObjectSchema(refType string, astFile *ast.File) (*spec.Schema, error) {
func parseCombinedObjectSchema(parser *Parser, refType string, astFile *ast.File) (*spec.Schema, error) {
matches := combinedPattern.FindStringSubmatch(refType)
if len(matches) != 3 {
return nil, fmt.Errorf("invalid type: %s", refType)
}

schema, err := operation.parseObjectSchema(matches[1], astFile)
schema, err := parseObjectSchema(parser, matches[1], astFile)
if err != nil {
return nil, err
}
Expand All @@ -912,7 +916,7 @@ func (operation *Operation) parseCombinedObjectSchema(refType string, astFile *a
for _, field := range fields {
keyVal := strings.SplitN(field, "=", 2)
if len(keyVal) == 2 {
schema, err := operation.parseObjectSchema(keyVal[1], astFile)
schema, err := parseObjectSchema(parser, keyVal[1], astFile)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion parser.go
Expand Up @@ -873,7 +873,7 @@ func convertFromSpecificToPrimitive(typeName string) (string, error) {
func (parser *Parser) getTypeSchema(typeName string, file *ast.File, ref bool) (*spec.Schema, error) {
if override, ok := parser.Overrides[typeName]; ok {
parser.debug.Printf("Override detected for %s: using %s instead", typeName, override)
typeName = override
return parseObjectSchema(parser, override, file)
}

if IsInterfaceLike(typeName) {
Expand Down
3 changes: 2 additions & 1 deletion testdata/generics_basic/.swaggo
@@ -1,2 +1,3 @@
replace types.Field[string] string
replace types.DoubleField[string,string] string
replace types.DoubleField[string,string] []string
replace types.TrippleField[string,string] [][]string
14 changes: 13 additions & 1 deletion testdata/generics_basic/expected.json
Expand Up @@ -181,8 +181,20 @@
"types.Hello": {
"type": "object",
"properties": {
"myNewArrayField": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string"
}
}
},
"myNewField": {
"type": "string"
"type": "array",
"items": {
"type": "string"
}
},
"myStringField1": {
"type": "string"
Expand Down
12 changes: 9 additions & 3 deletions testdata/generics_basic/types/string.go
Expand Up @@ -9,8 +9,14 @@ type DoubleField[T1 any, T2 any] struct {
Value2 T2
}

type TrippleField[T1 any, T2 any] struct {
Value1 T1
Value2 T2
}

type Hello struct {
MyStringField1 Field[*string] `json:"myStringField1"`
MyStringField2 Field[string] `json:"myStringField2"`
MyArrayField DoubleField[*string, string] `json:"myNewField"`
MyStringField1 Field[*string] `json:"myStringField1"`
MyStringField2 Field[string] `json:"myStringField2"`
MyArrayField DoubleField[*string, string] `json:"myNewField"`
MyArrayDepthField TrippleField[*string, string] `json:"myNewArrayField"`
}

0 comments on commit b8f53da

Please sign in to comment.