(goctl): fix unresolved type if linked api imported (#3881)
This commit is contained in:
@@ -403,6 +403,9 @@ func Parse(filename string, src interface{}) (*spec.ApiSpec, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := api.SelfCheck(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var result = new(spec.ApiSpec)
|
var result = new(spec.ApiSpec)
|
||||||
analyzer := Analyzer{
|
analyzer := Analyzer{
|
||||||
|
|||||||
@@ -42,4 +42,8 @@ func Test_Parse(t *testing.T) {
|
|||||||
_, err := Parse("./testdata/base.api", nil)
|
_, err := Parse("./testdata/base.api", nil)
|
||||||
assertx.Error(t, err)
|
assertx.Error(t, err)
|
||||||
})
|
})
|
||||||
|
t.Run("link_import", func(t *testing.T) {
|
||||||
|
_, err := Parse("./testdata/link_import.api", nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,15 +85,12 @@ func convert2API(a *ast.AST, importSet map[string]lang.PlaceholderType, is *impo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := api.SelfCheck(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return api, nil
|
return api, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) checkImportStmt() error {
|
func (api *API) checkImportStmt() error {
|
||||||
f := newFilter()
|
f := newFilter()
|
||||||
b := f.addCheckItem("import value expression")
|
b := f.addCheckItem(api.Filename, "import value expression")
|
||||||
for _, v := range api.importStmt {
|
for _, v := range api.importStmt {
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
case *ast.ImportLiteralStmt:
|
case *ast.ImportLiteralStmt:
|
||||||
@@ -110,7 +107,7 @@ func (api *API) checkInfoStmt() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
f := newFilter()
|
f := newFilter()
|
||||||
b := f.addCheckItem("info key expression")
|
b := f.addCheckItem(api.Filename, "info key expression")
|
||||||
for _, v := range api.info.Values {
|
for _, v := range api.info.Values {
|
||||||
b.check(v.Key)
|
b.check(v.Key)
|
||||||
}
|
}
|
||||||
@@ -119,9 +116,9 @@ func (api *API) checkInfoStmt() error {
|
|||||||
|
|
||||||
func (api *API) checkServiceStmt() error {
|
func (api *API) checkServiceStmt() error {
|
||||||
f := newFilter()
|
f := newFilter()
|
||||||
serviceNameChecker := f.addCheckItem("service name expression")
|
serviceNameChecker := f.addCheckItem(api.Filename, "service name expression")
|
||||||
handlerChecker := f.addCheckItem("handler expression")
|
handlerChecker := f.addCheckItem(api.Filename, "handler expression")
|
||||||
pathChecker := f.addCheckItem("path expression")
|
pathChecker := f.addCheckItem(api.Filename, "path expression")
|
||||||
var serviceName = map[string]string{}
|
var serviceName = map[string]string{}
|
||||||
for _, v := range api.ServiceStmts {
|
for _, v := range api.ServiceStmts {
|
||||||
name := strings.TrimSuffix(v.Name.Format(""), "-api")
|
name := strings.TrimSuffix(v.Name.Format(""), "-api")
|
||||||
@@ -150,7 +147,7 @@ func (api *API) checkServiceStmt() error {
|
|||||||
|
|
||||||
func (api *API) checkTypeStmt() error {
|
func (api *API) checkTypeStmt() error {
|
||||||
f := newFilter()
|
f := newFilter()
|
||||||
b := f.addCheckItem("type expression")
|
b := f.addCheckItem(api.Filename, "type expression")
|
||||||
for _, v := range api.TypeStmt {
|
for _, v := range api.TypeStmt {
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
case *ast.TypeLiteralStmt:
|
case *ast.TypeLiteralStmt:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type filterBuilder struct {
|
type filterBuilder struct {
|
||||||
|
filename string
|
||||||
m map[string]placeholder.Type
|
m map[string]placeholder.Type
|
||||||
checkExprName string
|
checkExprName string
|
||||||
errorManager *errorManager
|
errorManager *errorManager
|
||||||
@@ -15,10 +16,11 @@ type filterBuilder struct {
|
|||||||
|
|
||||||
func (b *filterBuilder) check(nodes ...*ast.TokenNode) {
|
func (b *filterBuilder) check(nodes ...*ast.TokenNode) {
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
if _, ok := b.m[node.Token.Text]; ok {
|
fileNodeText := fmt.Sprintf("%s/%s", b.filename, node.Token.Text)
|
||||||
|
if _, ok := b.m[fileNodeText]; ok {
|
||||||
b.errorManager.add(ast.DuplicateStmtError(node.Pos(), "duplicate "+b.checkExprName))
|
b.errorManager.add(ast.DuplicateStmtError(node.Pos(), "duplicate "+b.checkExprName))
|
||||||
} else {
|
} else {
|
||||||
b.m[node.Token.Text] = placeholder.PlaceHolder
|
b.m[fileNodeText] = placeholder.PlaceHolder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,8 +48,9 @@ func newFilter() *filter {
|
|||||||
return &filter{}
|
return &filter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filter) addCheckItem(checkExprName string) *filterBuilder {
|
func (f *filter) addCheckItem(filename, checkExprName string) *filterBuilder {
|
||||||
b := &filterBuilder{
|
b := &filterBuilder{
|
||||||
|
filename: filename,
|
||||||
m: make(map[string]placeholder.Type),
|
m: make(map[string]placeholder.Type),
|
||||||
checkExprName: checkExprName,
|
checkExprName: checkExprName,
|
||||||
errorManager: newErrorManager(),
|
errorManager: newErrorManager(),
|
||||||
|
|||||||
6
tools/goctl/pkg/parser/api/parser/testdata/base/request.api
vendored
Normal file
6
tools/goctl/pkg/parser/api/parser/testdata/base/request.api
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
type Baz {
|
||||||
|
Foo string `json:"foo"`
|
||||||
|
Baz bool `json:"bar"`
|
||||||
|
}
|
||||||
10
tools/goctl/pkg/parser/api/parser/testdata/base/response.api
vendored
Normal file
10
tools/goctl/pkg/parser/api/parser/testdata/base/response.api
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
import "request.api"
|
||||||
|
type Bar {
|
||||||
|
Foo int `json:"foo"`
|
||||||
|
Bar bool `json:"bar"`
|
||||||
|
Baz
|
||||||
|
Qux map[string]string `json:"qux"`
|
||||||
|
}
|
||||||
|
|
||||||
12
tools/goctl/pkg/parser/api/parser/testdata/link_import.api
vendored
Normal file
12
tools/goctl/pkg/parser/api/parser/testdata/link_import.api
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
import "base/request.api"
|
||||||
|
import "base/response.api"
|
||||||
|
|
||||||
|
type Foo {}
|
||||||
|
|
||||||
|
service demo {
|
||||||
|
@handler handlerName
|
||||||
|
get /users/id/:userId (Baz) returns (Bar)
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user