mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-14 10:20:00 +08:00
fix(goctl): allow duplicate_path_expression under different prefix (#4626)
This commit is contained in:
@@ -14,69 +14,97 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Test_Parse(t *testing.T) {
|
func Test_Parse(t *testing.T) {
|
||||||
t.Run("valid", func(t *testing.T) {
|
t.Run(
|
||||||
apiSpec, err := Parse("./testdata/example.api", nil)
|
"valid", func(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
apiSpec, err := Parse("./testdata/example.api", nil)
|
||||||
ast := assert.New(t)
|
assert.Nil(t, err)
|
||||||
ast.Equal(spec.Info{
|
ast := assert.New(t)
|
||||||
Title: "type title here",
|
ast.Equal(
|
||||||
Desc: "type desc here",
|
spec.Info{
|
||||||
Version: "type version here",
|
Title: "type title here",
|
||||||
Author: "type author here",
|
Desc: "type desc here",
|
||||||
Email: "type email here",
|
Version: "type version here",
|
||||||
Properties: map[string]string{
|
Author: "type author here",
|
||||||
"title": "type title here",
|
Email: "type email here",
|
||||||
"desc": "type desc here",
|
Properties: map[string]string{
|
||||||
"version": "type version here",
|
"title": "type title here",
|
||||||
"author": "type author here",
|
"desc": "type desc here",
|
||||||
"email": "type email here",
|
"version": "type version here",
|
||||||
},
|
"author": "type author here",
|
||||||
}, apiSpec.Info)
|
"email": "type email here",
|
||||||
ast.True(func() bool {
|
},
|
||||||
for _, group := range apiSpec.Service.Groups {
|
}, apiSpec.Info,
|
||||||
value, ok := group.Annotation.Properties["summary"]
|
)
|
||||||
if ok {
|
ast.True(
|
||||||
return value == "test"
|
func() bool {
|
||||||
}
|
for _, group := range apiSpec.Service.Groups {
|
||||||
}
|
value, ok := group.Annotation.Properties["summary"]
|
||||||
return false
|
if ok {
|
||||||
}())
|
return value == "test"
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
t.Run("invalid", func(t *testing.T) {
|
t.Run(
|
||||||
data, err := os.ReadFile("./testdata/invalid.api")
|
"invalid", func(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
data, err := os.ReadFile("./testdata/invalid.api")
|
||||||
splits := bytes.Split(data, []byte("-----"))
|
|
||||||
var testFile []string
|
|
||||||
for idx, split := range splits {
|
|
||||||
replacer := strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\f", "")
|
|
||||||
r := replacer.Replace(string(split))
|
|
||||||
if len(r) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
filename := filepath.Join(t.TempDir(), fmt.Sprintf("invalid%d.api", idx))
|
|
||||||
err := os.WriteFile(filename, split, 0666)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
testFile = append(testFile, filename)
|
splits := bytes.Split(data, []byte("-----"))
|
||||||
}
|
var testFile []string
|
||||||
for _, v := range testFile {
|
for idx, split := range splits {
|
||||||
_, err := Parse(v, nil)
|
replacer := strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\f", "")
|
||||||
|
r := replacer.Replace(string(split))
|
||||||
|
if len(r) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
filename := filepath.Join(t.TempDir(), fmt.Sprintf("invalid%d.api", idx))
|
||||||
|
err := os.WriteFile(filename, split, 0666)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
testFile = append(testFile, filename)
|
||||||
|
}
|
||||||
|
for _, v := range testFile {
|
||||||
|
_, err := Parse(v, nil)
|
||||||
|
assertx.Error(t, err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"circleImport", func(t *testing.T) {
|
||||||
|
_, err := Parse("./testdata/base.api", nil)
|
||||||
assertx.Error(t, err)
|
assertx.Error(t, err)
|
||||||
}
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
t.Run("circleImport", func(t *testing.T) {
|
t.Run(
|
||||||
_, err := Parse("./testdata/base.api", nil)
|
"link_import", func(t *testing.T) {
|
||||||
assertx.Error(t, err)
|
_, err := Parse("./testdata/link_import.api", nil)
|
||||||
})
|
assert.Nil(t, err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
t.Run("link_import", func(t *testing.T) {
|
t.Run(
|
||||||
_, err := Parse("./testdata/link_import.api", nil)
|
"duplicate_types", func(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
_, err := Parse("./testdata/duplicate_type.api", nil)
|
||||||
})
|
assertx.Error(t, err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
t.Run("duplicate_types", func(t *testing.T) {
|
t.Run(
|
||||||
_, err := Parse("./testdata/duplicate_type.api", nil)
|
"duplicate_path_expression", func(t *testing.T) {
|
||||||
assertx.Error(t, err)
|
_, err := Parse("./testdata/duplicate_path_expression.api", nil)
|
||||||
})
|
assertx.Error(t, err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
t.Run(
|
||||||
|
"duplicate_path_expression_different_prefix", func(t *testing.T) {
|
||||||
|
_, err := Parse("./testdata/duplicate_path_expression_different_prefix.api", nil)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
atServerGroupKey = "group:"
|
atServerGroupKey = "group"
|
||||||
atServerPrefixKey = "prefix:"
|
atServerPrefixKey = "prefix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// API is the parsed api file.
|
// API is the parsed api file.
|
||||||
@@ -38,18 +38,24 @@ func convert2API(a *ast.AST, importSet map[string]lang.PlaceholderType, is *impo
|
|||||||
syntax, ok := one.(*ast.SyntaxStmt)
|
syntax, ok := one.(*ast.SyntaxStmt)
|
||||||
if !ok {
|
if !ok {
|
||||||
syntax = &ast.SyntaxStmt{
|
syntax = &ast.SyntaxStmt{
|
||||||
Syntax: ast.NewTokenNode(token.Token{
|
Syntax: ast.NewTokenNode(
|
||||||
Type: token.IDENT,
|
token.Token{
|
||||||
Text: token.Syntax,
|
Type: token.IDENT,
|
||||||
}),
|
Text: token.Syntax,
|
||||||
Assign: ast.NewTokenNode(token.Token{
|
},
|
||||||
Type: token.ASSIGN,
|
),
|
||||||
Text: "=",
|
Assign: ast.NewTokenNode(
|
||||||
}),
|
token.Token{
|
||||||
Value: ast.NewTokenNode(token.Token{
|
Type: token.ASSIGN,
|
||||||
Type: token.STRING,
|
Text: "=",
|
||||||
Text: `"v1"`,
|
},
|
||||||
}),
|
),
|
||||||
|
Value: ast.NewTokenNode(
|
||||||
|
token.Token{
|
||||||
|
Type: token.STRING,
|
||||||
|
Text: `"v1"`,
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,10 +139,14 @@ func (api *API) checkServiceStmt() error {
|
|||||||
for _, item := range v.Routes {
|
for _, item := range v.Routes {
|
||||||
handlerChecker.checkNodeWithPrefix(group, item.AtHandler.Name)
|
handlerChecker.checkNodeWithPrefix(group, item.AtHandler.Name)
|
||||||
path := fmt.Sprintf("[%s]:%s", prefix, item.Route.Format(""))
|
path := fmt.Sprintf("[%s]:%s", prefix, item.Route.Format(""))
|
||||||
pathChecker.check(ast.NewTokenNode(token.Token{
|
pathChecker.check(
|
||||||
Text: path,
|
ast.NewTokenNode(
|
||||||
Position: item.Route.Pos(),
|
token.Token{
|
||||||
}))
|
Text: path,
|
||||||
|
Position: item.Route.Pos(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return f.error()
|
return f.error()
|
||||||
@@ -237,7 +247,8 @@ func (api *API) getAtServerValue(atServer *ast.AtServerStmt, key string) string
|
|||||||
|
|
||||||
func (api *API) mergeAPI(in *API) error {
|
func (api *API) mergeAPI(in *API) error {
|
||||||
if api.Syntax.Value.Format() != in.Syntax.Value.Format() {
|
if api.Syntax.Value.Format() != in.Syntax.Value.Format() {
|
||||||
return ast.SyntaxError(in.Syntax.Value.Pos(),
|
return ast.SyntaxError(
|
||||||
|
in.Syntax.Value.Pos(),
|
||||||
"multiple syntax value expression, expected <%s>, got <%s>",
|
"multiple syntax value expression, expected <%s>, got <%s>",
|
||||||
api.Syntax.Value.Format(),
|
api.Syntax.Value.Format(),
|
||||||
in.Syntax.Value.Format(),
|
in.Syntax.Value.Format(),
|
||||||
|
|||||||
21
tools/goctl/pkg/parser/api/parser/testdata/duplicate_path_expression.api
vendored
Normal file
21
tools/goctl/pkg/parser/api/parser/testdata/duplicate_path_expression.api
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
@server (
|
||||||
|
group: path2
|
||||||
|
middleware: Path
|
||||||
|
prefix: /v1/v3
|
||||||
|
timeout: 100ms
|
||||||
|
)
|
||||||
|
service example {
|
||||||
|
@doc (
|
||||||
|
desc: "path demo"
|
||||||
|
)
|
||||||
|
@handler getPath1
|
||||||
|
get / (string) returns (string)
|
||||||
|
|
||||||
|
@doc (
|
||||||
|
desc: "path demo"
|
||||||
|
)
|
||||||
|
@handler getPath2
|
||||||
|
get / (string) returns (string)
|
||||||
|
}
|
||||||
2
tools/goctl/pkg/parser/api/parser/testdata/duplicate_path_expression_different_prefix.api
vendored
Normal file
2
tools/goctl/pkg/parser/api/parser/testdata/duplicate_path_expression_different_prefix.api
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import "duplicate_path_expression_different_prefix__prefix_1.api"
|
||||||
|
import "duplicate_path_expression_different_prefix__prefix_2.api"
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
|
||||||
|
@server (
|
||||||
|
group: group2
|
||||||
|
middleware: Path
|
||||||
|
prefix: /v1/group2
|
||||||
|
timeout: 100ms
|
||||||
|
)
|
||||||
|
service example {
|
||||||
|
@doc (
|
||||||
|
desc: "path demo"
|
||||||
|
)
|
||||||
|
@handler getPath2
|
||||||
|
get / (string) returns (string)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
@server (
|
||||||
|
group: group1
|
||||||
|
middleware: Path
|
||||||
|
prefix: /v1/group1
|
||||||
|
timeout: 100ms
|
||||||
|
)
|
||||||
|
service example {
|
||||||
|
@doc (
|
||||||
|
desc: "path demo"
|
||||||
|
)
|
||||||
|
@handler getPath1
|
||||||
|
get / (string) returns (string)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user