Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug info should go to stdout instead of stderr #990

Merged
merged 5 commits into from
Sep 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 0 additions & 30 deletions debug.go

This file was deleted.

2 changes: 1 addition & 1 deletion operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ func (operation *Operation) ParseParamComment(commentLine string, astFile *ast.F
case IsSimplePrimitiveType(prop.Type[0]):
param = createParameter(paramType, prop.Description, name, prop.Type[0], findInSlice(schema.Required, name))
default:
Println(fmt.Sprintf("skip field [%s] in %s is not supported type for %s", name, refType, paramType))
operation.parser.debug.Printf("skip field [%s] in %s is not supported type for %s", name, refType, paramType)

continue
}
Expand Down
52 changes: 52 additions & 0 deletions operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1754,6 +1754,58 @@ func TestParseParamArrayWithEnums(t *testing.T) {
assert.Equal(t, expected, string(b))
}

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

op := NewOperation(nil)
numberParam := spec.Parameter{}
err := op.parseAndExtractionParamAttribute(
" default(1) maximum(100) minimum(0) format(csv)",
"",
NUMBER,
&numberParam,
)
assert.NoError(t, err)
assert.Equal(t, float64(0), *numberParam.Minimum)
assert.Equal(t, float64(100), *numberParam.Maximum)
assert.Equal(t, "csv", numberParam.SimpleSchema.Format)
assert.Equal(t, float64(1), numberParam.Default)

err = op.parseAndExtractionParamAttribute(" minlength(1)", "", NUMBER, nil)
assert.Error(t, err)

err = op.parseAndExtractionParamAttribute(" maxlength(1)", "", NUMBER, nil)
assert.Error(t, err)

stringParam := spec.Parameter{}
err = op.parseAndExtractionParamAttribute(
" default(test) maxlength(100) minlength(0) format(csv)",
"",
STRING,
&stringParam,
)
assert.NoError(t, err)
assert.Equal(t, int64(0), *stringParam.MinLength)
assert.Equal(t, int64(100), *stringParam.MaxLength)
assert.Equal(t, "csv", stringParam.SimpleSchema.Format)
err = op.parseAndExtractionParamAttribute(" minimum(0)", "", STRING, nil)
assert.Error(t, err)

err = op.parseAndExtractionParamAttribute(" maximum(0)", "", STRING, nil)
assert.Error(t, err)

arrayParram := spec.Parameter{}
err = op.parseAndExtractionParamAttribute(" collectionFormat(tsv)", ARRAY, STRING, &arrayParram)
assert.Equal(t, "tsv", arrayParram.CollectionFormat)
assert.NoError(t, err)

err = op.parseAndExtractionParamAttribute(" collectionFormat(tsv)", STRING, STRING, nil)
assert.Error(t, err)

err = op.parseAndExtractionParamAttribute(" default(0)", "", ARRAY, nil)
assert.NoError(t, err)
}

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

Expand Down
42 changes: 32 additions & 10 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
goparser "go/parser"
"go/token"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
Expand Down Expand Up @@ -100,6 +101,14 @@ type Parser struct {

// excludes excludes dirs and files in SearchDir
excludes map[string]bool

// debugging output goes here
debug Debugger
}

// Debugger is the interface that wraps the basic Printf method.
type Debugger interface {
Printf(format string, v ...interface{})
}

// New creates a new Parser with default properties.
Expand All @@ -126,6 +135,7 @@ func New(options ...func(*Parser)) *Parser {
},
},
packages: NewPackagesDefinitions(),
debug: log.New(os.Stdout, "", log.LstdFlags),
parsedSchemas: make(map[*TypeSpecDef]*Schema),
outputSchemas: make(map[*TypeSpecDef]*Schema),
existSchemaNames: make(map[string]*Schema),
Expand Down Expand Up @@ -174,6 +184,13 @@ func SetStrict(strict bool) func(*Parser) {
}
}

// SetDebugger allows the use of user-defined implementations.
func SetDebugger(logger Debugger) func(parser *Parser) {
return func(p *Parser) {
p.debug = logger
}
}

