package test import ( "io/ioutil" "testing" "github.com/stretchr/testify/assert" "github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" ) var parser = ast.NewParser(ast.WithParserPrefix("test.api"), ast.WithParserDebug()) func TestApi(t *testing.T) { fn := func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} { return p.Api().Accept(visitor) } content, err := ioutil.ReadFile("./apis/test.api") assert.Nil(t, err) v, err := parser.Accept(fn, string(content)) assert.Nil(t, err) api := v.(*ast.Api) body := &ast.Body{ Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), Name: &ast.Literal{Literal: ast.NewTextExpr("FooBar")}, } returns := ast.NewTextExpr("returns") assert.True(t, api.Equal(&ast.Api{ Syntax: &ast.SyntaxExpr{ Syntax: ast.NewTextExpr("syntax"), Assign: ast.NewTextExpr("="), Version: ast.NewTextExpr(`"v1"`), DocExpr: []ast.Expr{ ast.NewTextExpr("// syntax doc"), }, CommentExpr: ast.NewTextExpr("// syntax comment"), }, Import: []*ast.ImportExpr{ { Import: ast.NewTextExpr("import"), Value: ast.NewTextExpr(`"foo.api"`), DocExpr: []ast.Expr{ ast.NewTextExpr("// import doc"), }, CommentExpr: ast.NewTextExpr("// import comment"), }, { Import: ast.NewTextExpr("import"), Value: ast.NewTextExpr(`"bar.api"`), DocExpr: []ast.Expr{ ast.NewTextExpr("// import group doc"), }, CommentExpr: ast.NewTextExpr("// import group comment"), }, }, Info: &ast.InfoExpr{ Info: ast.NewTextExpr("info"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), Kvs: []*ast.KvExpr{ { Key: ast.NewTextExpr("author"), Value: ast.NewTextExpr(`"songmeizi"`), DocExpr: []ast.Expr{ ast.NewTextExpr("// author doc"), }, CommentExpr: ast.NewTextExpr("// author comment"), }, { Key: ast.NewTextExpr("date"), Value: ast.NewTextExpr(`2020-01-04`), DocExpr: []ast.Expr{ ast.NewTextExpr("// date doc"), }, CommentExpr: ast.NewTextExpr("// date comment"), }, { Key: ast.NewTextExpr("desc"), Value: ast.NewTextExpr(`"break line desc"`), DocExpr: []ast.Expr{ ast.NewTextExpr("// desc doc"), }, CommentExpr: ast.NewTextExpr("// desc comment"), }, }, }, Type: []ast.TypeExpr{ &ast.TypeStruct{ Name: ast.NewTextExpr("FooBar"), Struct: ast.NewTextExpr("struct"), LBrace: ast.NewTextExpr("{"), RBrace: ast.NewTextExpr("}"), Fields: []*ast.TypeField{ { Name: ast.NewTextExpr("Foo"), DataType: &ast.Literal{Literal: ast.NewTextExpr("int")}, }, }, }, &ast.TypeStruct{ Name: ast.NewTextExpr("Bar"), LBrace: ast.NewTextExpr("{"), RBrace: ast.NewTextExpr("}"), DocExpr: []ast.Expr{ ast.NewTextExpr("// remove struct"), }, Fields: []*ast.TypeField{ { Name: ast.NewTextExpr("VString"), DataType: &ast.Literal{Literal: ast.NewTextExpr("string")}, Tag: ast.NewTextExpr("`json:\"vString\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vString"), }, }, { Name: ast.NewTextExpr("VBool"), DataType: &ast.Literal{Literal: ast.NewTextExpr("bool")}, Tag: ast.NewTextExpr("`json:\"vBool\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vBool"), }, }, { Name: ast.NewTextExpr("VInt8"), DataType: &ast.Literal{Literal: ast.NewTextExpr("int8")}, Tag: ast.NewTextExpr("`json:\"vInt8\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vInt8"), }, }, { Name: ast.NewTextExpr("VInt16"), DataType: &ast.Literal{Literal: ast.NewTextExpr("int16")}, Tag: ast.NewTextExpr("`json:\"vInt16\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vInt16"), }, }, { Name: ast.NewTextExpr("VInt32"), DataType: &ast.Literal{Literal: ast.NewTextExpr("int32")}, Tag: ast.NewTextExpr("`json:\"vInt32\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vInt32"), }, }, { Name: ast.NewTextExpr("VInt64"), DataType: &ast.Literal{Literal: ast.NewTextExpr("int64")}, Tag: ast.NewTextExpr("`json:\"vInt64\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vInt64"), }, }, { Name: ast.NewTextExpr("VInt"), DataType: &ast.Literal{Literal: ast.NewTextExpr("int")}, Tag: ast.NewTextExpr("`json:\"vInt\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vInt"), }, }, { Name: ast.NewTextExpr("VUInt8"), DataType: &ast.Literal{Literal: ast.NewTextExpr("uint8")}, Tag: ast.NewTextExpr("`json:\"vUInt8\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vUInt8"), }, }, { Name: ast.NewTextExpr("VUInt16"), DataType: &ast.Literal{Literal: ast.NewTextExpr("uint16")}, Tag: ast.NewTextExpr("`json:\"vUInt16\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vUInt16"), }, }, { Name: ast.NewTextExpr("VUInt32"), DataType: &ast.Literal{Literal: ast.NewTextExpr("uint32")}, Tag: ast.NewTextExpr("`json:\"vUInt32\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vUInt32"), }, }, { Name: ast.NewTextExpr("VUInt64"), DataType: &ast.Literal{Literal: ast.NewTextExpr("uint64")}, Tag: ast.NewTextExpr("`json:\"vUInt64\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vUInt64"), }, }, { Name: ast.NewTextExpr("VFloat32"), DataType: &ast.Literal{Literal: ast.NewTextExpr("float32")}, Tag: ast.NewTextExpr("`json:\"vFloat32\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vFloat32"), }, }, { Name: ast.NewTextExpr("VFloat64"), DataType: &ast.Literal{Literal: ast.NewTextExpr("float64")}, Tag: ast.NewTextExpr("`json:\"vFloat64\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vFloat64"), }, }, { Name: ast.NewTextExpr("VByte"), DataType: &ast.Literal{Literal: ast.NewTextExpr("byte")}, Tag: ast.NewTextExpr("`json:\"vByte\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vByte"), }, }, { Name: ast.NewTextExpr("VRune"), DataType: &ast.Literal{Literal: ast.NewTextExpr("rune")}, Tag: ast.NewTextExpr("`json:\"vRune\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vRune"), }, }, { Name: ast.NewTextExpr("VMap"), DataType: &ast.Map{ MapExpr: ast.NewTextExpr("map[string]int"), Map: ast.NewTextExpr("map"), LBrack: ast.NewTextExpr("["), RBrack: ast.NewTextExpr("]"), Key: ast.NewTextExpr("string"), Value: &ast.Literal{Literal: ast.NewTextExpr("int")}, }, Tag: ast.NewTextExpr("`json:\"vMap\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vMap"), }, }, { Name: ast.NewTextExpr("VArray"), DataType: &ast.Array{ ArrayExpr: ast.NewTextExpr("[]int"), LBrack: ast.NewTextExpr("["), RBrack: ast.NewTextExpr("]"), Literal: &ast.Literal{Literal: ast.NewTextExpr("int")}, }, Tag: ast.NewTextExpr("`json:\"vArray\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vArray"), }, }, { Name: ast.NewTextExpr("VStruct"), DataType: &ast.Literal{Literal: ast.NewTextExpr("FooBar")}, Tag: ast.NewTextExpr("`json:\"vStruct\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vStruct"), }, }, { Name: ast.NewTextExpr("VStructPointer"), DataType: &ast.Pointer{ PointerExpr: ast.NewTextExpr("*FooBar"), Star: ast.NewTextExpr("*"), Name: ast.NewTextExpr("FooBar"), }, Tag: ast.NewTextExpr("`json:\"vStructPointer\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vStructPointer"), }, }, { Name: ast.NewTextExpr("VInterface"), DataType: &ast.Interface{Literal: ast.NewTextExpr("interface{}")}, Tag: ast.NewTextExpr("`json:\"vInterface\"`"), DocExpr: []ast.Expr{ ast.NewTextExpr("// vInterface"), }, }, { IsAnonymous: true, DataType: &ast.Literal{Literal: ast.NewTextExpr("FooBar")}, DocExpr: []ast.Expr{ ast.NewTextExpr("// inline"), }, }, }, }, }, Service: []*ast.Service{ { AtServer: &ast.AtServer{ AtServerToken: ast.NewTextExpr("@server"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), Kv: []*ast.KvExpr{ { Key: ast.NewTextExpr("host"), Value: ast.NewTextExpr("0.0.0.0"), }, { Key: ast.NewTextExpr("port"), Value: ast.NewTextExpr("8080"), }, { Key: ast.NewTextExpr("annotation"), Value: ast.NewTextExpr(`"break line desc"`), }, }, }, ServiceApi: &ast.ServiceApi{ ServiceToken: ast.NewTextExpr("service"), Name: ast.NewTextExpr("foo-api"), Lbrace: ast.NewTextExpr("{"), Rbrace: ast.NewTextExpr("}"), ServiceRoute: []*ast.ServiceRoute{ { AtDoc: &ast.AtDoc{ AtDocToken: ast.NewTextExpr("@doc"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), LineDoc: ast.NewTextExpr(`"foo"`), }, AtHandler: &ast.AtHandler{ AtHandlerToken: ast.NewTextExpr("@handler"), Name: ast.NewTextExpr("postFoo"), }, Route: &ast.Route{ Method: ast.NewTextExpr("post"), Path: ast.NewTextExpr("/foo"), Req: body, ReturnToken: returns, Reply: body, DocExpr: []ast.Expr{ ast.NewTextExpr("// foo"), }, }, }, { AtDoc: &ast.AtDoc{ AtDocToken: ast.NewTextExpr("@doc"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), Kv: []*ast.KvExpr{ { Key: ast.NewTextExpr("summary"), Value: ast.NewTextExpr("bar"), }, }, }, AtServer: &ast.AtServer{ AtServerToken: ast.NewTextExpr("@server"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), Kv: []*ast.KvExpr{ { Key: ast.NewTextExpr("handler"), Value: ast.NewTextExpr("postBar"), }, }, }, Route: &ast.Route{ Method: ast.NewTextExpr("post"), Path: ast.NewTextExpr("/bar"), Req: body, }, }, { AtDoc: &ast.AtDoc{ AtDocToken: ast.NewTextExpr("@doc"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), LineDoc: ast.NewTextExpr(`"foobar"`), }, AtHandler: &ast.AtHandler{ AtHandlerToken: ast.NewTextExpr("@handler"), Name: ast.NewTextExpr("postFooBar"), }, Route: &ast.Route{ Method: ast.NewTextExpr("post"), Path: ast.NewTextExpr("/foo/bar"), ReturnToken: returns, Reply: body, DocExpr: []ast.Expr{ ast.NewTextExpr(`/** * httpmethod: post * path: /foo/bar * reply: FooBar */`), }, }, }, { AtDoc: &ast.AtDoc{ AtDocToken: ast.NewTextExpr("@doc"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), LineDoc: ast.NewTextExpr(`"barfoo"`), }, AtHandler: &ast.AtHandler{ AtHandlerToken: ast.NewTextExpr("@handler"), Name: ast.NewTextExpr("postBarFoo"), }, Route: &ast.Route{ Method: ast.NewTextExpr("post"), Path: ast.NewTextExpr("/bar/foo"), ReturnToken: returns, Reply: body, CommentExpr: ast.NewTextExpr("// post:/bar/foo"), }, }, { AtDoc: &ast.AtDoc{ AtDocToken: ast.NewTextExpr("@doc"), Lp: ast.NewTextExpr("("), Rp: ast.NewTextExpr(")"), LineDoc: ast.NewTextExpr(`"barfoo"`), }, AtHandler: &ast.AtHandler{ AtHandlerToken: ast.NewTextExpr("@handler"), Name: ast.NewTextExpr("getBarFoo"), }, Route: &ast.Route{ Method: ast.NewTextExpr("get"), Path: ast.NewTextExpr("/bar/foo"), ReturnToken: returns, Reply: body, }, }, }, }, }, }, })) } func TestApiSyntax(t *testing.T) { fn := func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} { return p.Api().Accept(visitor) } parser.Accept(fn, ` // doc 1 // doc 2 syntax = "v1" // comment 1 // comment 2 import "foo.api" `) }