diff --git a/changelog.md b/changelog.md index 965ec47539..281a4f96d6 100644 --- a/changelog.md +++ b/changelog.md @@ -49,6 +49,7 @@ - [#3661](https://github.com/ignite/cli/pull/3661) Change `pkg/cosmosanalysis` to find Cosmos SDK runtime app registered modules - [#3716](https://github.com/ignite/cli/pull/3716) Fix invalid plugin hook check - [#3725](https://github.com/ignite/cli/pull/3725) Fix flaky TS client generation issues on linux +- [#3728](https://github.com/ignite/cli/pull/3728) Fix wrong parser for proto package names - [#3729](https://github.com/ignite/cli/pull/3729) Fix broken generator due to caching /tmp include folders ## [`v0.27.0`](https://github.com/ignite/cli/releases/tag/v0.27.0) diff --git a/go.mod b/go.mod index d3731f4876..8a1c602d74 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.1.0 - github.com/emicklei/proto v1.11.2 + github.com/emicklei/proto v1.12.1 github.com/emicklei/proto-contrib v0.14.0 github.com/go-delve/delve v1.20.2 github.com/go-git/go-git/v5 v5.6.1 diff --git a/go.sum b/go.sum index 39fb1d6f31..46700334e2 100644 --- a/go.sum +++ b/go.sum @@ -405,8 +405,8 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/emicklei/proto v1.11.1/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= -github.com/emicklei/proto v1.11.2 h1:DiIeyTJ+gPSyJI+RIAqvuTeKb0tLUmaGXbYg6aFKsnE= -github.com/emicklei/proto v1.11.2/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/emicklei/proto v1.12.1 h1:6n/Z2pZAnBwuhU66Gs8160B8rrrYKo7h2F2sCOnNceE= +github.com/emicklei/proto v1.12.1/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= github.com/emicklei/proto-contrib v0.14.0 h1:wFdptRZZ+JpkJtKTqOt2sXNPgwRGUkPzUL44cK9cMGE= github.com/emicklei/proto-contrib v0.14.0/go.mod h1:fpwMx68czS8x9ithaRGdLioTAadH01LLmND1Mr+FvP0= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= diff --git a/ignite/pkg/cosmosanalysis/module/module.go b/ignite/pkg/cosmosanalysis/module/module.go index 257aca07b5..0b506cb393 100644 --- a/ignite/pkg/cosmosanalysis/module/module.go +++ b/ignite/pkg/cosmosanalysis/module/module.go @@ -230,9 +230,8 @@ func (d *moduleDiscoverer) discover(pkg protoanalysis.Package) (Module, error) { return Module{}, nil } - namesplit := strings.Split(pkg.Name, ".") m := Module{ - Name: namesplit[len(namesplit)-1], + Name: pkg.ModuleName(), GoModulePath: d.basegopath, Pkg: pkg, } diff --git a/ignite/pkg/protoanalysis/package.go b/ignite/pkg/protoanalysis/package.go index 017d548452..9beb7122cc 100644 --- a/ignite/pkg/protoanalysis/package.go +++ b/ignite/pkg/protoanalysis/package.go @@ -1,58 +1,53 @@ package protoanalysis import ( + "errors" + "regexp" "strings" - "github.com/pkg/errors" + "golang.org/x/mod/semver" ) -type Packages []Package +type ( + // Packages represents slice of Package. + Packages []Package -func (p Packages) Files() Files { - var files []File - for _, pkg := range p { - files = append(files, pkg.Files...) - } - return files -} - -// Package represents a proto pkg. -type Package struct { - // Name of the proto pkg. - Name string `json:"name,omitempty"` - - // Path of the package in the fs. - Path string `json:"path,omitempty"` + PkgName string - // Files is a list of .proto files in the package. - Files Files `json:"files,omitempty"` + // Package represents a proto pkg. + Package struct { + // Name of the proto pkg. + Name string `json:"name,omitempty"` - // GoImportName is the go package name of proto package. - GoImportName string `json:"go_import_name,omitempty"` + // Path of the package in the fs. + Path string `json:"path,omitempty"` - // Messages is a list of proto messages defined in the package. - Messages []Message `json:"messages,omitempty"` + // Files is a list of .proto files in the package. + Files Files `json:"files,omitempty"` - // Services is a list of RPC services. - Services []Service `json:"services,omitempty"` -} + // GoImportName is the go package name of proto package. + GoImportName string `json:"go_import_name,omitempty"` -type Files []File + // Messages is a list of proto messages defined in the package. + Messages []Message `json:"messages,omitempty"` -type File struct { - // Path of the file. - Path string `json:"path,omitempty"` + // Services is a list of RPC services. + Services []Service `json:"services,omitempty"` + } +) - // Dependencies is a list of imported proto packages. - Dependencies []string `json:"dependencies,omitempty"` -} +var regexBetaVersion = regexp.MustCompile("^v[0-9]+(beta|alpha)[0-9]+") -func (f Files) Paths() []string { - var paths []string - for _, ff := range f { - paths = append(paths, ff.Path) +// ModuleName retrieves the single module name of the package. +func (p Package) ModuleName() (name string) { + names := strings.Split(p.Name, ".") + for i := len(names) - 1; i >= 0; i-- { + name = names[i] + if !semver.IsValid(name) && !regexBetaVersion.MatchString(name) { + break + } } - return paths + return } // MessageByName finds a message by its name inside Package. @@ -70,59 +65,91 @@ func (p Package) GoImportPath() string { return strings.Split(p.GoImportName, ";")[0] } -// Message represents a proto message. -type Message struct { - // Name of the message. - Name string `json:"name,omitempty"` +// Files retrieves the files from the package list. +func (p Packages) Files() Files { + var files []File + for _, pkg := range p { + files = append(files, pkg.Files...) + } + return files +} + +type ( + Files []File - // Path of the proto file where the message is defined. - Path string `json:"path,omitempty"` + File struct { + // Path of the file. + Path string `json:"path,omitempty"` - // HighestFieldNumber is the highest field number among fields of the message. - // This allows to determine new field number when writing to proto message. - HighestFieldNumber int `json:"highest_field_number,omitempty"` + // Dependencies is a list of imported proto packages. + Dependencies []string `json:"dependencies,omitempty"` + } +) - // Fields contains message's field names and types. - Fields map[string]string `json:"fields,omitempty"` +// Paths retrieves the list of paths from the files. +func (f Files) Paths() []string { + var paths []string + for _, ff := range f { + paths = append(paths, ff.Path) + } + return paths } -// Service is an RPC service. -type Service struct { - // Name of the services. - Name string `json:"name,omitempty"` +type ( + // Message represents a proto message. + Message struct { + // Name of the message. + Name string `json:"name,omitempty"` - // RPCFuncs is a list of RPC funcs of the service. - RPCFuncs []RPCFunc `json:"functions,omitempty"` -} + // Path of the proto file where the message is defined. + Path string `json:"path,omitempty"` -// RPCFunc is an RPC func. -type RPCFunc struct { - // Name of the RPC func. - Name string `json:"name,omitempty"` + // HighestFieldNumber is the highest field number among fields of the message. + // This allows to determine new field number when writing to proto message. + HighestFieldNumber int `json:"highest_field_number,omitempty"` - // RequestType is the request type of RPC func. - RequestType string `json:"request_type,omitempty"` + // Fields contains message's field names and types. + Fields map[string]string `json:"fields,omitempty"` + } - // ReturnsType is the response type of RPC func. - ReturnsType string `json:"return_type,omitempty"` + // Service is an RPC service. + Service struct { + // Name of the services. + Name string `json:"name,omitempty"` - // HTTPRules keeps info about http rules of an RPC func. - // spec: - // https://github.com/googleapis/googleapis/blob/master/google/api/http.proto. - HTTPRules []HTTPRule `json:"http_rules,omitempty"` + // RPCFuncs is a list of RPC funcs of the service. + RPCFuncs []RPCFunc `json:"functions,omitempty"` + } - // Paginated indicates that the RPC function is using pagination. - Paginated bool `json:"paginated,omitempty"` -} + // RPCFunc is an RPC func. + RPCFunc struct { + // Name of the RPC func. + Name string `json:"name,omitempty"` -// HTTPRule keeps info about a configured http rule of an RPC func. -type HTTPRule struct { - // Params is a list of parameters defined in the HTTP endpoint itself. - Params []string `json:"params,omitempty"` + // RequestType is the request type of RPC func. + RequestType string `json:"request_type,omitempty"` - // HasQuery indicates if there is a request query. - HasQuery bool `json:"has_query,omitempty"` + // ReturnsType is the response type of RPC func. + ReturnsType string `json:"return_type,omitempty"` - // HasBody indicates if there is a request payload. - HasBody bool `json:"has_body,omitempty"` -} + // HTTPRules keeps info about http rules of an RPC func. + // spec: + // https://github.com/googleapis/googleapis/blob/master/google/api/http.proto. + HTTPRules []HTTPRule `json:"http_rules,omitempty"` + + // Paginated indicates that the RPC function is using pagination. + Paginated bool `json:"paginated,omitempty"` + } + + // HTTPRule keeps info about a configured http rule of an RPC func. + HTTPRule struct { + // Params is a list of parameters defined in the HTTP endpoint itself. + Params []string `json:"params,omitempty"` + + // HasQuery indicates if there is a request query. + HasQuery bool `json:"has_query,omitempty"` + + // HasBody indicates if there is a request payload. + HasBody bool `json:"has_body,omitempty"` + } +) diff --git a/ignite/pkg/protoanalysis/package_test.go b/ignite/pkg/protoanalysis/package_test.go new file mode 100644 index 0000000000..e21c597f65 --- /dev/null +++ b/ignite/pkg/protoanalysis/package_test.go @@ -0,0 +1,82 @@ +package protoanalysis + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestPackage_ModuleName(t *testing.T) { + tests := []struct { + name string + p Package + want string + }{ + { + name: "test single name", + p: Package{Name: "staking"}, + want: "staking", + }, + { + name: "test two names", + p: Package{Name: "cosmos.staking"}, + want: "staking", + }, + { + name: "test three name", + p: Package{Name: "cosmos.ignite.staking"}, + want: "staking", + }, + { + name: "test with the version 1", + p: Package{Name: "cosmos.staking.v1"}, + want: "staking", + }, + { + name: "test with the version 2", + p: Package{Name: "cosmos.staking.v2"}, + want: "staking", + }, + { + name: "test with the version 10", + p: Package{Name: "cosmos.staking.v10"}, + want: "staking", + }, + { + name: "test with the version 1 beta 1", + p: Package{Name: "cosmos.staking.v1beta1"}, + want: "staking", + }, + { + name: "test with the version 1 beta 2", + p: Package{Name: "cosmos.staking.v1beta2"}, + want: "staking", + }, + { + name: "test with the version 2 beta 1", + p: Package{Name: "cosmos.staking.v2beta1"}, + want: "staking", + }, + { + name: "test with the version 2 beta 2", + p: Package{Name: "cosmos.staking.v2beta2"}, + want: "staking", + }, + { + name: "test with the version 3 alpha 5", + p: Package{Name: "cosmos.staking.v3alpha5"}, + want: "staking", + }, + { + name: "test with the wrong version", + p: Package{Name: "cosmos.staking.v3bank5"}, + want: "v3bank5", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.p.ModuleName() + require.Equal(t, tt.want, got) + }) + } +} diff --git a/ignite/services/chain/generate.go b/ignite/services/chain/generate.go index 64f5570b6e..2cfbf26efb 100644 --- a/ignite/services/chain/generate.go +++ b/ignite/services/chain/generate.go @@ -179,7 +179,7 @@ func (c *Chain) Generate( openAPIPath = chainconfig.DefaultOpenAPIPath } - // Non absolute OpenAPI paths must be treated as relative to the app directory + // Non-absolute OpenAPI paths must be treated as relative to the app directory if !filepath.IsAbs(openAPIPath) { openAPIPath = filepath.Join(c.app.Path, openAPIPath) } @@ -200,7 +200,7 @@ func (c *Chain) Generate( } } - // Non absolute TS client output paths must be treated as relative to the app directory + // Non-absolute TS client output paths must be treated as relative to the app directory if !filepath.IsAbs(tsClientPath) { tsClientPath = filepath.Join(c.app.Path, tsClientPath) } @@ -225,7 +225,7 @@ func (c *Chain) Generate( updateConfig = true } - // Non absolute Vuex output paths must be treated as relative to the app directory + // Non-absolute Vuex output paths must be treated as relative to the app directory if !filepath.IsAbs(vuexPath) { vuexPath = filepath.Join(c.app.Path, vuexPath) } @@ -251,7 +251,7 @@ func (c *Chain) Generate( } } - // Non absolute Composables output paths must be treated as relative to the app directory + // Non-absolute Composables output paths must be treated as relative to the app directory if !filepath.IsAbs(composablesPath) { composablesPath = filepath.Join(c.app.Path, composablesPath) } @@ -275,7 +275,7 @@ func (c *Chain) Generate( } } - // Non absolute Hooks output paths must be treated as relative to the app directory + // Non-absolute Hooks output paths must be treated as relative to the app directory if !filepath.IsAbs(hooksPath) { hooksPath = filepath.Join(c.app.Path, hooksPath) }