print more message when parse error (#131)

* rebase upstream

* rebase

* trim no need line

* trim no need line

* trim no need line

* update doc

* remove update

* remove no need

* remove no need

* goctl add jwt support

* goctl add jwt support

* goctl add jwt support

* goctl support import

* goctl support import

* support return ()

* revert

* refactor and rename folder to group

* print more error info when parse error

* remove no need

* refactor

Co-authored-by: kingxt <dream4kingxt@163.com>
master
kingxt 4 years ago committed by GitHub
parent fe3739b7f3
commit dc0534573c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -60,7 +60,8 @@ func NewParser(filename string) (*Parser, error) {
func (p *Parser) Parse() (api *spec.ApiSpec, err error) { func (p *Parser) Parse() (api *spec.ApiSpec, err error) {
api = new(spec.ApiSpec) api = new(spec.ApiSpec)
types, err := parseStructAst(p.typeDef) var sp = StructParser{Src: p.typeDef}
types, err := sp.Parse()
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -14,7 +14,6 @@ import (
var ( var (
ErrStructNotFound = errors.New("struct not found") ErrStructNotFound = errors.New("struct not found")
ErrUnSupportType = errors.New("unsupport type")
ErrUnSupportInlineType = errors.New("unsupport inline type") ErrUnSupportInlineType = errors.New("unsupport inline type")
interfaceExpr = `interface{}` interfaceExpr = `interface{}`
objectM = make(map[string]*spec.Type) objectM = make(map[string]*spec.Type)
@ -27,12 +26,17 @@ const (
pkgPrefix = "package" pkgPrefix = "package"
) )
func parseStructAst(golang string) ([]spec.Type, error) { type StructParser struct {
if !strings.HasPrefix(golang, pkgPrefix) { Src string
golang = fmt.Sprintf(golangF, golang) }
func (sp *StructParser) Parse() ([]spec.Type, error) {
if !strings.HasPrefix(sp.Src, pkgPrefix) {
sp.Src = fmt.Sprintf(golangF, sp.Src)
} }
fSet := token.NewFileSet() fSet := token.NewFileSet()
f, err := parser.ParseFile(fSet, "", golang, parser.ParseComments) f, err := parser.ParseFile(fSet, "", sp.Src, parser.ParseComments)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -45,7 +49,7 @@ func parseStructAst(golang string) ([]spec.Type, error) {
objects := scope.Objects objects := scope.Objects
structs := make([]*spec.Type, 0) structs := make([]*spec.Type, 0)
for structName, obj := range objects { for structName, obj := range objects {
st, err := parseObject(structName, obj) st, err := sp.parseObject(structName, obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -61,7 +65,7 @@ func parseStructAst(golang string) ([]spec.Type, error) {
return resp, nil return resp, nil
} }
func parseObject(structName string, obj *ast.Object) (*spec.Type, error) { func (sp *StructParser) parseObject(structName string, obj *ast.Object) (*spec.Type, error) {
if data, ok := objectM[structName]; ok { if data, ok := objectM[structName]; ok {
return data, nil return data, nil
} }
@ -91,7 +95,7 @@ func parseObject(structName string, obj *ast.Object) (*spec.Type, error) {
return &st, nil return &st, nil
} }
fieldList := fields.List fieldList := fields.List
members, err := parseFields(fieldList) members, err := sp.parseFields(fieldList)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -100,13 +104,13 @@ func parseObject(structName string, obj *ast.Object) (*spec.Type, error) {
return &st, nil return &st, nil
} }
func parseFields(fields []*ast.Field) ([]spec.Member, error) { func (sp *StructParser) parseFields(fields []*ast.Field) ([]spec.Member, error) {
members := make([]spec.Member, 0) members := make([]spec.Member, 0)
for _, field := range fields { for _, field := range fields {
docs := parseCommentOrDoc(field.Doc) docs := parseCommentOrDoc(field.Doc)
comments := parseCommentOrDoc(field.Comment) comments := parseCommentOrDoc(field.Comment)
name := parseName(field.Names) name := parseName(field.Names)
tp, stringExpr, err := parseType(field.Type) tp, stringExpr, err := sp.parseType(field.Type)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -114,7 +118,7 @@ func parseFields(fields []*ast.Field) ([]spec.Member, error) {
isInline := name == "" isInline := name == ""
if isInline { if isInline {
var err error var err error
name, err = getInlineName(tp) name, err = sp.getInlineName(tp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -133,12 +137,12 @@ func parseFields(fields []*ast.Field) ([]spec.Member, error) {
return members, nil return members, nil
} }
func getInlineName(tp interface{}) (string, error) { func (sp *StructParser) getInlineName(tp interface{}) (string, error) {
switch v := tp.(type) { switch v := tp.(type) {
case *spec.Type: case *spec.Type:
return v.Name, nil return v.Name, nil
case *spec.PointerType: case *spec.PointerType:
return getInlineName(v.Star) return sp.getInlineName(v.Star)
case *spec.StructType: case *spec.StructType:
return v.StringExpr, nil return v.StringExpr, nil
default: default:
@ -146,7 +150,7 @@ func getInlineName(tp interface{}) (string, error) {
} }
} }
func getInlineTypePrefix(tp interface{}) (string, error) { func (sp *StructParser) getInlineTypePrefix(tp interface{}) (string, error) {
if tp == nil { if tp == nil {
return "", nil return "", nil
} }
@ -173,13 +177,14 @@ func parseTag(basicLit *ast.BasicLit) string {
// resp1: type can convert to *spec.PointerType|*spec.BasicType|*spec.MapType|*spec.ArrayType|*spec.InterfaceType // resp1: type can convert to *spec.PointerType|*spec.BasicType|*spec.MapType|*spec.ArrayType|*spec.InterfaceType
// resp2: type's string expression,like int、string、[]int64、map[string]User、*User // resp2: type's string expression,like int、string、[]int64、map[string]User、*User
// resp3: error // resp3: error
func parseType(expr ast.Expr) (interface{}, string, error) { func (sp *StructParser) parseType(expr ast.Expr) (interface{}, string, error) {
if expr == nil { if expr == nil {
return nil, "", ErrUnSupportType return nil, "", errors.New("parse error " + sp.Src)
} }
exprStr := sp.Src[expr.Pos():expr.End()]
switch v := expr.(type) { switch v := expr.(type) {
case *ast.StarExpr: case *ast.StarExpr:
star, stringExpr, err := parseType(v.X) star, stringExpr, err := sp.parseType(v.X)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
@ -191,14 +196,14 @@ func parseType(expr ast.Expr) (interface{}, string, error) {
} else if v.Obj != nil { } else if v.Obj != nil {
obj := v.Obj obj := v.Obj
if obj.Name != v.Name { // 防止引用自己而无限递归 if obj.Name != v.Name { // 防止引用自己而无限递归
specType, err := parseObject(v.Name, v.Obj) specType, err := sp.parseObject(v.Name, v.Obj)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} else { } else {
return specType, v.Obj.Name, nil return specType, v.Obj.Name, nil
} }
} else { } else {
inlineType, err := getInlineTypePrefix(obj.Decl) inlineType, err := sp.getInlineTypePrefix(obj.Decl)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
@ -207,22 +212,22 @@ func parseType(expr ast.Expr) (interface{}, string, error) {
}, v.Name, nil }, v.Name, nil
} }
} else { } else {
return nil, "", fmt.Errorf(" [%s] - member is not exist", v.Name) return nil, "", fmt.Errorf(" [%s] - member is not exist, expr is %s", v.Name, exprStr)
} }
case *ast.MapType: case *ast.MapType:
key, keyStringExpr, err := parseType(v.Key) key, keyStringExpr, err := sp.parseType(v.Key)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
value, valueStringExpr, err := parseType(v.Value) value, valueStringExpr, err := sp.parseType(v.Value)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
keyType, ok := key.(*spec.BasicType) keyType, ok := key.(*spec.BasicType)
if !ok { if !ok {
return nil, "", fmt.Errorf("[%+v] - unsupported type of map key", v.Key) return nil, "", fmt.Errorf("[%+v] - unsupported type of map key, expr is %s", v.Key, exprStr)
} }
e := fmt.Sprintf("map[%s]%s", keyStringExpr, valueStringExpr) e := fmt.Sprintf("map[%s]%s", keyStringExpr, valueStringExpr)
@ -232,7 +237,7 @@ func parseType(expr ast.Expr) (interface{}, string, error) {
StringExpr: e, StringExpr: e,
}, e, nil }, e, nil
case *ast.ArrayType: case *ast.ArrayType:
arrayType, stringExpr, err := parseType(v.Elt) arrayType, stringExpr, err := sp.parseType(v.Elt)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
@ -242,11 +247,11 @@ func parseType(expr ast.Expr) (interface{}, string, error) {
case *ast.InterfaceType: case *ast.InterfaceType:
return &spec.InterfaceType{StringExpr: interfaceExpr}, interfaceExpr, nil return &spec.InterfaceType{StringExpr: interfaceExpr}, interfaceExpr, nil
case *ast.ChanType: case *ast.ChanType:
return nil, "", errors.New("[chan] - unsupported type") return nil, "", errors.New("[chan] - unsupported type, expr is " + exprStr)
case *ast.FuncType: case *ast.FuncType:
return nil, "", errors.New("[func] - unsupported type") return nil, "", errors.New("[func] - unsupported type, expr is " + exprStr)
case *ast.StructType: // todo can optimize case *ast.StructType: // todo can optimize
return nil, "", errors.New("[struct] - unsupported inline struct type") return nil, "", errors.New("[struct] - unsupported inline struct type, expr is " + exprStr)
case *ast.SelectorExpr: case *ast.SelectorExpr:
x := v.X x := v.X
sel := v.Sel sel := v.Sel
@ -254,7 +259,7 @@ func parseType(expr ast.Expr) (interface{}, string, error) {
if ok { if ok {
name := xIdent.Name name := xIdent.Name
if name != "time" && sel.Name != "Time" { if name != "time" && sel.Name != "Time" {
return nil, "", fmt.Errorf("[outter package] - package:%s, unsupport type", name) return nil, "", fmt.Errorf("[outter package] - package: %s, unsupport type", exprStr)
} }
tm := fmt.Sprintf("time.Time") tm := fmt.Sprintf("time.Time")
@ -262,9 +267,9 @@ func parseType(expr ast.Expr) (interface{}, string, error) {
StringExpr: tm, StringExpr: tm,
}, tm, nil }, tm, nil
} }
return nil, "", ErrUnSupportType return nil, "", errors.New("parse error " + exprStr)
default: default:
return nil, "", ErrUnSupportType return nil, "", errors.New("parse error " + exprStr)
} }
} }

Loading…
Cancel
Save