From b4905359ac0cedbf10e57a0ca498eca73b31e2fe Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 12:08:30 -0400 Subject: [PATCH 01/25] feat: implement autocli customization --- client/v2/{cli => autocli}/builder.go | 4 ++-- client/v2/{cli => autocli}/flag/address.go | 0 client/v2/{cli => autocli}/flag/builder.go | 0 client/v2/{cli => autocli}/flag/duration.go | 0 client/v2/{cli => autocli}/flag/enum.go | 0 client/v2/{cli => autocli}/flag/field.go | 0 client/v2/{cli => autocli}/flag/list.go | 0 client/v2/{cli => autocli}/flag/message.go | 0 client/v2/{cli => autocli}/flag/pagination.go | 0 client/v2/{cli => autocli}/flag/register.go | 0 client/v2/{cli => autocli}/flag/simple.go | 0 client/v2/{cli => autocli}/flag/timestamp.go | 0 client/v2/{cli => autocli}/flag/type.go | 0 client/v2/{cli => autocli}/flag/value.go | 0 client/v2/{cli => autocli}/query.go | 5 +++-- client/v2/{cli => autocli}/query_test.go | 2 +- client/v2/{cli => autocli}/testdata/bank_example.yaml | 0 client/v2/{cli => autocli}/testdata/help.golden | 0 18 files changed, 6 insertions(+), 5 deletions(-) rename client/v2/{cli => autocli}/builder.go (84%) rename client/v2/{cli => autocli}/flag/address.go (100%) rename client/v2/{cli => autocli}/flag/builder.go (100%) rename client/v2/{cli => autocli}/flag/duration.go (100%) rename client/v2/{cli => autocli}/flag/enum.go (100%) rename client/v2/{cli => autocli}/flag/field.go (100%) rename client/v2/{cli => autocli}/flag/list.go (100%) rename client/v2/{cli => autocli}/flag/message.go (100%) rename client/v2/{cli => autocli}/flag/pagination.go (100%) rename client/v2/{cli => autocli}/flag/register.go (100%) rename client/v2/{cli => autocli}/flag/simple.go (100%) rename client/v2/{cli => autocli}/flag/timestamp.go (100%) rename client/v2/{cli => autocli}/flag/type.go (100%) rename client/v2/{cli => autocli}/flag/value.go (100%) rename client/v2/{cli => autocli}/query.go (97%) rename client/v2/{cli => autocli}/query_test.go (99%) rename client/v2/{cli => autocli}/testdata/bank_example.yaml (100%) rename client/v2/{cli => autocli}/testdata/help.golden (100%) diff --git a/client/v2/cli/builder.go b/client/v2/autocli/builder.go similarity index 84% rename from client/v2/cli/builder.go rename to client/v2/autocli/builder.go index 992fc9df4e74..f2770b0623f9 100644 --- a/client/v2/cli/builder.go +++ b/client/v2/autocli/builder.go @@ -1,11 +1,11 @@ -package cli +package autocli import ( "context" "google.golang.org/grpc" - "github.com/cosmos/cosmos-sdk/client/v2/cli/flag" + "github.com/cosmos/cosmos-sdk/client/v2/autocli/flag" ) // Builder manages options for building CLI commands. diff --git a/client/v2/cli/flag/address.go b/client/v2/autocli/flag/address.go similarity index 100% rename from client/v2/cli/flag/address.go rename to client/v2/autocli/flag/address.go diff --git a/client/v2/cli/flag/builder.go b/client/v2/autocli/flag/builder.go similarity index 100% rename from client/v2/cli/flag/builder.go rename to client/v2/autocli/flag/builder.go diff --git a/client/v2/cli/flag/duration.go b/client/v2/autocli/flag/duration.go similarity index 100% rename from client/v2/cli/flag/duration.go rename to client/v2/autocli/flag/duration.go diff --git a/client/v2/cli/flag/enum.go b/client/v2/autocli/flag/enum.go similarity index 100% rename from client/v2/cli/flag/enum.go rename to client/v2/autocli/flag/enum.go diff --git a/client/v2/cli/flag/field.go b/client/v2/autocli/flag/field.go similarity index 100% rename from client/v2/cli/flag/field.go rename to client/v2/autocli/flag/field.go diff --git a/client/v2/cli/flag/list.go b/client/v2/autocli/flag/list.go similarity index 100% rename from client/v2/cli/flag/list.go rename to client/v2/autocli/flag/list.go diff --git a/client/v2/cli/flag/message.go b/client/v2/autocli/flag/message.go similarity index 100% rename from client/v2/cli/flag/message.go rename to client/v2/autocli/flag/message.go diff --git a/client/v2/cli/flag/pagination.go b/client/v2/autocli/flag/pagination.go similarity index 100% rename from client/v2/cli/flag/pagination.go rename to client/v2/autocli/flag/pagination.go diff --git a/client/v2/cli/flag/register.go b/client/v2/autocli/flag/register.go similarity index 100% rename from client/v2/cli/flag/register.go rename to client/v2/autocli/flag/register.go diff --git a/client/v2/cli/flag/simple.go b/client/v2/autocli/flag/simple.go similarity index 100% rename from client/v2/cli/flag/simple.go rename to client/v2/autocli/flag/simple.go diff --git a/client/v2/cli/flag/timestamp.go b/client/v2/autocli/flag/timestamp.go similarity index 100% rename from client/v2/cli/flag/timestamp.go rename to client/v2/autocli/flag/timestamp.go diff --git a/client/v2/cli/flag/type.go b/client/v2/autocli/flag/type.go similarity index 100% rename from client/v2/cli/flag/type.go rename to client/v2/autocli/flag/type.go diff --git a/client/v2/cli/flag/value.go b/client/v2/autocli/flag/value.go similarity index 100% rename from client/v2/cli/flag/value.go rename to client/v2/autocli/flag/value.go diff --git a/client/v2/cli/query.go b/client/v2/autocli/query.go similarity index 97% rename from client/v2/cli/query.go rename to client/v2/autocli/query.go index 28c02a4a79b8..3166d094e910 100644 --- a/client/v2/cli/query.go +++ b/client/v2/autocli/query.go @@ -1,4 +1,4 @@ -package cli +package autocli import ( "fmt" @@ -9,7 +9,8 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" - "github.com/cosmos/cosmos-sdk/client/v2/cli/flag" + "github.com/cosmos/cosmos-sdk/client/v2/autocli/flag" + "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) diff --git a/client/v2/cli/query_test.go b/client/v2/autocli/query_test.go similarity index 99% rename from client/v2/cli/query_test.go rename to client/v2/autocli/query_test.go index 6d6c96c49f74..81b442583b16 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/autocli/query_test.go @@ -1,4 +1,4 @@ -package cli +package autocli import ( "bytes" diff --git a/client/v2/cli/testdata/bank_example.yaml b/client/v2/autocli/testdata/bank_example.yaml similarity index 100% rename from client/v2/cli/testdata/bank_example.yaml rename to client/v2/autocli/testdata/bank_example.yaml diff --git a/client/v2/cli/testdata/help.golden b/client/v2/autocli/testdata/help.golden similarity index 100% rename from client/v2/cli/testdata/help.golden rename to client/v2/autocli/testdata/help.golden From f8dd7d22abae8cd0d2cc0903bc93bfdb39322f6d Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 12:33:28 -0400 Subject: [PATCH 02/25] WIP --- client/v2/autocli/query.go | 67 ++++++++++++++++++++++++++++++--- client/v2/autocli/query_test.go | 5 ++- client/v2/autocli/validate.go | 57 ++++++++++++++++++++++++++++ client/v2/go.mod | 2 +- client/v2/go.sum | 4 +- simapp/simd/cmd/root.go | 1 + 6 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 client/v2/autocli/validate.go diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index 3166d094e910..3e998a23d76a 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -3,6 +3,7 @@ package autocli import ( "fmt" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "github.com/iancoleman/strcase" "github.com/spf13/cobra" "google.golang.org/protobuf/encoding/protojson" @@ -14,14 +15,49 @@ import ( "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) +func (b *Builder) BuildQueryCommand(moduleOptions map[string]*autocliv1.ModuleOptions, customCmds map[string]*cobra.Command) (*cobra.Command, error) { + queryCmd := topLevelCmd("query", "Querying subcommands") + queryCmd.Aliases = []string{"q"} + for moduleName, modOpts := range moduleOptions { + if customCmds[moduleName] != nil { + // custom commands get added lower down + continue + } + + queryCmdDesc := modOpts.Query + if queryCmdDesc != nil { + cmd, err := b.BuildModuleQueryCommand(moduleName, queryCmdDesc) + if err != nil { + return nil, err + } + + queryCmd.AddCommand(cmd) + } + } + + for _, cmd := range customCmds { + queryCmd.AddCommand(cmd) + } + + return queryCmd, nil +} + +func (b *Builder) BuildModuleQueryCommand(moduleName string, cmdDescriptor *autocliv1.ServiceCommandDescriptor) (*cobra.Command, error) { + cmd := topLevelCmd(moduleName, fmt.Sprintf("Querying commands for the %s module", moduleName)) + + b.AddQueryServiceCommands(cmd, cmdDescriptor) + + return cmd, nil +} + // AddQueryServiceCommands adds a sub-command to the provided command for each // method in the specified service and returns the command. -func (b *Builder) AddQueryServiceCommands(command *cobra.Command, serviceName protoreflect.FullName) *cobra.Command { +func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor *autocliv1.ServiceCommandDescriptor) { resolver := b.FileResolver if resolver == nil { resolver = protoregistry.GlobalFiles } - descriptor, err := resolver.FindDescriptorByName(serviceName) + descriptor, err := resolver.FindDescriptorByName(protoreflect.FullName(cmdDescriptor.Service)) if err != nil { panic(err) } @@ -30,14 +66,25 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, serviceName pr methods := service.Methods() n := methods.Len() for i := 0; i < n; i++ { - cmd := b.CreateQueryMethodCommand(methods.Get(i)) + methodDescriptor := methods.Get(i) + var methodOpts *autocliv1.RpcCommandOptions + for _, option := range cmdDescriptor.RpcCommandOptions { + if protoreflect.Name(option.RpcMethod) == methodDescriptor.Name() { + methodOpts = option + } + } + cmd := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) command.AddCommand(cmd) } - return command + + for cmdName, subCmd := range cmdDescriptor.SubCommands { + cmd := topLevelCmd(cmdName, fmt.Sprintf("Querying commands for the %s service", subCmd.Service)) + b.AddQueryServiceCommands(cmd, subCmd) + } } // CreateQueryMethodCommand creates a gRPC query command for the given service method. -func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor) *cobra.Command { +func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) *cobra.Command { serviceDescriptor := descriptor.Parent().(protoreflect.ServiceDescriptor) docs := util.DescriptorDocs(descriptor) getClientConn := b.GetClientConn @@ -86,3 +133,13 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip func protoNameToCliName(name protoreflect.Name) string { return strcase.ToKebab(string(name)) } + +func topLevelCmd(use, short string) *cobra.Command { + return &cobra.Command{ + Use: use, + Short: short, + DisableFlagParsing: false, + SuggestionsMinimumDistance: 2, + RunE: ValidateCmd, + } +} diff --git a/client/v2/autocli/query_test.go b/client/v2/autocli/query_test.go index 81b442583b16..ddd8c7c8d0e4 100644 --- a/client/v2/autocli/query_test.go +++ b/client/v2/autocli/query_test.go @@ -6,10 +6,10 @@ import ( "net" "testing" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "github.com/spf13/cobra" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/testing/protocmp" "gotest.tools/v3/assert" "gotest.tools/v3/golden" @@ -38,7 +38,8 @@ func testExec(t *testing.T, args ...string) *testClientConn { return conn }, } - cmd := b.AddQueryServiceCommands(&cobra.Command{Use: "test"}, protoreflect.FullName(testpb.Query_ServiceDesc.ServiceName)) + cmd := &cobra.Command{Use: "test"} + b.AddQueryServiceCommands(cmd, &autocliv1.ServiceCommandDescriptor{Service: testpb.Query_ServiceDesc.ServiceName}) cmd.SetArgs(args) cmd.SetOut(conn.out) assert.NilError(t, cmd.Execute()) diff --git a/client/v2/autocli/validate.go b/client/v2/autocli/validate.go new file mode 100644 index 000000000000..7d84cf5bfa09 --- /dev/null +++ b/client/v2/autocli/validate.go @@ -0,0 +1,57 @@ +package autocli + +import ( + "errors" + "fmt" + "strings" + + "github.com/spf13/cobra" +) + +// ValidateCmd returns unknown command error or Help display if help flag set +func ValidateCmd(cmd *cobra.Command, args []string) error { + var unknownCmd string + var skipNext bool + + for _, arg := range args { + // search for help flag + if arg == "--help" || arg == "-h" { + return cmd.Help() + } + + // check if the current arg is a flag + switch { + case len(arg) > 0 && (arg[0] == '-'): + // the next arg should be skipped if the current arg is a + // flag and does not use "=" to assign the flag's value + if !strings.Contains(arg, "=") { + skipNext = true + } else { + skipNext = false + } + case skipNext: + // skip current arg + skipNext = false + case unknownCmd == "": + // unknown command found + // continue searching for help flag + unknownCmd = arg + } + } + + // return the help screen if no unknown command is found + if unknownCmd != "" { + err := fmt.Sprintf("unknown command \"%s\" for \"%s\"", unknownCmd, cmd.CalledAs()) + + // build suggestions for unknown argument + if suggestions := cmd.SuggestionsFor(unknownCmd); len(suggestions) > 0 { + err += "\n\nDid you mean this?\n" + for _, s := range suggestions { + err += fmt.Sprintf("\t%v\n", s) + } + } + return errors.New(err) + } + + return cmd.Help() +} diff --git a/client/v2/go.mod b/client/v2/go.mod index 9bd249f7700b..3d7b84b0ead3 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -3,7 +3,7 @@ module github.com/cosmos/cosmos-sdk/client/v2 go 1.18 require ( - cosmossdk.io/api v0.2.0 + cosmossdk.io/api v0.2.1 github.com/cosmos/cosmos-proto v1.0.0-alpha7 github.com/iancoleman/strcase v0.2.0 github.com/spf13/cobra v1.5.0 diff --git a/client/v2/go.sum b/client/v2/go.sum index 22982915c544..b404af78186a 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -1,5 +1,5 @@ -cosmossdk.io/api v0.2.0 h1:7qFwlsTzr71NycTa16ywI9kV7WylzAgd0o7qtqTS4yc= -cosmossdk.io/api v0.2.0/go.mod h1:kNpfY0UY7Cz4ZuLJ4hm9auUGfmj23UFpOQ/Bo8IKCFw= +cosmossdk.io/api v0.2.1 h1:4m6vIHKJygrixSIfOsD3Mhij9vZlQC/+BTeb+Un9os0= +cosmossdk.io/api v0.2.1/go.mod h1:kNpfY0UY7Cz4ZuLJ4hm9auUGfmj23UFpOQ/Bo8IKCFw= github.com/cosmos/cosmos-proto v1.0.0-alpha7 h1:yqYUOHF2jopwZh4dVQp3xgqwftE5/2hkrwIV6vkUbO0= github.com/cosmos/cosmos-proto v1.0.0-alpha7/go.mod h1:dosO4pSAbJF8zWCzCoTWP7nNsjcvSUBQmniFxDg5daw= github.com/cosmos/gogoproto v1.4.1 h1:WoyH+0/jbCTzpKNvyav5FL1ZTWsp1im1MxEpJEzKUB8= diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index e64a62b1e796..e6773d379212 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -191,6 +191,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { // add keybase, auxiliary RPC, query, and tx child commands rootCmd.AddCommand( rpc.StatusCommand(), + // queryCommand(), txCommand(), keys.Commands(simapp.DefaultNodeHome), From 749b7d16643175aee4c61c38a7a3523e51094577 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 12:43:08 -0400 Subject: [PATCH 03/25] integrate simple options --- client/v2/autocli/flag/field.go | 36 +++++++++++++++++++++------- client/v2/autocli/flag/pagination.go | 7 +----- client/v2/autocli/flag/register.go | 6 +++-- client/v2/autocli/query.go | 33 +++++++++++++++++++++---- 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/client/v2/autocli/flag/field.go b/client/v2/autocli/flag/field.go index c894e0610e48..1f636827b967 100644 --- a/client/v2/autocli/flag/field.go +++ b/client/v2/autocli/flag/field.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" cosmos_proto "github.com/cosmos/cosmos-proto" "github.com/spf13/pflag" "google.golang.org/protobuf/proto" @@ -25,23 +26,40 @@ type Options struct { } // AddFieldFlag adds a flag for the provided field to the flag set. -func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, options Options) FieldValueBinder { +func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) FieldValueBinder { if field.Kind() == protoreflect.MessageKind && field.Message().FullName() == "cosmos.base.query.v1beta1.PageRequest" { return b.bindPageRequest(ctx, flagSet, field) } - name := options.Prefix + util.DescriptorKebabName(field) - usage := util.DescriptorDocs(field) - shorthand := "" + name := opts.Name + if name == "" { + name = options.Prefix + util.DescriptorKebabName(field) + } + + usage := opts.Usage + if usage == "" { + usage = util.DescriptorDocs(field) + } + + shorthand := opts.Shorthand if typ := b.resolveFlagType(field); typ != nil { + defaultValue := opts.DefaultValue + if defaultValue == "" { + defaultValue = typ.DefaultValue() + } + val := typ.NewValue(ctx, b) flagSet.AddFlag(&pflag.Flag{ - Name: name, - Shorthand: shorthand, - Usage: usage, - DefValue: typ.DefaultValue(), - Value: val, + Name: name, + Shorthand: shorthand, + Usage: usage, + DefValue: defaultValue, + Deprecated: opts.Deprecated, + ShorthandDeprecated: opts.ShorthandDeprecated, + Hidden: opts.Hidden, + NoOptDefVal: opts.NoOptDefaultValue, + Value: val, }) switch val := val.(type) { case SimpleValue: diff --git a/client/v2/autocli/flag/pagination.go b/client/v2/autocli/flag/pagination.go index b4e77b8941eb..506984564fc4 100644 --- a/client/v2/autocli/flag/pagination.go +++ b/client/v2/autocli/flag/pagination.go @@ -10,11 +10,6 @@ import ( ) func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) FieldValueBinder { - handler := b.AddMessageFlags( - ctx, - flagSet, - util.ResolveMessageType(b.TypeResolver, field.Message()), - Options{Prefix: "page-"}, - ) + handler := b.AddMessageFlags(ctx, flagSet, util.ResolveMessageType(b.TypeResolver, field.Message()), nil, Options{Prefix: "page-"}) return simpleValueBinder{handler} } diff --git a/client/v2/autocli/flag/register.go b/client/v2/autocli/flag/register.go index c0d15c17d49a..1d0da3acb048 100644 --- a/client/v2/autocli/flag/register.go +++ b/client/v2/autocli/flag/register.go @@ -4,12 +4,13 @@ import ( "context" "fmt" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) // AddMessageFlags adds flags for each field in the message to the flag set. -func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messageType protoreflect.MessageType, options Options) *MessageBinder { +func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options Options) *MessageBinder { fields := messageType.Descriptor().Fields() numFields := fields.Len() handler := &MessageBinder{ @@ -17,7 +18,8 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa } for i := 0; i < numFields; i++ { field := fields.Get(i) - binder := b.AddFieldFlag(ctx, set, field, options) + flagOpts := commandOptions.FlagOptions[string(field.Name())] + binder := b.AddFieldFlag(ctx, set, field, flagOpts, options) if binder == nil { fmt.Printf("unable to bind field %s to a flag, support will be added soon\n", field) continue diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index 3e998a23d76a..73812006b32f 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -74,7 +74,9 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor } } cmd := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) - command.AddCommand(cmd) + if cmd != nil { + command.AddCommand(cmd) + } } for cmdName, subCmd := range cmdDescriptor.SubCommands { @@ -85,20 +87,41 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor // CreateQueryMethodCommand creates a gRPC query command for the given service method. func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) *cobra.Command { + if options != nil && options.Skip { + return nil + } + serviceDescriptor := descriptor.Parent().(protoreflect.ServiceDescriptor) - docs := util.DescriptorDocs(descriptor) + + long := options.Long + if long == "" { + long = util.DescriptorDocs(descriptor) + } + getClientConn := b.GetClientConn methodName := fmt.Sprintf("/%s/%s", serviceDescriptor.FullName(), descriptor.Name()) inputDesc := descriptor.Input() inputType := util.ResolveMessageType(b.TypeResolver, inputDesc) outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output()) + + use := options.Use + if use != "" { + use = protoNameToCliName(descriptor.Name()) + } + cmd := &cobra.Command{ - Use: protoNameToCliName(descriptor.Name()), - Long: docs, + Use: use, + Long: long, + Short: options.Short, + Example: options.Example, + Aliases: options.Alias, + SuggestFor: options.SuggestFor, + Deprecated: options.Deprecated, + Version: options.Version, } - binder := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, flag.Options{}) + binder := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, options, flag.Options{}) jsonMarshalOptions := protojson.MarshalOptions{ Indent: " ", From 3eca431672b794aef34a4d2a5cf169dcde59f6df Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 12:48:29 -0400 Subject: [PATCH 04/25] skip positional fields --- client/v2/autocli/flag/register.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/v2/autocli/flag/register.go b/client/v2/autocli/flag/register.go index 1d0da3acb048..3b62e231bcbd 100644 --- a/client/v2/autocli/flag/register.go +++ b/client/v2/autocli/flag/register.go @@ -18,6 +18,17 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa } for i := 0; i < numFields; i++ { field := fields.Get(i) + skip := false + for _, arg := range commandOptions.PositionalArgs { + if arg.ProtoField == string(field.Name()) { + skip = true + break + } + } + if skip { + continue + } + flagOpts := commandOptions.FlagOptions[string(field.Name())] binder := b.AddFieldFlag(ctx, set, field, flagOpts, options) if binder == nil { From 68c8ecddca8315258b35bf5d4c875e765069cc6d Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 14:01:13 -0400 Subject: [PATCH 05/25] WIP --- client/v2/autocli/flag/enum.go | 7 ++- client/v2/autocli/flag/field.go | 61 ++++++++------------ client/v2/autocli/flag/int32.go | 40 +++++++++++++ client/v2/autocli/flag/message.go | 7 ++- client/v2/autocli/flag/pagination.go | 9 ++- client/v2/autocli/flag/positional.go | 6 ++ client/v2/autocli/flag/register.go | 84 ++++++++++++++++++++++------ client/v2/autocli/flag/string.go | 36 ++++++++++++ client/v2/autocli/flag/type.go | 4 +- client/v2/autocli/flag/uint32.go | 40 +++++++++++++ client/v2/autocli/flag/uint64.go | 40 +++++++++++++ client/v2/autocli/flag/value.go | 6 ++ client/v2/autocli/query.go | 15 +++-- 13 files changed, 283 insertions(+), 72 deletions(-) create mode 100644 client/v2/autocli/flag/int32.go create mode 100644 client/v2/autocli/flag/positional.go create mode 100644 client/v2/autocli/flag/string.go create mode 100644 client/v2/autocli/flag/uint32.go create mode 100644 client/v2/autocli/flag/uint64.go diff --git a/client/v2/autocli/flag/enum.go b/client/v2/autocli/flag/enum.go index 65dd6fb813c6..2e8571132492 100644 --- a/client/v2/autocli/flag/enum.go +++ b/client/v2/autocli/flag/enum.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/iancoleman/strcase" - "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) @@ -14,7 +13,7 @@ type enumType struct { enum protoreflect.EnumDescriptor } -func (b enumType) NewValue(context.Context, *Builder) pflag.Value { +func (b enumType) NewValue(context.Context, *Builder) Value { val := &enumValue{ enum: b.enum, valMap: map[string]protoreflect.EnumValueDescriptor{}, @@ -41,6 +40,10 @@ type enumValue struct { valMap map[string]protoreflect.EnumValueDescriptor } +func (e enumValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfEnum(e.value)) +} + func (e enumValue) Get() protoreflect.Value { return protoreflect.ValueOfEnum(e.value) } diff --git a/client/v2/autocli/flag/field.go b/client/v2/autocli/flag/field.go index 1f636827b967..10133b1920fd 100644 --- a/client/v2/autocli/flag/field.go +++ b/client/v2/autocli/flag/field.go @@ -26,7 +26,7 @@ type Options struct { } // AddFieldFlag adds a flag for the provided field to the flag set. -func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) FieldValueBinder { +func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) (FieldValueBinder, error) { if field.Kind() == protoreflect.MessageKind && field.Message().FullName() == "cosmos.base.query.v1beta1.PageRequest" { return b.bindPageRequest(ctx, flagSet, field) } @@ -43,53 +43,38 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel shorthand := opts.Shorthand - if typ := b.resolveFlagType(field); typ != nil { - defaultValue := opts.DefaultValue - if defaultValue == "" { - defaultValue = typ.DefaultValue() - } - - val := typ.NewValue(ctx, b) - flagSet.AddFlag(&pflag.Flag{ - Name: name, - Shorthand: shorthand, - Usage: usage, - DefValue: defaultValue, - Deprecated: opts.Deprecated, - ShorthandDeprecated: opts.ShorthandDeprecated, - Hidden: opts.Hidden, - NoOptDefVal: opts.NoOptDefaultValue, - Value: val, - }) - switch val := val.(type) { - case SimpleValue: - return simpleValueBinder{val} - case ListValue: - return listValueBinder{val} - default: - panic(fmt.Errorf("%T does not implement SimpleValue or ListValue", val)) - } - } - - if field.IsList() { - if value := bindSimpleListFlag(flagSet, field.Kind(), name, shorthand, usage); value != nil { - return listValueBinder{value} - } - return nil + typ := b.resolveFlagType(field) + if typ == nil { + return nil, fmt.Errorf("unable to bind field %v", field) } - if value := bindSimpleFlag(flagSet, field.Kind(), name, shorthand, usage); value != nil { - return simpleValueBinder{value} + defaultValue := opts.DefaultValue + if defaultValue == "" { + defaultValue = typ.DefaultValue() } - return nil + val := typ.NewValue(ctx, b) + flagSet.AddFlag(&pflag.Flag{ + Name: name, + Shorthand: shorthand, + Usage: usage, + DefValue: defaultValue, + Deprecated: opts.Deprecated, + ShorthandDeprecated: opts.ShorthandDeprecated, + Hidden: opts.Hidden, + NoOptDefVal: opts.NoOptDefaultValue, + Value: val, + }) + + return val, nil } func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { typ := b.resolveFlagTypeBasic(field) if field.IsList() { if typ != nil { - return compositeListType{simpleType: typ} + //return compositeListType{simpleType: typ} + panic("TODO") } return nil diff --git a/client/v2/autocli/flag/int32.go b/client/v2/autocli/flag/int32.go new file mode 100644 index 000000000000..5666c1dd8bd1 --- /dev/null +++ b/client/v2/autocli/flag/int32.go @@ -0,0 +1,40 @@ +package flag + +import ( + "context" + "strconv" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type int32Type struct{} + +func (u int32Type) NewValue(ctx context.Context, builder *Builder) Value { + v := new(int32) + return (*int32Value)(v) +} + +func (u int32Type) DefaultValue() string { + //TODO implement me + panic("implement me") +} + +var _ Type = int32Type{} + +type int32Value int32 + +func (i *int32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfInt32(int32(*i))) +} + +func (i *int32Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 32) + *i = int32Value(v) + return err +} + +func (i *int32Value) Type() string { + return "int32" +} + +func (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) } diff --git a/client/v2/autocli/flag/message.go b/client/v2/autocli/flag/message.go index 4883b8933cd7..84e34b8c2808 100644 --- a/client/v2/autocli/flag/message.go +++ b/client/v2/autocli/flag/message.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/spf13/pflag" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" @@ -16,7 +15,7 @@ type jsonMessageFlagType struct { messageDesc protoreflect.MessageDescriptor } -func (j jsonMessageFlagType) NewValue(_ context.Context, builder *Builder) pflag.Value { +func (j jsonMessageFlagType) NewValue(_ context.Context, builder *Builder) Value { return &jsonMessageFlagValue{ messageType: util.ResolveMessageType(builder.TypeResolver, j.messageDesc), jsonMarshalOptions: protojson.MarshalOptions{Resolver: builder.TypeResolver}, @@ -35,6 +34,10 @@ type jsonMessageFlagValue struct { message proto.Message } +func (j jsonMessageFlagValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfMessage(j.message.ProtoReflect())) +} + func (j jsonMessageFlagValue) Get() protoreflect.Value { if j.message == nil { return protoreflect.Value{} diff --git a/client/v2/autocli/flag/pagination.go b/client/v2/autocli/flag/pagination.go index 506984564fc4..f79c16f0f652 100644 --- a/client/v2/autocli/flag/pagination.go +++ b/client/v2/autocli/flag/pagination.go @@ -9,7 +9,10 @@ import ( "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) -func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) FieldValueBinder { - handler := b.AddMessageFlags(ctx, flagSet, util.ResolveMessageType(b.TypeResolver, field.Message()), nil, Options{Prefix: "page-"}) - return simpleValueBinder{handler} +func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) (FieldValueBinder, error) { + handler, err := b.AddMessageFlags(ctx, flagSet, util.ResolveMessageType(b.TypeResolver, field.Message()), nil, Options{Prefix: "page-"}) + if err != nil { + return nil, err + } + return simpleValueBinder{handler}, nil } diff --git a/client/v2/autocli/flag/positional.go b/client/v2/autocli/flag/positional.go new file mode 100644 index 000000000000..fe6a7ea2807b --- /dev/null +++ b/client/v2/autocli/flag/positional.go @@ -0,0 +1,6 @@ +package flag + +type positionalArg interface { + Set(...string) + FieldValueBinder +} diff --git a/client/v2/autocli/flag/register.go b/client/v2/autocli/flag/register.go index 3b62e231bcbd..f7811531d3e3 100644 --- a/client/v2/autocli/flag/register.go +++ b/client/v2/autocli/flag/register.go @@ -5,46 +5,81 @@ import ( "fmt" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + "github.com/spf13/cobra" "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) // AddMessageFlags adds flags for each field in the message to the flag set. -func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options Options) *MessageBinder { +func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options Options) (*MessageBinder, error) { fields := messageType.Descriptor().Fields() numFields := fields.Len() handler := &MessageBinder{ messageType: messageType, } - for i := 0; i < numFields; i++ { - field := fields.Get(i) - skip := false - for _, arg := range commandOptions.PositionalArgs { - if arg.ProtoField == string(field.Name()) { - skip = true - break + + isPositional := map[string]bool{} + hasVarargs := false + n := len(commandOptions.PositionalArgs) + for i, arg := range commandOptions.PositionalArgs { + field := fields.ByName(protoreflect.Name(arg.ProtoField)) + if field == nil { + return nil, fmt.Errorf("can't find field %s on %s", arg.ProtoField, messageType.Descriptor().FullName()) + } + + if arg.Varargs { + if i != n-1 { + return nil, fmt.Errorf("varargs positional argument %s must be the last argument", arg.ProtoField) } + + hasVarargs = true } - if skip { + + // TODO binder + + handler.positionalArgs = append(handler.positionalArgs, struct { + binder positionalArg + field protoreflect.FieldDescriptor + varargs bool + }{binder: nil, field: field, varargs: arg.Varargs}) + } + + if hasVarargs { + handler.CobraArgs = cobra.MinimumNArgs(n) + } else { + handler.CobraArgs = cobra.ExactArgs(n) + } + + for i := 0; i < numFields; i++ { + field := fields.Get(i) + if isPositional[string(field.Name())] { continue } flagOpts := commandOptions.FlagOptions[string(field.Name())] - binder := b.AddFieldFlag(ctx, set, field, flagOpts, options) - if binder == nil { - fmt.Printf("unable to bind field %s to a flag, support will be added soon\n", field) - continue + binder, err := b.AddFieldFlag(ctx, set, field, flagOpts, options) + if err != nil { + return nil, err } + handler.flagFieldPairs = append(handler.flagFieldPairs, struct { binder FieldValueBinder field protoreflect.FieldDescriptor }{binder: binder, field: field}) } - return handler + return handler, nil } // MessageBinder binds multiple flags in a flag set to a protobuf message. type MessageBinder struct { + CobraArgs cobra.PositionalArgs + + positionalArgs []struct { + binder positionalArg + field protoreflect.FieldDescriptor + varargs bool + } + flagFieldPairs []struct { binder FieldValueBinder field protoreflect.FieldDescriptor @@ -53,14 +88,27 @@ type MessageBinder struct { } // BuildMessage builds and returns a new message for the bound flags. -func (m MessageBinder) BuildMessage() protoreflect.Message { +func (m MessageBinder) BuildMessage(positionalArgs []string) protoreflect.Message { msg := m.messageType.New() - m.Bind(msg) + m.Bind(msg, positionalArgs) return msg } // Bind binds the flag values to an existing protobuf message. -func (m MessageBinder) Bind(msg protoreflect.Message) { +func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) { + n := len(positionalArgs) + for i, arg := range m.positionalArgs { + if i >= n { + panic("unexpected: validate args should have caught this") + } + + if arg.varargs { + arg.binder.Set(positionalArgs[i:]...) + } else { + arg.binder.Set(positionalArgs[i]) + } + } + for _, pair := range m.flagFieldPairs { pair.binder.Bind(msg, pair.field) } @@ -68,5 +116,5 @@ func (m MessageBinder) Bind(msg protoreflect.Message) { // Get calls BuildMessage and wraps the result in a protoreflect.Value. func (m MessageBinder) Get() protoreflect.Value { - return protoreflect.ValueOfMessage(m.BuildMessage()) + return protoreflect.ValueOfMessage(m.BuildMessage(nil)) } diff --git a/client/v2/autocli/flag/string.go b/client/v2/autocli/flag/string.go new file mode 100644 index 000000000000..5b7a2ed9083e --- /dev/null +++ b/client/v2/autocli/flag/string.go @@ -0,0 +1,36 @@ +package flag + +import ( + "context" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type stringType struct{} + +func (s stringType) NewValue(ctx context.Context, builder *Builder) Value { + v := new(string) + return (*stringValue)(v) +} + +func (s stringType) DefaultValue() string { + return "" +} + +var _ Type = stringType{} + +type stringValue string + +func (s *stringValue) Set(val string) error { + *s = stringValue(val) + return nil +} +func (s *stringValue) Type() string { + return "string" +} + +func (s *stringValue) String() string { return string(*s) } + +func (s *stringValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfString(string(*s))) +} diff --git a/client/v2/autocli/flag/type.go b/client/v2/autocli/flag/type.go index 62fce2a6bcd2..a0e79b553d90 100644 --- a/client/v2/autocli/flag/type.go +++ b/client/v2/autocli/flag/type.go @@ -2,15 +2,13 @@ package flag import ( "context" - - "github.com/spf13/pflag" ) // Type specifies a custom flag type. type Type interface { // NewValue returns a new pflag.Value which must also implement either // SimpleValue or ListValue. - NewValue(context.Context, *Builder) pflag.Value + NewValue(context.Context, *Builder) Value // DefaultValue is the default value for this type. DefaultValue() string diff --git a/client/v2/autocli/flag/uint32.go b/client/v2/autocli/flag/uint32.go new file mode 100644 index 000000000000..510d4620973d --- /dev/null +++ b/client/v2/autocli/flag/uint32.go @@ -0,0 +1,40 @@ +package flag + +import ( + "context" + "strconv" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type uint32Type struct{} + +func (u uint32Type) NewValue(ctx context.Context, builder *Builder) Value { + v := new(uint32) + return (*uint32Value)(v) +} + +func (u uint32Type) DefaultValue() string { + //TODO implement me + panic("implement me") +} + +var _ Type = uint32Type{} + +type uint32Value uint32 + +func (i *uint32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfUint32(uint32(*i))) +} + +func (i *uint32Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 32) + *i = uint32Value(v) + return err +} + +func (i *uint32Value) Type() string { + return "uint32" +} + +func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) } diff --git a/client/v2/autocli/flag/uint64.go b/client/v2/autocli/flag/uint64.go new file mode 100644 index 000000000000..e032aa27e403 --- /dev/null +++ b/client/v2/autocli/flag/uint64.go @@ -0,0 +1,40 @@ +package flag + +import ( + "context" + "strconv" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type uint64Type struct{} + +func (u uint64Type) NewValue(ctx context.Context, builder *Builder) Value { + v := new(uint64) + return (*uint64Value)(v) +} + +func (u uint64Type) DefaultValue() string { + //TODO implement me + panic("implement me") +} + +var _ Type = uint64Type{} + +type uint64Value uint64 + +func (i *uint64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfUint64(uint64(*i))) +} + +func (i *uint64Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 64) + *i = uint64Value(v) + return err +} + +func (i *uint64Value) Type() string { + return "uint64" +} + +func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) } diff --git a/client/v2/autocli/flag/value.go b/client/v2/autocli/flag/value.go index 304139e642a2..826f862c8fed 100644 --- a/client/v2/autocli/flag/value.go +++ b/client/v2/autocli/flag/value.go @@ -1,6 +1,7 @@ package flag import ( + "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) @@ -15,3 +16,8 @@ type ListValue interface { // AppendTo appends the values to the provided list. AppendTo(protoreflect.List) } + +type Value interface { + pflag.Value + FieldValueBinder +} diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index 73812006b32f..bc63046dc6fb 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -73,7 +73,7 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor methodOpts = option } } - cmd := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) + cmd, _ := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) if cmd != nil { command.AddCommand(cmd) } @@ -86,9 +86,9 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor } // CreateQueryMethodCommand creates a gRPC query command for the given service method. -func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) *cobra.Command { +func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) (*cobra.Command, error) { if options != nil && options.Skip { - return nil + return nil, nil } serviceDescriptor := descriptor.Parent().(protoreflect.ServiceDescriptor) @@ -121,7 +121,10 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip Version: options.Version, } - binder := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, options, flag.Options{}) + binder, err := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, options, flag.Options{}) + if err != nil { + return nil, err + } jsonMarshalOptions := protojson.MarshalOptions{ Indent: " ", @@ -134,7 +137,7 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip cmd.RunE = func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() clientConn := getClientConn(ctx) - input := binder.BuildMessage() + input := binder.BuildMessage(args) output := outputType.New() err := clientConn.Invoke(ctx, methodName, input.Interface(), output.Interface()) if err != nil { @@ -150,7 +153,7 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip return err } - return cmd + return cmd, nil } func protoNameToCliName(name protoreflect.Name) string { From ce6d6193587bb07db87a723501463da833edfea9 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 14:12:18 -0400 Subject: [PATCH 06/25] WIP --- client/v2/autocli/flag/field.go | 3 +-- client/v2/autocli/flag/list.go | 6 +++++- client/v2/autocli/flag/positional.go | 5 ----- client/v2/autocli/flag/register.go | 29 +++++++++++++++++++++------- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/client/v2/autocli/flag/field.go b/client/v2/autocli/flag/field.go index 10133b1920fd..c14cb57a99a4 100644 --- a/client/v2/autocli/flag/field.go +++ b/client/v2/autocli/flag/field.go @@ -73,8 +73,7 @@ func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { typ := b.resolveFlagTypeBasic(field) if field.IsList() { if typ != nil { - //return compositeListType{simpleType: typ} - panic("TODO") + return compositeListType{simpleType: typ} } return nil diff --git a/client/v2/autocli/flag/list.go b/client/v2/autocli/flag/list.go index 28f3b8fe7f6f..30023b10ca83 100644 --- a/client/v2/autocli/flag/list.go +++ b/client/v2/autocli/flag/list.go @@ -58,7 +58,7 @@ type compositeListType struct { simpleType Type } -func (t compositeListType) NewValue(ctx context.Context, opts *Builder) pflag.Value { +func (t compositeListType) NewValue(ctx context.Context, opts *Builder) Value { return &compositeListValue{ simpleType: t.simpleType, values: nil, @@ -78,6 +78,10 @@ type compositeListValue struct { opts *Builder } +func (c compositeListValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + c.AppendTo(message.NewField(field).List()) +} + func (c compositeListValue) AppendTo(list protoreflect.List) { for _, value := range c.values { list.Append(value) diff --git a/client/v2/autocli/flag/positional.go b/client/v2/autocli/flag/positional.go index fe6a7ea2807b..02d20d554eab 100644 --- a/client/v2/autocli/flag/positional.go +++ b/client/v2/autocli/flag/positional.go @@ -1,6 +1 @@ package flag - -type positionalArg interface { - Set(...string) - FieldValueBinder -} diff --git a/client/v2/autocli/flag/register.go b/client/v2/autocli/flag/register.go index f7811531d3e3..d62875133b0b 100644 --- a/client/v2/autocli/flag/register.go +++ b/client/v2/autocli/flag/register.go @@ -35,13 +35,18 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa hasVarargs = true } - // TODO binder + typ := b.resolveFlagType(field) + if typ == nil { + return nil, fmt.Errorf("can't resolve field %v", field) + } + + value := typ.NewValue(ctx, b) handler.positionalArgs = append(handler.positionalArgs, struct { - binder positionalArg + binder Value field protoreflect.FieldDescriptor varargs bool - }{binder: nil, field: field, varargs: arg.Varargs}) + }{binder: value, field: field, varargs: arg.Varargs}) } if hasVarargs { @@ -75,7 +80,7 @@ type MessageBinder struct { CobraArgs cobra.PositionalArgs positionalArgs []struct { - binder positionalArg + binder Value field protoreflect.FieldDescriptor varargs bool } @@ -95,7 +100,7 @@ func (m MessageBinder) BuildMessage(positionalArgs []string) protoreflect.Messag } // Bind binds the flag values to an existing protobuf message. -func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) { +func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) error { n := len(positionalArgs) for i, arg := range m.positionalArgs { if i >= n { @@ -103,15 +108,25 @@ func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) { } if arg.varargs { - arg.binder.Set(positionalArgs[i:]...) + for _, v := range positionalArgs[i:] { + err := arg.binder.Set(v) + if err != nil { + return err + } + } } else { - arg.binder.Set(positionalArgs[i]) + err := arg.binder.Set(positionalArgs[i]) + if err != nil { + return err + } } } for _, pair := range m.flagFieldPairs { pair.binder.Bind(msg, pair.field) } + + return nil } // Get calls BuildMessage and wraps the result in a protoreflect.Value. From 989305de877a42db80a25def1ca4997187b0146b Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 15:30:51 -0400 Subject: [PATCH 07/25] WIP --- client/v2/autocli/flag/address.go | 11 ++-- client/v2/autocli/flag/bool.go | 41 +++++++++++++ client/v2/autocli/flag/bytes.go | 52 ++++++++++++++++ client/v2/autocli/flag/duration.go | 13 ++-- client/v2/autocli/flag/enum.go | 4 +- client/v2/autocli/flag/field.go | 38 ++++++++---- client/v2/autocli/flag/int32.go | 7 +-- client/v2/autocli/flag/int64.go | 40 ++++++++++++ client/v2/autocli/flag/list.go | 92 ++++++++++++++-------------- client/v2/autocli/flag/message.go | 6 +- client/v2/autocli/flag/pagination.go | 2 +- client/v2/autocli/flag/register.go | 11 ++-- client/v2/autocli/flag/simple.go | 54 ---------------- client/v2/autocli/flag/string.go | 2 +- client/v2/autocli/flag/timestamp.go | 13 ++-- client/v2/autocli/flag/uint32.go | 7 +-- client/v2/autocli/flag/uint64.go | 7 +-- client/v2/autocli/flag/value.go | 8 ++- client/v2/autocli/query.go | 8 ++- 19 files changed, 261 insertions(+), 155 deletions(-) create mode 100644 client/v2/autocli/flag/bool.go create mode 100644 client/v2/autocli/flag/bytes.go create mode 100644 client/v2/autocli/flag/int64.go delete mode 100644 client/v2/autocli/flag/simple.go diff --git a/client/v2/autocli/flag/address.go b/client/v2/autocli/flag/address.go index f2008e4b3251..c9a190147d4b 100644 --- a/client/v2/autocli/flag/address.go +++ b/client/v2/autocli/flag/address.go @@ -3,13 +3,12 @@ package flag import ( "context" - "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) type addressStringType struct{} -func (a addressStringType) NewValue(_ context.Context, _ *Builder) pflag.Value { +func (a addressStringType) NewValue(_ context.Context, _ *Builder) Value { return &addressValue{} } @@ -21,8 +20,12 @@ type addressValue struct { value string } -func (a addressValue) Get() protoreflect.Value { - return protoreflect.ValueOfString(a.value) +func (a addressValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfString(a.value)) +} + +func (a addressValue) Get() (protoreflect.Value, error) { + return protoreflect.ValueOfString(a.value), nil } func (a addressValue) String() string { diff --git a/client/v2/autocli/flag/bool.go b/client/v2/autocli/flag/bool.go new file mode 100644 index 000000000000..b3dd0c77a4b3 --- /dev/null +++ b/client/v2/autocli/flag/bool.go @@ -0,0 +1,41 @@ +package flag + +import ( + "context" + "strconv" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type boolType struct{} + +func (b boolType) NewValue(context.Context, *Builder) Value { + v := new(bool) + return (*boolValue)(v) +} + +func (b boolType) DefaultValue() string { + return defaultDefaultValue(b) +} + +var _ Type = boolType{} + +type boolValue bool + +func (b *boolValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfBool(bool(*b))) +} + +func (b *boolValue) Set(s string) error { + v, err := strconv.ParseBool(s) + *b = boolValue(v) + return err +} + +func (b *boolValue) Type() string { + return "bool" +} + +func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) } + +func (b *boolValue) IsBoolFlag() bool { return true } diff --git a/client/v2/autocli/flag/bytes.go b/client/v2/autocli/flag/bytes.go new file mode 100644 index 000000000000..49ae274eaaa2 --- /dev/null +++ b/client/v2/autocli/flag/bytes.go @@ -0,0 +1,52 @@ +package flag + +import ( + "context" + "encoding/base64" + "strings" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type bytesBase64Type struct{} + +func (b bytesBase64Type) NewValue(context.Context, *Builder) Value { + x := new([]byte) + return (*bytesBase64Value)(x) +} + +func (b bytesBase64Type) DefaultValue() string { + return defaultDefaultValue(b) +} + +var _ Type = bytesBase64Type{} + +// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded +type bytesBase64Value []byte + +func (bytesBase64 *bytesBase64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfBytes(*bytesBase64)) +} + +// String implements pflag.Value.String. +func (bytesBase64 *bytesBase64Value) String() string { + return base64.StdEncoding.EncodeToString(*bytesBase64) +} + +// Set implements pflag.Value.Set. +func (bytesBase64 *bytesBase64Value) Set(value string) error { + bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value)) + + if err != nil { + return err + } + + *bytesBase64 = bin + + return nil +} + +// Type implements pflag.Value.Type. +func (*bytesBase64Value) Type() string { + return "bytesBase64" +} diff --git a/client/v2/autocli/flag/duration.go b/client/v2/autocli/flag/duration.go index d40f3ad6eab7..1c6793b3c670 100644 --- a/client/v2/autocli/flag/duration.go +++ b/client/v2/autocli/flag/duration.go @@ -4,14 +4,13 @@ import ( "context" "time" - "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/durationpb" ) type durationType struct{} -func (t durationType) NewValue(context.Context, *Builder) pflag.Value { +func (t durationType) NewValue(context.Context, *Builder) Value { return &durationValue{} } @@ -23,11 +22,15 @@ type durationValue struct { value *durationpb.Duration } -func (t durationValue) Get() protoreflect.Value { +func (t durationValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfMessage(t.value.ProtoReflect())) +} + +func (t durationValue) Get() (protoreflect.Value, error) { if t.value == nil { - return protoreflect.Value{} + return protoreflect.Value{}, nil } - return protoreflect.ValueOfMessage(t.value.ProtoReflect()) + return protoreflect.ValueOfMessage(t.value.ProtoReflect()), nil } func (v durationValue) String() string { diff --git a/client/v2/autocli/flag/enum.go b/client/v2/autocli/flag/enum.go index 2e8571132492..b00c55b2fe40 100644 --- a/client/v2/autocli/flag/enum.go +++ b/client/v2/autocli/flag/enum.go @@ -44,8 +44,8 @@ func (e enumValue) Bind(message protoreflect.Message, field protoreflect.FieldDe message.Set(field, protoreflect.ValueOfEnum(e.value)) } -func (e enumValue) Get() protoreflect.Value { - return protoreflect.ValueOfEnum(e.value) +func (e enumValue) Get() (protoreflect.Value, error) { + return protoreflect.ValueOfEnum(e.value), nil } func enumValueName(enum protoreflect.EnumDescriptor, enumValue protoreflect.EnumValueDescriptor) string { diff --git a/client/v2/autocli/flag/field.go b/client/v2/autocli/flag/field.go index c14cb57a99a4..df634454f7ea 100644 --- a/client/v2/autocli/flag/field.go +++ b/client/v2/autocli/flag/field.go @@ -70,16 +70,16 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel } func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { - typ := b.resolveFlagTypeBasic(field) if field.IsList() { + typ := b.resolveFlagTypeBasic(field) if typ != nil { return compositeListType{simpleType: typ} } return nil + } else { + return b.resolveFlagTypeBasic(field) } - - return typ } func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type { @@ -92,6 +92,20 @@ func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type } switch field.Kind() { + case protoreflect.BytesKind: + return bytesBase64Type{} + case protoreflect.StringKind: + return stringType{} + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: + return uint32Type{} + case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + return uint64Type{} + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: + return int32Type{} + case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + return int64Type{} + case protoreflect.BoolKind: + return boolType{} case protoreflect.EnumKind: return enumType{enum: field.Enum()} case protoreflect.MessageKind: @@ -109,22 +123,20 @@ func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type } type simpleValueBinder struct { - SimpleValue + value interface { + Get() (protoreflect.Value, error) + } } func (s simpleValueBinder) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - val := s.Get() + val, err := s.value.Get() + if err != nil { + panic(err) + } + if val.IsValid() { message.Set(field, val) } else { message.Clear(field) } } - -type listValueBinder struct { - ListValue -} - -func (s listValueBinder) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - s.AppendTo(message.NewField(field).List()) -} diff --git a/client/v2/autocli/flag/int32.go b/client/v2/autocli/flag/int32.go index 5666c1dd8bd1..0b6a911fece1 100644 --- a/client/v2/autocli/flag/int32.go +++ b/client/v2/autocli/flag/int32.go @@ -9,14 +9,13 @@ import ( type int32Type struct{} -func (u int32Type) NewValue(ctx context.Context, builder *Builder) Value { +func (t int32Type) NewValue(context.Context, *Builder) Value { v := new(int32) return (*int32Value)(v) } -func (u int32Type) DefaultValue() string { - //TODO implement me - panic("implement me") +func (t int32Type) DefaultValue() string { + return defaultDefaultValue(t) } var _ Type = int32Type{} diff --git a/client/v2/autocli/flag/int64.go b/client/v2/autocli/flag/int64.go new file mode 100644 index 000000000000..3b1b5d930412 --- /dev/null +++ b/client/v2/autocli/flag/int64.go @@ -0,0 +1,40 @@ +package flag + +import ( + "context" + "strconv" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +type int64Type struct{} + +func (u int64Type) NewValue(context.Context, *Builder) Value { + v := new(int64) + return (*int64Value)(v) +} + +func (u int64Type) DefaultValue() string { + + return "0" +} + +var _ Type = int64Type{} + +type int64Value int64 + +func (i *int64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfInt64(int64(*i))) +} + +func (i *int64Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 64) + *i = int64Value(v) + return err +} + +func (i *int64Value) Type() string { + return "int64" +} + +func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) } diff --git a/client/v2/autocli/flag/list.go b/client/v2/autocli/flag/list.go index 30023b10ca83..691d12ddd420 100644 --- a/client/v2/autocli/flag/list.go +++ b/client/v2/autocli/flag/list.go @@ -4,55 +4,49 @@ import ( "context" "fmt" - "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) -func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) ListValue { - switch kind { - case protoreflect.StringKind: - val := flagSet.StringSliceP(name, shorthand, nil, usage) - return listValue(func(list protoreflect.List) { - for _, x := range *val { - list.Append(protoreflect.ValueOfString(x)) - } - }) - case protoreflect.BytesKind: - // TODO - return nil - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, - protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - val := flagSet.UintSliceP(name, shorthand, nil, usage) - return listValue(func(list protoreflect.List) { - for _, x := range *val { - list.Append(protoreflect.ValueOfUint64(uint64(x))) - } - }) - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, - protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - val := flagSet.IntSliceP(name, shorthand, nil, usage) - return listValue(func(list protoreflect.List) { - for _, x := range *val { - list.Append(protoreflect.ValueOfInt64(int64(x))) - } - }) - case protoreflect.BoolKind: - val := flagSet.BoolSliceP(name, shorthand, nil, usage) - return listValue(func(list protoreflect.List) { - for _, x := range *val { - list.Append(protoreflect.ValueOfBool(x)) - } - }) - default: - return nil - } -} - -type listValue func(protoreflect.List) - -func (f listValue) AppendTo(list protoreflect.List) { - f(list) -} +// TODO +//func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) ListValue { +// switch kind { +// case protoreflect.StringKind: +// val := flagSet.StringSliceP(name, shorthand, nil, usage) +// return listValue(func(list protoreflect.List) { +// for _, x := range *val { +// list.Append(protoreflect.ValueOfString(x)) +// } +// }) +// case protoreflect.BytesKind: +// // TODO +// return nil +// case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, +// protoreflect.Uint64Kind, protoreflect.Fixed64Kind: +// val := flagSet.UintSliceP(name, shorthand, nil, usage) +// return listValue(func(list protoreflect.List) { +// for _, x := range *val { +// list.Append(protoreflect.ValueOfUint64(uint64(x))) +// } +// }) +// case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, +// protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: +// val := flagSet.IntSliceP(name, shorthand, nil, usage) +// return listValue(func(list protoreflect.List) { +// for _, x := range *val { +// list.Append(protoreflect.ValueOfInt64(int64(x))) +// } +// }) +// case protoreflect.BoolKind: +// val := flagSet.BoolSliceP(name, shorthand, nil, usage) +// return listValue(func(list protoreflect.List) { +// for _, x := range *val { +// list.Append(protoreflect.ValueOfBool(x)) +// } +// }) +// default: +// return nil +// } +//} type compositeListType struct { simpleType Type @@ -102,7 +96,11 @@ func (c *compositeListValue) Set(val string) error { if err != nil { return err } - c.values = append(c.values, simpleVal.(SimpleValue).Get()) + v, err := simpleVal.(SimpleValue).Get() + if err != nil { + return err + } + c.values = append(c.values, v) return nil } diff --git a/client/v2/autocli/flag/message.go b/client/v2/autocli/flag/message.go index 84e34b8c2808..81a201cbd3ba 100644 --- a/client/v2/autocli/flag/message.go +++ b/client/v2/autocli/flag/message.go @@ -38,11 +38,11 @@ func (j jsonMessageFlagValue) Bind(message protoreflect.Message, field protorefl message.Set(field, protoreflect.ValueOfMessage(j.message.ProtoReflect())) } -func (j jsonMessageFlagValue) Get() protoreflect.Value { +func (j jsonMessageFlagValue) Get() (protoreflect.Value, error) { if j.message == nil { - return protoreflect.Value{} + return protoreflect.Value{}, nil } - return protoreflect.ValueOfMessage(j.message.ProtoReflect()) + return protoreflect.ValueOfMessage(j.message.ProtoReflect()), nil } func (j jsonMessageFlagValue) String() string { diff --git a/client/v2/autocli/flag/pagination.go b/client/v2/autocli/flag/pagination.go index f79c16f0f652..3ce8e6ae3839 100644 --- a/client/v2/autocli/flag/pagination.go +++ b/client/v2/autocli/flag/pagination.go @@ -14,5 +14,5 @@ func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, f if err != nil { return nil, err } - return simpleValueBinder{handler}, nil + return simpleValueBinder{value: handler}, nil } diff --git a/client/v2/autocli/flag/register.go b/client/v2/autocli/flag/register.go index d62875133b0b..b04672a7e712 100644 --- a/client/v2/autocli/flag/register.go +++ b/client/v2/autocli/flag/register.go @@ -93,10 +93,10 @@ type MessageBinder struct { } // BuildMessage builds and returns a new message for the bound flags. -func (m MessageBinder) BuildMessage(positionalArgs []string) protoreflect.Message { +func (m MessageBinder) BuildMessage(positionalArgs []string) (protoreflect.Message, error) { msg := m.messageType.New() - m.Bind(msg, positionalArgs) - return msg + err := m.Bind(msg, positionalArgs) + return msg, err } // Bind binds the flag values to an existing protobuf message. @@ -130,6 +130,7 @@ func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) e } // Get calls BuildMessage and wraps the result in a protoreflect.Value. -func (m MessageBinder) Get() protoreflect.Value { - return protoreflect.ValueOfMessage(m.BuildMessage(nil)) +func (m MessageBinder) Get() (protoreflect.Value, error) { + msg, err := m.BuildMessage(nil) + return protoreflect.ValueOfMessage(msg), err } diff --git a/client/v2/autocli/flag/simple.go b/client/v2/autocli/flag/simple.go deleted file mode 100644 index 6caf25c6cae0..000000000000 --- a/client/v2/autocli/flag/simple.go +++ /dev/null @@ -1,54 +0,0 @@ -package flag - -import ( - "github.com/spf13/pflag" - "google.golang.org/protobuf/reflect/protoreflect" -) - -func bindSimpleFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) SimpleValue { - switch kind { - case protoreflect.BytesKind: - val := flagSet.BytesBase64P(name, shorthand, nil, usage) - return simpleValue(func() protoreflect.Value { - return protoreflect.ValueOfBytes(*val) - }) - case protoreflect.StringKind: - val := flagSet.StringP(name, shorthand, "", usage) - return simpleValue(func() protoreflect.Value { - return protoreflect.ValueOfString(*val) - }) - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - val := flagSet.Uint32P(name, shorthand, 0, usage) - return simpleValue(func() protoreflect.Value { - return protoreflect.ValueOfUint32(*val) - }) - case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - val := flagSet.Uint64P(name, shorthand, 0, usage) - return simpleValue(func() protoreflect.Value { - return protoreflect.ValueOfUint64(*val) - }) - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - val := flagSet.Int32P(name, shorthand, 0, usage) - return simpleValue(func() protoreflect.Value { - return protoreflect.ValueOfInt32(*val) - }) - case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - val := flagSet.Int64P(name, shorthand, 0, usage) - return simpleValue(func() protoreflect.Value { - return protoreflect.ValueOfInt64(*val) - }) - case protoreflect.BoolKind: - val := flagSet.BoolP(name, shorthand, false, usage) - return simpleValue(func() protoreflect.Value { - return protoreflect.ValueOfBool(*val) - }) - default: - return nil - } -} - -type simpleValue func() protoreflect.Value - -func (f simpleValue) Get() protoreflect.Value { - return f() -} diff --git a/client/v2/autocli/flag/string.go b/client/v2/autocli/flag/string.go index 5b7a2ed9083e..0edd13933eac 100644 --- a/client/v2/autocli/flag/string.go +++ b/client/v2/autocli/flag/string.go @@ -8,7 +8,7 @@ import ( type stringType struct{} -func (s stringType) NewValue(ctx context.Context, builder *Builder) Value { +func (s stringType) NewValue(context.Context, *Builder) Value { v := new(string) return (*stringValue)(v) } diff --git a/client/v2/autocli/flag/timestamp.go b/client/v2/autocli/flag/timestamp.go index e9386bad3b9c..f83cbbfc9d6c 100644 --- a/client/v2/autocli/flag/timestamp.go +++ b/client/v2/autocli/flag/timestamp.go @@ -4,14 +4,13 @@ import ( "context" "time" - "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/timestamppb" ) type timestampType struct{} -func (t timestampType) NewValue(context.Context, *Builder) pflag.Value { +func (t timestampType) NewValue(context.Context, *Builder) Value { return ×tampValue{} } @@ -23,11 +22,15 @@ type timestampValue struct { value *timestamppb.Timestamp } -func (t timestampValue) Get() protoreflect.Value { +func (t timestampValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfMessage(t.value.ProtoReflect())) +} + +func (t timestampValue) Get() (protoreflect.Value, error) { if t.value == nil { - return protoreflect.Value{} + return protoreflect.Value{}, nil } - return protoreflect.ValueOfMessage(t.value.ProtoReflect()) + return protoreflect.ValueOfMessage(t.value.ProtoReflect()), nil } func (v timestampValue) String() string { diff --git a/client/v2/autocli/flag/uint32.go b/client/v2/autocli/flag/uint32.go index 510d4620973d..99967a616cfc 100644 --- a/client/v2/autocli/flag/uint32.go +++ b/client/v2/autocli/flag/uint32.go @@ -9,14 +9,13 @@ import ( type uint32Type struct{} -func (u uint32Type) NewValue(ctx context.Context, builder *Builder) Value { +func (t uint32Type) NewValue(context.Context, *Builder) Value { v := new(uint32) return (*uint32Value)(v) } -func (u uint32Type) DefaultValue() string { - //TODO implement me - panic("implement me") +func (t uint32Type) DefaultValue() string { + return defaultDefaultValue(t) } var _ Type = uint32Type{} diff --git a/client/v2/autocli/flag/uint64.go b/client/v2/autocli/flag/uint64.go index e032aa27e403..8997644a8a84 100644 --- a/client/v2/autocli/flag/uint64.go +++ b/client/v2/autocli/flag/uint64.go @@ -9,14 +9,13 @@ import ( type uint64Type struct{} -func (u uint64Type) NewValue(ctx context.Context, builder *Builder) Value { +func (t uint64Type) NewValue(context.Context, *Builder) Value { v := new(uint64) return (*uint64Value)(v) } -func (u uint64Type) DefaultValue() string { - //TODO implement me - panic("implement me") +func (t uint64Type) DefaultValue() string { + return defaultDefaultValue(t) } var _ Type = uint64Type{} diff --git a/client/v2/autocli/flag/value.go b/client/v2/autocli/flag/value.go index 826f862c8fed..dca2e0e26471 100644 --- a/client/v2/autocli/flag/value.go +++ b/client/v2/autocli/flag/value.go @@ -1,6 +1,8 @@ package flag import ( + "context" + "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) @@ -8,7 +10,7 @@ import ( // SimpleValue wraps a simple (non-list and non-map) protobuf value. type SimpleValue interface { // Get returns the value. - Get() protoreflect.Value + Get() (protoreflect.Value, error) } // ListValue wraps a protobuf list/repeating value. @@ -21,3 +23,7 @@ type Value interface { pflag.Value FieldValueBinder } + +func defaultDefaultValue(t Type) string { + return t.NewValue(context.Background(), &Builder{}).String() +} diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index bc63046dc6fb..e272a626174c 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -137,9 +137,13 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip cmd.RunE = func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() clientConn := getClientConn(ctx) - input := binder.BuildMessage(args) + input, err := binder.BuildMessage(args) + if err != nil { + return err + } + output := outputType.New() - err := clientConn.Invoke(ctx, methodName, input.Interface(), output.Interface()) + err = clientConn.Invoke(ctx, methodName, input.Interface(), output.Interface()) if err != nil { return err } From 5c85a8be6fd774fc68ed4d2d4d12f2c807bc5fba Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 16:35:34 -0400 Subject: [PATCH 08/25] trying to simplify diff, fixing errors --- client/v2/{autocli => cli}/builder.go | 4 ++-- client/v2/{autocli => cli}/flag/address.go | 0 client/v2/{autocli => cli}/flag/bool.go | 0 client/v2/{autocli => cli}/flag/builder.go | 0 client/v2/{autocli => cli}/flag/bytes.go | 0 client/v2/{autocli => cli}/flag/duration.go | 0 client/v2/{autocli => cli}/flag/enum.go | 0 client/v2/{autocli => cli}/flag/field.go | 5 +++++ client/v2/{autocli => cli}/flag/int32.go | 0 client/v2/{autocli => cli}/flag/int64.go | 0 client/v2/{autocli => cli}/flag/list.go | 0 client/v2/{autocli => cli}/flag/message.go | 0 client/v2/{autocli => cli}/flag/pagination.go | 9 ++++++++- client/v2/{autocli => cli}/flag/positional.go | 0 client/v2/{autocli => cli}/flag/register.go | 0 client/v2/{autocli => cli}/flag/string.go | 0 client/v2/{autocli => cli}/flag/timestamp.go | 0 client/v2/{autocli => cli}/flag/type.go | 0 client/v2/{autocli => cli}/flag/uint32.go | 0 client/v2/{autocli => cli}/flag/uint64.go | 0 client/v2/{autocli => cli}/flag/value.go | 0 client/v2/{autocli => cli}/query.go | 13 +++++++++---- client/v2/{autocli => cli}/query_test.go | 7 +++---- .../v2/{autocli => cli}/testdata/bank_example.yaml | 0 client/v2/{autocli => cli}/testdata/help.golden | 0 client/v2/{autocli => cli}/validate.go | 2 +- simapp/simd/cmd/root.go | 1 - 27 files changed, 28 insertions(+), 13 deletions(-) rename client/v2/{autocli => cli}/builder.go (84%) rename client/v2/{autocli => cli}/flag/address.go (100%) rename client/v2/{autocli => cli}/flag/bool.go (100%) rename client/v2/{autocli => cli}/flag/builder.go (100%) rename client/v2/{autocli => cli}/flag/bytes.go (100%) rename client/v2/{autocli => cli}/flag/duration.go (100%) rename client/v2/{autocli => cli}/flag/enum.go (100%) rename client/v2/{autocli => cli}/flag/field.go (98%) rename client/v2/{autocli => cli}/flag/int32.go (100%) rename client/v2/{autocli => cli}/flag/int64.go (100%) rename client/v2/{autocli => cli}/flag/list.go (100%) rename client/v2/{autocli => cli}/flag/message.go (100%) rename client/v2/{autocli => cli}/flag/pagination.go (63%) rename client/v2/{autocli => cli}/flag/positional.go (100%) rename client/v2/{autocli => cli}/flag/register.go (100%) rename client/v2/{autocli => cli}/flag/string.go (100%) rename client/v2/{autocli => cli}/flag/timestamp.go (100%) rename client/v2/{autocli => cli}/flag/type.go (100%) rename client/v2/{autocli => cli}/flag/uint32.go (100%) rename client/v2/{autocli => cli}/flag/uint64.go (100%) rename client/v2/{autocli => cli}/flag/value.go (100%) rename client/v2/{autocli => cli}/query.go (96%) rename client/v2/{autocli => cli}/query_test.go (93%) rename client/v2/{autocli => cli}/testdata/bank_example.yaml (100%) rename client/v2/{autocli => cli}/testdata/help.golden (100%) rename client/v2/{autocli => cli}/validate.go (98%) diff --git a/client/v2/autocli/builder.go b/client/v2/cli/builder.go similarity index 84% rename from client/v2/autocli/builder.go rename to client/v2/cli/builder.go index f2770b0623f9..992fc9df4e74 100644 --- a/client/v2/autocli/builder.go +++ b/client/v2/cli/builder.go @@ -1,11 +1,11 @@ -package autocli +package cli import ( "context" "google.golang.org/grpc" - "github.com/cosmos/cosmos-sdk/client/v2/autocli/flag" + "github.com/cosmos/cosmos-sdk/client/v2/cli/flag" ) // Builder manages options for building CLI commands. diff --git a/client/v2/autocli/flag/address.go b/client/v2/cli/flag/address.go similarity index 100% rename from client/v2/autocli/flag/address.go rename to client/v2/cli/flag/address.go diff --git a/client/v2/autocli/flag/bool.go b/client/v2/cli/flag/bool.go similarity index 100% rename from client/v2/autocli/flag/bool.go rename to client/v2/cli/flag/bool.go diff --git a/client/v2/autocli/flag/builder.go b/client/v2/cli/flag/builder.go similarity index 100% rename from client/v2/autocli/flag/builder.go rename to client/v2/cli/flag/builder.go diff --git a/client/v2/autocli/flag/bytes.go b/client/v2/cli/flag/bytes.go similarity index 100% rename from client/v2/autocli/flag/bytes.go rename to client/v2/cli/flag/bytes.go diff --git a/client/v2/autocli/flag/duration.go b/client/v2/cli/flag/duration.go similarity index 100% rename from client/v2/autocli/flag/duration.go rename to client/v2/cli/flag/duration.go diff --git a/client/v2/autocli/flag/enum.go b/client/v2/cli/flag/enum.go similarity index 100% rename from client/v2/autocli/flag/enum.go rename to client/v2/cli/flag/enum.go diff --git a/client/v2/autocli/flag/field.go b/client/v2/cli/flag/field.go similarity index 98% rename from client/v2/autocli/flag/field.go rename to client/v2/cli/flag/field.go index df634454f7ea..638595c3fdc7 100644 --- a/client/v2/autocli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -27,6 +27,11 @@ type Options struct { // AddFieldFlag adds a flag for the provided field to the flag set. func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) (FieldValueBinder, error) { + if opts == nil { + // use defaults + opts = &autocliv1.FlagOptions{} + } + if field.Kind() == protoreflect.MessageKind && field.Message().FullName() == "cosmos.base.query.v1beta1.PageRequest" { return b.bindPageRequest(ctx, flagSet, field) } diff --git a/client/v2/autocli/flag/int32.go b/client/v2/cli/flag/int32.go similarity index 100% rename from client/v2/autocli/flag/int32.go rename to client/v2/cli/flag/int32.go diff --git a/client/v2/autocli/flag/int64.go b/client/v2/cli/flag/int64.go similarity index 100% rename from client/v2/autocli/flag/int64.go rename to client/v2/cli/flag/int64.go diff --git a/client/v2/autocli/flag/list.go b/client/v2/cli/flag/list.go similarity index 100% rename from client/v2/autocli/flag/list.go rename to client/v2/cli/flag/list.go diff --git a/client/v2/autocli/flag/message.go b/client/v2/cli/flag/message.go similarity index 100% rename from client/v2/autocli/flag/message.go rename to client/v2/cli/flag/message.go diff --git a/client/v2/autocli/flag/pagination.go b/client/v2/cli/flag/pagination.go similarity index 63% rename from client/v2/autocli/flag/pagination.go rename to client/v2/cli/flag/pagination.go index 3ce8e6ae3839..6b1e56ea3041 100644 --- a/client/v2/autocli/flag/pagination.go +++ b/client/v2/cli/flag/pagination.go @@ -3,6 +3,7 @@ package flag import ( "context" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" @@ -10,7 +11,13 @@ import ( ) func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) (FieldValueBinder, error) { - handler, err := b.AddMessageFlags(ctx, flagSet, util.ResolveMessageType(b.TypeResolver, field.Message()), nil, Options{Prefix: "page-"}) + handler, err := b.AddMessageFlags( + ctx, + flagSet, + util.ResolveMessageType(b.TypeResolver, field.Message()), + &autocliv1.RpcCommandOptions{}, + Options{Prefix: "page-"}, + ) if err != nil { return nil, err } diff --git a/client/v2/autocli/flag/positional.go b/client/v2/cli/flag/positional.go similarity index 100% rename from client/v2/autocli/flag/positional.go rename to client/v2/cli/flag/positional.go diff --git a/client/v2/autocli/flag/register.go b/client/v2/cli/flag/register.go similarity index 100% rename from client/v2/autocli/flag/register.go rename to client/v2/cli/flag/register.go diff --git a/client/v2/autocli/flag/string.go b/client/v2/cli/flag/string.go similarity index 100% rename from client/v2/autocli/flag/string.go rename to client/v2/cli/flag/string.go diff --git a/client/v2/autocli/flag/timestamp.go b/client/v2/cli/flag/timestamp.go similarity index 100% rename from client/v2/autocli/flag/timestamp.go rename to client/v2/cli/flag/timestamp.go diff --git a/client/v2/autocli/flag/type.go b/client/v2/cli/flag/type.go similarity index 100% rename from client/v2/autocli/flag/type.go rename to client/v2/cli/flag/type.go diff --git a/client/v2/autocli/flag/uint32.go b/client/v2/cli/flag/uint32.go similarity index 100% rename from client/v2/autocli/flag/uint32.go rename to client/v2/cli/flag/uint32.go diff --git a/client/v2/autocli/flag/uint64.go b/client/v2/cli/flag/uint64.go similarity index 100% rename from client/v2/autocli/flag/uint64.go rename to client/v2/cli/flag/uint64.go diff --git a/client/v2/autocli/flag/value.go b/client/v2/cli/flag/value.go similarity index 100% rename from client/v2/autocli/flag/value.go rename to client/v2/cli/flag/value.go diff --git a/client/v2/autocli/query.go b/client/v2/cli/query.go similarity index 96% rename from client/v2/autocli/query.go rename to client/v2/cli/query.go index e272a626174c..c69d01fd98f1 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/cli/query.go @@ -1,4 +1,4 @@ -package autocli +package cli import ( "fmt" @@ -10,7 +10,7 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" - "github.com/cosmos/cosmos-sdk/client/v2/autocli/flag" + "github.com/cosmos/cosmos-sdk/client/v2/cli/flag" "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) @@ -87,7 +87,12 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor // CreateQueryMethodCommand creates a gRPC query command for the given service method. func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) (*cobra.Command, error) { - if options != nil && options.Skip { + if options == nil { + // use the defaults + options = &autocliv1.RpcCommandOptions{} + } + + if options.Skip { return nil, nil } @@ -106,7 +111,7 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output()) use := options.Use - if use != "" { + if use == "" { use = protoNameToCliName(descriptor.Name()) } diff --git a/client/v2/autocli/query_test.go b/client/v2/cli/query_test.go similarity index 93% rename from client/v2/autocli/query_test.go rename to client/v2/cli/query_test.go index ddd8c7c8d0e4..d820503c9dfe 100644 --- a/client/v2/autocli/query_test.go +++ b/client/v2/cli/query_test.go @@ -1,4 +1,4 @@ -package autocli +package cli import ( "bytes" @@ -7,7 +7,6 @@ import ( "testing" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" - "github.com/spf13/cobra" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/testing/protocmp" @@ -38,8 +37,8 @@ func testExec(t *testing.T, args ...string) *testClientConn { return conn }, } - cmd := &cobra.Command{Use: "test"} - b.AddQueryServiceCommands(cmd, &autocliv1.ServiceCommandDescriptor{Service: testpb.Query_ServiceDesc.ServiceName}) + cmd, err := b.BuildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{Service: testpb.Query_ServiceDesc.ServiceName}) + assert.NilError(t, err) cmd.SetArgs(args) cmd.SetOut(conn.out) assert.NilError(t, cmd.Execute()) diff --git a/client/v2/autocli/testdata/bank_example.yaml b/client/v2/cli/testdata/bank_example.yaml similarity index 100% rename from client/v2/autocli/testdata/bank_example.yaml rename to client/v2/cli/testdata/bank_example.yaml diff --git a/client/v2/autocli/testdata/help.golden b/client/v2/cli/testdata/help.golden similarity index 100% rename from client/v2/autocli/testdata/help.golden rename to client/v2/cli/testdata/help.golden diff --git a/client/v2/autocli/validate.go b/client/v2/cli/validate.go similarity index 98% rename from client/v2/autocli/validate.go rename to client/v2/cli/validate.go index 7d84cf5bfa09..158b739fb35b 100644 --- a/client/v2/autocli/validate.go +++ b/client/v2/cli/validate.go @@ -1,4 +1,4 @@ -package autocli +package cli import ( "errors" diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index e6773d379212..e64a62b1e796 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -191,7 +191,6 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { // add keybase, auxiliary RPC, query, and tx child commands rootCmd.AddCommand( rpc.StatusCommand(), - // queryCommand(), txCommand(), keys.Commands(simapp.DefaultNodeHome), From 20a3807a3a07a67117bbb82301dc49d8c9122224 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 17:13:13 -0400 Subject: [PATCH 09/25] WIP --- client/v2/cli/flag/address.go | 12 ++-- client/v2/cli/flag/bool.go | 18 +++--- client/v2/cli/flag/builder.go | 2 +- client/v2/cli/flag/bytes.go | 16 ++---- client/v2/cli/flag/doc.go | 4 ++ client/v2/cli/flag/duration.go | 13 ++--- client/v2/cli/flag/enum.go | 38 ++++++------- client/v2/cli/flag/field.go | 49 +++++++++------- client/v2/cli/flag/int32.go | 16 ++---- client/v2/cli/flag/int64.go | 17 ++---- client/v2/cli/flag/list.go | 31 +++++----- client/v2/cli/flag/message.go | 91 +++++++++++++++--------------- client/v2/cli/flag/message_json.go | 67 ++++++++++++++++++++++ client/v2/cli/flag/positional.go | 1 - client/v2/cli/flag/register.go | 66 +--------------------- client/v2/cli/flag/string.go | 16 ++---- client/v2/cli/flag/timestamp.go | 13 ++--- client/v2/cli/flag/type.go | 11 ++-- client/v2/cli/flag/uint32.go | 16 ++---- client/v2/cli/flag/uint64.go | 16 ++---- 20 files changed, 238 insertions(+), 275 deletions(-) create mode 100644 client/v2/cli/flag/doc.go create mode 100644 client/v2/cli/flag/message_json.go delete mode 100644 client/v2/cli/flag/positional.go diff --git a/client/v2/cli/flag/address.go b/client/v2/cli/flag/address.go index c9a190147d4b..8a9e6b4160ed 100644 --- a/client/v2/cli/flag/address.go +++ b/client/v2/cli/flag/address.go @@ -6,14 +6,10 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type addressStringType struct{} - -func (a addressStringType) NewValue(_ context.Context, _ *Builder) Value { - return &addressValue{} -} - -func (a addressStringType) DefaultValue() string { - return "" +var addressStringType = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + return &addressValue{} + }, } type addressValue struct { diff --git a/client/v2/cli/flag/bool.go b/client/v2/cli/flag/bool.go index b3dd0c77a4b3..32f21e25f5bf 100644 --- a/client/v2/cli/flag/bool.go +++ b/client/v2/cli/flag/bool.go @@ -7,19 +7,15 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type boolType struct{} - -func (b boolType) NewValue(context.Context, *Builder) Value { - v := new(bool) - return (*boolValue)(v) -} - -func (b boolType) DefaultValue() string { - return defaultDefaultValue(b) +var boolType = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + v := new(bool) + return (*boolValue)(v) + }, + DefaultValue: "", + NoOptDefaultValue: "", } -var _ Type = boolType{} - type boolValue bool func (b *boolValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/builder.go b/client/v2/cli/flag/builder.go index 2969314e84db..1c77017a1c8c 100644 --- a/client/v2/cli/flag/builder.go +++ b/client/v2/cli/flag/builder.go @@ -32,7 +32,7 @@ func (b *Builder) init() { if b.scalarFlagTypes == nil { b.scalarFlagTypes = map[string]Type{} - b.scalarFlagTypes["cosmos.AddressString"] = addressStringType{} + b.scalarFlagTypes["cosmos.AddressString"] = addressStringType } } diff --git a/client/v2/cli/flag/bytes.go b/client/v2/cli/flag/bytes.go index 49ae274eaaa2..d1eac37c9e5c 100644 --- a/client/v2/cli/flag/bytes.go +++ b/client/v2/cli/flag/bytes.go @@ -8,19 +8,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type bytesBase64Type struct{} - -func (b bytesBase64Type) NewValue(context.Context, *Builder) Value { - x := new([]byte) - return (*bytesBase64Value)(x) -} - -func (b bytesBase64Type) DefaultValue() string { - return defaultDefaultValue(b) +var bytesBase64Type = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + x := new([]byte) + return (*bytesBase64Value)(x) + }, } -var _ Type = bytesBase64Type{} - // BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded type bytesBase64Value []byte diff --git a/client/v2/cli/flag/doc.go b/client/v2/cli/flag/doc.go new file mode 100644 index 000000000000..5e8a1f365d37 --- /dev/null +++ b/client/v2/cli/flag/doc.go @@ -0,0 +1,4 @@ +// Package flag defines functionality for automatically managing command +// line flags as well positional arguments that are based on protobuf message +// fields. +package flag diff --git a/client/v2/cli/flag/duration.go b/client/v2/cli/flag/duration.go index 1c6793b3c670..2573f4971191 100644 --- a/client/v2/cli/flag/duration.go +++ b/client/v2/cli/flag/duration.go @@ -8,14 +8,11 @@ import ( "google.golang.org/protobuf/types/known/durationpb" ) -type durationType struct{} - -func (t durationType) NewValue(context.Context, *Builder) Value { - return &durationValue{} -} - -func (t durationType) DefaultValue() string { - return "" +var durationType = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + return &durationValue{} + }, + DefaultValue: "", } type durationValue struct { diff --git a/client/v2/cli/flag/enum.go b/client/v2/cli/flag/enum.go index b00c55b2fe40..1fba9a72dd42 100644 --- a/client/v2/cli/flag/enum.go +++ b/client/v2/cli/flag/enum.go @@ -9,29 +9,27 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type enumType struct { - enum protoreflect.EnumDescriptor -} - -func (b enumType) NewValue(context.Context, *Builder) Value { - val := &enumValue{ - enum: b.enum, - valMap: map[string]protoreflect.EnumValueDescriptor{}, - } - n := b.enum.Values().Len() - for i := 0; i < n; i++ { - valDesc := b.enum.Values().Get(i) - val.valMap[enumValueName(b.enum, valDesc)] = valDesc +func enumType(enum protoreflect.EnumDescriptor) Type { + defValue := "" + if def := enum.Values().ByNumber(0); def != nil { + defValue = enumValueName(enum, def) } - return val -} -func (b enumType) DefaultValue() string { - defValue := "" - if def := b.enum.Values().ByNumber(0); def != nil { - defValue = enumValueName(b.enum, def) + return Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + val := &enumValue{ + enum: enum, + valMap: map[string]protoreflect.EnumValueDescriptor{}, + } + n := enum.Values().Len() + for i := 0; i < n; i++ { + valDesc := enum.Values().Get(i) + val.valMap[enumValueName(enum, valDesc)] = valDesc + } + return val + }, + DefaultValue: defValue, } - return defValue } type enumValue struct { diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index 638595c3fdc7..68e880b544d0 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -48,14 +48,19 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel shorthand := opts.Shorthand - typ := b.resolveFlagType(field) - if typ == nil { - return nil, fmt.Errorf("unable to bind field %v", field) + typ, found := b.resolveFlagType(field) + if !found { + return nil, fmt.Errorf("can't resolve field %v", field) } defaultValue := opts.DefaultValue if defaultValue == "" { - defaultValue = typ.DefaultValue() + defaultValue = typ.DefaultValue + } + + noOptDefVal := opts.NoOptDefaultValue + if noOptDefVal == "" { + noOptDefVal = typ.NoOptDefaultValue } val := typ.NewValue(ctx, b) @@ -67,64 +72,66 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel Deprecated: opts.Deprecated, ShorthandDeprecated: opts.ShorthandDeprecated, Hidden: opts.Hidden, - NoOptDefVal: opts.NoOptDefaultValue, + NoOptDefVal: noOptDefVal, Value: val, }) return val, nil } -func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { +func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) (typ Type, found bool) { if field.IsList() { - typ := b.resolveFlagTypeBasic(field) - if typ != nil { - return compositeListType{simpleType: typ} + typ, found := b.resolveFlagTypeBasic(field) + if found { + return compositeListType(typ), true } - return nil + return Type{}, false } else { return b.resolveFlagTypeBasic(field) } } -func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type { +func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) (typ Type, found bool) { scalar := proto.GetExtension(field.Options(), cosmos_proto.E_Scalar) if scalar != nil { b.init() if typ, ok := b.scalarFlagTypes[scalar.(string)]; ok { - return typ + return typ, true } } switch field.Kind() { case protoreflect.BytesKind: - return bytesBase64Type{} + typ = bytesBase64Type case protoreflect.StringKind: - return stringType{} + typ = stringType case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - return uint32Type{} + typ = uint32Type case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: return uint64Type{} case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - return int32Type{} + typ = int32Type case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: return int64Type{} case protoreflect.BoolKind: - return boolType{} + typ = boolType case protoreflect.EnumKind: - return enumType{enum: field.Enum()} + typ = enumType(field.Enum()) case protoreflect.MessageKind: b.init() if flagType, ok := b.messageFlagTypes[field.Message().FullName()]; ok { - return flagType + return flagType, true } - return jsonMessageFlagType{ + typ = jsonMessageFlagType{ messageDesc: field.Message(), } default: - return nil + return Type{}, false } + + return typ, true } type simpleValueBinder struct { diff --git a/client/v2/cli/flag/int32.go b/client/v2/cli/flag/int32.go index 0b6a911fece1..093c60d84165 100644 --- a/client/v2/cli/flag/int32.go +++ b/client/v2/cli/flag/int32.go @@ -7,19 +7,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type int32Type struct{} - -func (t int32Type) NewValue(context.Context, *Builder) Value { - v := new(int32) - return (*int32Value)(v) -} - -func (t int32Type) DefaultValue() string { - return defaultDefaultValue(t) +var int32Type = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + v := new(int32) + return (*int32Value)(v) + }, } -var _ Type = int32Type{} - type int32Value int32 func (i *int32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/int64.go b/client/v2/cli/flag/int64.go index 3b1b5d930412..5b40bee6608a 100644 --- a/client/v2/cli/flag/int64.go +++ b/client/v2/cli/flag/int64.go @@ -7,20 +7,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type int64Type struct{} - -func (u int64Type) NewValue(context.Context, *Builder) Value { - v := new(int64) - return (*int64Value)(v) +var int64Type = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + v := new(int64) + return (*int64Value)(v) + }, } -func (u int64Type) DefaultValue() string { - - return "0" -} - -var _ Type = int64Type{} - type int64Value int64 func (i *int64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/list.go b/client/v2/cli/flag/list.go index 691d12ddd420..96e283f3d91a 100644 --- a/client/v2/cli/flag/list.go +++ b/client/v2/cli/flag/list.go @@ -48,23 +48,20 @@ import ( // } //} -type compositeListType struct { - simpleType Type -} +func compositeListType(simpleType Type) Type { + return Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { -func (t compositeListType) NewValue(ctx context.Context, opts *Builder) Value { - return &compositeListValue{ - simpleType: t.simpleType, - values: nil, - ctx: ctx, - opts: opts, + return &compositeListValue{ + simpleType: simpleType, + values: nil, + ctx: ctx, + opts: builder, + } + }, } } -func (t compositeListType) DefaultValue() string { - return "" -} - type compositeListValue struct { simpleType Type values []protoreflect.Value @@ -72,17 +69,17 @@ type compositeListValue struct { opts *Builder } -func (c compositeListValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { +func (c *compositeListValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { c.AppendTo(message.NewField(field).List()) } -func (c compositeListValue) AppendTo(list protoreflect.List) { +func (c *compositeListValue) AppendTo(list protoreflect.List) { for _, value := range c.values { list.Append(value) } } -func (c compositeListValue) String() string { +func (c *compositeListValue) String() string { if len(c.values) == 0 { return "" } @@ -104,6 +101,6 @@ func (c *compositeListValue) Set(val string) error { return nil } -func (c compositeListValue) Type() string { +func (c *compositeListValue) Type() string { return fmt.Sprintf("%s (repeated)", c.simpleType.NewValue(c.ctx, c.opts).Type()) } diff --git a/client/v2/cli/flag/message.go b/client/v2/cli/flag/message.go index 81a201cbd3ba..6bc331e6de92 100644 --- a/client/v2/cli/flag/message.go +++ b/client/v2/cli/flag/message.go @@ -1,67 +1,66 @@ package flag import ( - "context" - "fmt" - - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" + "github.com/spf13/cobra" "google.golang.org/protobuf/reflect/protoreflect" - - "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) -type jsonMessageFlagType struct { - messageDesc protoreflect.MessageDescriptor -} +// MessageBinder binds multiple flags in a flag set to a protobuf message. +type MessageBinder struct { + CobraArgs cobra.PositionalArgs -func (j jsonMessageFlagType) NewValue(_ context.Context, builder *Builder) Value { - return &jsonMessageFlagValue{ - messageType: util.ResolveMessageType(builder.TypeResolver, j.messageDesc), - jsonMarshalOptions: protojson.MarshalOptions{Resolver: builder.TypeResolver}, - jsonUnmarshalOptions: protojson.UnmarshalOptions{Resolver: builder.TypeResolver}, + positionalArgs []struct { + binder Value + field protoreflect.FieldDescriptor + varargs bool } -} - -func (j jsonMessageFlagType) DefaultValue() string { - return "" -} -type jsonMessageFlagValue struct { - jsonMarshalOptions protojson.MarshalOptions - jsonUnmarshalOptions protojson.UnmarshalOptions - messageType protoreflect.MessageType - message proto.Message + flagFieldPairs []struct { + binder FieldValueBinder + field protoreflect.FieldDescriptor + } + messageType protoreflect.MessageType } -func (j jsonMessageFlagValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfMessage(j.message.ProtoReflect())) +// BuildMessage builds and returns a new message for the bound flags. +func (m MessageBinder) BuildMessage(positionalArgs []string) (protoreflect.Message, error) { + msg := m.messageType.New() + err := m.Bind(msg, positionalArgs) + return msg, err } -func (j jsonMessageFlagValue) Get() (protoreflect.Value, error) { - if j.message == nil { - return protoreflect.Value{}, nil - } - return protoreflect.ValueOfMessage(j.message.ProtoReflect()), nil -} +// Bind binds the flag values to an existing protobuf message. +func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) error { + n := len(positionalArgs) + for i, arg := range m.positionalArgs { + if i >= n { + panic("unexpected: validate args should have caught this") + } -func (j jsonMessageFlagValue) String() string { - if j.message == nil { - return "" + if arg.varargs { + for _, v := range positionalArgs[i:] { + err := arg.binder.Set(v) + if err != nil { + return err + } + } + } else { + err := arg.binder.Set(positionalArgs[i]) + if err != nil { + return err + } + } } - bz, err := j.jsonMarshalOptions.Marshal(j.message) - if err != nil { - return err.Error() + for _, pair := range m.flagFieldPairs { + pair.binder.Bind(msg, pair.field) } - return string(bz) -} -func (j *jsonMessageFlagValue) Set(s string) error { - j.message = j.messageType.New().Interface() - return j.jsonUnmarshalOptions.Unmarshal([]byte(s), j.message) + return nil } -func (j jsonMessageFlagValue) Type() string { - return fmt.Sprintf("%s (json)", j.messageType.Descriptor().FullName()) +// Get calls BuildMessage and wraps the result in a protoreflect.Value. +func (m MessageBinder) Get() (protoreflect.Value, error) { + msg, err := m.BuildMessage(nil) + return protoreflect.ValueOfMessage(msg), err } diff --git a/client/v2/cli/flag/message_json.go b/client/v2/cli/flag/message_json.go new file mode 100644 index 000000000000..81a201cbd3ba --- /dev/null +++ b/client/v2/cli/flag/message_json.go @@ -0,0 +1,67 @@ +package flag + +import ( + "context" + "fmt" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/cosmos/cosmos-sdk/client/v2/internal/util" +) + +type jsonMessageFlagType struct { + messageDesc protoreflect.MessageDescriptor +} + +func (j jsonMessageFlagType) NewValue(_ context.Context, builder *Builder) Value { + return &jsonMessageFlagValue{ + messageType: util.ResolveMessageType(builder.TypeResolver, j.messageDesc), + jsonMarshalOptions: protojson.MarshalOptions{Resolver: builder.TypeResolver}, + jsonUnmarshalOptions: protojson.UnmarshalOptions{Resolver: builder.TypeResolver}, + } +} + +func (j jsonMessageFlagType) DefaultValue() string { + return "" +} + +type jsonMessageFlagValue struct { + jsonMarshalOptions protojson.MarshalOptions + jsonUnmarshalOptions protojson.UnmarshalOptions + messageType protoreflect.MessageType + message proto.Message +} + +func (j jsonMessageFlagValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { + message.Set(field, protoreflect.ValueOfMessage(j.message.ProtoReflect())) +} + +func (j jsonMessageFlagValue) Get() (protoreflect.Value, error) { + if j.message == nil { + return protoreflect.Value{}, nil + } + return protoreflect.ValueOfMessage(j.message.ProtoReflect()), nil +} + +func (j jsonMessageFlagValue) String() string { + if j.message == nil { + return "" + } + + bz, err := j.jsonMarshalOptions.Marshal(j.message) + if err != nil { + return err.Error() + } + return string(bz) +} + +func (j *jsonMessageFlagValue) Set(s string) error { + j.message = j.messageType.New().Interface() + return j.jsonUnmarshalOptions.Unmarshal([]byte(s), j.message) +} + +func (j jsonMessageFlagValue) Type() string { + return fmt.Sprintf("%s (json)", j.messageType.Descriptor().FullName()) +} diff --git a/client/v2/cli/flag/positional.go b/client/v2/cli/flag/positional.go deleted file mode 100644 index 02d20d554eab..000000000000 --- a/client/v2/cli/flag/positional.go +++ /dev/null @@ -1 +0,0 @@ -package flag diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index b04672a7e712..0d56a03ee603 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -35,9 +35,9 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa hasVarargs = true } - typ := b.resolveFlagType(field) - if typ == nil { - return nil, fmt.Errorf("can't resolve field %v", field) + typ, err := b.resolveFlagType(field) + if err != nil { + return nil, err } value := typ.NewValue(ctx, b) @@ -74,63 +74,3 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa } return handler, nil } - -// MessageBinder binds multiple flags in a flag set to a protobuf message. -type MessageBinder struct { - CobraArgs cobra.PositionalArgs - - positionalArgs []struct { - binder Value - field protoreflect.FieldDescriptor - varargs bool - } - - flagFieldPairs []struct { - binder FieldValueBinder - field protoreflect.FieldDescriptor - } - messageType protoreflect.MessageType -} - -// BuildMessage builds and returns a new message for the bound flags. -func (m MessageBinder) BuildMessage(positionalArgs []string) (protoreflect.Message, error) { - msg := m.messageType.New() - err := m.Bind(msg, positionalArgs) - return msg, err -} - -// Bind binds the flag values to an existing protobuf message. -func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) error { - n := len(positionalArgs) - for i, arg := range m.positionalArgs { - if i >= n { - panic("unexpected: validate args should have caught this") - } - - if arg.varargs { - for _, v := range positionalArgs[i:] { - err := arg.binder.Set(v) - if err != nil { - return err - } - } - } else { - err := arg.binder.Set(positionalArgs[i]) - if err != nil { - return err - } - } - } - - for _, pair := range m.flagFieldPairs { - pair.binder.Bind(msg, pair.field) - } - - return nil -} - -// Get calls BuildMessage and wraps the result in a protoreflect.Value. -func (m MessageBinder) Get() (protoreflect.Value, error) { - msg, err := m.BuildMessage(nil) - return protoreflect.ValueOfMessage(msg), err -} diff --git a/client/v2/cli/flag/string.go b/client/v2/cli/flag/string.go index 0edd13933eac..6898cae2ec37 100644 --- a/client/v2/cli/flag/string.go +++ b/client/v2/cli/flag/string.go @@ -6,19 +6,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type stringType struct{} - -func (s stringType) NewValue(context.Context, *Builder) Value { - v := new(string) - return (*stringValue)(v) -} - -func (s stringType) DefaultValue() string { - return "" +var stringType = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + v := new(string) + return (*stringValue)(v) + }, } -var _ Type = stringType{} - type stringValue string func (s *stringValue) Set(val string) error { diff --git a/client/v2/cli/flag/timestamp.go b/client/v2/cli/flag/timestamp.go index f83cbbfc9d6c..800ba13f2e33 100644 --- a/client/v2/cli/flag/timestamp.go +++ b/client/v2/cli/flag/timestamp.go @@ -8,14 +8,11 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" ) -type timestampType struct{} - -func (t timestampType) NewValue(context.Context, *Builder) Value { - return ×tampValue{} -} - -func (t timestampType) DefaultValue() string { - return "" +var timestampType = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + return ×tampValue{} + }, + DefaultValue: "", } type timestampValue struct { diff --git a/client/v2/cli/flag/type.go b/client/v2/cli/flag/type.go index a0e79b553d90..e08cc62d051c 100644 --- a/client/v2/cli/flag/type.go +++ b/client/v2/cli/flag/type.go @@ -5,11 +5,14 @@ import ( ) // Type specifies a custom flag type. -type Type interface { +type Type struct { // NewValue returns a new pflag.Value which must also implement either // SimpleValue or ListValue. - NewValue(context.Context, *Builder) Value + NewValue func(context.Context, *Builder) Value - // DefaultValue is the default value for this type. - DefaultValue() string + // DefaultValue is the default value for this type. If it is set to the + // empty string, NewValue().String will be used. + DefaultValue string + + NoOptDefaultValue string } diff --git a/client/v2/cli/flag/uint32.go b/client/v2/cli/flag/uint32.go index 99967a616cfc..cb43ac3d9303 100644 --- a/client/v2/cli/flag/uint32.go +++ b/client/v2/cli/flag/uint32.go @@ -7,19 +7,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type uint32Type struct{} - -func (t uint32Type) NewValue(context.Context, *Builder) Value { - v := new(uint32) - return (*uint32Value)(v) -} - -func (t uint32Type) DefaultValue() string { - return defaultDefaultValue(t) +var uint32Type = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + v := new(uint32) + return (*uint32Value)(v) + }, } -var _ Type = uint32Type{} - type uint32Value uint32 func (i *uint32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/uint64.go b/client/v2/cli/flag/uint64.go index 8997644a8a84..3c894fbf67f8 100644 --- a/client/v2/cli/flag/uint64.go +++ b/client/v2/cli/flag/uint64.go @@ -7,19 +7,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -type uint64Type struct{} - -func (t uint64Type) NewValue(context.Context, *Builder) Value { - v := new(uint64) - return (*uint64Value)(v) -} - -func (t uint64Type) DefaultValue() string { - return defaultDefaultValue(t) +var uint64Type = Type{ + NewValue: func(ctx context.Context, builder *Builder) Value { + v := new(uint64) + return (*uint64Value)(v) + }, } -var _ Type = uint64Type{} - type uint64Value uint64 func (i *uint64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { From 3d438eaf9999cd4b45de1e1d43745d62939b2f1f Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 19:31:11 -0400 Subject: [PATCH 10/25] WIP --- client/v2/cli/flag/address.go | 12 ++++--- client/v2/cli/flag/bool.go | 23 +++++++++----- client/v2/cli/flag/builder.go | 2 +- client/v2/cli/flag/bytes.go | 12 ++++--- client/v2/cli/flag/duration.go | 13 +++++--- client/v2/cli/flag/enum.go | 38 +++++++++++----------- client/v2/cli/flag/field.go | 56 +++++++++++++++++---------------- client/v2/cli/flag/int32.go | 12 ++++--- client/v2/cli/flag/int64.go | 12 ++++--- client/v2/cli/flag/list.go | 19 ++++++----- client/v2/cli/flag/register.go | 6 ++-- client/v2/cli/flag/string.go | 12 ++++--- client/v2/cli/flag/timestamp.go | 13 +++++--- client/v2/cli/flag/type.go | 21 +++++++++---- client/v2/cli/flag/uint32.go | 12 ++++--- client/v2/cli/flag/uint64.go | 12 ++++--- client/v2/cli/flag/value.go | 20 +++++------- 17 files changed, 167 insertions(+), 128 deletions(-) diff --git a/client/v2/cli/flag/address.go b/client/v2/cli/flag/address.go index 8a9e6b4160ed..c9a190147d4b 100644 --- a/client/v2/cli/flag/address.go +++ b/client/v2/cli/flag/address.go @@ -6,10 +6,14 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var addressStringType = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - return &addressValue{} - }, +type addressStringType struct{} + +func (a addressStringType) NewValue(_ context.Context, _ *Builder) Value { + return &addressValue{} +} + +func (a addressStringType) DefaultValue() string { + return "" } type addressValue struct { diff --git a/client/v2/cli/flag/bool.go b/client/v2/cli/flag/bool.go index 32f21e25f5bf..07ac4a42bafd 100644 --- a/client/v2/cli/flag/bool.go +++ b/client/v2/cli/flag/bool.go @@ -7,17 +7,26 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var boolType = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - v := new(bool) - return (*boolValue)(v) - }, - DefaultValue: "", - NoOptDefaultValue: "", +type boolType struct{} + +func (b boolType) NewValue(context.Context, *Builder) Value { + v := new(bool) + return (*boolValue)(v) +} + +func (b boolType) NoOptDefaultValue() string { + return "true" } +var _ Type = boolType{} +var _ HasNoOptDefaultValue = boolType{} + type boolValue bool +func (b *boolValue) Get(protoreflect.Value) (protoreflect.Value, error) { + return protoreflect.ValueOfBool(bool(*b)), nil +} + func (b *boolValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { message.Set(field, protoreflect.ValueOfBool(bool(*b))) } diff --git a/client/v2/cli/flag/builder.go b/client/v2/cli/flag/builder.go index 1c77017a1c8c..2969314e84db 100644 --- a/client/v2/cli/flag/builder.go +++ b/client/v2/cli/flag/builder.go @@ -32,7 +32,7 @@ func (b *Builder) init() { if b.scalarFlagTypes == nil { b.scalarFlagTypes = map[string]Type{} - b.scalarFlagTypes["cosmos.AddressString"] = addressStringType + b.scalarFlagTypes["cosmos.AddressString"] = addressStringType{} } } diff --git a/client/v2/cli/flag/bytes.go b/client/v2/cli/flag/bytes.go index d1eac37c9e5c..2c3560f4aeb8 100644 --- a/client/v2/cli/flag/bytes.go +++ b/client/v2/cli/flag/bytes.go @@ -8,13 +8,15 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var bytesBase64Type = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - x := new([]byte) - return (*bytesBase64Value)(x) - }, +type bytesBase64Type struct{} + +func (b bytesBase64Type) NewValue(context.Context, *Builder) Value { + x := new([]byte) + return (*bytesBase64Value)(x) } +var _ Type = bytesBase64Type{} + // BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded type bytesBase64Value []byte diff --git a/client/v2/cli/flag/duration.go b/client/v2/cli/flag/duration.go index 2573f4971191..1c6793b3c670 100644 --- a/client/v2/cli/flag/duration.go +++ b/client/v2/cli/flag/duration.go @@ -8,11 +8,14 @@ import ( "google.golang.org/protobuf/types/known/durationpb" ) -var durationType = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - return &durationValue{} - }, - DefaultValue: "", +type durationType struct{} + +func (t durationType) NewValue(context.Context, *Builder) Value { + return &durationValue{} +} + +func (t durationType) DefaultValue() string { + return "" } type durationValue struct { diff --git a/client/v2/cli/flag/enum.go b/client/v2/cli/flag/enum.go index 1fba9a72dd42..b00c55b2fe40 100644 --- a/client/v2/cli/flag/enum.go +++ b/client/v2/cli/flag/enum.go @@ -9,27 +9,29 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -func enumType(enum protoreflect.EnumDescriptor) Type { - defValue := "" - if def := enum.Values().ByNumber(0); def != nil { - defValue = enumValueName(enum, def) +type enumType struct { + enum protoreflect.EnumDescriptor +} + +func (b enumType) NewValue(context.Context, *Builder) Value { + val := &enumValue{ + enum: b.enum, + valMap: map[string]protoreflect.EnumValueDescriptor{}, } + n := b.enum.Values().Len() + for i := 0; i < n; i++ { + valDesc := b.enum.Values().Get(i) + val.valMap[enumValueName(b.enum, valDesc)] = valDesc + } + return val +} - return Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - val := &enumValue{ - enum: enum, - valMap: map[string]protoreflect.EnumValueDescriptor{}, - } - n := enum.Values().Len() - for i := 0; i < n; i++ { - valDesc := enum.Values().Get(i) - val.valMap[enumValueName(enum, valDesc)] = valDesc - } - return val - }, - DefaultValue: defValue, +func (b enumType) DefaultValue() string { + defValue := "" + if def := b.enum.Values().ByNumber(0); def != nil { + defValue = enumValueName(b.enum, def) } + return defValue } type enumValue struct { diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index 68e880b544d0..044463ac12e7 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -48,90 +48,92 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel shorthand := opts.Shorthand - typ, found := b.resolveFlagType(field) - if !found { - return nil, fmt.Errorf("can't resolve field %v", field) + typ := b.resolveFlagType(field) + if typ == nil { + return nil, fmt.Errorf("unable to bind field %v", field) } defaultValue := opts.DefaultValue if defaultValue == "" { - defaultValue = typ.DefaultValue + if hasDefaultValue, ok := typ.(HasDefaultValue); ok { + defaultValue = hasDefaultValue.DefaultValue() + } } - noOptDefVal := opts.NoOptDefaultValue - if noOptDefVal == "" { - noOptDefVal = typ.NoOptDefaultValue + noOptDefaultValue := opts.NoOptDefaultValue + if noOptDefaultValue == "" { + if hasNoOptDefaultValue, ok := typ.(HasNoOptDefaultValue); ok { + noOptDefaultValue = hasNoOptDefaultValue.NoOptDefaultValue() + } } val := typ.NewValue(ctx, b) flagSet.AddFlag(&pflag.Flag{ Name: name, + Value: val, Shorthand: shorthand, Usage: usage, DefValue: defaultValue, + NoOptDefVal: noOptDefaultValue, Deprecated: opts.Deprecated, ShorthandDeprecated: opts.ShorthandDeprecated, Hidden: opts.Hidden, - NoOptDefVal: noOptDefVal, - Value: val, }) return val, nil } -func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) (typ Type, found bool) { +func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { if field.IsList() { - typ, found := b.resolveFlagTypeBasic(field) - if found { - return compositeListType(typ), true + typ := b.resolveFlagTypeBasic(field) + if typ != nil { + return compositeListType{simpleType: typ} } - return Type{}, false + return nil } else { return b.resolveFlagTypeBasic(field) } } -func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) (typ Type, found bool) { +func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type { scalar := proto.GetExtension(field.Options(), cosmos_proto.E_Scalar) if scalar != nil { b.init() if typ, ok := b.scalarFlagTypes[scalar.(string)]; ok { - return typ, true + return typ } } switch field.Kind() { case protoreflect.BytesKind: - typ = bytesBase64Type + return bytesBase64Type{} case protoreflect.StringKind: - typ = stringType + return stringType{} case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - typ = uint32Type + return uint32Type{} case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: return uint64Type{} case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - typ = int32Type + return int32Type{} case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: return int64Type{} case protoreflect.BoolKind: - typ = boolType + return boolType{} case protoreflect.EnumKind: - typ = enumType(field.Enum()) + return enumType{enum: field.Enum()} case protoreflect.MessageKind: b.init() if flagType, ok := b.messageFlagTypes[field.Message().FullName()]; ok { - return flagType, true + return flagType } - typ = jsonMessageFlagType{ + return jsonMessageFlagType{ messageDesc: field.Message(), } default: - return Type{}, false + return nil } - - return typ, true } type simpleValueBinder struct { diff --git a/client/v2/cli/flag/int32.go b/client/v2/cli/flag/int32.go index 093c60d84165..7188d71383f8 100644 --- a/client/v2/cli/flag/int32.go +++ b/client/v2/cli/flag/int32.go @@ -7,13 +7,15 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var int32Type = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - v := new(int32) - return (*int32Value)(v) - }, +type int32Type struct{} + +func (t int32Type) NewValue(context.Context, *Builder) Value { + v := new(int32) + return (*int32Value)(v) } +var _ Type = int32Type{} + type int32Value int32 func (i *int32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/int64.go b/client/v2/cli/flag/int64.go index 5b40bee6608a..709c2b472843 100644 --- a/client/v2/cli/flag/int64.go +++ b/client/v2/cli/flag/int64.go @@ -7,13 +7,15 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var int64Type = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - v := new(int64) - return (*int64Value)(v) - }, +type int64Type struct{} + +func (u int64Type) NewValue(context.Context, *Builder) Value { + v := new(int64) + return (*int64Value)(v) } +var _ Type = int64Type{} + type int64Value int64 func (i *int64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/list.go b/client/v2/cli/flag/list.go index 96e283f3d91a..efcd66d74cb2 100644 --- a/client/v2/cli/flag/list.go +++ b/client/v2/cli/flag/list.go @@ -48,17 +48,16 @@ import ( // } //} -func compositeListType(simpleType Type) Type { - return Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { +type compositeListType struct { + simpleType Type +} - return &compositeListValue{ - simpleType: simpleType, - values: nil, - ctx: ctx, - opts: builder, - } - }, +func (t compositeListType) NewValue(ctx context.Context, opts *Builder) Value { + return &compositeListValue{ + simpleType: t.simpleType, + values: nil, + ctx: ctx, + opts: opts, } } diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index 0d56a03ee603..069402e41748 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -35,9 +35,9 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa hasVarargs = true } - typ, err := b.resolveFlagType(field) - if err != nil { - return nil, err + typ := b.resolveFlagType(field) + if typ == nil { + return nil, fmt.Errorf("can't resolve field %v", field) } value := typ.NewValue(ctx, b) diff --git a/client/v2/cli/flag/string.go b/client/v2/cli/flag/string.go index 6898cae2ec37..b82a66143257 100644 --- a/client/v2/cli/flag/string.go +++ b/client/v2/cli/flag/string.go @@ -6,13 +6,15 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var stringType = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - v := new(string) - return (*stringValue)(v) - }, +type stringType struct{} + +func (s stringType) NewValue(context.Context, *Builder) Value { + v := new(string) + return (*stringValue)(v) } +var _ Type = stringType{} + type stringValue string func (s *stringValue) Set(val string) error { diff --git a/client/v2/cli/flag/timestamp.go b/client/v2/cli/flag/timestamp.go index 800ba13f2e33..f83cbbfc9d6c 100644 --- a/client/v2/cli/flag/timestamp.go +++ b/client/v2/cli/flag/timestamp.go @@ -8,11 +8,14 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" ) -var timestampType = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - return ×tampValue{} - }, - DefaultValue: "", +type timestampType struct{} + +func (t timestampType) NewValue(context.Context, *Builder) Value { + return ×tampValue{} +} + +func (t timestampType) DefaultValue() string { + return "" } type timestampValue struct { diff --git a/client/v2/cli/flag/type.go b/client/v2/cli/flag/type.go index e08cc62d051c..9bc0ee7b2344 100644 --- a/client/v2/cli/flag/type.go +++ b/client/v2/cli/flag/type.go @@ -5,14 +5,23 @@ import ( ) // Type specifies a custom flag type. -type Type struct { +type Type interface { // NewValue returns a new pflag.Value which must also implement either // SimpleValue or ListValue. - NewValue func(context.Context, *Builder) Value + NewValue(context.Context, *Builder) Value +} - // DefaultValue is the default value for this type. If it is set to the - // empty string, NewValue().String will be used. - DefaultValue string +// HasDefaultValue defines a type which has an explicitly specified default +// value. If this interface isn't specified, Type.NewValue().String() will +// be used. +type HasDefaultValue interface { + // DefaultValue is the default value for this type. + DefaultValue() string +} - NoOptDefaultValue string +// HasNoOptDefaultValue defines a type which has an explicitly specified no-option +// default value. If this interface isn't specified, the empty string will be used. +type HasNoOptDefaultValue interface { + // NoOptDefaultValue is the no-option default value for this type. + NoOptDefaultValue() string } diff --git a/client/v2/cli/flag/uint32.go b/client/v2/cli/flag/uint32.go index cb43ac3d9303..aede1be14177 100644 --- a/client/v2/cli/flag/uint32.go +++ b/client/v2/cli/flag/uint32.go @@ -7,13 +7,15 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var uint32Type = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - v := new(uint32) - return (*uint32Value)(v) - }, +type uint32Type struct{} + +func (t uint32Type) NewValue(context.Context, *Builder) Value { + v := new(uint32) + return (*uint32Value)(v) } +var _ Type = uint32Type{} + type uint32Value uint32 func (i *uint32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/uint64.go b/client/v2/cli/flag/uint64.go index 3c894fbf67f8..994247c6a583 100644 --- a/client/v2/cli/flag/uint64.go +++ b/client/v2/cli/flag/uint64.go @@ -7,13 +7,15 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -var uint64Type = Type{ - NewValue: func(ctx context.Context, builder *Builder) Value { - v := new(uint64) - return (*uint64Value)(v) - }, +type uint64Type struct{} + +func (t uint64Type) NewValue(context.Context, *Builder) Value { + v := new(uint64) + return (*uint64Value)(v) } +var _ Type = uint64Type{} + type uint64Value uint64 func (i *uint64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { diff --git a/client/v2/cli/flag/value.go b/client/v2/cli/flag/value.go index dca2e0e26471..a13274385885 100644 --- a/client/v2/cli/flag/value.go +++ b/client/v2/cli/flag/value.go @@ -1,16 +1,21 @@ package flag import ( - "context" - "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) +type Value interface { + pflag.Value + + // Get returns + Get(protoreflect.Value) (protoreflect.Value, error) + FieldValueBinder +} + // SimpleValue wraps a simple (non-list and non-map) protobuf value. type SimpleValue interface { // Get returns the value. - Get() (protoreflect.Value, error) } // ListValue wraps a protobuf list/repeating value. @@ -18,12 +23,3 @@ type ListValue interface { // AppendTo appends the values to the provided list. AppendTo(protoreflect.List) } - -type Value interface { - pflag.Value - FieldValueBinder -} - -func defaultDefaultValue(t Type) string { - return t.NewValue(context.Background(), &Builder{}).String() -} From 5a6ea1951020468b219aa0e49a30145d5c71cf4c Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 20:50:36 -0400 Subject: [PATCH 11/25] tests passing again --- client/v2/cli/flag/address.go | 6 +- client/v2/cli/flag/bool.go | 46 -------------- client/v2/cli/flag/bytes.go | 48 --------------- client/v2/cli/flag/duration.go | 10 +-- client/v2/cli/flag/enum.go | 6 +- client/v2/cli/flag/field.go | 99 ++++++++---------------------- client/v2/cli/flag/int32.go | 35 ----------- client/v2/cli/flag/int64.go | 35 ----------- client/v2/cli/flag/list.go | 94 ++++++++++++++-------------- client/v2/cli/flag/message.go | 62 ++++++++++--------- client/v2/cli/flag/message_json.go | 10 +-- client/v2/cli/flag/pagination.go | 5 +- client/v2/cli/flag/register.go | 22 ++++--- client/v2/cli/flag/simple.go | 47 ++++++++++++++ client/v2/cli/flag/string.go | 32 ---------- client/v2/cli/flag/timestamp.go | 6 +- client/v2/cli/flag/type.go | 12 ---- client/v2/cli/flag/uint32.go | 35 ----------- client/v2/cli/flag/uint64.go | 35 ----------- client/v2/cli/flag/value.go | 16 +---- 20 files changed, 182 insertions(+), 479 deletions(-) delete mode 100644 client/v2/cli/flag/bool.go delete mode 100644 client/v2/cli/flag/bytes.go delete mode 100644 client/v2/cli/flag/int32.go delete mode 100644 client/v2/cli/flag/int64.go create mode 100644 client/v2/cli/flag/simple.go delete mode 100644 client/v2/cli/flag/string.go delete mode 100644 client/v2/cli/flag/uint32.go delete mode 100644 client/v2/cli/flag/uint64.go diff --git a/client/v2/cli/flag/address.go b/client/v2/cli/flag/address.go index c9a190147d4b..163fbfc9ae37 100644 --- a/client/v2/cli/flag/address.go +++ b/client/v2/cli/flag/address.go @@ -20,11 +20,7 @@ type addressValue struct { value string } -func (a addressValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfString(a.value)) -} - -func (a addressValue) Get() (protoreflect.Value, error) { +func (a addressValue) Get(protoreflect.Value) (protoreflect.Value, error) { return protoreflect.ValueOfString(a.value), nil } diff --git a/client/v2/cli/flag/bool.go b/client/v2/cli/flag/bool.go deleted file mode 100644 index 07ac4a42bafd..000000000000 --- a/client/v2/cli/flag/bool.go +++ /dev/null @@ -1,46 +0,0 @@ -package flag - -import ( - "context" - "strconv" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type boolType struct{} - -func (b boolType) NewValue(context.Context, *Builder) Value { - v := new(bool) - return (*boolValue)(v) -} - -func (b boolType) NoOptDefaultValue() string { - return "true" -} - -var _ Type = boolType{} -var _ HasNoOptDefaultValue = boolType{} - -type boolValue bool - -func (b *boolValue) Get(protoreflect.Value) (protoreflect.Value, error) { - return protoreflect.ValueOfBool(bool(*b)), nil -} - -func (b *boolValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfBool(bool(*b))) -} - -func (b *boolValue) Set(s string) error { - v, err := strconv.ParseBool(s) - *b = boolValue(v) - return err -} - -func (b *boolValue) Type() string { - return "bool" -} - -func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) } - -func (b *boolValue) IsBoolFlag() bool { return true } diff --git a/client/v2/cli/flag/bytes.go b/client/v2/cli/flag/bytes.go deleted file mode 100644 index 2c3560f4aeb8..000000000000 --- a/client/v2/cli/flag/bytes.go +++ /dev/null @@ -1,48 +0,0 @@ -package flag - -import ( - "context" - "encoding/base64" - "strings" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type bytesBase64Type struct{} - -func (b bytesBase64Type) NewValue(context.Context, *Builder) Value { - x := new([]byte) - return (*bytesBase64Value)(x) -} - -var _ Type = bytesBase64Type{} - -// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded -type bytesBase64Value []byte - -func (bytesBase64 *bytesBase64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfBytes(*bytesBase64)) -} - -// String implements pflag.Value.String. -func (bytesBase64 *bytesBase64Value) String() string { - return base64.StdEncoding.EncodeToString(*bytesBase64) -} - -// Set implements pflag.Value.Set. -func (bytesBase64 *bytesBase64Value) Set(value string) error { - bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value)) - - if err != nil { - return err - } - - *bytesBase64 = bin - - return nil -} - -// Type implements pflag.Value.Type. -func (*bytesBase64Value) Type() string { - return "bytesBase64" -} diff --git a/client/v2/cli/flag/duration.go b/client/v2/cli/flag/duration.go index 1c6793b3c670..5e02c00d29e6 100644 --- a/client/v2/cli/flag/duration.go +++ b/client/v2/cli/flag/duration.go @@ -22,15 +22,11 @@ type durationValue struct { value *durationpb.Duration } -func (t durationValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfMessage(t.value.ProtoReflect())) -} - -func (t durationValue) Get() (protoreflect.Value, error) { - if t.value == nil { +func (a durationValue) Get(protoreflect.Value) (protoreflect.Value, error) { + if a.value == nil { return protoreflect.Value{}, nil } - return protoreflect.ValueOfMessage(t.value.ProtoReflect()), nil + return protoreflect.ValueOfMessage(a.value.ProtoReflect()), nil } func (v durationValue) String() string { diff --git a/client/v2/cli/flag/enum.go b/client/v2/cli/flag/enum.go index b00c55b2fe40..79e1cba53a44 100644 --- a/client/v2/cli/flag/enum.go +++ b/client/v2/cli/flag/enum.go @@ -40,11 +40,7 @@ type enumValue struct { valMap map[string]protoreflect.EnumValueDescriptor } -func (e enumValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfEnum(e.value)) -} - -func (e enumValue) Get() (protoreflect.Value, error) { +func (e enumValue) Get(protoreflect.Value) (protoreflect.Value, error) { return protoreflect.ValueOfEnum(e.value), nil } diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index 044463ac12e7..226708e4a796 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -2,7 +2,6 @@ package flag import ( "context" - "fmt" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" cosmos_proto "github.com/cosmos/cosmos-proto" @@ -13,12 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) -// FieldValueBinder wraps a flag value in a way that allows it to be bound -// to a particular field in a protobuf message. -type FieldValueBinder interface { - Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) -} - // Options specifies options for specific flags. type Options struct { // Prefix is a prefix to prepend to all flags. @@ -26,9 +19,8 @@ type Options struct { } // AddFieldFlag adds a flag for the provided field to the flag set. -func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) (FieldValueBinder, error) { +func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) (HasValue, error) { if opts == nil { - // use defaults opts = &autocliv1.FlagOptions{} } @@ -48,52 +40,48 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel shorthand := opts.Shorthand - typ := b.resolveFlagType(field) - if typ == nil { - return nil, fmt.Errorf("unable to bind field %v", field) - } - - defaultValue := opts.DefaultValue - if defaultValue == "" { - if hasDefaultValue, ok := typ.(HasDefaultValue); ok { - defaultValue = hasDefaultValue.DefaultValue() + if typ := b.resolveFlagType(field); typ != nil { + defaultValue := opts.DefaultValue + if defaultValue == "" { + defaultValue = typ.DefaultValue() } - } - noOptDefaultValue := opts.NoOptDefaultValue - if noOptDefaultValue == "" { - if hasNoOptDefaultValue, ok := typ.(HasNoOptDefaultValue); ok { - noOptDefaultValue = hasNoOptDefaultValue.NoOptDefaultValue() - } + val := typ.NewValue(ctx, b) + flagSet.AddFlag(&pflag.Flag{ + Name: name, + Shorthand: shorthand, + Usage: usage, + DefValue: defaultValue, + Deprecated: opts.Deprecated, + ShorthandDeprecated: opts.ShorthandDeprecated, + Hidden: opts.Hidden, + NoOptDefVal: opts.NoOptDefaultValue, + Value: val, + }) + return val, nil } - val := typ.NewValue(ctx, b) - flagSet.AddFlag(&pflag.Flag{ - Name: name, - Value: val, - Shorthand: shorthand, - Usage: usage, - DefValue: defaultValue, - NoOptDefVal: noOptDefaultValue, - Deprecated: opts.Deprecated, - ShorthandDeprecated: opts.ShorthandDeprecated, - Hidden: opts.Hidden, - }) + if field.IsList() { + val := bindSimpleListFlag(flagSet, field.Kind(), name, shorthand, usage) + return val, nil + + } + val := bindSimpleFlag(flagSet, field.Kind(), name, shorthand, usage) return val, nil } func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { + typ := b.resolveFlagTypeBasic(field) if field.IsList() { - typ := b.resolveFlagTypeBasic(field) if typ != nil { return compositeListType{simpleType: typ} } return nil - } else { - return b.resolveFlagTypeBasic(field) } + + return typ } func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type { @@ -106,20 +94,6 @@ func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type } switch field.Kind() { - case protoreflect.BytesKind: - return bytesBase64Type{} - case protoreflect.StringKind: - return stringType{} - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - return uint32Type{} - case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return uint64Type{} - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - return int32Type{} - case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return int64Type{} - case protoreflect.BoolKind: - return boolType{} case protoreflect.EnumKind: return enumType{enum: field.Enum()} case protoreflect.MessageKind: @@ -135,22 +109,3 @@ func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type return nil } } - -type simpleValueBinder struct { - value interface { - Get() (protoreflect.Value, error) - } -} - -func (s simpleValueBinder) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - val, err := s.value.Get() - if err != nil { - panic(err) - } - - if val.IsValid() { - message.Set(field, val) - } else { - message.Clear(field) - } -} diff --git a/client/v2/cli/flag/int32.go b/client/v2/cli/flag/int32.go deleted file mode 100644 index 7188d71383f8..000000000000 --- a/client/v2/cli/flag/int32.go +++ /dev/null @@ -1,35 +0,0 @@ -package flag - -import ( - "context" - "strconv" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type int32Type struct{} - -func (t int32Type) NewValue(context.Context, *Builder) Value { - v := new(int32) - return (*int32Value)(v) -} - -var _ Type = int32Type{} - -type int32Value int32 - -func (i *int32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfInt32(int32(*i))) -} - -func (i *int32Value) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 32) - *i = int32Value(v) - return err -} - -func (i *int32Value) Type() string { - return "int32" -} - -func (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) } diff --git a/client/v2/cli/flag/int64.go b/client/v2/cli/flag/int64.go deleted file mode 100644 index 709c2b472843..000000000000 --- a/client/v2/cli/flag/int64.go +++ /dev/null @@ -1,35 +0,0 @@ -package flag - -import ( - "context" - "strconv" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type int64Type struct{} - -func (u int64Type) NewValue(context.Context, *Builder) Value { - v := new(int64) - return (*int64Value)(v) -} - -var _ Type = int64Type{} - -type int64Value int64 - -func (i *int64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfInt64(int64(*i))) -} - -func (i *int64Value) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - *i = int64Value(v) - return err -} - -func (i *int64Value) Type() string { - return "int64" -} - -func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) } diff --git a/client/v2/cli/flag/list.go b/client/v2/cli/flag/list.go index efcd66d74cb2..72f84c8be3ee 100644 --- a/client/v2/cli/flag/list.go +++ b/client/v2/cli/flag/list.go @@ -4,49 +4,49 @@ import ( "context" "fmt" + "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) -// TODO -//func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) ListValue { -// switch kind { -// case protoreflect.StringKind: -// val := flagSet.StringSliceP(name, shorthand, nil, usage) -// return listValue(func(list protoreflect.List) { -// for _, x := range *val { -// list.Append(protoreflect.ValueOfString(x)) -// } -// }) -// case protoreflect.BytesKind: -// // TODO -// return nil -// case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, -// protoreflect.Uint64Kind, protoreflect.Fixed64Kind: -// val := flagSet.UintSliceP(name, shorthand, nil, usage) -// return listValue(func(list protoreflect.List) { -// for _, x := range *val { -// list.Append(protoreflect.ValueOfUint64(uint64(x))) -// } -// }) -// case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, -// protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: -// val := flagSet.IntSliceP(name, shorthand, nil, usage) -// return listValue(func(list protoreflect.List) { -// for _, x := range *val { -// list.Append(protoreflect.ValueOfInt64(int64(x))) -// } -// }) -// case protoreflect.BoolKind: -// val := flagSet.BoolSliceP(name, shorthand, nil, usage) -// return listValue(func(list protoreflect.List) { -// for _, x := range *val { -// list.Append(protoreflect.ValueOfBool(x)) -// } -// }) -// default: -// return nil -// } -//} +func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) HasValue { + switch kind { + case protoreflect.StringKind: + val := flagSet.StringSliceP(name, shorthand, nil, usage) + return newListValue(val, protoreflect.ValueOfString) + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, + protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + val := flagSet.UintSliceP(name, shorthand, nil, usage) + return newListValue(val, func(x uint) protoreflect.Value { return protoreflect.ValueOfUint64(uint64(x)) }) + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: + val := flagSet.Int32SliceP(name, shorthand, nil, usage) + return newListValue(val, protoreflect.ValueOfInt32) + case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + val := flagSet.Int64SliceP(name, shorthand, nil, usage) + return newListValue(val, protoreflect.ValueOfInt64) + case protoreflect.BoolKind: + val := flagSet.BoolSliceP(name, shorthand, nil, usage) + return newListValue(val, protoreflect.ValueOfBool) + default: + return nil + } +} + +type listValue[T any] struct { + array *[]T + toProtoreflectValue func(T) protoreflect.Value +} + +func newListValue[T any](array *[]T, toProtoreflectValue func(T) protoreflect.Value) listValue[T] { + return listValue[T]{array: array, toProtoreflectValue: toProtoreflectValue} +} + +func (v listValue[T]) Get(mutable protoreflect.Value) (protoreflect.Value, error) { + list := mutable.List() + for _, x := range *v.array { + list.Append(v.toProtoreflectValue(x)) + } + return mutable, nil +} type compositeListType struct { simpleType Type @@ -61,6 +61,10 @@ func (t compositeListType) NewValue(ctx context.Context, opts *Builder) Value { } } +func (t compositeListType) DefaultValue() string { + return "" +} + type compositeListValue struct { simpleType Type values []protoreflect.Value @@ -68,14 +72,12 @@ type compositeListValue struct { opts *Builder } -func (c *compositeListValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - c.AppendTo(message.NewField(field).List()) -} - -func (c *compositeListValue) AppendTo(list protoreflect.List) { +func (c *compositeListValue) Get(mutable protoreflect.Value) (protoreflect.Value, error) { + list := mutable.List() for _, value := range c.values { list.Append(value) } + return mutable, nil } func (c *compositeListValue) String() string { @@ -92,7 +94,7 @@ func (c *compositeListValue) Set(val string) error { if err != nil { return err } - v, err := simpleVal.(SimpleValue).Get() + v, err := simpleVal.Get(protoreflect.Value{}) if err != nil { return err } diff --git a/client/v2/cli/flag/message.go b/client/v2/cli/flag/message.go index 6bc331e6de92..60b10a1f8ad0 100644 --- a/client/v2/cli/flag/message.go +++ b/client/v2/cli/flag/message.go @@ -9,15 +9,15 @@ import ( type MessageBinder struct { CobraArgs cobra.PositionalArgs - positionalArgs []struct { - binder Value - field protoreflect.FieldDescriptor - varargs bool - } + //positionalArgs []struct { + // binder Value + // field protoreflect.FieldDescriptor + // varargs bool + //} flagFieldPairs []struct { - binder FieldValueBinder - field protoreflect.FieldDescriptor + hasValue HasValue + field protoreflect.FieldDescriptor } messageType protoreflect.MessageType } @@ -31,36 +31,40 @@ func (m MessageBinder) BuildMessage(positionalArgs []string) (protoreflect.Messa // Bind binds the flag values to an existing protobuf message. func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) error { - n := len(positionalArgs) - for i, arg := range m.positionalArgs { - if i >= n { - panic("unexpected: validate args should have caught this") - } - - if arg.varargs { - for _, v := range positionalArgs[i:] { - err := arg.binder.Set(v) - if err != nil { - return err - } - } - } else { - err := arg.binder.Set(positionalArgs[i]) - if err != nil { - return err - } - } - } + //n := len(positionalArgs) + //for i, arg := range m.positionalArgs { + // if i >= n { + // panic("unexpected: validate args should have caught this") + // } + // + // if arg.varargs { + // for _, v := range positionalArgs[i:] { + // err := arg.binder.Set(v) + // if err != nil { + // return err + // } + // } + // } else { + // err := arg.binder.Set(positionalArgs[i]) + // if err != nil { + // return err + // } + // } + //} for _, pair := range m.flagFieldPairs { - pair.binder.Bind(msg, pair.field) + val, err := pair.hasValue.Get(msg.NewField(pair.field)) + if err != nil { + return err + } + msg.Set(pair.field, val) } return nil } // Get calls BuildMessage and wraps the result in a protoreflect.Value. -func (m MessageBinder) Get() (protoreflect.Value, error) { +func (m MessageBinder) Get(protoreflect.Value) (protoreflect.Value, error) { msg, err := m.BuildMessage(nil) return protoreflect.ValueOfMessage(msg), err } diff --git a/client/v2/cli/flag/message_json.go b/client/v2/cli/flag/message_json.go index 81a201cbd3ba..76366dda1804 100644 --- a/client/v2/cli/flag/message_json.go +++ b/client/v2/cli/flag/message_json.go @@ -34,18 +34,14 @@ type jsonMessageFlagValue struct { message proto.Message } -func (j jsonMessageFlagValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfMessage(j.message.ProtoReflect())) -} - -func (j jsonMessageFlagValue) Get() (protoreflect.Value, error) { +func (j *jsonMessageFlagValue) Get(protoreflect.Value) (protoreflect.Value, error) { if j.message == nil { return protoreflect.Value{}, nil } return protoreflect.ValueOfMessage(j.message.ProtoReflect()), nil } -func (j jsonMessageFlagValue) String() string { +func (j *jsonMessageFlagValue) String() string { if j.message == nil { return "" } @@ -62,6 +58,6 @@ func (j *jsonMessageFlagValue) Set(s string) error { return j.jsonUnmarshalOptions.Unmarshal([]byte(s), j.message) } -func (j jsonMessageFlagValue) Type() string { +func (j *jsonMessageFlagValue) Type() string { return fmt.Sprintf("%s (json)", j.messageType.Descriptor().FullName()) } diff --git a/client/v2/cli/flag/pagination.go b/client/v2/cli/flag/pagination.go index 6b1e56ea3041..83d58424793d 100644 --- a/client/v2/cli/flag/pagination.go +++ b/client/v2/cli/flag/pagination.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) -func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) (FieldValueBinder, error) { +func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) (HasValue, error) { handler, err := b.AddMessageFlags( ctx, flagSet, @@ -21,5 +21,6 @@ func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, f if err != nil { return nil, err } - return simpleValueBinder{value: handler}, nil + + return handler, nil } diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index 069402e41748..bdfc9f24b4c2 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -22,6 +22,8 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa hasVarargs := false n := len(commandOptions.PositionalArgs) for i, arg := range commandOptions.PositionalArgs { + isPositional[arg.ProtoField] = true + field := fields.ByName(protoreflect.Name(arg.ProtoField)) if field == nil { return nil, fmt.Errorf("can't find field %s on %s", arg.ProtoField, messageType.Descriptor().FullName()) @@ -40,13 +42,13 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa return nil, fmt.Errorf("can't resolve field %v", field) } - value := typ.NewValue(ctx, b) - - handler.positionalArgs = append(handler.positionalArgs, struct { - binder Value - field protoreflect.FieldDescriptor - varargs bool - }{binder: value, field: field, varargs: arg.Varargs}) + //value := typ.NewValue(ctx, b) + // + //handler.positionalArgs = append(handler.positionalArgs, struct { + // binder Value + // field protoreflect.FieldDescriptor + // varargs bool + //}{binder: value, field: field, varargs: arg.Varargs}) } if hasVarargs { @@ -68,9 +70,9 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa } handler.flagFieldPairs = append(handler.flagFieldPairs, struct { - binder FieldValueBinder - field protoreflect.FieldDescriptor - }{binder: binder, field: field}) + hasValue HasValue + field protoreflect.FieldDescriptor + }{hasValue: binder, field: field}) } return handler, nil } diff --git a/client/v2/cli/flag/simple.go b/client/v2/cli/flag/simple.go new file mode 100644 index 000000000000..d4ed6d4464e3 --- /dev/null +++ b/client/v2/cli/flag/simple.go @@ -0,0 +1,47 @@ +package flag + +import ( + "github.com/spf13/pflag" + "google.golang.org/protobuf/reflect/protoreflect" +) + +func bindSimpleFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) HasValue { + switch kind { + case protoreflect.BytesKind: + val := flagSet.BytesBase64P(name, shorthand, nil, usage) + return newSimpleValue(val, protoreflect.ValueOfBytes) + case protoreflect.StringKind: + val := flagSet.StringP(name, shorthand, "", usage) + return newSimpleValue(val, protoreflect.ValueOfString) + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: + val := flagSet.Uint32P(name, shorthand, 0, usage) + return newSimpleValue(val, protoreflect.ValueOfUint32) + case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + val := flagSet.Uint64P(name, shorthand, 0, usage) + return newSimpleValue(val, protoreflect.ValueOfUint64) + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: + val := flagSet.Int32P(name, shorthand, 0, usage) + return newSimpleValue(val, protoreflect.ValueOfInt32) + case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + val := flagSet.Int64P(name, shorthand, 0, usage) + return newSimpleValue(val, protoreflect.ValueOfInt64) + case protoreflect.BoolKind: + val := flagSet.BoolP(name, shorthand, false, usage) + return newSimpleValue(val, protoreflect.ValueOfBool) + default: + return nil + } +} + +type simpleValue[T any] struct { + val *T + toProtoreflectValue func(T) protoreflect.Value +} + +func newSimpleValue[T any](val *T, toProtoreflectValue func(T) protoreflect.Value) HasValue { + return simpleValue[T]{val: val, toProtoreflectValue: toProtoreflectValue} +} + +func (v simpleValue[T]) Get(protoreflect.Value) (protoreflect.Value, error) { + return v.toProtoreflectValue(*v.val), nil +} diff --git a/client/v2/cli/flag/string.go b/client/v2/cli/flag/string.go deleted file mode 100644 index b82a66143257..000000000000 --- a/client/v2/cli/flag/string.go +++ /dev/null @@ -1,32 +0,0 @@ -package flag - -import ( - "context" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type stringType struct{} - -func (s stringType) NewValue(context.Context, *Builder) Value { - v := new(string) - return (*stringValue)(v) -} - -var _ Type = stringType{} - -type stringValue string - -func (s *stringValue) Set(val string) error { - *s = stringValue(val) - return nil -} -func (s *stringValue) Type() string { - return "string" -} - -func (s *stringValue) String() string { return string(*s) } - -func (s *stringValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfString(string(*s))) -} diff --git a/client/v2/cli/flag/timestamp.go b/client/v2/cli/flag/timestamp.go index f83cbbfc9d6c..799dab4f32bf 100644 --- a/client/v2/cli/flag/timestamp.go +++ b/client/v2/cli/flag/timestamp.go @@ -22,11 +22,7 @@ type timestampValue struct { value *timestamppb.Timestamp } -func (t timestampValue) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfMessage(t.value.ProtoReflect())) -} - -func (t timestampValue) Get() (protoreflect.Value, error) { +func (t timestampValue) Get(protoreflect.Value) (protoreflect.Value, error) { if t.value == nil { return protoreflect.Value{}, nil } diff --git a/client/v2/cli/flag/type.go b/client/v2/cli/flag/type.go index 9bc0ee7b2344..a0e79b553d90 100644 --- a/client/v2/cli/flag/type.go +++ b/client/v2/cli/flag/type.go @@ -9,19 +9,7 @@ type Type interface { // NewValue returns a new pflag.Value which must also implement either // SimpleValue or ListValue. NewValue(context.Context, *Builder) Value -} -// HasDefaultValue defines a type which has an explicitly specified default -// value. If this interface isn't specified, Type.NewValue().String() will -// be used. -type HasDefaultValue interface { // DefaultValue is the default value for this type. DefaultValue() string } - -// HasNoOptDefaultValue defines a type which has an explicitly specified no-option -// default value. If this interface isn't specified, the empty string will be used. -type HasNoOptDefaultValue interface { - // NoOptDefaultValue is the no-option default value for this type. - NoOptDefaultValue() string -} diff --git a/client/v2/cli/flag/uint32.go b/client/v2/cli/flag/uint32.go deleted file mode 100644 index aede1be14177..000000000000 --- a/client/v2/cli/flag/uint32.go +++ /dev/null @@ -1,35 +0,0 @@ -package flag - -import ( - "context" - "strconv" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type uint32Type struct{} - -func (t uint32Type) NewValue(context.Context, *Builder) Value { - v := new(uint32) - return (*uint32Value)(v) -} - -var _ Type = uint32Type{} - -type uint32Value uint32 - -func (i *uint32Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfUint32(uint32(*i))) -} - -func (i *uint32Value) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 32) - *i = uint32Value(v) - return err -} - -func (i *uint32Value) Type() string { - return "uint32" -} - -func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) } diff --git a/client/v2/cli/flag/uint64.go b/client/v2/cli/flag/uint64.go deleted file mode 100644 index 994247c6a583..000000000000 --- a/client/v2/cli/flag/uint64.go +++ /dev/null @@ -1,35 +0,0 @@ -package flag - -import ( - "context" - "strconv" - - "google.golang.org/protobuf/reflect/protoreflect" -) - -type uint64Type struct{} - -func (t uint64Type) NewValue(context.Context, *Builder) Value { - v := new(uint64) - return (*uint64Value)(v) -} - -var _ Type = uint64Type{} - -type uint64Value uint64 - -func (i *uint64Value) Bind(message protoreflect.Message, field protoreflect.FieldDescriptor) { - message.Set(field, protoreflect.ValueOfUint64(uint64(*i))) -} - -func (i *uint64Value) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 64) - *i = uint64Value(v) - return err -} - -func (i *uint64Value) Type() string { - return "uint64" -} - -func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) } diff --git a/client/v2/cli/flag/value.go b/client/v2/cli/flag/value.go index a13274385885..8a62253f75d3 100644 --- a/client/v2/cli/flag/value.go +++ b/client/v2/cli/flag/value.go @@ -7,19 +7,9 @@ import ( type Value interface { pflag.Value - - // Get returns - Get(protoreflect.Value) (protoreflect.Value, error) - FieldValueBinder -} - -// SimpleValue wraps a simple (non-list and non-map) protobuf value. -type SimpleValue interface { - // Get returns the value. + HasValue } -// ListValue wraps a protobuf list/repeating value. -type ListValue interface { - // AppendTo appends the values to the provided list. - AppendTo(protoreflect.List) +type HasValue interface { + Get(mutable protoreflect.Value) (protoreflect.Value, error) } From bc746b43400e52eb0055e2dce99ed556dd4e4c65 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 21:17:01 -0400 Subject: [PATCH 12/25] positional params working --- client/v2/cli/flag/message.go | 88 +++-- client/v2/cli/flag/register.go | 35 +- client/v2/cli/query.go | 2 + client/v2/cli/query_test.go | 29 +- client/v2/cli/testdata/help.golden | 2 +- client/v2/internal/testpb/query.proto | 50 +-- client/v2/internal/testpb/query.pulsar.go | 392 +++++++++++++++++++--- 7 files changed, 474 insertions(+), 124 deletions(-) diff --git a/client/v2/cli/flag/message.go b/client/v2/cli/flag/message.go index 60b10a1f8ad0..bdb3bb1c1f05 100644 --- a/client/v2/cli/flag/message.go +++ b/client/v2/cli/flag/message.go @@ -1,7 +1,10 @@ package flag import ( + "fmt" + "github.com/spf13/cobra" + "github.com/spf13/pflag" "google.golang.org/protobuf/reflect/protoreflect" ) @@ -9,17 +12,12 @@ import ( type MessageBinder struct { CobraArgs cobra.PositionalArgs - //positionalArgs []struct { - // binder Value - // field protoreflect.FieldDescriptor - // varargs bool - //} + positionalFlagSet *pflag.FlagSet + positionalArgs []fieldBinding + hasVarargs bool - flagFieldPairs []struct { - hasValue HasValue - field protoreflect.FieldDescriptor - } - messageType protoreflect.MessageType + flagBindings []fieldBinding + messageType protoreflect.MessageType } // BuildMessage builds and returns a new message for the bound flags. @@ -31,33 +29,43 @@ func (m MessageBinder) BuildMessage(positionalArgs []string) (protoreflect.Messa // Bind binds the flag values to an existing protobuf message. func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) error { - //n := len(positionalArgs) - //for i, arg := range m.positionalArgs { - // if i >= n { - // panic("unexpected: validate args should have caught this") - // } - // - // if arg.varargs { - // for _, v := range positionalArgs[i:] { - // err := arg.binder.Set(v) - // if err != nil { - // return err - // } - // } - // } else { - // err := arg.binder.Set(positionalArgs[i]) - // if err != nil { - // return err - // } - // } - //} + // first set positional args in the positional arg flag set + n := len(positionalArgs) + for i := range m.positionalArgs { + if i >= n { + panic("unexpected: validate args should have caught this") + } - for _, pair := range m.flagFieldPairs { - val, err := pair.hasValue.Get(msg.NewField(pair.field)) + name := fmt.Sprintf("%d", i) + if i == n-1 && m.hasVarargs { + for _, v := range positionalArgs[i:] { + err := m.positionalFlagSet.Set(name, v) + if err != nil { + return err + } + } + } else { + err := m.positionalFlagSet.Set(name, positionalArgs[i]) + if err != nil { + return err + } + } + } + + // bind positional arg values to the message + for _, arg := range m.positionalArgs { + err := arg.bind(msg) + if err != nil { + return err + } + } + + // bind flag values to the message + for _, binding := range m.flagBindings { + err := binding.bind(msg) if err != nil { return err } - msg.Set(pair.field, val) } return nil @@ -68,3 +76,17 @@ func (m MessageBinder) Get(protoreflect.Value) (protoreflect.Value, error) { msg, err := m.BuildMessage(nil) return protoreflect.ValueOfMessage(msg), err } + +type fieldBinding struct { + hasValue HasValue + field protoreflect.FieldDescriptor +} + +func (f fieldBinding) bind(msg protoreflect.Message) error { + val, err := f.hasValue.Get(msg.NewField(f.field)) + if err != nil { + return err + } + msg.Set(f.field, val) + return nil +} diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index bdfc9f24b4c2..0e5d6a9689d3 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -21,6 +21,7 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa isPositional := map[string]bool{} hasVarargs := false n := len(commandOptions.PositionalArgs) + handler.positionalFlagSet = pflag.NewFlagSet("positional", pflag.ContinueOnError) for i, arg := range commandOptions.PositionalArgs { isPositional[arg.ProtoField] = true @@ -37,22 +38,26 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa hasVarargs = true } - typ := b.resolveFlagType(field) - if typ == nil { - return nil, fmt.Errorf("can't resolve field %v", field) + hasValue, err := b.AddFieldFlag( + ctx, + handler.positionalFlagSet, + field, + &autocliv1.FlagOptions{Name: fmt.Sprintf("%d", i)}, + Options{}, + ) + if err != nil { + return nil, err } - //value := typ.NewValue(ctx, b) - // - //handler.positionalArgs = append(handler.positionalArgs, struct { - // binder Value - // field protoreflect.FieldDescriptor - // varargs bool - //}{binder: value, field: field, varargs: arg.Varargs}) + handler.positionalArgs = append(handler.positionalArgs, fieldBinding{ + field: field, + hasValue: hasValue, + }) } if hasVarargs { handler.CobraArgs = cobra.MinimumNArgs(n) + handler.hasVarargs = true } else { handler.CobraArgs = cobra.ExactArgs(n) } @@ -64,15 +69,15 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa } flagOpts := commandOptions.FlagOptions[string(field.Name())] - binder, err := b.AddFieldFlag(ctx, set, field, flagOpts, options) + hasValue, err := b.AddFieldFlag(ctx, set, field, flagOpts, options) if err != nil { return nil, err } - handler.flagFieldPairs = append(handler.flagFieldPairs, struct { - hasValue HasValue - field protoreflect.FieldDescriptor - }{hasValue: binder, field: field}) + handler.flagBindings = append(handler.flagBindings, fieldBinding{ + hasValue: hasValue, + field: field, + }) } return handler, nil } diff --git a/client/v2/cli/query.go b/client/v2/cli/query.go index c69d01fd98f1..447d68071b9d 100644 --- a/client/v2/cli/query.go +++ b/client/v2/cli/query.go @@ -131,6 +131,8 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip return nil, err } + cmd.Args = binder.CobraArgs + jsonMarshalOptions := protojson.MarshalOptions{ Indent: " ", UseProtoNames: true, diff --git a/client/v2/cli/query_test.go b/client/v2/cli/query_test.go index d820503c9dfe..122713868271 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/cli/query_test.go @@ -37,7 +37,30 @@ func testExec(t *testing.T, args ...string) *testClientConn { return conn }, } - cmd, err := b.BuildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{Service: testpb.Query_ServiceDesc.ServiceName}) + cmd, err := b.BuildModuleQueryCommand( + "test", + &autocliv1.ServiceCommandDescriptor{ + Service: testpb.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Echo", + Use: "echo [pos1] [pos2] [pos3...]", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + { + ProtoField: "positional1", + }, + { + ProtoField: "positional2", + }, + { + ProtoField: "positional3_varargs", + Varargs: true, + }, + }, + }, + }, + }, + ) assert.NilError(t, err) cmd.SetArgs(args) cmd.SetOut(conn.out) @@ -48,6 +71,10 @@ func testExec(t *testing.T, args ...string) *testClientConn { func TestEcho(t *testing.T) { conn := testExec(t, "echo", + "1", + "abc", + `{"denom":"foo","amount":"1234"}`, + `{"denom":"bar","amount":"4321"}`, "--a-bool", "--an-enum", "one", "--a-message", `{"bar":"abc", "baz":-3}`, diff --git a/client/v2/cli/testdata/help.golden b/client/v2/cli/testdata/help.golden index bcb9c087fdc9..0e3ddf5d131c 100644 --- a/client/v2/cli/testdata/help.golden +++ b/client/v2/cli/testdata/help.golden @@ -1,5 +1,5 @@ Usage: - test echo [flags] + test echo [pos1] [pos2] [pos3...] [flags] Flags: --a-bool diff --git a/client/v2/internal/testpb/query.proto b/client/v2/internal/testpb/query.proto index 5bb49a0b2aec..6e2f91a6f18f 100644 --- a/client/v2/internal/testpb/query.proto +++ b/client/v2/internal/testpb/query.proto @@ -15,34 +15,38 @@ service Query { message EchoRequest { // u32 is an uint32 - uint32 u32 = 1; - uint64 u64 = 2; - string str = 3; - bytes bz = 4; - google.protobuf.Timestamp timestamp = 5; - google.protobuf.Duration duration = 6; - int32 i32 = 7; - int64 i64 = 10; - bool a_bool = 15; - Enum an_enum = 16; - AMessage a_message = 17; - cosmos.base.v1beta1.Coin a_coin = 18; + uint32 u32 = 1; + uint64 u64 = 2; + string str = 3; + bytes bz = 4; + google.protobuf.Timestamp timestamp = 5; + google.protobuf.Duration duration = 6; + int32 i32 = 7; + int64 i64 = 10; + bool a_bool = 15; + Enum an_enum = 16; + AMessage a_message = 17; + cosmos.base.v1beta1.Coin a_coin = 18; string an_address = 19 [(cosmos_proto.scalar) = "cosmos.AddressString"]; - cosmos.base.query.v1beta1.PageRequest page = 20; - repeated bool bools = 21; - repeated uint32 uints = 22; - repeated string strings = 23; - repeated Enum enums = 24; - repeated google.protobuf.Duration durations = 25; - repeated AMessage some_messages = 26; + cosmos.base.query.v1beta1.PageRequest page = 20; + repeated bool bools = 21; + repeated uint32 uints = 22; + repeated string strings = 23; + repeated Enum enums = 24; + repeated google.protobuf.Duration durations = 25; + repeated AMessage some_messages = 26; + + int32 positional1 = 27; + string positional2 = 28; + repeated cosmos.base.v1beta1.Coin positional3_varargs = 29; } enum Enum { ENUM_UNSPECIFIED = 0; - ENUM_ONE = 1; - ENUM_TWO = 2; - ENUM_FIVE = 5; - ENUM_NEG_THREE = -3; + ENUM_ONE = 1; + ENUM_TWO = 2; + ENUM_FIVE = 5; + ENUM_NEG_THREE = -3; } message AMessage { diff --git a/client/v2/internal/testpb/query.pulsar.go b/client/v2/internal/testpb/query.pulsar.go index 16e9e8ffa8b5..938d7b4190c2 100644 --- a/client/v2/internal/testpb/query.pulsar.go +++ b/client/v2/internal/testpb/query.pulsar.go @@ -303,28 +303,82 @@ func (x *_EchoRequest_26_list) IsValid() bool { return x.list != nil } +var _ protoreflect.List = (*_EchoRequest_29_list)(nil) + +type _EchoRequest_29_list struct { + list *[]*v1beta1.Coin +} + +func (x *_EchoRequest_29_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_EchoRequest_29_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfMessage((*x.list)[i].ProtoReflect()) +} + +func (x *_EchoRequest_29_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*v1beta1.Coin) + (*x.list)[i] = concreteValue +} + +func (x *_EchoRequest_29_list) Append(value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*v1beta1.Coin) + *x.list = append(*x.list, concreteValue) +} + +func (x *_EchoRequest_29_list) AppendMutable() protoreflect.Value { + v := new(v1beta1.Coin) + *x.list = append(*x.list, v) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_EchoRequest_29_list) Truncate(n int) { + for i := n; i < len(*x.list); i++ { + (*x.list)[i] = nil + } + *x.list = (*x.list)[:n] +} + +func (x *_EchoRequest_29_list) NewElement() protoreflect.Value { + v := new(v1beta1.Coin) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_EchoRequest_29_list) IsValid() bool { + return x.list != nil +} + var ( - md_EchoRequest protoreflect.MessageDescriptor - fd_EchoRequest_u32 protoreflect.FieldDescriptor - fd_EchoRequest_u64 protoreflect.FieldDescriptor - fd_EchoRequest_str protoreflect.FieldDescriptor - fd_EchoRequest_bz protoreflect.FieldDescriptor - fd_EchoRequest_timestamp protoreflect.FieldDescriptor - fd_EchoRequest_duration protoreflect.FieldDescriptor - fd_EchoRequest_i32 protoreflect.FieldDescriptor - fd_EchoRequest_i64 protoreflect.FieldDescriptor - fd_EchoRequest_a_bool protoreflect.FieldDescriptor - fd_EchoRequest_an_enum protoreflect.FieldDescriptor - fd_EchoRequest_a_message protoreflect.FieldDescriptor - fd_EchoRequest_a_coin protoreflect.FieldDescriptor - fd_EchoRequest_an_address protoreflect.FieldDescriptor - fd_EchoRequest_page protoreflect.FieldDescriptor - fd_EchoRequest_bools protoreflect.FieldDescriptor - fd_EchoRequest_uints protoreflect.FieldDescriptor - fd_EchoRequest_strings protoreflect.FieldDescriptor - fd_EchoRequest_enums protoreflect.FieldDescriptor - fd_EchoRequest_durations protoreflect.FieldDescriptor - fd_EchoRequest_some_messages protoreflect.FieldDescriptor + md_EchoRequest protoreflect.MessageDescriptor + fd_EchoRequest_u32 protoreflect.FieldDescriptor + fd_EchoRequest_u64 protoreflect.FieldDescriptor + fd_EchoRequest_str protoreflect.FieldDescriptor + fd_EchoRequest_bz protoreflect.FieldDescriptor + fd_EchoRequest_timestamp protoreflect.FieldDescriptor + fd_EchoRequest_duration protoreflect.FieldDescriptor + fd_EchoRequest_i32 protoreflect.FieldDescriptor + fd_EchoRequest_i64 protoreflect.FieldDescriptor + fd_EchoRequest_a_bool protoreflect.FieldDescriptor + fd_EchoRequest_an_enum protoreflect.FieldDescriptor + fd_EchoRequest_a_message protoreflect.FieldDescriptor + fd_EchoRequest_a_coin protoreflect.FieldDescriptor + fd_EchoRequest_an_address protoreflect.FieldDescriptor + fd_EchoRequest_page protoreflect.FieldDescriptor + fd_EchoRequest_bools protoreflect.FieldDescriptor + fd_EchoRequest_uints protoreflect.FieldDescriptor + fd_EchoRequest_strings protoreflect.FieldDescriptor + fd_EchoRequest_enums protoreflect.FieldDescriptor + fd_EchoRequest_durations protoreflect.FieldDescriptor + fd_EchoRequest_some_messages protoreflect.FieldDescriptor + fd_EchoRequest_positional1 protoreflect.FieldDescriptor + fd_EchoRequest_positional2 protoreflect.FieldDescriptor + fd_EchoRequest_positional3_varargs protoreflect.FieldDescriptor ) func init() { @@ -350,6 +404,9 @@ func init() { fd_EchoRequest_enums = md_EchoRequest.Fields().ByName("enums") fd_EchoRequest_durations = md_EchoRequest.Fields().ByName("durations") fd_EchoRequest_some_messages = md_EchoRequest.Fields().ByName("some_messages") + fd_EchoRequest_positional1 = md_EchoRequest.Fields().ByName("positional1") + fd_EchoRequest_positional2 = md_EchoRequest.Fields().ByName("positional2") + fd_EchoRequest_positional3_varargs = md_EchoRequest.Fields().ByName("positional3_varargs") } var _ protoreflect.Message = (*fastReflection_EchoRequest)(nil) @@ -537,6 +594,24 @@ func (x *fastReflection_EchoRequest) Range(f func(protoreflect.FieldDescriptor, return } } + if x.Positional1 != int32(0) { + value := protoreflect.ValueOfInt32(x.Positional1) + if !f(fd_EchoRequest_positional1, value) { + return + } + } + if x.Positional2 != "" { + value := protoreflect.ValueOfString(x.Positional2) + if !f(fd_EchoRequest_positional2, value) { + return + } + } + if len(x.Positional3Varargs) != 0 { + value := protoreflect.ValueOfList(&_EchoRequest_29_list{list: &x.Positional3Varargs}) + if !f(fd_EchoRequest_positional3_varargs, value) { + return + } + } } // Has reports whether a field is populated. @@ -592,6 +667,12 @@ func (x *fastReflection_EchoRequest) Has(fd protoreflect.FieldDescriptor) bool { return len(x.Durations) != 0 case "testpb.EchoRequest.some_messages": return len(x.SomeMessages) != 0 + case "testpb.EchoRequest.positional1": + return x.Positional1 != int32(0) + case "testpb.EchoRequest.positional2": + return x.Positional2 != "" + case "testpb.EchoRequest.positional3_varargs": + return len(x.Positional3Varargs) != 0 default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -648,6 +729,12 @@ func (x *fastReflection_EchoRequest) Clear(fd protoreflect.FieldDescriptor) { x.Durations = nil case "testpb.EchoRequest.some_messages": x.SomeMessages = nil + case "testpb.EchoRequest.positional1": + x.Positional1 = int32(0) + case "testpb.EchoRequest.positional2": + x.Positional2 = "" + case "testpb.EchoRequest.positional3_varargs": + x.Positional3Varargs = nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -742,6 +829,18 @@ func (x *fastReflection_EchoRequest) Get(descriptor protoreflect.FieldDescriptor } listValue := &_EchoRequest_26_list{list: &x.SomeMessages} return protoreflect.ValueOfList(listValue) + case "testpb.EchoRequest.positional1": + value := x.Positional1 + return protoreflect.ValueOfInt32(value) + case "testpb.EchoRequest.positional2": + value := x.Positional2 + return protoreflect.ValueOfString(value) + case "testpb.EchoRequest.positional3_varargs": + if len(x.Positional3Varargs) == 0 { + return protoreflect.ValueOfList(&_EchoRequest_29_list{}) + } + listValue := &_EchoRequest_29_list{list: &x.Positional3Varargs} + return protoreflect.ValueOfList(listValue) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -814,6 +913,14 @@ func (x *fastReflection_EchoRequest) Set(fd protoreflect.FieldDescriptor, value lv := value.List() clv := lv.(*_EchoRequest_26_list) x.SomeMessages = *clv.list + case "testpb.EchoRequest.positional1": + x.Positional1 = int32(value.Int()) + case "testpb.EchoRequest.positional2": + x.Positional2 = value.Interface().(string) + case "testpb.EchoRequest.positional3_varargs": + lv := value.List() + clv := lv.(*_EchoRequest_29_list) + x.Positional3Varargs = *clv.list default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -895,6 +1002,12 @@ func (x *fastReflection_EchoRequest) Mutable(fd protoreflect.FieldDescriptor) pr } value := &_EchoRequest_26_list{list: &x.SomeMessages} return protoreflect.ValueOfList(value) + case "testpb.EchoRequest.positional3_varargs": + if x.Positional3Varargs == nil { + x.Positional3Varargs = []*v1beta1.Coin{} + } + value := &_EchoRequest_29_list{list: &x.Positional3Varargs} + return protoreflect.ValueOfList(value) case "testpb.EchoRequest.u32": panic(fmt.Errorf("field u32 of message testpb.EchoRequest is not mutable")) case "testpb.EchoRequest.u64": @@ -913,6 +1026,10 @@ func (x *fastReflection_EchoRequest) Mutable(fd protoreflect.FieldDescriptor) pr panic(fmt.Errorf("field an_enum of message testpb.EchoRequest is not mutable")) case "testpb.EchoRequest.an_address": panic(fmt.Errorf("field an_address of message testpb.EchoRequest is not mutable")) + case "testpb.EchoRequest.positional1": + panic(fmt.Errorf("field positional1 of message testpb.EchoRequest is not mutable")) + case "testpb.EchoRequest.positional2": + panic(fmt.Errorf("field positional2 of message testpb.EchoRequest is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -977,6 +1094,13 @@ func (x *fastReflection_EchoRequest) NewField(fd protoreflect.FieldDescriptor) p case "testpb.EchoRequest.some_messages": list := []*AMessage{} return protoreflect.ValueOfList(&_EchoRequest_26_list{list: &list}) + case "testpb.EchoRequest.positional1": + return protoreflect.ValueOfInt32(int32(0)) + case "testpb.EchoRequest.positional2": + return protoreflect.ValueOfString("") + case "testpb.EchoRequest.positional3_varargs": + list := []*v1beta1.Coin{} + return protoreflect.ValueOfList(&_EchoRequest_29_list{list: &list}) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -1131,6 +1255,19 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { n += 2 + l + runtime.Sov(uint64(l)) } } + if x.Positional1 != 0 { + n += 2 + runtime.Sov(uint64(x.Positional1)) + } + l = len(x.Positional2) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } + if len(x.Positional3Varargs) > 0 { + for _, e := range x.Positional3Varargs { + l = options.Size(e) + n += 2 + l + runtime.Sov(uint64(l)) + } + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -1160,6 +1297,40 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if len(x.Positional3Varargs) > 0 { + for iNdEx := len(x.Positional3Varargs) - 1; iNdEx >= 0; iNdEx-- { + encoded, err := options.Marshal(x.Positional3Varargs[iNdEx]) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xea + } + } + if len(x.Positional2) > 0 { + i -= len(x.Positional2) + copy(dAtA[i:], x.Positional2) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Positional2))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xe2 + } + if x.Positional1 != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.Positional1)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xd8 + } if len(x.SomeMessages) > 0 { for iNdEx := len(x.SomeMessages) - 1; iNdEx >= 0; iNdEx-- { encoded, err := options.Marshal(x.SomeMessages[iNdEx]) @@ -2160,6 +2331,91 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex + case 27: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Positional1", wireType) + } + x.Positional1 = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.Positional1 |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 28: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Positional2", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Positional2 = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 29: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Positional3Varargs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Positional3Varargs = append(x.Positional3Varargs, &v1beta1.Coin{}) + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Positional3Varargs[len(x.Positional3Varargs)-1]); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -3172,26 +3428,29 @@ type EchoRequest struct { unknownFields protoimpl.UnknownFields // u32 is an uint32 - U32 uint32 `protobuf:"varint,1,opt,name=u32,proto3" json:"u32,omitempty"` - U64 uint64 `protobuf:"varint,2,opt,name=u64,proto3" json:"u64,omitempty"` - Str string `protobuf:"bytes,3,opt,name=str,proto3" json:"str,omitempty"` - Bz []byte `protobuf:"bytes,4,opt,name=bz,proto3" json:"bz,omitempty"` - Timestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Duration *durationpb.Duration `protobuf:"bytes,6,opt,name=duration,proto3" json:"duration,omitempty"` - I32 int32 `protobuf:"varint,7,opt,name=i32,proto3" json:"i32,omitempty"` - I64 int64 `protobuf:"varint,10,opt,name=i64,proto3" json:"i64,omitempty"` - ABool bool `protobuf:"varint,15,opt,name=a_bool,json=aBool,proto3" json:"a_bool,omitempty"` - AnEnum Enum `protobuf:"varint,16,opt,name=an_enum,json=anEnum,proto3,enum=testpb.Enum" json:"an_enum,omitempty"` - AMessage *AMessage `protobuf:"bytes,17,opt,name=a_message,json=aMessage,proto3" json:"a_message,omitempty"` - ACoin *v1beta1.Coin `protobuf:"bytes,18,opt,name=a_coin,json=aCoin,proto3" json:"a_coin,omitempty"` - AnAddress string `protobuf:"bytes,19,opt,name=an_address,json=anAddress,proto3" json:"an_address,omitempty"` - Page *v1beta11.PageRequest `protobuf:"bytes,20,opt,name=page,proto3" json:"page,omitempty"` - Bools []bool `protobuf:"varint,21,rep,packed,name=bools,proto3" json:"bools,omitempty"` - Uints []uint32 `protobuf:"varint,22,rep,packed,name=uints,proto3" json:"uints,omitempty"` - Strings []string `protobuf:"bytes,23,rep,name=strings,proto3" json:"strings,omitempty"` - Enums []Enum `protobuf:"varint,24,rep,packed,name=enums,proto3,enum=testpb.Enum" json:"enums,omitempty"` - Durations []*durationpb.Duration `protobuf:"bytes,25,rep,name=durations,proto3" json:"durations,omitempty"` - SomeMessages []*AMessage `protobuf:"bytes,26,rep,name=some_messages,json=someMessages,proto3" json:"some_messages,omitempty"` + U32 uint32 `protobuf:"varint,1,opt,name=u32,proto3" json:"u32,omitempty"` + U64 uint64 `protobuf:"varint,2,opt,name=u64,proto3" json:"u64,omitempty"` + Str string `protobuf:"bytes,3,opt,name=str,proto3" json:"str,omitempty"` + Bz []byte `protobuf:"bytes,4,opt,name=bz,proto3" json:"bz,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Duration *durationpb.Duration `protobuf:"bytes,6,opt,name=duration,proto3" json:"duration,omitempty"` + I32 int32 `protobuf:"varint,7,opt,name=i32,proto3" json:"i32,omitempty"` + I64 int64 `protobuf:"varint,10,opt,name=i64,proto3" json:"i64,omitempty"` + ABool bool `protobuf:"varint,15,opt,name=a_bool,json=aBool,proto3" json:"a_bool,omitempty"` + AnEnum Enum `protobuf:"varint,16,opt,name=an_enum,json=anEnum,proto3,enum=testpb.Enum" json:"an_enum,omitempty"` + AMessage *AMessage `protobuf:"bytes,17,opt,name=a_message,json=aMessage,proto3" json:"a_message,omitempty"` + ACoin *v1beta1.Coin `protobuf:"bytes,18,opt,name=a_coin,json=aCoin,proto3" json:"a_coin,omitempty"` + AnAddress string `protobuf:"bytes,19,opt,name=an_address,json=anAddress,proto3" json:"an_address,omitempty"` + Page *v1beta11.PageRequest `protobuf:"bytes,20,opt,name=page,proto3" json:"page,omitempty"` + Bools []bool `protobuf:"varint,21,rep,packed,name=bools,proto3" json:"bools,omitempty"` + Uints []uint32 `protobuf:"varint,22,rep,packed,name=uints,proto3" json:"uints,omitempty"` + Strings []string `protobuf:"bytes,23,rep,name=strings,proto3" json:"strings,omitempty"` + Enums []Enum `protobuf:"varint,24,rep,packed,name=enums,proto3,enum=testpb.Enum" json:"enums,omitempty"` + Durations []*durationpb.Duration `protobuf:"bytes,25,rep,name=durations,proto3" json:"durations,omitempty"` + SomeMessages []*AMessage `protobuf:"bytes,26,rep,name=some_messages,json=someMessages,proto3" json:"some_messages,omitempty"` + Positional1 int32 `protobuf:"varint,27,opt,name=positional1,proto3" json:"positional1,omitempty"` + Positional2 string `protobuf:"bytes,28,opt,name=positional2,proto3" json:"positional2,omitempty"` + Positional3Varargs []*v1beta1.Coin `protobuf:"bytes,29,rep,name=positional3_varargs,json=positional3Varargs,proto3" json:"positional3_varargs,omitempty"` } func (x *EchoRequest) Reset() { @@ -3354,6 +3613,27 @@ func (x *EchoRequest) GetSomeMessages() []*AMessage { return nil } +func (x *EchoRequest) GetPositional1() int32 { + if x != nil { + return x.Positional1 + } + return 0 +} + +func (x *EchoRequest) GetPositional2() string { + if x != nil { + return x.Positional2 + } + return "" +} + +func (x *EchoRequest) GetPositional3Varargs() []*v1beta1.Coin { + if x != nil { + return x.Positional3Varargs + } + return nil +} + type AMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3447,7 +3727,7 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, 0x05, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe6, 0x06, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, @@ -3492,7 +3772,16 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x0d, 0x73, 0x6f, 0x6d, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x0c, 0x73, 0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x2e, 0x0a, + 0x0c, 0x73, 0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x20, 0x0a, + 0x0b, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x31, 0x18, 0x1b, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0b, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x31, 0x12, + 0x20, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x32, 0x18, 0x1c, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x32, 0x12, 0x4a, 0x0a, 0x13, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x33, + 0x5f, 0x76, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x18, 0x1d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x33, 0x56, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x22, 0x2e, 0x0a, 0x08, 0x41, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x62, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x22, 0x3d, 0x0a, @@ -3556,14 +3845,15 @@ var file_testpb_query_proto_depIdxs = []int32{ 0, // 6: testpb.EchoRequest.enums:type_name -> testpb.Enum 5, // 7: testpb.EchoRequest.durations:type_name -> google.protobuf.Duration 2, // 8: testpb.EchoRequest.some_messages:type_name -> testpb.AMessage - 1, // 9: testpb.EchoResponse.request:type_name -> testpb.EchoRequest - 1, // 10: testpb.Query.Echo:input_type -> testpb.EchoRequest - 3, // 11: testpb.Query.Echo:output_type -> testpb.EchoResponse - 11, // [11:12] is the sub-list for method output_type - 10, // [10:11] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 6, // 9: testpb.EchoRequest.positional3_varargs:type_name -> cosmos.base.v1beta1.Coin + 1, // 10: testpb.EchoResponse.request:type_name -> testpb.EchoRequest + 1, // 11: testpb.Query.Echo:input_type -> testpb.EchoRequest + 3, // 12: testpb.Query.Echo:output_type -> testpb.EchoResponse + 12, // [12:13] is the sub-list for method output_type + 11, // [11:12] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_testpb_query_proto_init() } From ed3897e8f41bc3e61b6bcfec3a89491a12e50d7c Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 12 Sep 2022 21:18:32 -0400 Subject: [PATCH 13/25] add TODO --- client/v2/cli/flag/field.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index 226708e4a796..8c6a94e4ff97 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -48,10 +48,11 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel val := typ.NewValue(ctx, b) flagSet.AddFlag(&pflag.Flag{ - Name: name, - Shorthand: shorthand, - Usage: usage, - DefValue: defaultValue, + Name: name, + Shorthand: shorthand, + Usage: usage, + DefValue: defaultValue, + // TODO: these need to be set on all flags - not just ones for custom types Deprecated: opts.Deprecated, ShorthandDeprecated: opts.ShorthandDeprecated, Hidden: opts.Hidden, From 97fbbc93d582639ab0110ce9d95a8e0460b5d5fc Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 13 Sep 2022 12:13:21 -0400 Subject: [PATCH 14/25] WIP on tests --- client/v2/cli/flag/field.go | 27 +- client/v2/cli/flag/list.go | 2 +- client/v2/cli/flag/message.go | 11 +- client/v2/cli/flag/pagination.go | 7 +- client/v2/cli/flag/register.go | 20 +- client/v2/cli/flag/simple.go | 4 +- client/v2/cli/query_test.go | 106 +++++-- client/v2/internal/testpb/query.proto | 4 + client/v2/internal/testpb/query.pulsar.go | 340 ++++++++++++++++++---- 9 files changed, 414 insertions(+), 107 deletions(-) diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index 8c6a94e4ff97..b6cd19b37d86 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -18,17 +18,18 @@ type Options struct { Prefix string } -// AddFieldFlag adds a flag for the provided field to the flag set. -func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) (HasValue, error) { +// addFieldFlag adds a flag for the provided field to the flag set. +func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) (name string, hasValue HasValue, err error) { if opts == nil { opts = &autocliv1.FlagOptions{} } if field.Kind() == protoreflect.MessageKind && field.Message().FullName() == "cosmos.base.query.v1beta1.PageRequest" { - return b.bindPageRequest(ctx, flagSet, field) + hasValue, err := b.bindPageRequest(ctx, flagSet, field) + return "", hasValue, err } - name := opts.Name + name = opts.Name if name == "" { name = options.Prefix + util.DescriptorKebabName(field) } @@ -39,9 +40,9 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel } shorthand := opts.Shorthand + defaultValue := opts.DefaultValue if typ := b.resolveFlagType(field); typ != nil { - defaultValue := opts.DefaultValue if defaultValue == "" { defaultValue = typ.DefaultValue() } @@ -53,23 +54,19 @@ func (b *Builder) AddFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel Usage: usage, DefValue: defaultValue, // TODO: these need to be set on all flags - not just ones for custom types - Deprecated: opts.Deprecated, - ShorthandDeprecated: opts.ShorthandDeprecated, - Hidden: opts.Hidden, - NoOptDefVal: opts.NoOptDefaultValue, - Value: val, + Value: val, }) - return val, nil + return name, val, nil } if field.IsList() { - val := bindSimpleListFlag(flagSet, field.Kind(), name, shorthand, usage) - return val, nil + val := bindSimpleListFlag(flagSet, field.Kind(), name, shorthand, usage, defaultValue) + return name, val, nil } - val := bindSimpleFlag(flagSet, field.Kind(), name, shorthand, usage) - return val, nil + val := bindSimpleFlag(flagSet, field.Kind(), name, shorthand, usage, defaultValue) + return name, val, nil } func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { diff --git a/client/v2/cli/flag/list.go b/client/v2/cli/flag/list.go index 72f84c8be3ee..ad0948b8464f 100644 --- a/client/v2/cli/flag/list.go +++ b/client/v2/cli/flag/list.go @@ -8,7 +8,7 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) HasValue { +func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage, defaultValue string) HasValue { switch kind { case protoreflect.StringKind: val := flagSet.StringSliceP(name, shorthand, nil, usage) diff --git a/client/v2/cli/flag/message.go b/client/v2/cli/flag/message.go index bdb3bb1c1f05..6d07e3564a07 100644 --- a/client/v2/cli/flag/message.go +++ b/client/v2/cli/flag/message.go @@ -83,10 +83,17 @@ type fieldBinding struct { } func (f fieldBinding) bind(msg protoreflect.Message) error { - val, err := f.hasValue.Get(msg.NewField(f.field)) + field := f.field + val, err := f.hasValue.Get(msg.NewField(field)) if err != nil { return err } - msg.Set(f.field, val) + kind := f.field.Kind() + if !(field.IsList() || + field.IsMap() || + kind == protoreflect.MessageKind || + kind == protoreflect.GroupKind) { + msg.Set(f.field, val) + } return nil } diff --git a/client/v2/cli/flag/pagination.go b/client/v2/cli/flag/pagination.go index 83d58424793d..c935a2aad742 100644 --- a/client/v2/cli/flag/pagination.go +++ b/client/v2/cli/flag/pagination.go @@ -11,16 +11,11 @@ import ( ) func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) (HasValue, error) { - handler, err := b.AddMessageFlags( + return b.AddMessageFlags( ctx, flagSet, util.ResolveMessageType(b.TypeResolver, field.Message()), &autocliv1.RpcCommandOptions{}, Options{Prefix: "page-"}, ) - if err != nil { - return nil, err - } - - return handler, nil } diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index 0e5d6a9689d3..827511a82c8f 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -38,7 +38,7 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa hasVarargs = true } - hasValue, err := b.AddFieldFlag( + _, hasValue, err := b.addFieldFlag( ctx, handler.positionalFlagSet, field, @@ -62,6 +62,7 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa handler.CobraArgs = cobra.ExactArgs(n) } + flagOptsByFlagName := map[string]*autocliv1.FlagOptions{} for i := 0; i < numFields; i++ { field := fields.Get(i) if isPositional[string(field.Name())] { @@ -69,7 +70,8 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa } flagOpts := commandOptions.FlagOptions[string(field.Name())] - hasValue, err := b.AddFieldFlag(ctx, set, field, flagOpts, options) + name, hasValue, err := b.addFieldFlag(ctx, set, field, flagOpts, options) + flagOptsByFlagName[name] = flagOpts if err != nil { return nil, err } @@ -79,5 +81,19 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa field: field, }) } + + set.VisitAll(func(flag *pflag.Flag) { + opts := flagOptsByFlagName[flag.Name] + if opts != nil { + // we need to set these options here using Flag.VisitAll because the flag + // constructors that pflag gives us (StringP, Int32P, etc.) do not + // actually return the *Flag instance + flag.Deprecated = opts.Deprecated + flag.ShorthandDeprecated = opts.ShorthandDeprecated + flag.Hidden = opts.Hidden + flag.NoOptDefVal = opts.NoOptDefaultValue + } + }) + return handler, nil } diff --git a/client/v2/cli/flag/simple.go b/client/v2/cli/flag/simple.go index d4ed6d4464e3..f43a79516e20 100644 --- a/client/v2/cli/flag/simple.go +++ b/client/v2/cli/flag/simple.go @@ -5,13 +5,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -func bindSimpleFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) HasValue { +func bindSimpleFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage, defaultValue string) HasValue { switch kind { case protoreflect.BytesKind: val := flagSet.BytesBase64P(name, shorthand, nil, usage) return newSimpleValue(val, protoreflect.ValueOfBytes) case protoreflect.StringKind: - val := flagSet.StringP(name, shorthand, "", usage) + val := flagSet.StringP(name, shorthand, defaultValue, usage) return newSimpleValue(val, protoreflect.ValueOfString) case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: val := flagSet.Uint32P(name, shorthand, 0, usage) diff --git a/client/v2/cli/query_test.go b/client/v2/cli/query_test.go index 122713868271..117b1a0bdf6b 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/cli/query_test.go @@ -16,6 +16,50 @@ import ( "github.com/cosmos/cosmos-sdk/client/v2/internal/testpb" ) +var testCmdDesc = &autocliv1.ServiceCommandDescriptor{ + Service: testpb.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Echo", + Use: "echo [pos1] [pos2] [pos3...]", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + { + ProtoField: "positional1", + }, + { + ProtoField: "positional2", + }, + { + ProtoField: "positional3_varargs", + Varargs: true, + }, + }, + FlagOptions: map[string]*autocliv1.FlagOptions{ + "u32": { + Name: "uint32", + Shorthand: "u", + Usage: "some random uint32", + }, + "i32": { + Usage: "some random int32", + DefaultValue: "3", + }, + "u64": { + Usage: "some random uint64", + NoOptDefaultValue: "5", + }, + "cli_deprecated_field": { + Deprecated: "don't use this", + }, + "shorthand_deprecated_field": { + Shorthand: "s", + Deprecated: "bad idea", + }, + }, + }, + }, +} + func testExec(t *testing.T, args ...string) *testClientConn { server := grpc.NewServer() testpb.RegisterQueryServer(server, &testEchoServer{}) @@ -37,30 +81,7 @@ func testExec(t *testing.T, args ...string) *testClientConn { return conn }, } - cmd, err := b.BuildModuleQueryCommand( - "test", - &autocliv1.ServiceCommandDescriptor{ - Service: testpb.Query_ServiceDesc.ServiceName, - RpcCommandOptions: []*autocliv1.RpcCommandOptions{ - { - RpcMethod: "Echo", - Use: "echo [pos1] [pos2] [pos3...]", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{ - { - ProtoField: "positional1", - }, - { - ProtoField: "positional2", - }, - { - ProtoField: "positional3_varargs", - Varargs: true, - }, - }, - }, - }, - }, - ) + cmd, err := b.BuildModuleQueryCommand("test", testCmdDesc) assert.NilError(t, err) cmd.SetArgs(args) cmd.SetOut(conn.out) @@ -68,7 +89,7 @@ func testExec(t *testing.T, args ...string) *testClientConn { return conn } -func TestEcho(t *testing.T) { +func TestEverything(t *testing.T) { conn := testExec(t, "echo", "1", @@ -79,7 +100,7 @@ func TestEcho(t *testing.T) { "--an-enum", "one", "--a-message", `{"bar":"abc", "baz":-3}`, "--duration", "4h3s", - "--u-32", "27", + "--uint32", "27", "--u-64", "3267246890", "--i-32", "-253", "--i-64", "-234602347", @@ -113,6 +134,39 @@ func TestEcho(t *testing.T) { assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) } +func TestOptions(t *testing.T) { + conn := testExec(t, + "echo", + "1", "abc", `{"denom":"foo","amount":"1"}`, + "-u", "27", // shorthand + "--u-64", // no opt default value + ) + lastReq := conn.lastRequest.(*testpb.EchoRequest) + assert.Equal(t, uint32(27), lastReq.U32) // shorthand got set + assert.Equal(t, int32(3), lastReq.I32) // default value got set + assert.Equal(t, uint64(5), lastReq.U64) // no opt default value got set +} + +func TestDeprecated(t *testing.T) { + // deprecated field in proto file + testExec(t, + "echo", "1", "abc", `{}`, + "--proto-deprecated-field", "abc", + ) + + // deprecated field in cli options + testExec(t, + "echo", "1", "abc", `{}`, + "--cli-deprecated-field", "abc", + ) + + // deprecated shorthand in cli options + testExec(t, + "echo", "1", "abc", `{}`, + "-s", "abc", + ) +} + func TestHelp(t *testing.T) { conn := testExec(t, "echo", "-h") golden.Assert(t, conn.out.String(), "help.golden") diff --git a/client/v2/internal/testpb/query.proto b/client/v2/internal/testpb/query.proto index 6e2f91a6f18f..dab420b622b0 100644 --- a/client/v2/internal/testpb/query.proto +++ b/client/v2/internal/testpb/query.proto @@ -39,6 +39,10 @@ message EchoRequest { int32 positional1 = 27; string positional2 = 28; repeated cosmos.base.v1beta1.Coin positional3_varargs = 29; + + string proto_deprecated_field = 30 [deprecated = true]; + string cli_deprecated_field = 31; + string shorthand_deprecated_field = 32; } enum Enum { diff --git a/client/v2/internal/testpb/query.pulsar.go b/client/v2/internal/testpb/query.pulsar.go index 938d7b4190c2..1ef98f36407a 100644 --- a/client/v2/internal/testpb/query.pulsar.go +++ b/client/v2/internal/testpb/query.pulsar.go @@ -355,30 +355,33 @@ func (x *_EchoRequest_29_list) IsValid() bool { } var ( - md_EchoRequest protoreflect.MessageDescriptor - fd_EchoRequest_u32 protoreflect.FieldDescriptor - fd_EchoRequest_u64 protoreflect.FieldDescriptor - fd_EchoRequest_str protoreflect.FieldDescriptor - fd_EchoRequest_bz protoreflect.FieldDescriptor - fd_EchoRequest_timestamp protoreflect.FieldDescriptor - fd_EchoRequest_duration protoreflect.FieldDescriptor - fd_EchoRequest_i32 protoreflect.FieldDescriptor - fd_EchoRequest_i64 protoreflect.FieldDescriptor - fd_EchoRequest_a_bool protoreflect.FieldDescriptor - fd_EchoRequest_an_enum protoreflect.FieldDescriptor - fd_EchoRequest_a_message protoreflect.FieldDescriptor - fd_EchoRequest_a_coin protoreflect.FieldDescriptor - fd_EchoRequest_an_address protoreflect.FieldDescriptor - fd_EchoRequest_page protoreflect.FieldDescriptor - fd_EchoRequest_bools protoreflect.FieldDescriptor - fd_EchoRequest_uints protoreflect.FieldDescriptor - fd_EchoRequest_strings protoreflect.FieldDescriptor - fd_EchoRequest_enums protoreflect.FieldDescriptor - fd_EchoRequest_durations protoreflect.FieldDescriptor - fd_EchoRequest_some_messages protoreflect.FieldDescriptor - fd_EchoRequest_positional1 protoreflect.FieldDescriptor - fd_EchoRequest_positional2 protoreflect.FieldDescriptor - fd_EchoRequest_positional3_varargs protoreflect.FieldDescriptor + md_EchoRequest protoreflect.MessageDescriptor + fd_EchoRequest_u32 protoreflect.FieldDescriptor + fd_EchoRequest_u64 protoreflect.FieldDescriptor + fd_EchoRequest_str protoreflect.FieldDescriptor + fd_EchoRequest_bz protoreflect.FieldDescriptor + fd_EchoRequest_timestamp protoreflect.FieldDescriptor + fd_EchoRequest_duration protoreflect.FieldDescriptor + fd_EchoRequest_i32 protoreflect.FieldDescriptor + fd_EchoRequest_i64 protoreflect.FieldDescriptor + fd_EchoRequest_a_bool protoreflect.FieldDescriptor + fd_EchoRequest_an_enum protoreflect.FieldDescriptor + fd_EchoRequest_a_message protoreflect.FieldDescriptor + fd_EchoRequest_a_coin protoreflect.FieldDescriptor + fd_EchoRequest_an_address protoreflect.FieldDescriptor + fd_EchoRequest_page protoreflect.FieldDescriptor + fd_EchoRequest_bools protoreflect.FieldDescriptor + fd_EchoRequest_uints protoreflect.FieldDescriptor + fd_EchoRequest_strings protoreflect.FieldDescriptor + fd_EchoRequest_enums protoreflect.FieldDescriptor + fd_EchoRequest_durations protoreflect.FieldDescriptor + fd_EchoRequest_some_messages protoreflect.FieldDescriptor + fd_EchoRequest_positional1 protoreflect.FieldDescriptor + fd_EchoRequest_positional2 protoreflect.FieldDescriptor + fd_EchoRequest_positional3_varargs protoreflect.FieldDescriptor + fd_EchoRequest_proto_deprecated_field protoreflect.FieldDescriptor + fd_EchoRequest_cli_deprecated_field protoreflect.FieldDescriptor + fd_EchoRequest_shorthand_deprecated_field protoreflect.FieldDescriptor ) func init() { @@ -407,6 +410,9 @@ func init() { fd_EchoRequest_positional1 = md_EchoRequest.Fields().ByName("positional1") fd_EchoRequest_positional2 = md_EchoRequest.Fields().ByName("positional2") fd_EchoRequest_positional3_varargs = md_EchoRequest.Fields().ByName("positional3_varargs") + fd_EchoRequest_proto_deprecated_field = md_EchoRequest.Fields().ByName("proto_deprecated_field") + fd_EchoRequest_cli_deprecated_field = md_EchoRequest.Fields().ByName("cli_deprecated_field") + fd_EchoRequest_shorthand_deprecated_field = md_EchoRequest.Fields().ByName("shorthand_deprecated_field") } var _ protoreflect.Message = (*fastReflection_EchoRequest)(nil) @@ -612,6 +618,24 @@ func (x *fastReflection_EchoRequest) Range(f func(protoreflect.FieldDescriptor, return } } + if x.ProtoDeprecatedField != "" { + value := protoreflect.ValueOfString(x.ProtoDeprecatedField) + if !f(fd_EchoRequest_proto_deprecated_field, value) { + return + } + } + if x.CliDeprecatedField != "" { + value := protoreflect.ValueOfString(x.CliDeprecatedField) + if !f(fd_EchoRequest_cli_deprecated_field, value) { + return + } + } + if x.ShorthandDeprecatedField != "" { + value := protoreflect.ValueOfString(x.ShorthandDeprecatedField) + if !f(fd_EchoRequest_shorthand_deprecated_field, value) { + return + } + } } // Has reports whether a field is populated. @@ -673,6 +697,12 @@ func (x *fastReflection_EchoRequest) Has(fd protoreflect.FieldDescriptor) bool { return x.Positional2 != "" case "testpb.EchoRequest.positional3_varargs": return len(x.Positional3Varargs) != 0 + case "testpb.EchoRequest.proto_deprecated_field": + return x.ProtoDeprecatedField != "" + case "testpb.EchoRequest.cli_deprecated_field": + return x.CliDeprecatedField != "" + case "testpb.EchoRequest.shorthand_deprecated_field": + return x.ShorthandDeprecatedField != "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -735,6 +765,12 @@ func (x *fastReflection_EchoRequest) Clear(fd protoreflect.FieldDescriptor) { x.Positional2 = "" case "testpb.EchoRequest.positional3_varargs": x.Positional3Varargs = nil + case "testpb.EchoRequest.proto_deprecated_field": + x.ProtoDeprecatedField = "" + case "testpb.EchoRequest.cli_deprecated_field": + x.CliDeprecatedField = "" + case "testpb.EchoRequest.shorthand_deprecated_field": + x.ShorthandDeprecatedField = "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -841,6 +877,15 @@ func (x *fastReflection_EchoRequest) Get(descriptor protoreflect.FieldDescriptor } listValue := &_EchoRequest_29_list{list: &x.Positional3Varargs} return protoreflect.ValueOfList(listValue) + case "testpb.EchoRequest.proto_deprecated_field": + value := x.ProtoDeprecatedField + return protoreflect.ValueOfString(value) + case "testpb.EchoRequest.cli_deprecated_field": + value := x.CliDeprecatedField + return protoreflect.ValueOfString(value) + case "testpb.EchoRequest.shorthand_deprecated_field": + value := x.ShorthandDeprecatedField + return protoreflect.ValueOfString(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -921,6 +966,12 @@ func (x *fastReflection_EchoRequest) Set(fd protoreflect.FieldDescriptor, value lv := value.List() clv := lv.(*_EchoRequest_29_list) x.Positional3Varargs = *clv.list + case "testpb.EchoRequest.proto_deprecated_field": + x.ProtoDeprecatedField = value.Interface().(string) + case "testpb.EchoRequest.cli_deprecated_field": + x.CliDeprecatedField = value.Interface().(string) + case "testpb.EchoRequest.shorthand_deprecated_field": + x.ShorthandDeprecatedField = value.Interface().(string) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -1030,6 +1081,12 @@ func (x *fastReflection_EchoRequest) Mutable(fd protoreflect.FieldDescriptor) pr panic(fmt.Errorf("field positional1 of message testpb.EchoRequest is not mutable")) case "testpb.EchoRequest.positional2": panic(fmt.Errorf("field positional2 of message testpb.EchoRequest is not mutable")) + case "testpb.EchoRequest.proto_deprecated_field": + panic(fmt.Errorf("field proto_deprecated_field of message testpb.EchoRequest is not mutable")) + case "testpb.EchoRequest.cli_deprecated_field": + panic(fmt.Errorf("field cli_deprecated_field of message testpb.EchoRequest is not mutable")) + case "testpb.EchoRequest.shorthand_deprecated_field": + panic(fmt.Errorf("field shorthand_deprecated_field of message testpb.EchoRequest is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -1101,6 +1158,12 @@ func (x *fastReflection_EchoRequest) NewField(fd protoreflect.FieldDescriptor) p case "testpb.EchoRequest.positional3_varargs": list := []*v1beta1.Coin{} return protoreflect.ValueOfList(&_EchoRequest_29_list{list: &list}) + case "testpb.EchoRequest.proto_deprecated_field": + return protoreflect.ValueOfString("") + case "testpb.EchoRequest.cli_deprecated_field": + return protoreflect.ValueOfString("") + case "testpb.EchoRequest.shorthand_deprecated_field": + return protoreflect.ValueOfString("") default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -1268,6 +1331,18 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { n += 2 + l + runtime.Sov(uint64(l)) } } + l = len(x.ProtoDeprecatedField) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } + l = len(x.CliDeprecatedField) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } + l = len(x.ShorthandDeprecatedField) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -1297,6 +1372,33 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if len(x.ShorthandDeprecatedField) > 0 { + i -= len(x.ShorthandDeprecatedField) + copy(dAtA[i:], x.ShorthandDeprecatedField) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ShorthandDeprecatedField))) + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0x82 + } + if len(x.CliDeprecatedField) > 0 { + i -= len(x.CliDeprecatedField) + copy(dAtA[i:], x.CliDeprecatedField) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.CliDeprecatedField))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xfa + } + if len(x.ProtoDeprecatedField) > 0 { + i -= len(x.ProtoDeprecatedField) + copy(dAtA[i:], x.ProtoDeprecatedField) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ProtoDeprecatedField))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xf2 + } if len(x.Positional3Varargs) > 0 { for iNdEx := len(x.Positional3Varargs) - 1; iNdEx >= 0; iNdEx-- { encoded, err := options.Marshal(x.Positional3Varargs[iNdEx]) @@ -2416,6 +2518,102 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex + case 30: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ProtoDeprecatedField", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ProtoDeprecatedField = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 31: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field CliDeprecatedField", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.CliDeprecatedField = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 32: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ShorthandDeprecatedField", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ShorthandDeprecatedField = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -3451,6 +3649,10 @@ type EchoRequest struct { Positional1 int32 `protobuf:"varint,27,opt,name=positional1,proto3" json:"positional1,omitempty"` Positional2 string `protobuf:"bytes,28,opt,name=positional2,proto3" json:"positional2,omitempty"` Positional3Varargs []*v1beta1.Coin `protobuf:"bytes,29,rep,name=positional3_varargs,json=positional3Varargs,proto3" json:"positional3_varargs,omitempty"` + // Deprecated: Do not use. + ProtoDeprecatedField string `protobuf:"bytes,30,opt,name=proto_deprecated_field,json=protoDeprecatedField,proto3" json:"proto_deprecated_field,omitempty"` + CliDeprecatedField string `protobuf:"bytes,31,opt,name=cli_deprecated_field,json=cliDeprecatedField,proto3" json:"cli_deprecated_field,omitempty"` + ShorthandDeprecatedField string `protobuf:"bytes,32,opt,name=shorthand_deprecated_field,json=shorthandDeprecatedField,proto3" json:"shorthand_deprecated_field,omitempty"` } func (x *EchoRequest) Reset() { @@ -3634,6 +3836,28 @@ func (x *EchoRequest) GetPositional3Varargs() []*v1beta1.Coin { return nil } +// Deprecated: Do not use. +func (x *EchoRequest) GetProtoDeprecatedField() string { + if x != nil { + return x.ProtoDeprecatedField + } + return "" +} + +func (x *EchoRequest) GetCliDeprecatedField() string { + if x != nil { + return x.CliDeprecatedField + } + return "" +} + +func (x *EchoRequest) GetShorthandDeprecatedField() string { + if x != nil { + return x.ShorthandDeprecatedField + } + return "" +} + type AMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3727,7 +3951,7 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe6, 0x06, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x90, 0x08, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, @@ -3781,34 +4005,44 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x5f, 0x76, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x18, 0x1d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x33, 0x56, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x22, 0x2e, 0x0a, - 0x08, 0x41, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x62, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, - 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x22, 0x3d, 0x0a, - 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, - 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x64, 0x0a, 0x04, - 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, - 0x55, 0x4d, 0x5f, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, - 0x5f, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, - 0x49, 0x56, 0x45, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, - 0x47, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x45, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0x32, 0x3a, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x04, 0x45, - 0x63, 0x68, 0x6f, 0x12, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, - 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x88, - 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x0a, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, - 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, - 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, - 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x33, 0x56, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x12, 0x38, 0x0a, + 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, + 0x01, 0x52, 0x14, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, + 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6c, 0x69, 0x5f, 0x64, + 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, + 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x68, 0x6f, + 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, + 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x2e, 0x0a, 0x08, 0x41, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x62, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x22, 0x3d, 0x0a, 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x64, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, + 0x0a, 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4f, 0x4e, 0x45, + 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x57, 0x4f, 0x10, 0x02, + 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x56, 0x45, 0x10, 0x05, 0x12, + 0x1b, 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, 0x47, 0x5f, 0x54, 0x48, 0x52, 0x45, + 0x45, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x32, 0x3a, 0x0a, 0x05, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x13, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x88, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, + 0x73, 0x64, 0x6b, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, + 0x54, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, + 0x65, 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, + 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( From 98cd77fd53370739c4cb74e21e9780ac0b31c3d7 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 13 Sep 2022 15:19:09 -0400 Subject: [PATCH 15/25] WIP on tests --- client/v2/cli/flag/field.go | 16 ++++++++++------ client/v2/cli/flag/list.go | 2 +- client/v2/cli/flag/simple.go | 4 ++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index b6cd19b37d86..63b9f0c5377a 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -53,20 +53,24 @@ func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel Shorthand: shorthand, Usage: usage, DefValue: defaultValue, - // TODO: these need to be set on all flags - not just ones for custom types - Value: val, + Value: val, }) return name, val, nil } + // use the built-in pflag StringP, Int32P, etc. functions + var val HasValue if field.IsList() { - val := bindSimpleListFlag(flagSet, field.Kind(), name, shorthand, usage, defaultValue) - return name, val, nil + val = bindSimpleListFlag(flagSet, field.Kind(), name, shorthand, usage) + } else { + val = bindSimpleFlag(flagSet, field.Kind(), name, shorthand, usage) } - val := bindSimpleFlag(flagSet, field.Kind(), name, shorthand, usage, defaultValue) - return name, val, nil + // set the defaultValue in this way because this is much easier than trying + // to parse the string into the types that StringSliceP, Int32P, etc. expect + err = flagSet.Set(name, defaultValue) + return name, val, err } func (b *Builder) resolveFlagType(field protoreflect.FieldDescriptor) Type { diff --git a/client/v2/cli/flag/list.go b/client/v2/cli/flag/list.go index ad0948b8464f..72f84c8be3ee 100644 --- a/client/v2/cli/flag/list.go +++ b/client/v2/cli/flag/list.go @@ -8,7 +8,7 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage, defaultValue string) HasValue { +func bindSimpleListFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) HasValue { switch kind { case protoreflect.StringKind: val := flagSet.StringSliceP(name, shorthand, nil, usage) diff --git a/client/v2/cli/flag/simple.go b/client/v2/cli/flag/simple.go index f43a79516e20..d4ed6d4464e3 100644 --- a/client/v2/cli/flag/simple.go +++ b/client/v2/cli/flag/simple.go @@ -5,13 +5,13 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -func bindSimpleFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage, defaultValue string) HasValue { +func bindSimpleFlag(flagSet *pflag.FlagSet, kind protoreflect.Kind, name, shorthand, usage string) HasValue { switch kind { case protoreflect.BytesKind: val := flagSet.BytesBase64P(name, shorthand, nil, usage) return newSimpleValue(val, protoreflect.ValueOfBytes) case protoreflect.StringKind: - val := flagSet.StringP(name, shorthand, defaultValue, usage) + val := flagSet.StringP(name, shorthand, "", usage) return newSimpleValue(val, protoreflect.ValueOfString) case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: val := flagSet.Uint32P(name, shorthand, 0, usage) From b61be02f7a957b21c294079143bab049c101380e Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 13 Sep 2022 15:33:06 -0400 Subject: [PATCH 16/25] working tests --- client/v2/cli/flag/field.go | 4 +- client/v2/cli/query.go | 18 +- client/v2/cli/query_test.go | 22 +- client/v2/cli/testdata/help.golden | 8 +- client/v2/internal/testpb/query.proto | 5 +- client/v2/internal/testpb/query.pulsar.go | 250 ++++++++-------------- 6 files changed, 109 insertions(+), 198 deletions(-) diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index 63b9f0c5377a..2d954c611fc5 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -69,7 +69,9 @@ func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel // set the defaultValue in this way because this is much easier than trying // to parse the string into the types that StringSliceP, Int32P, etc. expect - err = flagSet.Set(name, defaultValue) + if defaultValue != "" { + err = flagSet.Set(name, defaultValue) + } return name, val, err } diff --git a/client/v2/cli/query.go b/client/v2/cli/query.go index 447d68071b9d..2a76a1cc8371 100644 --- a/client/v2/cli/query.go +++ b/client/v2/cli/query.go @@ -45,14 +45,14 @@ func (b *Builder) BuildQueryCommand(moduleOptions map[string]*autocliv1.ModuleOp func (b *Builder) BuildModuleQueryCommand(moduleName string, cmdDescriptor *autocliv1.ServiceCommandDescriptor) (*cobra.Command, error) { cmd := topLevelCmd(moduleName, fmt.Sprintf("Querying commands for the %s module", moduleName)) - b.AddQueryServiceCommands(cmd, cmdDescriptor) + err := b.AddQueryServiceCommands(cmd, cmdDescriptor) - return cmd, nil + return cmd, err } // AddQueryServiceCommands adds a sub-command to the provided command for each // method in the specified service and returns the command. -func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor *autocliv1.ServiceCommandDescriptor) { +func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor *autocliv1.ServiceCommandDescriptor) error { resolver := b.FileResolver if resolver == nil { resolver = protoregistry.GlobalFiles @@ -73,7 +73,11 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor methodOpts = option } } - cmd, _ := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) + cmd, err := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) + if err != nil { + return err + } + if cmd != nil { command.AddCommand(cmd) } @@ -81,8 +85,12 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor for cmdName, subCmd := range cmdDescriptor.SubCommands { cmd := topLevelCmd(cmdName, fmt.Sprintf("Querying commands for the %s service", subCmd.Service)) - b.AddQueryServiceCommands(cmd, subCmd) + err = b.AddQueryServiceCommands(cmd, subCmd) + if err != nil { + return err + } } + return nil } // CreateQueryMethodCommand creates a gRPC query command for the given service method. diff --git a/client/v2/cli/query_test.go b/client/v2/cli/query_test.go index 117b1a0bdf6b..8536fc2e86b4 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/cli/query_test.go @@ -48,7 +48,7 @@ var testCmdDesc = &autocliv1.ServiceCommandDescriptor{ Usage: "some random uint64", NoOptDefaultValue: "5", }, - "cli_deprecated_field": { + "deprecated_field": { Deprecated: "don't use this", }, "shorthand_deprecated_field": { @@ -147,26 +147,6 @@ func TestOptions(t *testing.T) { assert.Equal(t, uint64(5), lastReq.U64) // no opt default value got set } -func TestDeprecated(t *testing.T) { - // deprecated field in proto file - testExec(t, - "echo", "1", "abc", `{}`, - "--proto-deprecated-field", "abc", - ) - - // deprecated field in cli options - testExec(t, - "echo", "1", "abc", `{}`, - "--cli-deprecated-field", "abc", - ) - - // deprecated shorthand in cli options - testExec(t, - "echo", "1", "abc", `{}`, - "-s", "abc", - ) -} - func TestHelp(t *testing.T) { conn := testExec(t, "echo", "-h") golden.Assert(t, conn.out.String(), "help.golden") diff --git a/client/v2/cli/testdata/help.golden b/client/v2/cli/testdata/help.golden index 0e3ddf5d131c..df65ccd4b0b7 100644 --- a/client/v2/cli/testdata/help.golden +++ b/client/v2/cli/testdata/help.golden @@ -9,21 +9,23 @@ Flags: --an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified) --bools bools (default []) --bz bytesBase64 + --deprecated-field string (DEPRECATED: don't use this) --duration duration --durations duration (repeated) --enums Enum (unspecified | one | two | five | neg-three) (repeated) -h, --help help for echo - --i-32 int32 + --i-32 int32 some random int32 --i-64 int --page-count-total --page-key bytesBase64 --page-limit uint --page-offset uint --page-reverse + -s, --shorthand-deprecated-field string (DEPRECATED: bad idea) --some-messages testpb.AMessage (json) (repeated) --str string --strings strings --timestamp timestamp (RFC 3339) - --u-32 uint32 - --u-64 uint + --u-64 uint[=5] some random uint64 + -u, --uint32 uint32 some random uint32 --uints uints (default []) diff --git a/client/v2/internal/testpb/query.proto b/client/v2/internal/testpb/query.proto index dab420b622b0..e781626aadb6 100644 --- a/client/v2/internal/testpb/query.proto +++ b/client/v2/internal/testpb/query.proto @@ -40,9 +40,8 @@ message EchoRequest { string positional2 = 28; repeated cosmos.base.v1beta1.Coin positional3_varargs = 29; - string proto_deprecated_field = 30 [deprecated = true]; - string cli_deprecated_field = 31; - string shorthand_deprecated_field = 32; + string deprecated_field = 30; + string shorthand_deprecated_field = 31; } enum Enum { diff --git a/client/v2/internal/testpb/query.pulsar.go b/client/v2/internal/testpb/query.pulsar.go index 1ef98f36407a..a21d6c6bfd4d 100644 --- a/client/v2/internal/testpb/query.pulsar.go +++ b/client/v2/internal/testpb/query.pulsar.go @@ -379,8 +379,7 @@ var ( fd_EchoRequest_positional1 protoreflect.FieldDescriptor fd_EchoRequest_positional2 protoreflect.FieldDescriptor fd_EchoRequest_positional3_varargs protoreflect.FieldDescriptor - fd_EchoRequest_proto_deprecated_field protoreflect.FieldDescriptor - fd_EchoRequest_cli_deprecated_field protoreflect.FieldDescriptor + fd_EchoRequest_deprecated_field protoreflect.FieldDescriptor fd_EchoRequest_shorthand_deprecated_field protoreflect.FieldDescriptor ) @@ -410,8 +409,7 @@ func init() { fd_EchoRequest_positional1 = md_EchoRequest.Fields().ByName("positional1") fd_EchoRequest_positional2 = md_EchoRequest.Fields().ByName("positional2") fd_EchoRequest_positional3_varargs = md_EchoRequest.Fields().ByName("positional3_varargs") - fd_EchoRequest_proto_deprecated_field = md_EchoRequest.Fields().ByName("proto_deprecated_field") - fd_EchoRequest_cli_deprecated_field = md_EchoRequest.Fields().ByName("cli_deprecated_field") + fd_EchoRequest_deprecated_field = md_EchoRequest.Fields().ByName("deprecated_field") fd_EchoRequest_shorthand_deprecated_field = md_EchoRequest.Fields().ByName("shorthand_deprecated_field") } @@ -618,15 +616,9 @@ func (x *fastReflection_EchoRequest) Range(f func(protoreflect.FieldDescriptor, return } } - if x.ProtoDeprecatedField != "" { - value := protoreflect.ValueOfString(x.ProtoDeprecatedField) - if !f(fd_EchoRequest_proto_deprecated_field, value) { - return - } - } - if x.CliDeprecatedField != "" { - value := protoreflect.ValueOfString(x.CliDeprecatedField) - if !f(fd_EchoRequest_cli_deprecated_field, value) { + if x.DeprecatedField != "" { + value := protoreflect.ValueOfString(x.DeprecatedField) + if !f(fd_EchoRequest_deprecated_field, value) { return } } @@ -697,10 +689,8 @@ func (x *fastReflection_EchoRequest) Has(fd protoreflect.FieldDescriptor) bool { return x.Positional2 != "" case "testpb.EchoRequest.positional3_varargs": return len(x.Positional3Varargs) != 0 - case "testpb.EchoRequest.proto_deprecated_field": - return x.ProtoDeprecatedField != "" - case "testpb.EchoRequest.cli_deprecated_field": - return x.CliDeprecatedField != "" + case "testpb.EchoRequest.deprecated_field": + return x.DeprecatedField != "" case "testpb.EchoRequest.shorthand_deprecated_field": return x.ShorthandDeprecatedField != "" default: @@ -765,10 +755,8 @@ func (x *fastReflection_EchoRequest) Clear(fd protoreflect.FieldDescriptor) { x.Positional2 = "" case "testpb.EchoRequest.positional3_varargs": x.Positional3Varargs = nil - case "testpb.EchoRequest.proto_deprecated_field": - x.ProtoDeprecatedField = "" - case "testpb.EchoRequest.cli_deprecated_field": - x.CliDeprecatedField = "" + case "testpb.EchoRequest.deprecated_field": + x.DeprecatedField = "" case "testpb.EchoRequest.shorthand_deprecated_field": x.ShorthandDeprecatedField = "" default: @@ -877,11 +865,8 @@ func (x *fastReflection_EchoRequest) Get(descriptor protoreflect.FieldDescriptor } listValue := &_EchoRequest_29_list{list: &x.Positional3Varargs} return protoreflect.ValueOfList(listValue) - case "testpb.EchoRequest.proto_deprecated_field": - value := x.ProtoDeprecatedField - return protoreflect.ValueOfString(value) - case "testpb.EchoRequest.cli_deprecated_field": - value := x.CliDeprecatedField + case "testpb.EchoRequest.deprecated_field": + value := x.DeprecatedField return protoreflect.ValueOfString(value) case "testpb.EchoRequest.shorthand_deprecated_field": value := x.ShorthandDeprecatedField @@ -966,10 +951,8 @@ func (x *fastReflection_EchoRequest) Set(fd protoreflect.FieldDescriptor, value lv := value.List() clv := lv.(*_EchoRequest_29_list) x.Positional3Varargs = *clv.list - case "testpb.EchoRequest.proto_deprecated_field": - x.ProtoDeprecatedField = value.Interface().(string) - case "testpb.EchoRequest.cli_deprecated_field": - x.CliDeprecatedField = value.Interface().(string) + case "testpb.EchoRequest.deprecated_field": + x.DeprecatedField = value.Interface().(string) case "testpb.EchoRequest.shorthand_deprecated_field": x.ShorthandDeprecatedField = value.Interface().(string) default: @@ -1081,10 +1064,8 @@ func (x *fastReflection_EchoRequest) Mutable(fd protoreflect.FieldDescriptor) pr panic(fmt.Errorf("field positional1 of message testpb.EchoRequest is not mutable")) case "testpb.EchoRequest.positional2": panic(fmt.Errorf("field positional2 of message testpb.EchoRequest is not mutable")) - case "testpb.EchoRequest.proto_deprecated_field": - panic(fmt.Errorf("field proto_deprecated_field of message testpb.EchoRequest is not mutable")) - case "testpb.EchoRequest.cli_deprecated_field": - panic(fmt.Errorf("field cli_deprecated_field of message testpb.EchoRequest is not mutable")) + case "testpb.EchoRequest.deprecated_field": + panic(fmt.Errorf("field deprecated_field of message testpb.EchoRequest is not mutable")) case "testpb.EchoRequest.shorthand_deprecated_field": panic(fmt.Errorf("field shorthand_deprecated_field of message testpb.EchoRequest is not mutable")) default: @@ -1158,9 +1139,7 @@ func (x *fastReflection_EchoRequest) NewField(fd protoreflect.FieldDescriptor) p case "testpb.EchoRequest.positional3_varargs": list := []*v1beta1.Coin{} return protoreflect.ValueOfList(&_EchoRequest_29_list{list: &list}) - case "testpb.EchoRequest.proto_deprecated_field": - return protoreflect.ValueOfString("") - case "testpb.EchoRequest.cli_deprecated_field": + case "testpb.EchoRequest.deprecated_field": return protoreflect.ValueOfString("") case "testpb.EchoRequest.shorthand_deprecated_field": return protoreflect.ValueOfString("") @@ -1331,11 +1310,7 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { n += 2 + l + runtime.Sov(uint64(l)) } } - l = len(x.ProtoDeprecatedField) - if l > 0 { - n += 2 + l + runtime.Sov(uint64(l)) - } - l = len(x.CliDeprecatedField) + l = len(x.DeprecatedField) if l > 0 { n += 2 + l + runtime.Sov(uint64(l)) } @@ -1377,23 +1352,14 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { copy(dAtA[i:], x.ShorthandDeprecatedField) i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ShorthandDeprecatedField))) i-- - dAtA[i] = 0x2 - i-- - dAtA[i] = 0x82 - } - if len(x.CliDeprecatedField) > 0 { - i -= len(x.CliDeprecatedField) - copy(dAtA[i:], x.CliDeprecatedField) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.CliDeprecatedField))) - i-- dAtA[i] = 0x1 i-- dAtA[i] = 0xfa } - if len(x.ProtoDeprecatedField) > 0 { - i -= len(x.ProtoDeprecatedField) - copy(dAtA[i:], x.ProtoDeprecatedField) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ProtoDeprecatedField))) + if len(x.DeprecatedField) > 0 { + i -= len(x.DeprecatedField) + copy(dAtA[i:], x.DeprecatedField) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.DeprecatedField))) i-- dAtA[i] = 0x1 i-- @@ -2520,7 +2486,7 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { iNdEx = postIndex case 30: if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ProtoDeprecatedField", wireType) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field DeprecatedField", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2548,41 +2514,9 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { if postIndex > l { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } - x.ProtoDeprecatedField = string(dAtA[iNdEx:postIndex]) + x.DeprecatedField = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 31: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field CliDeprecatedField", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - x.CliDeprecatedField = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 32: if wireType != 2 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ShorthandDeprecatedField", wireType) } @@ -3626,33 +3560,31 @@ type EchoRequest struct { unknownFields protoimpl.UnknownFields // u32 is an uint32 - U32 uint32 `protobuf:"varint,1,opt,name=u32,proto3" json:"u32,omitempty"` - U64 uint64 `protobuf:"varint,2,opt,name=u64,proto3" json:"u64,omitempty"` - Str string `protobuf:"bytes,3,opt,name=str,proto3" json:"str,omitempty"` - Bz []byte `protobuf:"bytes,4,opt,name=bz,proto3" json:"bz,omitempty"` - Timestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Duration *durationpb.Duration `protobuf:"bytes,6,opt,name=duration,proto3" json:"duration,omitempty"` - I32 int32 `protobuf:"varint,7,opt,name=i32,proto3" json:"i32,omitempty"` - I64 int64 `protobuf:"varint,10,opt,name=i64,proto3" json:"i64,omitempty"` - ABool bool `protobuf:"varint,15,opt,name=a_bool,json=aBool,proto3" json:"a_bool,omitempty"` - AnEnum Enum `protobuf:"varint,16,opt,name=an_enum,json=anEnum,proto3,enum=testpb.Enum" json:"an_enum,omitempty"` - AMessage *AMessage `protobuf:"bytes,17,opt,name=a_message,json=aMessage,proto3" json:"a_message,omitempty"` - ACoin *v1beta1.Coin `protobuf:"bytes,18,opt,name=a_coin,json=aCoin,proto3" json:"a_coin,omitempty"` - AnAddress string `protobuf:"bytes,19,opt,name=an_address,json=anAddress,proto3" json:"an_address,omitempty"` - Page *v1beta11.PageRequest `protobuf:"bytes,20,opt,name=page,proto3" json:"page,omitempty"` - Bools []bool `protobuf:"varint,21,rep,packed,name=bools,proto3" json:"bools,omitempty"` - Uints []uint32 `protobuf:"varint,22,rep,packed,name=uints,proto3" json:"uints,omitempty"` - Strings []string `protobuf:"bytes,23,rep,name=strings,proto3" json:"strings,omitempty"` - Enums []Enum `protobuf:"varint,24,rep,packed,name=enums,proto3,enum=testpb.Enum" json:"enums,omitempty"` - Durations []*durationpb.Duration `protobuf:"bytes,25,rep,name=durations,proto3" json:"durations,omitempty"` - SomeMessages []*AMessage `protobuf:"bytes,26,rep,name=some_messages,json=someMessages,proto3" json:"some_messages,omitempty"` - Positional1 int32 `protobuf:"varint,27,opt,name=positional1,proto3" json:"positional1,omitempty"` - Positional2 string `protobuf:"bytes,28,opt,name=positional2,proto3" json:"positional2,omitempty"` - Positional3Varargs []*v1beta1.Coin `protobuf:"bytes,29,rep,name=positional3_varargs,json=positional3Varargs,proto3" json:"positional3_varargs,omitempty"` - // Deprecated: Do not use. - ProtoDeprecatedField string `protobuf:"bytes,30,opt,name=proto_deprecated_field,json=protoDeprecatedField,proto3" json:"proto_deprecated_field,omitempty"` - CliDeprecatedField string `protobuf:"bytes,31,opt,name=cli_deprecated_field,json=cliDeprecatedField,proto3" json:"cli_deprecated_field,omitempty"` - ShorthandDeprecatedField string `protobuf:"bytes,32,opt,name=shorthand_deprecated_field,json=shorthandDeprecatedField,proto3" json:"shorthand_deprecated_field,omitempty"` + U32 uint32 `protobuf:"varint,1,opt,name=u32,proto3" json:"u32,omitempty"` + U64 uint64 `protobuf:"varint,2,opt,name=u64,proto3" json:"u64,omitempty"` + Str string `protobuf:"bytes,3,opt,name=str,proto3" json:"str,omitempty"` + Bz []byte `protobuf:"bytes,4,opt,name=bz,proto3" json:"bz,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Duration *durationpb.Duration `protobuf:"bytes,6,opt,name=duration,proto3" json:"duration,omitempty"` + I32 int32 `protobuf:"varint,7,opt,name=i32,proto3" json:"i32,omitempty"` + I64 int64 `protobuf:"varint,10,opt,name=i64,proto3" json:"i64,omitempty"` + ABool bool `protobuf:"varint,15,opt,name=a_bool,json=aBool,proto3" json:"a_bool,omitempty"` + AnEnum Enum `protobuf:"varint,16,opt,name=an_enum,json=anEnum,proto3,enum=testpb.Enum" json:"an_enum,omitempty"` + AMessage *AMessage `protobuf:"bytes,17,opt,name=a_message,json=aMessage,proto3" json:"a_message,omitempty"` + ACoin *v1beta1.Coin `protobuf:"bytes,18,opt,name=a_coin,json=aCoin,proto3" json:"a_coin,omitempty"` + AnAddress string `protobuf:"bytes,19,opt,name=an_address,json=anAddress,proto3" json:"an_address,omitempty"` + Page *v1beta11.PageRequest `protobuf:"bytes,20,opt,name=page,proto3" json:"page,omitempty"` + Bools []bool `protobuf:"varint,21,rep,packed,name=bools,proto3" json:"bools,omitempty"` + Uints []uint32 `protobuf:"varint,22,rep,packed,name=uints,proto3" json:"uints,omitempty"` + Strings []string `protobuf:"bytes,23,rep,name=strings,proto3" json:"strings,omitempty"` + Enums []Enum `protobuf:"varint,24,rep,packed,name=enums,proto3,enum=testpb.Enum" json:"enums,omitempty"` + Durations []*durationpb.Duration `protobuf:"bytes,25,rep,name=durations,proto3" json:"durations,omitempty"` + SomeMessages []*AMessage `protobuf:"bytes,26,rep,name=some_messages,json=someMessages,proto3" json:"some_messages,omitempty"` + Positional1 int32 `protobuf:"varint,27,opt,name=positional1,proto3" json:"positional1,omitempty"` + Positional2 string `protobuf:"bytes,28,opt,name=positional2,proto3" json:"positional2,omitempty"` + Positional3Varargs []*v1beta1.Coin `protobuf:"bytes,29,rep,name=positional3_varargs,json=positional3Varargs,proto3" json:"positional3_varargs,omitempty"` + DeprecatedField string `protobuf:"bytes,30,opt,name=deprecated_field,json=deprecatedField,proto3" json:"deprecated_field,omitempty"` + ShorthandDeprecatedField string `protobuf:"bytes,31,opt,name=shorthand_deprecated_field,json=shorthandDeprecatedField,proto3" json:"shorthand_deprecated_field,omitempty"` } func (x *EchoRequest) Reset() { @@ -3836,17 +3768,9 @@ func (x *EchoRequest) GetPositional3Varargs() []*v1beta1.Coin { return nil } -// Deprecated: Do not use. -func (x *EchoRequest) GetProtoDeprecatedField() string { - if x != nil { - return x.ProtoDeprecatedField - } - return "" -} - -func (x *EchoRequest) GetCliDeprecatedField() string { +func (x *EchoRequest) GetDeprecatedField() string { if x != nil { - return x.CliDeprecatedField + return x.DeprecatedField } return "" } @@ -3951,7 +3875,7 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x90, 0x08, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcf, 0x07, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, @@ -4005,44 +3929,40 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x5f, 0x76, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x18, 0x1d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x33, 0x56, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x12, 0x38, 0x0a, - 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, - 0x01, 0x52, 0x14, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6c, 0x69, 0x5f, 0x64, - 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, - 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, - 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x68, 0x6f, - 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x73, - 0x68, 0x6f, 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x2e, 0x0a, 0x08, 0x41, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x62, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x22, 0x3d, 0x0a, 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, - 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x64, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, - 0x0a, 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4f, 0x4e, 0x45, - 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x57, 0x4f, 0x10, 0x02, - 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x56, 0x45, 0x10, 0x05, 0x12, - 0x1b, 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, 0x47, 0x5f, 0x54, 0x48, 0x52, 0x45, - 0x45, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x32, 0x3a, 0x0a, 0x05, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x13, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x88, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, - 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, - 0x73, 0x64, 0x6b, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, - 0x54, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, - 0x65, 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, - 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x33, 0x56, 0x61, 0x72, 0x61, 0x72, 0x67, 0x73, 0x12, 0x29, 0x0a, + 0x10, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x2e, 0x0a, 0x08, 0x41, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x62, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x22, 0x3d, 0x0a, 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, + 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x64, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, 0x0a, + 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4f, 0x4e, 0x45, 0x10, + 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x12, + 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x56, 0x45, 0x10, 0x05, 0x12, 0x1b, + 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, 0x47, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x45, + 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x32, 0x3a, 0x0a, 0x05, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x13, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x88, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, + 0x64, 0x6b, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x54, + 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, 0x65, + 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( From ca9c90428043b45224b5cf985e1bfb89c0326661 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 13 Sep 2022 15:37:19 -0400 Subject: [PATCH 17/25] doc strings --- client/v2/cli/flag/field.go | 3 ++- client/v2/cli/flag/register.go | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index 2d954c611fc5..d841b82fe1c2 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -67,7 +67,8 @@ func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel val = bindSimpleFlag(flagSet, field.Kind(), name, shorthand, usage) } - // set the defaultValue in this way because this is much easier than trying + // This is a bit of hacking around the pflag API, but the + // defaultValue is set in this way because this is much easier than trying // to parse the string into the types that StringSliceP, Int32P, etc. expect if defaultValue != "" { err = flagSet.Set(name, defaultValue) diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index 827511a82c8f..fa4da5ffba15 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -11,7 +11,7 @@ import ( ) // AddMessageFlags adds flags for each field in the message to the flag set. -func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options Options) (*MessageBinder, error) { +func (b *Builder) AddMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options Options) (*MessageBinder, error) { fields := messageType.Descriptor().Fields() numFields := fields.Len() handler := &MessageBinder{ @@ -21,6 +21,7 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa isPositional := map[string]bool{} hasVarargs := false n := len(commandOptions.PositionalArgs) + // positional args are also parsed using a FlagSet so that we can reuse all the same parsers handler.positionalFlagSet = pflag.NewFlagSet("positional", pflag.ContinueOnError) for i, arg := range commandOptions.PositionalArgs { isPositional[arg.ProtoField] = true @@ -70,7 +71,7 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa } flagOpts := commandOptions.FlagOptions[string(field.Name())] - name, hasValue, err := b.addFieldFlag(ctx, set, field, flagOpts, options) + name, hasValue, err := b.addFieldFlag(ctx, flagSet, field, flagOpts, options) flagOptsByFlagName[name] = flagOpts if err != nil { return nil, err @@ -82,9 +83,10 @@ func (b *Builder) AddMessageFlags(ctx context.Context, set *pflag.FlagSet, messa }) } - set.VisitAll(func(flag *pflag.Flag) { + flagSet.VisitAll(func(flag *pflag.Flag) { opts := flagOptsByFlagName[flag.Name] if opts != nil { + // This is a bit of hacking around the pflag API, but // we need to set these options here using Flag.VisitAll because the flag // constructors that pflag gives us (StringP, Int32P, etc.) do not // actually return the *Flag instance From 7fbd0443edae1dbab4072caac0af24c4673279b2 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 13 Sep 2022 15:40:49 -0400 Subject: [PATCH 18/25] docs --- client/v2/cli/query.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/v2/cli/query.go b/client/v2/cli/query.go index 2a76a1cc8371..d177ec195bab 100644 --- a/client/v2/cli/query.go +++ b/client/v2/cli/query.go @@ -15,6 +15,8 @@ import ( "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) +// BuildQueryCommand builds the query commands for all the provided modules. If a custom command is provided for a +// module, this is used instead of any automatically generated CLI commands. func (b *Builder) BuildQueryCommand(moduleOptions map[string]*autocliv1.ModuleOptions, customCmds map[string]*cobra.Command) (*cobra.Command, error) { queryCmd := topLevelCmd("query", "Querying subcommands") queryCmd.Aliases = []string{"q"} @@ -42,6 +44,7 @@ func (b *Builder) BuildQueryCommand(moduleOptions map[string]*autocliv1.ModuleOp return queryCmd, nil } +// BuildModuleQueryCommand builds the query command for a single module. func (b *Builder) BuildModuleQueryCommand(moduleName string, cmdDescriptor *autocliv1.ServiceCommandDescriptor) (*cobra.Command, error) { cmd := topLevelCmd(moduleName, fmt.Sprintf("Querying commands for the %s module", moduleName)) @@ -51,7 +54,8 @@ func (b *Builder) BuildModuleQueryCommand(moduleName string, cmdDescriptor *auto } // AddQueryServiceCommands adds a sub-command to the provided command for each -// method in the specified service and returns the command. +// method in the specified service and returns the command. This can be used in +// order to add auto-generated commands to an existing command. func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor *autocliv1.ServiceCommandDescriptor) error { resolver := b.FileResolver if resolver == nil { @@ -93,7 +97,8 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor return nil } -// CreateQueryMethodCommand creates a gRPC query command for the given service method. +// CreateQueryMethodCommand creates a gRPC query command for the given service method. This can be used to auto-generate +// just a single command for a single service rpc method. func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) (*cobra.Command, error) { if options == nil { // use the defaults From 12d2a4a7b3e764f38348498a1309d599c5d10821 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 13 Sep 2022 16:04:40 -0400 Subject: [PATCH 19/25] tests --- client/v2/cli/query.go | 16 ++- client/v2/cli/query_test.go | 47 ++++++- client/v2/cli/testdata/help-deprecated.golden | 36 ++++++ client/v2/cli/testdata/help-echo.golden | 40 ++++++ client/v2/cli/testdata/help-skip.golden | 7 + client/v2/cli/testdata/help-toplevel.golden | 17 +++ client/v2/cli/testdata/help.golden | 9 ++ client/v2/internal/testpb/query.proto | 1 + client/v2/internal/testpb/query.pulsar.go | 122 ++++++++++++++---- 9 files changed, 256 insertions(+), 39 deletions(-) create mode 100644 client/v2/cli/testdata/help-deprecated.golden create mode 100644 client/v2/cli/testdata/help-echo.golden create mode 100644 client/v2/cli/testdata/help-skip.golden create mode 100644 client/v2/cli/testdata/help-toplevel.golden diff --git a/client/v2/cli/query.go b/client/v2/cli/query.go index d177ec195bab..d80d6a0f0cd0 100644 --- a/client/v2/cli/query.go +++ b/client/v2/cli/query.go @@ -56,7 +56,7 @@ func (b *Builder) BuildModuleQueryCommand(moduleName string, cmdDescriptor *auto // AddQueryServiceCommands adds a sub-command to the provided command for each // method in the specified service and returns the command. This can be used in // order to add auto-generated commands to an existing command. -func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor *autocliv1.ServiceCommandDescriptor) error { +func (b *Builder) AddQueryServiceCommands(cmd *cobra.Command, cmdDescriptor *autocliv1.ServiceCommandDescriptor) error { resolver := b.FileResolver if resolver == nil { resolver = protoregistry.GlobalFiles @@ -77,22 +77,24 @@ func (b *Builder) AddQueryServiceCommands(command *cobra.Command, cmdDescriptor methodOpts = option } } - cmd, err := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) + methodCmd, err := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) if err != nil { return err } - if cmd != nil { - command.AddCommand(cmd) + if methodCmd != nil { + cmd.AddCommand(methodCmd) } } - for cmdName, subCmd := range cmdDescriptor.SubCommands { - cmd := topLevelCmd(cmdName, fmt.Sprintf("Querying commands for the %s service", subCmd.Service)) - err = b.AddQueryServiceCommands(cmd, subCmd) + for cmdName, subCmdDesc := range cmdDescriptor.SubCommands { + subCmd := topLevelCmd(cmdName, fmt.Sprintf("Querying commands for the %s service", subCmdDesc.Service)) + err = b.AddQueryServiceCommands(subCmd, subCmdDesc) if err != nil { return err } + + cmd.AddCommand(subCmd) } return nil } diff --git a/client/v2/cli/query_test.go b/client/v2/cli/query_test.go index 8536fc2e86b4..de50ebdfd6fd 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/cli/query_test.go @@ -20,8 +20,14 @@ var testCmdDesc = &autocliv1.ServiceCommandDescriptor{ Service: testpb.Query_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { - RpcMethod: "Echo", - Use: "echo [pos1] [pos2] [pos3...]", + RpcMethod: "Echo", + Use: "echo [pos1] [pos2] [pos3...]", + Version: "1.0", + Alias: []string{"e"}, + SuggestFor: []string{"eco"}, + Example: "echo 1 abc {}", + Short: "echo echos the value provided by the user", + Long: "echo echos the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments", PositionalArgs: []*autocliv1.PositionalArgDescriptor{ { ProtoField: "positional1", @@ -55,6 +61,30 @@ var testCmdDesc = &autocliv1.ServiceCommandDescriptor{ Shorthand: "s", Deprecated: "bad idea", }, + "hidden_bool": { + Hidden: true, + }, + }, + }, + }, + SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{ + // we test the sub-command functionality using the same service with different options + "deprecatedecho": { + Service: testpb.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Echo", + Deprecated: "don't use this", + }, + }, + }, + "skipecho": { + Service: testpb.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Echo", + Skip: true, + }, }, }, }, @@ -148,8 +178,17 @@ func TestOptions(t *testing.T) { } func TestHelp(t *testing.T) { - conn := testExec(t, "echo", "-h") - golden.Assert(t, conn.out.String(), "help.golden") + conn := testExec(t, "-h") + golden.Assert(t, conn.out.String(), "help-toplevel.golden") + + conn = testExec(t, "echo", "-h") + golden.Assert(t, conn.out.String(), "help-echo.golden") + + conn = testExec(t, "deprecatedecho", "echo", "-h") + golden.Assert(t, conn.out.String(), "help-deprecated.golden") + + conn = testExec(t, "skipecho", "-h") + golden.Assert(t, conn.out.String(), "help-skip.golden") } type testClientConn struct { diff --git a/client/v2/cli/testdata/help-deprecated.golden b/client/v2/cli/testdata/help-deprecated.golden new file mode 100644 index 000000000000..110b88129359 --- /dev/null +++ b/client/v2/cli/testdata/help-deprecated.golden @@ -0,0 +1,36 @@ +Command "echo" is deprecated, don't use this +Usage: + test deprecatedecho echo [flags] + +Flags: + --a-bool + --a-coin cosmos.base.v1beta1.Coin (json) + --a-message testpb.AMessage (json) + --an-address bech32 account address key name + --an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified) + --bools bools (default []) + --bz bytesBase64 + --deprecated-field string + --duration duration + --durations duration (repeated) + --enums Enum (unspecified | one | two | five | neg-three) (repeated) + -h, --help help for echo + --hidden-bool + --i-32 int32 + --i-64 int + --page-count-total + --page-key bytesBase64 + --page-limit uint + --page-offset uint + --page-reverse + --positional-1 int32 + --positional-2 string + --positional-3-varargs cosmos.base.v1beta1.Coin (json) (repeated) + --shorthand-deprecated-field string + --some-messages testpb.AMessage (json) (repeated) + --str string + --strings strings + --timestamp timestamp (RFC 3339) + --u-32 uint32 + --u-64 uint + --uints uints (default []) diff --git a/client/v2/cli/testdata/help-echo.golden b/client/v2/cli/testdata/help-echo.golden new file mode 100644 index 000000000000..a12955334690 --- /dev/null +++ b/client/v2/cli/testdata/help-echo.golden @@ -0,0 +1,40 @@ +echo echos the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments + +Usage: + test echo [pos1] [pos2] [pos3...] [flags] + +Aliases: + echo, e + +Examples: +echo 1 abc {} + +Flags: + --a-bool + --a-coin cosmos.base.v1beta1.Coin (json) + --a-message testpb.AMessage (json) + --an-address bech32 account address key name + --an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified) + --bools bools (default []) + --bz bytesBase64 + --deprecated-field string (DEPRECATED: don't use this) + --duration duration + --durations duration (repeated) + --enums Enum (unspecified | one | two | five | neg-three) (repeated) + -h, --help help for echo + --i-32 int32 some random int32 + --i-64 int + --page-count-total + --page-key bytesBase64 + --page-limit uint + --page-offset uint + --page-reverse + -s, --shorthand-deprecated-field string (DEPRECATED: bad idea) + --some-messages testpb.AMessage (json) (repeated) + --str string + --strings strings + --timestamp timestamp (RFC 3339) + --u-64 uint[=5] some random uint64 + -u, --uint32 uint32 some random uint32 + --uints uints (default []) + -v, --version version for echo diff --git a/client/v2/cli/testdata/help-skip.golden b/client/v2/cli/testdata/help-skip.golden new file mode 100644 index 000000000000..a85dbef695ca --- /dev/null +++ b/client/v2/cli/testdata/help-skip.golden @@ -0,0 +1,7 @@ +Querying commands for the testpb.Query service + +Usage: + test skipecho [flags] + +Flags: + -h, --help help for skipecho diff --git a/client/v2/cli/testdata/help-toplevel.golden b/client/v2/cli/testdata/help-toplevel.golden new file mode 100644 index 000000000000..7bab88a556b9 --- /dev/null +++ b/client/v2/cli/testdata/help-toplevel.golden @@ -0,0 +1,17 @@ +Querying commands for the test module + +Usage: + test [flags] + test [command] + +Available Commands: + completion Generate the autocompletion script for the specified shell + deprecatedecho Querying commands for the testpb.Query service + echo echo echos the value provided by the user + help Help about any command + skipecho Querying commands for the testpb.Query service + +Flags: + -h, --help help for test + +Use "test [command] --help" for more information about a command. diff --git a/client/v2/cli/testdata/help.golden b/client/v2/cli/testdata/help.golden index df65ccd4b0b7..a12955334690 100644 --- a/client/v2/cli/testdata/help.golden +++ b/client/v2/cli/testdata/help.golden @@ -1,6 +1,14 @@ +echo echos the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments + Usage: test echo [pos1] [pos2] [pos3...] [flags] +Aliases: + echo, e + +Examples: +echo 1 abc {} + Flags: --a-bool --a-coin cosmos.base.v1beta1.Coin (json) @@ -29,3 +37,4 @@ Flags: --u-64 uint[=5] some random uint64 -u, --uint32 uint32 some random uint32 --uints uints (default []) + -v, --version version for echo diff --git a/client/v2/internal/testpb/query.proto b/client/v2/internal/testpb/query.proto index e781626aadb6..dd5b9b67e5c9 100644 --- a/client/v2/internal/testpb/query.proto +++ b/client/v2/internal/testpb/query.proto @@ -42,6 +42,7 @@ message EchoRequest { string deprecated_field = 30; string shorthand_deprecated_field = 31; + bool hidden_bool = 32; } enum Enum { diff --git a/client/v2/internal/testpb/query.pulsar.go b/client/v2/internal/testpb/query.pulsar.go index a21d6c6bfd4d..e8743333c3d0 100644 --- a/client/v2/internal/testpb/query.pulsar.go +++ b/client/v2/internal/testpb/query.pulsar.go @@ -381,6 +381,7 @@ var ( fd_EchoRequest_positional3_varargs protoreflect.FieldDescriptor fd_EchoRequest_deprecated_field protoreflect.FieldDescriptor fd_EchoRequest_shorthand_deprecated_field protoreflect.FieldDescriptor + fd_EchoRequest_hidden_bool protoreflect.FieldDescriptor ) func init() { @@ -411,6 +412,7 @@ func init() { fd_EchoRequest_positional3_varargs = md_EchoRequest.Fields().ByName("positional3_varargs") fd_EchoRequest_deprecated_field = md_EchoRequest.Fields().ByName("deprecated_field") fd_EchoRequest_shorthand_deprecated_field = md_EchoRequest.Fields().ByName("shorthand_deprecated_field") + fd_EchoRequest_hidden_bool = md_EchoRequest.Fields().ByName("hidden_bool") } var _ protoreflect.Message = (*fastReflection_EchoRequest)(nil) @@ -628,6 +630,12 @@ func (x *fastReflection_EchoRequest) Range(f func(protoreflect.FieldDescriptor, return } } + if x.HiddenBool != false { + value := protoreflect.ValueOfBool(x.HiddenBool) + if !f(fd_EchoRequest_hidden_bool, value) { + return + } + } } // Has reports whether a field is populated. @@ -693,6 +701,8 @@ func (x *fastReflection_EchoRequest) Has(fd protoreflect.FieldDescriptor) bool { return x.DeprecatedField != "" case "testpb.EchoRequest.shorthand_deprecated_field": return x.ShorthandDeprecatedField != "" + case "testpb.EchoRequest.hidden_bool": + return x.HiddenBool != false default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -759,6 +769,8 @@ func (x *fastReflection_EchoRequest) Clear(fd protoreflect.FieldDescriptor) { x.DeprecatedField = "" case "testpb.EchoRequest.shorthand_deprecated_field": x.ShorthandDeprecatedField = "" + case "testpb.EchoRequest.hidden_bool": + x.HiddenBool = false default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -871,6 +883,9 @@ func (x *fastReflection_EchoRequest) Get(descriptor protoreflect.FieldDescriptor case "testpb.EchoRequest.shorthand_deprecated_field": value := x.ShorthandDeprecatedField return protoreflect.ValueOfString(value) + case "testpb.EchoRequest.hidden_bool": + value := x.HiddenBool + return protoreflect.ValueOfBool(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -955,6 +970,8 @@ func (x *fastReflection_EchoRequest) Set(fd protoreflect.FieldDescriptor, value x.DeprecatedField = value.Interface().(string) case "testpb.EchoRequest.shorthand_deprecated_field": x.ShorthandDeprecatedField = value.Interface().(string) + case "testpb.EchoRequest.hidden_bool": + x.HiddenBool = value.Bool() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -1068,6 +1085,8 @@ func (x *fastReflection_EchoRequest) Mutable(fd protoreflect.FieldDescriptor) pr panic(fmt.Errorf("field deprecated_field of message testpb.EchoRequest is not mutable")) case "testpb.EchoRequest.shorthand_deprecated_field": panic(fmt.Errorf("field shorthand_deprecated_field of message testpb.EchoRequest is not mutable")) + case "testpb.EchoRequest.hidden_bool": + panic(fmt.Errorf("field hidden_bool of message testpb.EchoRequest is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -1143,6 +1162,8 @@ func (x *fastReflection_EchoRequest) NewField(fd protoreflect.FieldDescriptor) p return protoreflect.ValueOfString("") case "testpb.EchoRequest.shorthand_deprecated_field": return protoreflect.ValueOfString("") + case "testpb.EchoRequest.hidden_bool": + return protoreflect.ValueOfBool(false) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.EchoRequest")) @@ -1318,6 +1339,9 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { if l > 0 { n += 2 + l + runtime.Sov(uint64(l)) } + if x.HiddenBool { + n += 3 + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -1347,6 +1371,18 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.HiddenBool { + i-- + if x.HiddenBool { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0x80 + } if len(x.ShorthandDeprecatedField) > 0 { i -= len(x.ShorthandDeprecatedField) copy(dAtA[i:], x.ShorthandDeprecatedField) @@ -2548,6 +2584,26 @@ func (x *fastReflection_EchoRequest) ProtoMethods() *protoiface.Methods { } x.ShorthandDeprecatedField = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 32: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field HiddenBool", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + x.HiddenBool = bool(v != 0) default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -3585,6 +3641,7 @@ type EchoRequest struct { Positional3Varargs []*v1beta1.Coin `protobuf:"bytes,29,rep,name=positional3_varargs,json=positional3Varargs,proto3" json:"positional3_varargs,omitempty"` DeprecatedField string `protobuf:"bytes,30,opt,name=deprecated_field,json=deprecatedField,proto3" json:"deprecated_field,omitempty"` ShorthandDeprecatedField string `protobuf:"bytes,31,opt,name=shorthand_deprecated_field,json=shorthandDeprecatedField,proto3" json:"shorthand_deprecated_field,omitempty"` + HiddenBool bool `protobuf:"varint,32,opt,name=hidden_bool,json=hiddenBool,proto3" json:"hidden_bool,omitempty"` } func (x *EchoRequest) Reset() { @@ -3782,6 +3839,13 @@ func (x *EchoRequest) GetShorthandDeprecatedField() string { return "" } +func (x *EchoRequest) GetHiddenBool() bool { + if x != nil { + return x.HiddenBool + } + return false +} + type AMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3875,7 +3939,7 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcf, 0x07, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf0, 0x07, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, @@ -3936,33 +4000,35 @@ var file_testpb_query_proto_rawDesc = []byte{ 0x74, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x2e, 0x0a, 0x08, 0x41, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x62, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x22, 0x3d, 0x0a, 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, - 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x64, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, 0x0a, - 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4f, 0x4e, 0x45, 0x10, - 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x12, - 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x56, 0x45, 0x10, 0x05, 0x12, 0x1b, - 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, 0x47, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x45, - 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x32, 0x3a, 0x0a, 0x05, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x13, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x88, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, - 0x64, 0x6b, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x54, - 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, 0x65, - 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, - 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, + 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x20, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x68, 0x69, 0x64, + 0x64, 0x65, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x22, 0x2e, 0x0a, 0x08, 0x41, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x62, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x7a, 0x22, 0x3d, 0x0a, 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x64, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x14, + 0x0a, 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4f, 0x4e, 0x45, + 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x57, 0x4f, 0x10, 0x02, + 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x56, 0x45, 0x10, 0x05, 0x12, + 0x1b, 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, 0x47, 0x5f, 0x54, 0x48, 0x52, 0x45, + 0x45, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x32, 0x3a, 0x0a, 0x05, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x13, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x63, 0x68, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x88, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, + 0x73, 0x64, 0x6b, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, + 0x54, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, + 0x65, 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, + 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( From 38f31e7c61a0734946098801d8be9ca6020d3b92 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 13 Sep 2022 16:55:23 -0400 Subject: [PATCH 20/25] tests --- client/v2/cli/query.go | 3 ++- client/v2/cli/query_test.go | 33 +++++++++++++++++++++++++++++++-- client/v2/cli/validate.go | 2 ++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/client/v2/cli/query.go b/client/v2/cli/query.go index d80d6a0f0cd0..2e869f92a355 100644 --- a/client/v2/cli/query.go +++ b/client/v2/cli/query.go @@ -16,7 +16,8 @@ import ( ) // BuildQueryCommand builds the query commands for all the provided modules. If a custom command is provided for a -// module, this is used instead of any automatically generated CLI commands. +// module, this is used instead of any automatically generated CLI commands. This allows apps to a fully dynamic client +// with a more customized experience if a binary with custom commands is downloaded. func (b *Builder) BuildQueryCommand(moduleOptions map[string]*autocliv1.ModuleOptions, customCmds map[string]*cobra.Command) (*cobra.Command, error) { queryCmd := topLevelCmd("query", "Querying subcommands") queryCmd.Aliases = []string{"q"} diff --git a/client/v2/cli/query_test.go b/client/v2/cli/query_test.go index de50ebdfd6fd..f8b44beea867 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/cli/query_test.go @@ -7,6 +7,7 @@ import ( "testing" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + "github.com/spf13/cobra" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/testing/protocmp" @@ -95,11 +96,21 @@ func testExec(t *testing.T, args ...string) *testClientConn { testpb.RegisterQueryServer(server, &testEchoServer{}) listener, err := net.Listen("tcp", "127.0.0.1:0") assert.NilError(t, err) - go server.Serve(listener) + go func() { + err := server.Serve(listener) + if err != nil { + panic(err) + } + }() defer server.GracefulStop() clientConn, err := grpc.Dial(listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) assert.NilError(t, err) - defer clientConn.Close() + defer func() { + err := clientConn.Close() + if err != nil { + panic(err) + } + }() conn := &testClientConn{ ClientConn: clientConn, @@ -191,6 +202,24 @@ func TestHelp(t *testing.T) { golden.Assert(t, conn.out.String(), "help-skip.golden") } +func TestBuildCustomQueryCommand(t *testing.T) { + b := &Builder{} + customCommandCalled := false + cmd, err := b.BuildQueryCommand(map[string]*autocliv1.ModuleOptions{ + "test": { + Query: testCmdDesc, + }, + }, map[string]*cobra.Command{ + "test": {Use: "test", Run: func(cmd *cobra.Command, args []string) { + customCommandCalled = true + }}, + }) + assert.NilError(t, err) + cmd.SetArgs([]string{"test", "query"}) + assert.NilError(t, cmd.Execute()) + assert.Assert(t, customCommandCalled) +} + type testClientConn struct { *grpc.ClientConn t *testing.T diff --git a/client/v2/cli/validate.go b/client/v2/cli/validate.go index 158b739fb35b..ddd56a640b44 100644 --- a/client/v2/cli/validate.go +++ b/client/v2/cli/validate.go @@ -8,6 +8,8 @@ import ( "github.com/spf13/cobra" ) +// NOTE: this was copied from client/cmd.go + // ValidateCmd returns unknown command error or Help display if help flag set func ValidateCmd(cmd *cobra.Command, args []string) error { var unknownCmd string From 5ff5c3d42deb4dd84cfdb199fa2f9a1e80102156 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Wed, 14 Sep 2022 15:44:52 -0400 Subject: [PATCH 21/25] simplify API --- client/v2/cli/flag/field.go | 6 +++--- client/v2/cli/flag/pagination.go | 4 ++-- client/v2/cli/flag/register.go | 8 ++++++-- client/v2/cli/query.go | 4 +--- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/client/v2/cli/flag/field.go b/client/v2/cli/flag/field.go index d841b82fe1c2..0337aebdd4bd 100644 --- a/client/v2/cli/flag/field.go +++ b/client/v2/cli/flag/field.go @@ -12,14 +12,14 @@ import ( "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) -// Options specifies options for specific flags. -type Options struct { +// namingOptions specifies internal naming options for flags. +type namingOptions struct { // Prefix is a prefix to prepend to all flags. Prefix string } // addFieldFlag adds a flag for the provided field to the flag set. -func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options Options) (name string, hasValue HasValue, err error) { +func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor, opts *autocliv1.FlagOptions, options namingOptions) (name string, hasValue HasValue, err error) { if opts == nil { opts = &autocliv1.FlagOptions{} } diff --git a/client/v2/cli/flag/pagination.go b/client/v2/cli/flag/pagination.go index c935a2aad742..376aa2d6de21 100644 --- a/client/v2/cli/flag/pagination.go +++ b/client/v2/cli/flag/pagination.go @@ -11,11 +11,11 @@ import ( ) func (b *Builder) bindPageRequest(ctx context.Context, flagSet *pflag.FlagSet, field protoreflect.FieldDescriptor) (HasValue, error) { - return b.AddMessageFlags( + return b.addMessageFlags( ctx, flagSet, util.ResolveMessageType(b.TypeResolver, field.Message()), &autocliv1.RpcCommandOptions{}, - Options{Prefix: "page-"}, + namingOptions{Prefix: "page-"}, ) } diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index fa4da5ffba15..918759ec05a1 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -10,8 +10,12 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) +func (b *Builder) AddMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions) (*MessageBinder, error) { + return b.addMessageFlags(ctx, flagSet, messageType, commandOptions, namingOptions{}) +} + // AddMessageFlags adds flags for each field in the message to the flag set. -func (b *Builder) AddMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options Options) (*MessageBinder, error) { +func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options namingOptions) (*MessageBinder, error) { fields := messageType.Descriptor().Fields() numFields := fields.Len() handler := &MessageBinder{ @@ -44,7 +48,7 @@ func (b *Builder) AddMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m handler.positionalFlagSet, field, &autocliv1.FlagOptions{Name: fmt.Sprintf("%d", i)}, - Options{}, + namingOptions{}, ) if err != nil { return nil, err diff --git a/client/v2/cli/query.go b/client/v2/cli/query.go index 2e869f92a355..57f3c1e21645 100644 --- a/client/v2/cli/query.go +++ b/client/v2/cli/query.go @@ -10,8 +10,6 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" - "github.com/cosmos/cosmos-sdk/client/v2/cli/flag" - "github.com/cosmos/cosmos-sdk/client/v2/internal/util" ) @@ -142,7 +140,7 @@ func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescrip Version: options.Version, } - binder, err := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, options, flag.Options{}) + binder, err := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, options) if err != nil { return nil, err } From 81dd21020e3287c59ec27b6e7ffc6221bc35f6da Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Wed, 14 Sep 2022 15:58:24 -0400 Subject: [PATCH 22/25] proper validation --- client/v2/cli/{validate.go => cmd.go} | 4 +-- client/v2/cli/flag/register.go | 7 +++++ client/v2/cli/query.go | 29 ++++++++++------- client/v2/cli/query_test.go | 45 +++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 13 deletions(-) rename client/v2/cli/{validate.go => cmd.go} (90%) diff --git a/client/v2/cli/validate.go b/client/v2/cli/cmd.go similarity index 90% rename from client/v2/cli/validate.go rename to client/v2/cli/cmd.go index ddd56a640b44..0f4b7d2457c7 100644 --- a/client/v2/cli/validate.go +++ b/client/v2/cli/cmd.go @@ -10,8 +10,8 @@ import ( // NOTE: this was copied from client/cmd.go -// ValidateCmd returns unknown command error or Help display if help flag set -func ValidateCmd(cmd *cobra.Command, args []string) error { +// validateCmd returns unknown command error or Help display if help flag set +func validateCmd(cmd *cobra.Command, args []string) error { var unknownCmd string var skipNext bool diff --git a/client/v2/cli/flag/register.go b/client/v2/cli/flag/register.go index 918759ec05a1..cc18df69b6e7 100644 --- a/client/v2/cli/flag/register.go +++ b/client/v2/cli/flag/register.go @@ -67,6 +67,13 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m handler.CobraArgs = cobra.ExactArgs(n) } + // validate flag options + for name := range commandOptions.FlagOptions { + if fields.ByName(protoreflect.Name(name)) == nil { + return nil, fmt.Errorf("can't find field %s on %s specified as a flag", name, messageType.Descriptor().FullName()) + } + } + flagOptsByFlagName := map[string]*autocliv1.FlagOptions{} for i := 0; i < numFields; i++ { field := fields.Get(i) diff --git a/client/v2/cli/query.go b/client/v2/cli/query.go index 57f3c1e21645..3f93c24d58df 100644 --- a/client/v2/cli/query.go +++ b/client/v2/cli/query.go @@ -62,21 +62,27 @@ func (b *Builder) AddQueryServiceCommands(cmd *cobra.Command, cmdDescriptor *aut } descriptor, err := resolver.FindDescriptorByName(protoreflect.FullName(cmdDescriptor.Service)) if err != nil { - panic(err) + return fmt.Errorf("can't find service %s: %v", cmdDescriptor.Service, err) } service := descriptor.(protoreflect.ServiceDescriptor) methods := service.Methods() + + rpcOptMap := map[protoreflect.Name]*autocliv1.RpcCommandOptions{} + for _, option := range cmdDescriptor.RpcCommandOptions { + name := protoreflect.Name(option.RpcMethod) + rpcOptMap[name] = option + // make sure method exists + if m := methods.ByName(name); m == nil { + return fmt.Errorf("rpc method %s not found for service %s", name, service.FullName()) + } + } + n := methods.Len() for i := 0; i < n; i++ { methodDescriptor := methods.Get(i) - var methodOpts *autocliv1.RpcCommandOptions - for _, option := range cmdDescriptor.RpcCommandOptions { - if protoreflect.Name(option.RpcMethod) == methodDescriptor.Name() { - methodOpts = option - } - } - methodCmd, err := b.CreateQueryMethodCommand(methodDescriptor, methodOpts) + methodOpts := rpcOptMap[methodDescriptor.Name()] + methodCmd, err := b.BuildQueryMethodCommand(methodDescriptor, methodOpts) if err != nil { return err } @@ -95,12 +101,13 @@ func (b *Builder) AddQueryServiceCommands(cmd *cobra.Command, cmdDescriptor *aut cmd.AddCommand(subCmd) } + return nil } -// CreateQueryMethodCommand creates a gRPC query command for the given service method. This can be used to auto-generate +// BuildQueryMethodCommand creates a gRPC query command for the given service method. This can be used to auto-generate // just a single command for a single service rpc method. -func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) (*cobra.Command, error) { +func (b *Builder) BuildQueryMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) (*cobra.Command, error) { if options == nil { // use the defaults options = &autocliv1.RpcCommandOptions{} @@ -191,6 +198,6 @@ func topLevelCmd(use, short string) *cobra.Command { Short: short, DisableFlagParsing: false, SuggestionsMinimumDistance: 2, - RunE: ValidateCmd, + RunE: validateCmd, } } diff --git a/client/v2/cli/query_test.go b/client/v2/cli/query_test.go index f8b44beea867..24712a81ffdb 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/cli/query_test.go @@ -220,6 +220,51 @@ func TestBuildCustomQueryCommand(t *testing.T) { assert.Assert(t, customCommandCalled) } +func TestNotFoundErrors(t *testing.T) { + b := &Builder{} + + // bad service + _, err := b.BuildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{Service: "foo"}) + assert.ErrorContains(t, err, "can't find service foo") + + // bad method + _, err = b.BuildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{ + Service: testpb.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{{RpcMethod: "bar"}}, + }) + assert.ErrorContains(t, err, "rpc method bar not found") + + // bad positional field + _, err = b.BuildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{ + Service: testpb.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Echo", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + { + ProtoField: "foo", + }, + }, + }, + }, + }) + assert.ErrorContains(t, err, "can't find field foo") + + // bad flag field + _, err = b.BuildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{ + Service: testpb.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Echo", + FlagOptions: map[string]*autocliv1.FlagOptions{ + "baz": {}, + }, + }, + }, + }) + assert.ErrorContains(t, err, "can't find field baz") +} + type testClientConn struct { *grpc.ClientConn t *testing.T From 19b5b5b517529f30988b5c744e4c2e2c9f7359e0 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 27 Sep 2022 09:43:25 -0400 Subject: [PATCH 23/25] fix import --- client/v2/cli/flag/message_json.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/v2/cli/flag/message_json.go b/client/v2/cli/flag/message_json.go index 76366dda1804..69b0d69fea43 100644 --- a/client/v2/cli/flag/message_json.go +++ b/client/v2/cli/flag/message_json.go @@ -8,7 +8,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" - "github.com/cosmos/cosmos-sdk/client/v2/internal/util" + "cosmossdk.io/client/v2/internal/util" ) type jsonMessageFlagType struct { From fb9312b98035e97a9cf7cb32381c2383932e059b Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 10 Oct 2022 15:57:28 -0400 Subject: [PATCH 24/25] address review comments --- client/v2/cli/cmd.go | 3 ++- client/v2/cli/query_test.go | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/client/v2/cli/cmd.go b/client/v2/cli/cmd.go index 0f4b7d2457c7..69011c5f5a00 100644 --- a/client/v2/cli/cmd.go +++ b/client/v2/cli/cmd.go @@ -8,7 +8,8 @@ import ( "github.com/spf13/cobra" ) -// NOTE: this was copied from client/cmd.go +// NOTE: this was copied from client/cmd.go to avoid introducing a dependency +// on the v1 client package. // validateCmd returns unknown command error or Help display if help flag set func validateCmd(cmd *cobra.Command, args []string) error { diff --git a/client/v2/cli/query_test.go b/client/v2/cli/query_test.go index c0915b55a8ab..3d4c71550c35 100644 --- a/client/v2/cli/query_test.go +++ b/client/v2/cli/query_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "net" + "strings" "testing" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" @@ -202,6 +203,18 @@ func TestHelp(t *testing.T) { golden.Assert(t, conn.out.String(), "help-skip.golden") } +func TestDeprecated(t *testing.T) { + conn := testExec(t, "echo", + "1", "abc", `{}`, + "--deprecated-field", "foo") + assert.Assert(t, strings.Contains(conn.out.String(), "--deprecated-field has been deprecated")) + + conn = testExec(t, "echo", + "1", "abc", `{}`, + "-s", "foo") + assert.Assert(t, strings.Contains(conn.out.String(), "--shorthand-deprecated-field has been deprecated")) +} + func TestBuildCustomQueryCommand(t *testing.T) { b := &Builder{} customCommandCalled := false From 1782e7b32a0b8d47e977d10c3dde056e7cea1ae9 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Mon, 10 Oct 2022 16:05:20 -0400 Subject: [PATCH 25/25] address review comments --- client/v2/cli/flag/value.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/v2/cli/flag/value.go b/client/v2/cli/flag/value.go index 8a62253f75d3..e42c524d7859 100644 --- a/client/v2/cli/flag/value.go +++ b/client/v2/cli/flag/value.go @@ -5,11 +5,17 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) +// Value represents a single pflag.Value value. type Value interface { pflag.Value HasValue } +// HasValue wraps a reference to a protobuf value. type HasValue interface { - Get(mutable protoreflect.Value) (protoreflect.Value, error) + // Get gets the value of the protobuf value reference and returns that value + // or an error. For composite protoreflect.Value types such as messages, + // lists and maps, a mutable reference to the value of field obtained with + // protoreflect.Message.NewField should be passed as the newFieldValue parameter. + Get(newFieldValue protoreflect.Value) (protoreflect.Value, error) }