Skip to content

Commit

Permalink
Merge branch 'master' into internal-package-parsing-support
Browse files Browse the repository at this point in the history
  • Loading branch information
ubogdan committed Sep 11, 2019
2 parents df54d45 + d74ed70 commit 9307fce
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 2 deletions.
5 changes: 5 additions & 0 deletions operation.go
Expand Up @@ -563,6 +563,11 @@ func (operation *Operation) ParseResponseComment(commentLine string, astFile *as
schemaType := strings.Trim(matches[2], "{}")
refType := matches[3]

if !IsPrimitiveType(refType) && !strings.Contains(refType, ".") {
currentPkgName := astFile.Name.String()
refType = currentPkgName + "." + refType
}

if operation.parser != nil { // checking refType has existing in 'TypeDefinitions'
if err := operation.registerSchemaType(refType, astFile); err != nil {
return err
Expand Down
37 changes: 37 additions & 0 deletions operation_test.go
Expand Up @@ -156,6 +156,43 @@ func TestParseResponseCommentWithObjectType(t *testing.T) {
assert.Equal(t, expected, string(b))
}

func TestParseResponseCommentWithObjectTypeInSameFile(t *testing.T) {
comment := `@Success 200 {object} testOwner "Error message, if code != 200"`
operation := NewOperation()
operation.parser = New()

operation.parser.TypeDefinitions["swag"] = make(map[string]*ast.TypeSpec)
operation.parser.TypeDefinitions["swag"]["testOwner"] = &ast.TypeSpec{}

fset := token.NewFileSet()
astFile, err := goparser.ParseFile(fset, "operation_test.go", `package swag
type testOwner struct {
}
`, goparser.ParseComments)
assert.NoError(t, err)

err = operation.ParseComment(comment, astFile)
assert.NoError(t, err)

response := operation.Responses.StatusCodeResponses[200]
assert.Equal(t, `Error message, if code != 200`, response.Description)

b, _ := json.MarshalIndent(operation, "", " ")

expected := `{
"responses": {
"200": {
"description": "Error message, if code != 200",
"schema": {
"$ref": "#/definitions/swag.testOwner"
}
}
}
}`
assert.Equal(t, expected, string(b))
}

func TestParseResponseCommentWithObjectTypeAnonymousField(t *testing.T) {
//TODO: test Anonymous
}
Expand Down
23 changes: 21 additions & 2 deletions parser.go
Expand Up @@ -562,6 +562,12 @@ func (parser *Parser) parseDefinitions() error {
// with a schema for the given type
func (parser *Parser) ParseDefinition(pkgName, typeName string, typeSpec *ast.TypeSpec) error {
refTypeName := fullTypeName(pkgName, typeName)

if typeSpec == nil {
Println("Skipping '" + refTypeName + "', pkg '" + pkgName + "' not found, try add flag --parseDependency or --parseVendor.")
return nil
}

if _, isParsed := parser.swagger.Definitions[refTypeName]; isParsed {
Println("Skipping '" + refTypeName + "', already parsed.")
return nil
Expand Down Expand Up @@ -942,6 +948,18 @@ func (parser *Parser) parseStructField(pkgName string, field *ast.Field) (map[st
},
}

if nestStruct, ok := field.Type.(*ast.StarExpr); ok {
schema, err := parser.parseTypeExpr(pkgName, structField.schemaType, nestStruct.X)
if err != nil {
return nil, nil, err
}

if len(schema.SchemaProps.Type) > 0 {
properties[structField.name] = schema
return properties, nil, nil
}
}

nestStruct, ok := field.Type.(*ast.StructType)
if ok {
props := map[string]spec.Schema{}
Expand Down Expand Up @@ -1290,7 +1308,8 @@ func (parser *Parser) getAllGoFileInfoFromDeps(pkg *depth.Pkg) error {
return nil
}

files, err := ioutil.ReadDir(pkg.SrcDir) // only parsing files in the dir(don't contains sub dir files)
srcDir := pkg.Raw.Dir
files, err := ioutil.ReadDir(srcDir) // only parsing files in the dir(don't contains sub dir files)
if err != nil {
return err
}
Expand All @@ -1300,7 +1319,7 @@ func (parser *Parser) getAllGoFileInfoFromDeps(pkg *depth.Pkg) error {
continue
}

path := filepath.Join(pkg.SrcDir, f.Name())
path := filepath.Join(srcDir, f.Name())
if err := parser.parseFile(path); err != nil {
return err
}
Expand Down
16 changes: 16 additions & 0 deletions parser_test.go
Expand Up @@ -2243,6 +2243,22 @@ func TestParseComposition(t *testing.T) {
assert.Equal(t, string(expected), string(b))
}

func TestParseNested(t *testing.T) {
searchDir := "testdata/nested"
mainAPIFile := "main.go"
p := New()
p.ParseDependency = true
err := p.ParseAPI(searchDir, mainAPIFile)
assert.NoError(t, err)

expected, err := ioutil.ReadFile(path.Join(searchDir, "expected.json"))
assert.NoError(t, err)

b, _ := json.MarshalIndent(p.swagger, "", " ")
Printf(string(b))
assert.Equal(t, string(expected), string(b))
}

func TestParser_ParseStuctArrayObject(t *testing.T) {
src := `
package api
Expand Down
22 changes: 22 additions & 0 deletions testdata/nested/api/api.go
@@ -0,0 +1,22 @@
package api

import (
"github.com/gin-gonic/gin"
"github.com/swaggo/swag/testdata/nested2"
)

type Foo struct {
Field1 string
OutsideData *nested2.Body
}

// @Description get Foo
// @ID get-foo
// @Accept json
// @Produce json
// @Success 200 {object} api.Foo
// @Router /testapi/get-foo [get]
func GetFoo(c *gin.Context) {
//write your code
var _ = Foo{}
}
5 changes: 5 additions & 0 deletions testdata/nested/common/data.go
@@ -0,0 +1,5 @@
package common

type Data struct {
Value string `json:"message"`
}
57 changes: 57 additions & 0 deletions testdata/nested/expected.json
@@ -0,0 +1,57 @@
{
"swagger": "2.0",
"info": {
"description": "This is a sample server",
"title": "Swagger Example API",
"termsOfService": "http://swagger.io/terms/",
"contact": {},
"license": {},
"version": "1.0"
},
"host": "petstore.swagger.io",
"basePath": "/v2",
"paths": {
"/testapi/get-foo": {
"get": {
"description": "get Foo",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"operationId": "get-foo",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.Foo"
}
}
}
}
}
},
"definitions": {
"api.Foo": {
"type": "object",
"properties": {
"field1": {
"type": "string"
},
"outsideData": {
"type": "object",
"$ref": "#/definitions/nested2.Body"
}
}
},
"nested2.Body": {
"type": "object",
"properties": {
"value": {
"type": "string"
}
}
}
}
}
20 changes: 20 additions & 0 deletions testdata/nested/main.go
@@ -0,0 +1,20 @@
package composition

import (
"github.com/gin-gonic/gin"
"github.com/swaggo/swag/testdata/nested/api"
)

// @title Swagger Example API
// @version 1.0
// @description This is a sample server
// @termsOfService http://swagger.io/terms/

// @host petstore.swagger.io
// @BasePath /v2

func main() {
r := gin.New()
r.GET("/testapi/get-foo", api.GetFoo)
r.Run()
}
5 changes: 5 additions & 0 deletions testdata/nested2/data.go
@@ -0,0 +1,5 @@
package nested2

type Body struct {
Value string `json:"value"`
}

0 comments on commit 9307fce

Please sign in to comment.