Skip to content

Commit

Permalink
debug info should go to stdout instead of stderr (#990)
Browse files Browse the repository at this point in the history
* debug info should go to stdout instead of stderr

* lint

* more coverage

* improve parser coverage

* improve operation coverage
  • Loading branch information
ubogdan committed Sep 23, 2021
1 parent 523e046 commit a76cfa3
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 41 deletions.
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)

}

0 comments on commit a76cfa3

Please sign in to comment.