|
|
@ -156,28 +156,9 @@ func (p *Parser) invoke(linePrefix, content string) (v *Api, err error) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) valid(mainApi *Api, nestedApi *Api) error {
|
|
|
|
func (p *Parser) valid(mainApi *Api, nestedApi *Api) error {
|
|
|
|
if len(nestedApi.Import) > 0 {
|
|
|
|
err := p.nestedApiCheck(mainApi, nestedApi)
|
|
|
|
importToken := nestedApi.Import[0].Import
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("%s line %d:%d the nested api does not support import",
|
|
|
|
return err
|
|
|
|
nestedApi.LinePrefix, importToken.Line(), importToken.Column())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if mainApi.Syntax != nil && nestedApi.Syntax != nil {
|
|
|
|
|
|
|
|
if mainApi.Syntax.Version.Text() != nestedApi.Syntax.Version.Text() {
|
|
|
|
|
|
|
|
syntaxToken := nestedApi.Syntax.Syntax
|
|
|
|
|
|
|
|
return fmt.Errorf("%s line %d:%d multiple syntax declaration, expecting syntax '%s', but found '%s'",
|
|
|
|
|
|
|
|
nestedApi.LinePrefix, syntaxToken.Line(), syntaxToken.Column(), mainApi.Syntax.Version.Text(), nestedApi.Syntax.Version.Text())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(mainApi.Service) > 0 {
|
|
|
|
|
|
|
|
mainService := mainApi.Service[0]
|
|
|
|
|
|
|
|
for _, service := range nestedApi.Service {
|
|
|
|
|
|
|
|
if mainService.ServiceApi.Name.Text() != service.ServiceApi.Name.Text() {
|
|
|
|
|
|
|
|
return fmt.Errorf("%s multiple service name declaration, expecting service name '%s', but found '%s'",
|
|
|
|
|
|
|
|
nestedApi.LinePrefix, mainService.ServiceApi.Name.Text(), service.ServiceApi.Name.Text())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mainHandlerMap := make(map[string]PlaceHolder)
|
|
|
|
mainHandlerMap := make(map[string]PlaceHolder)
|
|
|
@ -218,6 +199,23 @@ func (p *Parser) valid(mainApi *Api, nestedApi *Api) error {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// duplicate route check
|
|
|
|
// duplicate route check
|
|
|
|
|
|
|
|
err = p.duplicateRouteCheck(nestedApi, mainHandlerMap, mainRouteMap)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// duplicate type check
|
|
|
|
|
|
|
|
for _, each := range nestedApi.Type {
|
|
|
|
|
|
|
|
if _, ok := mainTypeMap[each.NameExpr().Text()]; ok {
|
|
|
|
|
|
|
|
return fmt.Errorf("%s line %d:%d duplicate type declaration '%s'",
|
|
|
|
|
|
|
|
nestedApi.LinePrefix, each.NameExpr().Line(), each.NameExpr().Column(), each.NameExpr().Text())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) duplicateRouteCheck(nestedApi *Api, mainHandlerMap map[string]PlaceHolder, mainRouteMap map[string]PlaceHolder) error {
|
|
|
|
for _, each := range nestedApi.Service {
|
|
|
|
for _, each := range nestedApi.Service {
|
|
|
|
for _, r := range each.ServiceApi.ServiceRoute {
|
|
|
|
for _, r := range each.ServiceApi.ServiceRoute {
|
|
|
|
handler := r.GetHandler()
|
|
|
|
handler := r.GetHandler()
|
|
|
@ -237,12 +235,31 @@ func (p *Parser) valid(mainApi *Api, nestedApi *Api) error {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// duplicate type check
|
|
|
|
func (p *Parser) nestedApiCheck(mainApi *Api, nestedApi *Api) error {
|
|
|
|
for _, each := range nestedApi.Type {
|
|
|
|
if len(nestedApi.Import) > 0 {
|
|
|
|
if _, ok := mainTypeMap[each.NameExpr().Text()]; ok {
|
|
|
|
importToken := nestedApi.Import[0].Import
|
|
|
|
return fmt.Errorf("%s line %d:%d duplicate type declaration '%s'",
|
|
|
|
return fmt.Errorf("%s line %d:%d the nested api does not support import",
|
|
|
|
nestedApi.LinePrefix, each.NameExpr().Line(), each.NameExpr().Column(), each.NameExpr().Text())
|
|
|
|
nestedApi.LinePrefix, importToken.Line(), importToken.Column())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if mainApi.Syntax != nil && nestedApi.Syntax != nil {
|
|
|
|
|
|
|
|
if mainApi.Syntax.Version.Text() != nestedApi.Syntax.Version.Text() {
|
|
|
|
|
|
|
|
syntaxToken := nestedApi.Syntax.Syntax
|
|
|
|
|
|
|
|
return fmt.Errorf("%s line %d:%d multiple syntax declaration, expecting syntax '%s', but found '%s'",
|
|
|
|
|
|
|
|
nestedApi.LinePrefix, syntaxToken.Line(), syntaxToken.Column(), mainApi.Syntax.Version.Text(), nestedApi.Syntax.Version.Text())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(mainApi.Service) > 0 {
|
|
|
|
|
|
|
|
mainService := mainApi.Service[0]
|
|
|
|
|
|
|
|
for _, service := range nestedApi.Service {
|
|
|
|
|
|
|
|
if mainService.ServiceApi.Name.Text() != service.ServiceApi.Name.Text() {
|
|
|
|
|
|
|
|
return fmt.Errorf("%s multiple service name declaration, expecting service name '%s', but found '%s'",
|
|
|
|
|
|
|
|
nestedApi.LinePrefix, mainService.ServiceApi.Name.Text(), service.ServiceApi.Name.Text())
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
@ -276,55 +293,51 @@ func (p *Parser) checkTypeDeclaration(apiList []*Api) error {
|
|
|
|
|
|
|
|
|
|
|
|
for _, apiItem := range apiList {
|
|
|
|
for _, apiItem := range apiList {
|
|
|
|
linePrefix := apiItem.LinePrefix
|
|
|
|
linePrefix := apiItem.LinePrefix
|
|
|
|
for _, each := range apiItem.Type {
|
|
|
|
err := p.checkTypes(apiItem, linePrefix, types)
|
|
|
|
tp, ok := each.(*TypeStruct)
|
|
|
|
if err != nil {
|
|
|
|
if !ok {
|
|
|
|
return err
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, member := range tp.Fields {
|
|
|
|
err = p.checkServices(apiItem, types, linePrefix)
|
|
|
|
err := p.checkType(linePrefix, types, member.DataType)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, service := range apiItem.Service {
|
|
|
|
func (p *Parser) checkServices(apiItem *Api, types map[string]TypeExpr, linePrefix string) error {
|
|
|
|
for _, each := range service.ServiceApi.ServiceRoute {
|
|
|
|
for _, service := range apiItem.Service {
|
|
|
|
route := each.Route
|
|
|
|
for _, each := range service.ServiceApi.ServiceRoute {
|
|
|
|
if route.Req != nil && route.Req.Name.IsNotNil() && route.Req.Name.Expr().IsNotNil() {
|
|
|
|
route := each.Route
|
|
|
|
_, ok := types[route.Req.Name.Expr().Text()]
|
|
|
|
err := p.checkRequestBody(route, types, linePrefix)
|
|
|
|
if !ok {
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("%s line %d:%d can not found declaration '%s' in context",
|
|
|
|
return err
|
|
|
|
linePrefix, route.Req.Name.Expr().Line(), route.Req.Name.Expr().Column(), route.Req.Name.Expr().Text())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if route.Reply != nil && route.Reply.Name.IsNotNil() && route.Reply.Name.Expr().IsNotNil() {
|
|
|
|
if route.Reply != nil && route.Reply.Name.IsNotNil() && route.Reply.Name.Expr().IsNotNil() {
|
|
|
|
reply := route.Reply.Name
|
|
|
|
reply := route.Reply.Name
|
|
|
|
var structName string
|
|
|
|
var structName string
|
|
|
|
switch tp := reply.(type) {
|
|
|
|
switch tp := reply.(type) {
|
|
|
|
|
|
|
|
case *Literal:
|
|
|
|
|
|
|
|
structName = tp.Literal.Text()
|
|
|
|
|
|
|
|
case *Array:
|
|
|
|
|
|
|
|
switch innerTp := tp.Literal.(type) {
|
|
|
|
case *Literal:
|
|
|
|
case *Literal:
|
|
|
|
structName = tp.Literal.Text()
|
|
|
|
structName = innerTp.Literal.Text()
|
|
|
|
case *Array:
|
|
|
|
case *Pointer:
|
|
|
|
switch innerTp := tp.Literal.(type) {
|
|
|
|
structName = innerTp.Name.Text()
|
|
|
|
case *Literal:
|
|
|
|
|
|
|
|
structName = innerTp.Literal.Text()
|
|
|
|
|
|
|
|
case *Pointer:
|
|
|
|
|
|
|
|
structName = innerTp.Name.Text()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if api.IsBasicType(structName) {
|
|
|
|
if api.IsBasicType(structName) {
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_, ok := types[structName]
|
|
|
|
_, ok := types[structName]
|
|
|
|
if !ok {
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("%s line %d:%d can not found declaration '%s' in context",
|
|
|
|
return fmt.Errorf("%s line %d:%d can not found declaration '%s' in context",
|
|
|
|
linePrefix, route.Reply.Name.Expr().Line(), route.Reply.Name.Expr().Column(), structName)
|
|
|
|
linePrefix, route.Reply.Name.Expr().Line(), route.Reply.Name.Expr().Column(), structName)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -332,6 +345,34 @@ func (p *Parser) checkTypeDeclaration(apiList []*Api) error {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) checkRequestBody(route *Route, types map[string]TypeExpr, linePrefix string) error {
|
|
|
|
|
|
|
|
if route.Req != nil && route.Req.Name.IsNotNil() && route.Req.Name.Expr().IsNotNil() {
|
|
|
|
|
|
|
|
_, ok := types[route.Req.Name.Expr().Text()]
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
return fmt.Errorf("%s line %d:%d can not found declaration '%s' in context",
|
|
|
|
|
|
|
|
linePrefix, route.Req.Name.Expr().Line(), route.Req.Name.Expr().Column(), route.Req.Name.Expr().Text())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) checkTypes(apiItem *Api, linePrefix string, types map[string]TypeExpr) error {
|
|
|
|
|
|
|
|
for _, each := range apiItem.Type {
|
|
|
|
|
|
|
|
tp, ok := each.(*TypeStruct)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, member := range tp.Fields {
|
|
|
|
|
|
|
|
err := p.checkType(linePrefix, types, member.DataType)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) checkType(linePrefix string, types map[string]TypeExpr, expr DataType) error {
|
|
|
|
func (p *Parser) checkType(linePrefix string, types map[string]TypeExpr, expr DataType) error {
|
|
|
|
if expr == nil {
|
|
|
|
if expr == nil {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|