// ParseAPI parses general api info for given searchDir and mainAPIFile.
func (parser *Parser) ParseAPI(searchDir string, mainAPIFile string, parseDepth int) error {
return parser.ParseAPIMultiSearchDir([]string{searchDir}, mainAPIFile, parseDepth)
Expand All @@ -182,11 +199,11 @@ func (parser *Parser) ParseAPI(searchDir string, mainAPIFile string, parseDepth
// ParseAPIMultiSearchDir is like ParseAPI but for multiple search dirs.
func (parser *Parser) ParseAPIMultiSearchDir(searchDirs []string, mainAPIFile string, parseDepth int) error {
for _, searchDir := range searchDirs {
Printf("Generate general API Info, search dir:%s", searchDir)
parser.debug.Printf("Generate general API Info, search dir:%s", searchDir)

packageDir, err := getPkgName(searchDir)
if err != nil {
Printf("warning: failed to get package name in dir: %s, error: %s", searchDir, err.Error())
parser.debug.Printf("warning: failed to get package name in dir: %s, error: %s", searchDir, err.Error())
}

err = parser.getAllGoFileInfo(packageDir, searchDir)
Expand Down Expand Up @@ -638,7 +655,7 @@ func (parser *Parser) ParseRouterAPIInfo(fileName string, astFile *ast.File) err
if parser.Strict {
return err
}
Printf("warning: %s\n", err)
parser.debug.Printf("warning: %s\n", err)
}

setRouteMethodOp(&pathItem, routeProperties.HTTPMethod, &operation.Operation)
Expand Down Expand Up @@ -824,13 +841,13 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef) (*Schema, error)

schema, ok := parser.parsedSchemas[typeSpecDef]
if ok {
Println("Skipping '" + typeName + "', already parsed.")
parser.debug.Printf("Skipping '%s', already parsed.", typeName)

return schema, nil
}

if parser.isInStructStack(typeSpecDef) {
Println("Skipping '" + typeName + "', recursion detected.")
parser.debug.Printf("Skipping '%s', recursion detected.", typeName)

return &Schema{
Name: refTypeName,
Expand All @@ -841,22 +858,27 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef) (*Schema, error)
}
parser.structStack = append(parser.structStack, typeSpecDef)

Println("Generating " + typeName)
parser.debug.Printf("Generating %s", typeName)

definition, err := parser.parseTypeExpr(typeSpecDef.File, typeSpecDef.TypeSpec.Type, false)
if err != nil {
return nil, err
}
s := &Schema{Name: refTypeName, PkgPath: typeSpecDef.PkgPath, Schema: definition}
parser.parsedSchemas[typeSpecDef] = s

s := Schema{
Name: refTypeName,
PkgPath: typeSpecDef.PkgPath,
Schema: definition,
}
parser.parsedSchemas[typeSpecDef] = &s

// update an empty schema as a result of recursion
s2, ok := parser.outputSchemas[typeSpecDef]
if ok {
parser.swagger.Definitions[s2.Name] = *definition
}

return s, nil
return &s, nil
}

func fullTypeName(pkgName, typeName string) string {
Expand Down Expand Up @@ -916,7 +938,7 @@ func (parser *Parser) parseTypeExpr(file *ast.File, typeExpr ast.Expr, ref bool)
return nil, ErrFuncTypeField
// ...
default:
Printf("Type definition of type '%T' is not supported yet. Using 'object' instead.\n", typeExpr)
parser.debug.Printf("Type definition of type '%T' is not supported yet. Using 'object' instead.\n", typeExpr)
}

return PrimitiveSchema(OBJECT), nil
Expand Down
85 changes: 85 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package swag

import (
"bytes"
"encoding/json"
"go/ast"
goparser "go/parser"
"go/token"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
Expand Down Expand Up @@ -49,6 +51,59 @@ func TestSetStrict(t *testing.T) {
assert.Equal(t, true, p.Strict)
}

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

logger := log.New(&bytes.Buffer{}, "", log.LstdFlags)

p := New(SetDebugger(logger))
assert.Equal(t, p.debug, logger)
}

func TestParser_ParseDefinition(t *testing.T) {
p := New()

// Parsing existing type
definition := &TypeSpecDef{
PkgPath: "github.com/swagger/swag",
File: &ast.File{
Name: &ast.Ident{
Name: "swag",
},
},
TypeSpec: &ast.TypeSpec{
Name: &ast.Ident{
Name: "Test",
},
},
}

expected := &Schema{}
p.parsedSchemas[definition] = expected

schema, err := p.ParseDefinition(definition)
assert.NoError(t, err)
assert.Equal(t, expected, schema)

// Parsing *ast.FuncType
definition = &TypeSpecDef{
PkgPath: "github.com/swagger/swag/model",
File: &ast.File{
Name: &ast.Ident{
Name: "model",
},
},
TypeSpec: &ast.TypeSpec{
Name: &ast.Ident{
Name: "Test",
},
Type: &ast.FuncType{},
},
}
_, err = p.ParseDefinition(definition)
assert.Error(t, err)
}

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

Expand Down Expand Up @@ -3380,3 +3435,33 @@ func TestParser_Skip(t *testing.T) {
assert.Error(t, parser.Skip("admin/models", &mockFS{IsDirectory: true}))
assert.Error(t, parser.Skip("admin/release", &mockFS{IsDirectory: true}))
}

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

field, err := getFieldType(&ast.Ident{Name: "User"})
assert.NoError(t, err)
assert.Equal(t, "User", field)

_, err = getFieldType(&ast.FuncType{})
assert.Error(t, err)

field, err = getFieldType(&ast.SelectorExpr{X: &ast.Ident{Name: "models"}, Sel: &ast.Ident{Name: "User"}})
assert.NoError(t, err)
assert.Equal(t, "models.User", field)

_, err = getFieldType(&ast.SelectorExpr{X: &ast.FuncType{}, Sel: &ast.Ident{Name: "User"}})
assert.Error(t, err)

field, err = getFieldType(&ast.StarExpr{X: &ast.Ident{Name: "User"}})
assert.NoError(t, err)
assert.Equal(t, "User", field)

field, err = getFieldType(&ast.StarExpr{X: &ast.FuncType{}})
assert.Error(t, err)

field, err = getFieldType(&ast.StarExpr{X: &ast.SelectorExpr{X: &ast.Ident{Name: "models"}, Sel: &ast.Ident{Name: "User"}}})
assert.NoError(t, err)
assert.Equal(t, "models.User", field)

}