You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-zero/tools/goctl/api/parser/g4/test/ast_test.go

459 lines
13 KiB
Go

package test
import (
_ "embed"
"testing"
"github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
)
//go:embed apis/test.api
var testApi string
var parser = ast.NewParser(ast.WithParserPrefix("test.api"), ast.WithParserDebug())
func TestApi(t *testing.T) {
fn := func(p *api.ApiParserParser, visitor *ast.ApiVisitor) any {
return p.Api().Accept(visitor)
}
v, err := parser.Accept(fn, testApi)
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) any {
return p.Api().Accept(visitor)
}
parser.Accept(fn, `
// doc 1
// doc 2
syntax = "v1" // comment 1
// comment 2
import "foo.api"
`)
}