Skip to content

Commit

Permalink
fix: #3390 name&shor tag mapping failed to command input object for p…
Browse files Browse the repository at this point in the history
…ackage gcmd
  • Loading branch information
gqcn committed Mar 26, 2024
1 parent 8669512 commit 8c1db29
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 3 deletions.
37 changes: 34 additions & 3 deletions os/gcmd/gcmd_command_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ func newCommandFromMethod(
return
}

// Options creating.
var paramKeyToAttrMap map[string]string
if paramKeyToAttrMap, err = newTagToAttrMappingFromInput(inputObject.Interface()); err != nil {
return
}

// =============================================================================================
// Create function that has value return.
// =============================================================================================
Expand Down Expand Up @@ -278,8 +284,11 @@ func newCommandFromMethod(
if arg.Orphan {
if orphanValue := parser.GetOpt(arg.Name); orphanValue != nil {
if orphanValue.String() == "" {
// Eg: gf -f
// Example: gf -f
data[arg.Name] = "true"
if arg.Short != "" {
data[arg.Short] = "true"
}
} else {
// Adapter with common user habits.
// Eg:
Expand All @@ -301,9 +310,9 @@ func newCommandFromMethod(
return fmt.Sprintf(`input command data map: %s`, gjson.MustEncode(data))
})
if inputObject.Kind() == reflect.Ptr {
err = gconv.Scan(data, inputObject.Interface())
err = gconv.Scan(data, inputObject.Interface(), paramKeyToAttrMap)
} else {
err = gconv.Struct(data, inputObject.Addr().Interface())
err = gconv.Struct(data, inputObject.Addr().Interface(), paramKeyToAttrMap)
}
intlog.PrintFunc(ctx, func() string {
return fmt.Sprintf(`input object assigned data: %s`, gjson.MustEncode(inputObject.Interface()))
Expand Down Expand Up @@ -333,6 +342,28 @@ func newCommandFromMethod(
return
}

func newTagToAttrMappingFromInput(object interface{}) (paramKeyToAttrMap map[string]string, err error) {
var fields []gstructs.Field
fields, err = gstructs.Fields(gstructs.FieldsInput{
Pointer: object,
RecursiveOption: gstructs.RecursiveOptionEmbeddedNoTag,
})
paramKeyToAttrMap = make(map[string]string)
for _, field := range fields {
var (
nameValue = field.Tag(tagNameName)
shortValue = field.Tag(tagNameShort)
)
if nameValue != "" {
paramKeyToAttrMap[nameValue] = field.Name()
}
if shortValue != "" {
paramKeyToAttrMap[shortValue] = field.Name()
}
}
return
}

func newArgumentsFromInput(object interface{}) (args []Argument, err error) {
var (
fields []gstructs.Field
Expand Down
101 changes: 101 additions & 0 deletions os/gcmd/gcmd_z_unit_issue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

// go test *.go -bench=".*" -benchmem

package gcmd_test

import (
"context"
"testing"

"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/test/gtest"
)

type Issue3390CommandCase1 struct {
*gcmd.Command
}

type Issue3390TestCase1 struct {
g.Meta `name:"index" ad:"test"`
}

type Issue3390Case1Input struct {
g.Meta `name:"index"`
A string `short:"a" name:"aa"`
Be string `short:"b" name:"bb"`
}

type Issue3390Case1Output struct {
Content string
}

func (c Issue3390TestCase1) Index(ctx context.Context, in Issue3390Case1Input) (out *Issue3390Case1Output, err error) {
out = &Issue3390Case1Output{
Content: gjson.MustEncodeString(in),
}
return
}

func Test_Issue3390_Case1(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
root, err := gcmd.NewFromObject(Issue3390TestCase1{})
if err != nil {
panic(err)
}
command := &Issue3390CommandCase1{root}
value, err := command.RunWithSpecificArgs(
gctx.New(),
[]string{"main", "-a", "aaa", "-b", "bbb"},
)
t.AssertNil(err)
t.Assert(value.(*Issue3390Case1Output).Content, `{"A":"aaa","Be":"bbb"}`)
})
}

type Issue3390CommandCase2 struct {
*gcmd.Command
}

type Issue3390TestCase2 struct {
g.Meta `name:"index" ad:"test"`
}

type Issue3390Case2Input struct {
g.Meta `name:"index"`
A string `short:"b" name:"bb"`
Be string `short:"a" name:"aa"`
}

type Issue3390Case2Output struct {
Content string
}

func (c Issue3390TestCase2) Index(ctx context.Context, in Issue3390Case2Input) (out *Issue3390Case2Output, err error) {
out = &Issue3390Case2Output{
Content: gjson.MustEncodeString(in),
}
return
}
func Test_Issue3390_Case2(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
root, err := gcmd.NewFromObject(Issue3390TestCase2{})
if err != nil {
panic(err)
}
command := &Issue3390CommandCase2{root}
value, err := command.RunWithSpecificArgs(
gctx.New(),
[]string{"main", "-a", "aaa", "-b", "bbb"},
)
t.AssertNil(err)
t.Assert(value.(*Issue3390Case2Output).Content, `{"A":"bbb","Be":"aaa"}`)
})
}

0 comments on commit 8c1db29

Please sign in to comment.