Skip to content

Commit

Permalink
feat: permit error (and any) interface definition (#1212)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapk authored Jun 16, 2022
1 parent f09eaa1 commit 213f6b8
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 2 deletions.
42 changes: 42 additions & 0 deletions gen/gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,45 @@ func TestGen_Debugger(t *testing.T) {
_ = os.Remove(expectedFile)
}
}

func TestGen_ErrorAndInterface(t *testing.T) {
config := &Config{
SearchDir: "../testdata/error",
MainAPIFile: "./main.go",
OutputDir: "../testdata/error/docs",
OutputTypes: outputTypes,
PropNamingStrategy: "",
}

assert.NoError(t, New().Build(config))

expectedFiles := []string{
filepath.Join(config.OutputDir, "docs.go"),
filepath.Join(config.OutputDir, "swagger.json"),
filepath.Join(config.OutputDir, "swagger.yaml"),
}
t.Cleanup(func() {
for _, expectedFile := range expectedFiles {
_ = os.Remove(expectedFile)
}
})

// check files
for _, expectedFile := range expectedFiles {
if _, err := os.Stat(expectedFile); os.IsNotExist(err) {
require.NoError(t, err)
}
}

// check content
jsonOutput, err := ioutil.ReadFile(filepath.Join(config.OutputDir, "swagger.json"))
if err != nil {
require.NoError(t, err)
}
expectedJSON, err := ioutil.ReadFile(filepath.Join(config.SearchDir, "expected.json"))
if err != nil {
require.NoError(t, err)
}

assert.JSONEq(t, string(expectedJSON), string(jsonOutput))
}
3 changes: 3 additions & 0 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,9 @@ func convertFromSpecificToPrimitive(typeName string) (string, error) {
}

func (parser *Parser) getTypeSchema(typeName string, file *ast.File, ref bool) (*spec.Schema, error) {
if IsInterfaceLike(typeName) {
return &spec.Schema{}, nil
}
if IsGolangPrimitiveType(typeName) {
return PrimitiveSchema(TransToValidSchemeType(typeName)), nil
}
Expand Down
14 changes: 14 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,20 @@ func TestParseSimpleApi1(t *testing.T) {
assert.JSONEq(t, string(expected), string(b))
}

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

expected, err := ioutil.ReadFile("testdata/error/expected.json")
assert.NoError(t, err)
searchDir := "testdata/error"
p := New()
err = p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth)
assert.NoError(t, err)

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

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

Expand Down
10 changes: 8 additions & 2 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const (
STRING = "string"
// FUNC represent a function value.
FUNC = "func"
// ERROR represent a error value.
ERROR = "error"
// INTERFACE represent a interface value.
INTERFACE = "interface{}"
// ANY represent a any value.
Expand Down Expand Up @@ -63,6 +65,11 @@ func IsPrimitiveType(typeName string) bool {
return false
}

// IsInterfaceLike determines whether the swagger type name is an go named interface type like error type.
func IsInterfaceLike(typeName string) bool {
return typeName == ERROR || typeName == ANY
}

// IsNumericType determines whether the swagger type name is a numeric type.
func IsNumericType(typeName string) bool {
return typeName == INTEGER || typeName == NUMBER
Expand Down Expand Up @@ -106,8 +113,7 @@ func IsGolangPrimitiveType(typeName string) bool {
"float32",
"float64",
"bool",
"string",
"any":
"string":
return true
}

Expand Down
9 changes: 9 additions & 0 deletions schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ func TestIsNumericType(t *testing.T) {
assert.Equal(t, IsNumericType(STRING), false)
}

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

assert.Equal(t, IsInterfaceLike(ERROR), true)
assert.Equal(t, IsInterfaceLike(ANY), true)

assert.Equal(t, IsInterfaceLike(STRING), false)
}

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

Expand Down
23 changes: 23 additions & 0 deletions testdata/error/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package api

import (
"net/http"

. "github.com/swaggo/swag/testdata/error/errors"
_ "github.com/swaggo/swag/testdata/error/web"
)

// Upload do something
// @Summary Upload file
// @Description Upload file
// @ID file.upload
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "this is a test file"
// @Success 200 {string} string "ok"
// @Failure 400 {object} web.CrossErrors "Abort !!"
// @Router /file/upload [post]
func Upload(w http.ResponseWriter, r *http.Request) {
//write your code
_ = Errors{}
}
14 changes: 14 additions & 0 deletions testdata/error/errors/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package errors

// CustomInterface some interface
type CustomInterface interface {
Error() string
}

// Errors errors and interfaces
type Errors struct {
Error error
ErrorInterface CustomInterface
Interface interface{}
Any any
}
69 changes: 69 additions & 0 deletions testdata/error/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"swagger": "2.0",
"info": {
"description": "This is a sample server Petstore server.",
"title": "Swagger Example API",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "API Support",
"url": "http://www.swagger.io/support",
"email": "[email protected]"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.0"
},
"host": "petstore.swagger.io",
"basePath": "/v2",
"paths": {
"/file/upload": {
"post": {
"description": "Upload file",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"summary": "Upload file",
"operationId": "file.upload",
"parameters": [
{
"type": "file",
"description": "this is a test file",
"name": "file",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "ok",
"schema": {
"type": "string"
}
},
"400": {
"description": "Abort !!",
"schema": {
"$ref": "#/definitions/web.CrossErrors"
}
}
}
}
}
},
"definitions": {
"web.CrossErrors": {
"type": "object",
"properties": {
"any": {},
"error": {},
"errorInterface": {},
"interface": {}
}
}
}
}
27 changes: 27 additions & 0 deletions testdata/error/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
"net/http"

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

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

// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email [email protected]

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

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

func main() {
http.HandleFunc("/testapi/upload", api.Upload)
http.ListenAndServe(":8080", nil)
}
7 changes: 7 additions & 0 deletions testdata/error/web/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package web

import (
"github.com/swaggo/swag/testdata/error/errors"
)

type CrossErrors errors.Errors

0 comments on commit 213f6b8

Please sign in to comment.