Skip to content

Commit

Permalink
fix: generic arrays generate successfully
Browse files Browse the repository at this point in the history
  • Loading branch information
pdylanross committed Jun 30, 2022
1 parent 1cd0b53 commit 327ea07
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 5 deletions.
19 changes: 14 additions & 5 deletions generics.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,8 @@ func (pkgDefs *PackagesDefinitions) parametrizeStruct(original *TypeSpecDef, ful
Tag: field.Tag,
Comment: field.Comment,
}
if genTypeSpec, ok := genericParamTypeDefs[field.Type.(*ast.Ident).Name]; ok {
newField.Type = genTypeSpec.TypeSpec.Type
} else {
newField.Type = field.Type
}

newField.Type = resolveType(field.Type, field, genericParamTypeDefs)

newStructTypeDef.Fields.List = append(newStructTypeDef.Fields.List, newField)
}
Expand All @@ -107,3 +104,15 @@ func (pkgDefs *PackagesDefinitions) parametrizeStruct(original *TypeSpecDef, ful

return parametrizedTypeSpec
}

func resolveType(expr ast.Expr, field *ast.Field, genericParamTypeDefs map[string]*TypeSpecDef) ast.Expr {
if asIdent, ok := expr.(*ast.Ident); ok {
if genTypeSpec, ok := genericParamTypeDefs[asIdent.Name]; ok {
return genTypeSpec.TypeSpec.Type
}
} else if asArray, ok := expr.(*ast.ArrayType); ok {
return &ast.ArrayType{Elt: resolveType(asArray.Elt, field, genericParamTypeDefs), Len: asArray.Len, Lbrack: asArray.Lbrack}
}

return field.Type
}
168 changes: 168 additions & 0 deletions generics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,171 @@ func TestParseGenericsBasic(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expected, string(b))
}

func TestParseGenericsArrays(t *testing.T) {
t.Parallel()

expected := `{
"swagger": "2.0",
"info": {
"description": "This is a sample server Petstore server.",
"title": "Swagger Example API",
"contact": {},
"version": "1.0"
},
"host": "localhost:4000",
"basePath": "/api",
"paths": {
"/posts": {
"get": {
"description": "Get All of the Posts",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"summary": "List Posts",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/web.GenericListResponse-web_Post"
}
},
"222": {
"description": "",
"schema": {
"$ref": "#/definitions/web.GenericListResponseMulti-web_Post-web_Post"
}
}
}
}
}
},
"definitions": {
"web.GenericListResponse-web_Post": {
"type": "object",
"properties": {
"items": {
"description": "Items from the list response",
"type": "array",
"items": {
"type": "object",
"properties": {
"data": {
"description": "Post data",
"type": "object",
"properties": {
"name": {
"description": "Post tag",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"id": {
"type": "integer",
"format": "int64",
"example": 1
},
"name": {
"description": "Post name",
"type": "string",
"example": "poti"
}
}
}
},
"status": {
"description": "Status of some other stuff",
"type": "string"
}
}
},
"web.GenericListResponseMulti-web_Post-web_Post": {
"type": "object",
"properties": {
"itemsOne": {
"description": "ItemsOne is the first thing",
"type": "array",
"items": {
"type": "object",
"properties": {
"data": {
"description": "Post data",
"type": "object",
"properties": {
"name": {
"description": "Post tag",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"id": {
"type": "integer",
"format": "int64",
"example": 1
},
"name": {
"description": "Post name",
"type": "string",
"example": "poti"
}
}
}
},
"itemsTwo": {
"description": "ItemsTwo is the second thing",
"type": "array",
"items": {
"type": "object",
"properties": {
"data": {
"description": "Post data",
"type": "object",
"properties": {
"name": {
"description": "Post tag",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"id": {
"type": "integer",
"format": "int64",
"example": 1
},
"name": {
"description": "Post name",
"type": "string",
"example": "poti"
}
}
}
},
"status": {
"description": "Status of the things",
"type": "string"
}
}
}
}
}`

searchDir := "testdata/generics_arrays"
p := New()
err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth)
assert.NoError(t, err)
b, err := json.MarshalIndent(p.swagger, "", " ")
assert.NoError(t, err)
assert.Equal(t, expected, string(b))
}
18 changes: 18 additions & 0 deletions testdata/generics_arrays/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package api

import (
"net/http"

"github.com/swaggo/swag/testdata/generics_arrays/web"
)

// @Summary List Posts
// @Description Get All of the Posts
// @Accept json
// @Produce json
// @Success 200 {object} web.GenericListResponse[web.Post]
// @Success 222 {object} web.GenericListResponseMulti[web.Post, web.Post]
// @Router /posts [get]
func GetPosts(w http.ResponseWriter, r *http.Request) {
_ = web.GenericListResponse[web.Post]{}
}
17 changes: 17 additions & 0 deletions testdata/generics_arrays/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"net/http"

"github.com/swaggo/swag/testdata/generics_basic/api"
)

// @title Swagger Example API
// @version 1.0
// @description This is a sample server Petstore server.
// @host localhost:4000
// @basePath /api
func main() {
http.HandleFunc("/posts/", api.GetPost)
http.ListenAndServe(":8080", nil)
}
50 changes: 50 additions & 0 deletions testdata/generics_arrays/web/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package web

import (
"time"
)

// GenericListResponse[T]
// @Description Some Generic List Response
type GenericListResponse[T any] struct {
// Items from the list response
Items []T
// Status of some other stuff
Status string
}

// GenericListResponseMulti[T, X]
// @Description this contains a few things
type GenericListResponseMulti[T any, X any] struct {
// ItemsOne is the first thing
ItemsOne []T
// ItemsTwo is the second thing
ItemsTwo []X

// Status of the things
Status string
}

type Post struct {
ID int `json:"id" example:"1" format:"int64"`
// Post name
Name string `json:"name" example:"poti"`
// Post data
Data struct {
// Post tag
Tag []string `json:"name"`
} `json:"data"`
}

// APIError
// @Description API error
// @Description with information about it
// Other some summary
type APIError struct {
// Error an Api error
Error string // Error this is Line comment
// Error `number` tick comment
ErrorNo int64
ErrorCtx string // Error `context` tick comment
CreatedAt time.Time // Error time
}

0 comments on commit 327ea07

Please sign in to comment.