mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-13 18:00:00 +08:00
fix(goctl): multi imports the api cause redeclared error in types.go (#3988)
Co-authored-by: Kevin Wan <wanjunfeng@gmail.com>
This commit is contained in:
@@ -2,7 +2,12 @@ package gogen
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"go/ast"
|
||||||
goformat "go/format"
|
goformat "go/format"
|
||||||
|
"go/importer"
|
||||||
|
goparser "go/parser"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -48,6 +53,10 @@ var (
|
|||||||
noStructTagApi string
|
noStructTagApi string
|
||||||
//go:embed testdata/nest_type_api.api
|
//go:embed testdata/nest_type_api.api
|
||||||
nestTypeApi string
|
nestTypeApi string
|
||||||
|
//go:embed testdata/import_twice.api
|
||||||
|
importTwiceApi string
|
||||||
|
//go:embed testdata/another_import_api.api
|
||||||
|
anotherImportApi string
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParser(t *testing.T) {
|
func TestParser(t *testing.T) {
|
||||||
@@ -232,6 +241,46 @@ func TestHasImportApi(t *testing.T) {
|
|||||||
validate(t, filename)
|
validate(t, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestImportTwiceOnExperimental(t *testing.T) {
|
||||||
|
defaultExperimental := env.Get(env.GoctlExperimental)
|
||||||
|
env.Set(t, env.GoctlExperimental, "on")
|
||||||
|
defer env.Set(t, env.GoctlExperimental, defaultExperimental)
|
||||||
|
|
||||||
|
filename := "greet.api"
|
||||||
|
err := os.WriteFile(filename, []byte(importTwiceApi), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(filename)
|
||||||
|
|
||||||
|
importApiName := "importApi.api"
|
||||||
|
err = os.WriteFile(importApiName, []byte(importApi), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(importApiName)
|
||||||
|
|
||||||
|
hasImportApiName := "hasImportApi.api"
|
||||||
|
err = os.WriteFile(hasImportApiName, []byte(hasImportApi), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(hasImportApiName)
|
||||||
|
|
||||||
|
anotherImportApiName := "anotherImportApi.api"
|
||||||
|
err = os.WriteFile(anotherImportApiName, []byte(anotherImportApi), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(anotherImportApiName)
|
||||||
|
|
||||||
|
api, err := parser.Parse(filename)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
var hasInline bool
|
||||||
|
for _, ty := range api.Types {
|
||||||
|
if ty.Name() == "ImportData" {
|
||||||
|
hasInline = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.True(t, hasInline)
|
||||||
|
|
||||||
|
validate(t, filename)
|
||||||
|
}
|
||||||
|
|
||||||
func TestNoStructApi(t *testing.T) {
|
func TestNoStructApi(t *testing.T) {
|
||||||
filename := "greet.api"
|
filename := "greet.api"
|
||||||
err := os.WriteFile(filename, []byte(noStructTagApi), os.ModePerm)
|
err := os.WriteFile(filename, []byte(noStructTagApi), os.ModePerm)
|
||||||
@@ -287,6 +336,9 @@ func validateWithCamel(t *testing.T, api, camel string) {
|
|||||||
code, err := os.ReadFile(path)
|
code, err := os.ReadFile(path)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Nil(t, validateCode(string(code)))
|
assert.Nil(t, validateCode(string(code)))
|
||||||
|
if strings.HasSuffix(path, "types.go") {
|
||||||
|
assert.Nil(t, checkRedeclaredType(string(code)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -301,3 +353,20 @@ func validateCode(code string) error {
|
|||||||
_, err := goformat.Source([]byte(code))
|
_, err := goformat.Source([]byte(code))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkRedeclaredType(code string) error {
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
f, err := goparser.ParseFile(fset, "", code, goparser.ParseComments)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := types.Config{
|
||||||
|
Error: func(err error) {},
|
||||||
|
Importer: importer.Default(),
|
||||||
|
}
|
||||||
|
|
||||||
|
info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
|
||||||
|
_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &info)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
17
tools/goctl/api/gogen/testdata/another_import_api.api
vendored
Normal file
17
tools/goctl/api/gogen/testdata/another_import_api.api
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import "importApi.api"
|
||||||
|
|
||||||
|
type AnotherRequest {
|
||||||
|
Name string `path:"name,options=you|me"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnotherResponse {
|
||||||
|
Message string `json:"message"` // message
|
||||||
|
}
|
||||||
|
|
||||||
|
@server(
|
||||||
|
group: greet
|
||||||
|
)
|
||||||
|
service A-api {
|
||||||
|
@handler AnotherImportHandler
|
||||||
|
get /greet/from/another/:name(AnotherRequest) returns (AnotherResponse)
|
||||||
|
}
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
import "importApi.api"
|
import "importApi.api"
|
||||||
|
|
||||||
type Request struct {
|
type Request {
|
||||||
Name string `path:"name,options=you|me"`
|
Name string `path:"name,options=you|me"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
type Response {
|
||||||
Message string `json:"message"` // message
|
Message string `json:"message"` // message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@server(
|
||||||
|
group: greet
|
||||||
|
)
|
||||||
service A-api {
|
service A-api {
|
||||||
@server(
|
@handler GreetHandler
|
||||||
handler: GreetHandler
|
|
||||||
)
|
|
||||||
get /greet/from/:name(Request) returns (Response)
|
get /greet/from/:name(Request) returns (Response)
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
type ImportData struct {
|
type ImportData {
|
||||||
Name string `path:"name,options=you|me"`
|
Name string `path:"name,options=you|me"`
|
||||||
}
|
}
|
||||||
2
tools/goctl/api/gogen/testdata/import_twice.api
vendored
Normal file
2
tools/goctl/api/gogen/testdata/import_twice.api
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import "hasImportApi.api"
|
||||||
|
import "anotherImportApi.api"
|
||||||
@@ -32,11 +32,8 @@ type API struct {
|
|||||||
func convert2API(a *ast.AST, importSet map[string]lang.PlaceholderType, is *importstack.ImportStack) (*API, error) {
|
func convert2API(a *ast.AST, importSet map[string]lang.PlaceholderType, is *importstack.ImportStack) (*API, error) {
|
||||||
var api = new(API)
|
var api = new(API)
|
||||||
api.importManager = is
|
api.importManager = is
|
||||||
api.importSet = make(map[string]lang.PlaceholderType)
|
api.importSet = importSet
|
||||||
api.Filename = a.Filename
|
api.Filename = a.Filename
|
||||||
for k, v := range importSet {
|
|
||||||
api.importSet[k] = v
|
|
||||||
}
|
|
||||||
one := a.Stmts[0]
|
one := a.Stmts[0]
|
||||||
syntax, ok := one.(*ast.SyntaxStmt)
|
syntax, ok := one.(*ast.SyntaxStmt)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
Reference in New Issue
Block a user