]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
tpl/collections: Fix append when appending a slice to a slice of slices
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 14 Jun 2023 07:00:28 +0000 (09:00 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 14 Jun 2023 18:18:54 +0000 (20:18 +0200)
Fixes #11093

common/collections/append.go
common/collections/append_test.go
tpl/collections/integration_test.go

index a9c14c1aa1d18e031ad1d9d19c1966bb4ea51fe5..fe8792fc421d390e73f6a37d4a59bf3670669d1d 100644 (file)
@@ -22,6 +22,9 @@ import (
 // If length of from is one and the only element is a slice of same type as to,
 // it will be appended.
 func Append(to any, from ...any) (any, error) {
+       if len(from) == 0 {
+               return to, nil
+       }
        tov, toIsNil := indirect(reflect.ValueOf(to))
 
        toIsNil = toIsNil || to == nil
@@ -33,18 +36,39 @@ func Append(to any, from ...any) (any, error) {
                }
 
                tot = tov.Type().Elem()
+               if tot.Kind() == reflect.Slice {
+                       totvt := tot.Elem()
+                       fromvs := make([]reflect.Value, len(from))
+                       for i, f := range from {
+                               fromv := reflect.ValueOf(f)
+                               fromt := fromv.Type()
+                               if fromt.Kind() == reflect.Slice {
+                                       fromt = fromt.Elem()
+                               }
+                               if totvt != fromt {
+                                       return nil, fmt.Errorf("cannot append slice of %s to slice of %s", fromt, totvt)
+                               } else {
+                                       fromvs[i] = fromv
+                               }
+                       }
+                       return reflect.Append(tov, fromvs...).Interface(), nil
+
+               }
+
                toIsNil = tov.Len() == 0
 
                if len(from) == 1 {
                        fromv := reflect.ValueOf(from[0])
+                       fromt := fromv.Type()
+                       if fromt.Kind() == reflect.Slice {
+                               fromt = fromt.Elem()
+                       }
                        if fromv.Kind() == reflect.Slice {
                                if toIsNil {
                                        // If we get nil []string, we just return the []string
                                        return from[0], nil
                                }
 
-                               fromt := reflect.TypeOf(from[0]).Elem()
-
                                // If we get []string []string, we append the from slice to to
                                if tot == fromt {
                                        return reflect.AppendSlice(tov, fromv).Interface(), nil
@@ -52,6 +76,7 @@ func Append(to any, from ...any) (any, error) {
                                        // Fall back to a []interface{} slice.
                                        return appendToInterfaceSliceFromValues(tov, fromv)
                                }
+
                        }
                }
        }
index 6df32fee68dd6b6319cf785f1b2ad41374be8fef..f997e7a20b0a01d8745f8fac7bb59016d8ee0fdf 100644 (file)
@@ -24,7 +24,7 @@ func TestAppend(t *testing.T) {
        t.Parallel()
        c := qt.New(t)
 
-       for _, test := range []struct {
+       for i, test := range []struct {
                start    any
                addend   []any
                expected any
@@ -85,6 +85,47 @@ func TestAppend(t *testing.T) {
                }
 
                c.Assert(err, qt.IsNil)
-               c.Assert(result, qt.DeepEquals, test.expected)
+               c.Assert(result, qt.DeepEquals, test.expected, qt.Commentf("test: [%d] %v", i, test))
        }
 }
+
+// #11093
+func TestAppendToMultiDimensionalSlice(t *testing.T) {
+       t.Parallel()
+       c := qt.New(t)
+
+       for _, test := range []struct {
+               to       any
+               from     []any
+               expected any
+       }{
+               {[][]string{{"a", "b"}},
+                       []any{[]string{"c", "d"}},
+                       [][]string{
+                               {"a", "b"},
+                               {"c", "d"},
+                       },
+               },
+               {[][]string{{"a", "b"}},
+                       []any{[]string{"c", "d"}, []string{"e", "f"}},
+                       [][]string{
+                               {"a", "b"},
+                               {"c", "d"},
+                               {"e", "f"},
+                       },
+               },
+               {[][]string{{"a", "b"}},
+                       []any{[]int{1, 2}},
+                       false,
+               },
+       } {
+               result, err := Append(test.to, test.from...)
+               if b, ok := test.expected.(bool); ok && !b {
+                       c.Assert(err, qt.Not(qt.IsNil))
+               } else {
+                       c.Assert(err, qt.IsNil)
+                       c.Assert(result, qt.DeepEquals, test.expected)
+               }
+       }
+
+}
index 225eab9faca5b2597bcee41d69fd3fbbd5a4d2b5..da1d6e488a628f2e5f29a10a541d9156320f03b3 100644 (file)
@@ -73,3 +73,34 @@ Desc: [map[a:3 b:3] map[a:3 b:1] map[a:3 b:1] map[a:3 b:1] map[a:3 b:0] map[a:3
 
        }
 }
+
+// Issue #11004.
+func TestAppendSliceToASliceOfSlices(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+-- layouts/index.html --
+{{ $obj := slice (slice "a") }}
+{{ $obj = $obj | append (slice "b") }}
+{{ $obj = $obj | append (slice "c") }}
+
+{{ $obj }}
+
+
+  `
+
+       for i := 0; i < 4; i++ {
+
+               b := hugolib.NewIntegrationTestBuilder(
+                       hugolib.IntegrationTestConfig{
+                               T:           t,
+                               TxtarString: files,
+                       },
+               ).Build()
+
+               b.AssertFileContent("public/index.html", "[[a] [b] [c]]")
+
+       }
+
+}