Skip to content

Commit

Permalink
tpl/collections: Fix some index cases where the indices given is a sl…
Browse files Browse the repository at this point in the history
…ice and be more lenient with nil inputs

See adjusted tests for detail.

Fixes #10489
  • Loading branch information
bep committed Dec 3, 2022
1 parent 7d5e3ab commit d373774
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 12 deletions.
22 changes: 13 additions & 9 deletions tpl/collections/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,9 @@ import (
func (ns *Namespace) Index(item any, args ...any) (any, error) {
v := reflect.ValueOf(item)
if !v.IsValid() {
return nil, errors.New("index of untyped nil")
}

lowerm, ok := item.(maps.Params)
if ok {
return lowerm.Get(cast.ToStringSlice(args)...), nil
// See issue 10489
// This used to be an error.
return nil, nil
}

var indices []any
Expand All @@ -51,18 +48,25 @@ func (ns *Namespace) Index(item any, args ...any) (any, error) {
for i := 0; i < v.Len(); i++ {
indices = append(indices, v.Index(i).Interface())
}
} else {
indices = append(indices, args[0])
}
} else {
indices = args
}

if indices == nil {
indices = args
lowerm, ok := item.(maps.Params)
if ok {
return lowerm.Get(cast.ToStringSlice(indices)...), nil
}

for _, i := range indices {
index := reflect.ValueOf(i)
var isNil bool
if v, isNil = indirect(v); isNil {
return nil, errors.New("index of nil pointer")
// See issue 10489
// This used to be an error.
return nil, nil
}
switch v.Kind() {
case reflect.Array, reflect.Slice, reflect.String:
Expand Down
31 changes: 28 additions & 3 deletions tpl/collections/index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func TestIndex(t *testing.T) {
c := qt.New(t)
ns := New(&deps.Deps{Language: langs.NewDefaultLanguage(config.New())})

var (
emptyInterface any
nilPointer *int
)

for i, test := range []struct {
item any
indices []any
Expand All @@ -45,16 +50,23 @@ func TestIndex(t *testing.T) {
{map[string]map[string]string{"a": {"b": "c"}}, []any{"a", "b"}, "c", false},
{[]map[string]map[string]string{{"a": {"b": "c"}}}, []any{0, "a", "b"}, "c", false},
{map[string]map[string]any{"a": {"b": []string{"c", "d"}}}, []any{"a", "b", 1}, "d", false},
{map[string]map[string]string{"a": {"b": "c"}}, []any{[]string{"a", "b"}}, "c", false},
{maps.Params{"a": "av"}, []any{"A"}, "av", false},
{maps.Params{"a": map[string]any{"b": "bv"}}, []any{"A", "B"}, "bv", false},

// These used to be errors.
// See issue 10489.
{nil, nil, nil, false},
{nil, []any{0}, nil, false},
{emptyInterface, []any{0}, nil, false},
{nilPointer, []any{0}, nil, false},

// errors
{nil, nil, nil, true},
{[]int{0, 1}, []any{"1"}, nil, true},
{[]int{0, 1}, []any{nil}, nil, true},
{tstNoStringer{}, []any{0}, nil, true},
} {
c.Run(fmt.Sprint(i), func(c *qt.C) {

c.Run(fmt.Sprintf("vararg %d", i), func(c *qt.C) {
errMsg := qt.Commentf("[%d] %v", i, test)

result, err := ns.Index(test.item, test.indices...)
Expand All @@ -66,5 +78,18 @@ func TestIndex(t *testing.T) {
c.Assert(err, qt.IsNil, errMsg)
c.Assert(result, qt.DeepEquals, test.expect, errMsg)
})

c.Run(fmt.Sprintf("slice %d", i), func(c *qt.C) {
errMsg := qt.Commentf("[%d] %v", i, test)

result, err := ns.Index(test.item, test.indices)

if test.isErr {
c.Assert(err, qt.Not(qt.IsNil), errMsg)
return
}
c.Assert(err, qt.IsNil, errMsg)
c.Assert(result, qt.DeepEquals, test.expect, errMsg)
})
}
}

0 comments on commit d373774

Please sign in to comment.