mirror of
https://github.com/golang/go
synced 2024-11-21 21:14:47 -07:00
text/template: support range-over-int
Fixes #66107 Change-Id: I19b466e3fb17557cf4f198b7fd8c13e774d854b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/615095 Auto-Submit: Ian Lance Taylor <iant@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Carlos Amedee <carlos@golang.org> Commit-Queue: Ian Lance Taylor <iant@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
b7e4d2067c
commit
712d47ce15
@ -1 +1 @@
|
||||
Templates now support range-over-func.
|
||||
Templates now support range-over-func and range-over-int.
|
||||
|
@ -99,7 +99,7 @@ data, defined in detail in the corresponding sections that follow.
|
||||
|
||||
{{range pipeline}} T1 {{end}}
|
||||
The value of the pipeline must be an array, slice, map, iter.Seq,
|
||||
iter.Seq2 or channel.
|
||||
iter.Seq2, integer or channel.
|
||||
If the value of the pipeline has length zero, nothing is output;
|
||||
otherwise, dot is set to the successive elements of the array,
|
||||
slice, or map and T1 is executed. If the value is a map and the
|
||||
@ -108,7 +108,7 @@ data, defined in detail in the corresponding sections that follow.
|
||||
|
||||
{{range pipeline}} T1 {{else}} T0 {{end}}
|
||||
The value of the pipeline must be an array, slice, map, iter.Seq,
|
||||
iter.Seq2 or channel.
|
||||
iter.Seq2, integer or channel.
|
||||
If the value of the pipeline has length zero, dot is unaffected and
|
||||
T0 is executed; otherwise, dot is set to the successive elements
|
||||
of the array, slice, or map and T1 is executed.
|
||||
|
@ -395,6 +395,22 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
|
||||
s.walk(elem, r.List)
|
||||
}
|
||||
switch val.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
if len(r.Pipe.Decl) > 1 {
|
||||
s.errorf("can't use %s to iterate over more than one variable", val)
|
||||
break
|
||||
}
|
||||
run := false
|
||||
for v := range val.Seq() {
|
||||
run = true
|
||||
// Pass element as second value, as we do for channels.
|
||||
oneIteration(reflect.Value{}, v)
|
||||
}
|
||||
if !run {
|
||||
break
|
||||
}
|
||||
return
|
||||
case reflect.Array, reflect.Slice:
|
||||
if val.Len() == 0 {
|
||||
break
|
||||
|
@ -613,6 +613,19 @@ var execTests = []execTest{
|
||||
{"i,x range iter.Seq[int]", `{{$i := 0}}{{$x := 0}}{{range $i = .}}{{$i}}{{end}}`, "01", fVal1(2), true},
|
||||
{"range iter.Seq[int] else", `{{range $i := .}}{{$i}}{{else}}empty{{end}}`, "empty", fVal1(0), true},
|
||||
{"range iter.Seq2[int,int] else", `{{range $i := .}}{{$i}}{{else}}empty{{end}}`, "empty", fVal2(0), true},
|
||||
{"range int8", rangeTestInt, rangeTestData[int8](), int8(5), true},
|
||||
{"range int16", rangeTestInt, rangeTestData[int16](), int16(5), true},
|
||||
{"range int32", rangeTestInt, rangeTestData[int32](), int32(5), true},
|
||||
{"range int64", rangeTestInt, rangeTestData[int64](), int64(5), true},
|
||||
{"range int", rangeTestInt, rangeTestData[int](), int(5), true},
|
||||
{"range uint8", rangeTestInt, rangeTestData[uint8](), uint8(5), true},
|
||||
{"range uint16", rangeTestInt, rangeTestData[uint16](), uint16(5), true},
|
||||
{"range uint32", rangeTestInt, rangeTestData[uint32](), uint32(5), true},
|
||||
{"range uint64", rangeTestInt, rangeTestData[uint64](), uint64(5), true},
|
||||
{"range uint", rangeTestInt, rangeTestData[uint](), uint(5), true},
|
||||
{"range uintptr", rangeTestInt, rangeTestData[uintptr](), uintptr(5), true},
|
||||
{"range uintptr(0)", `{{range $v := .}}{{print $v}}{{else}}empty{{end}}`, "empty", uintptr(0), true},
|
||||
{"range 5", `{{range $v := 5}}{{printf "%T%d" $v $v}}{{end}}`, rangeTestData[int](), nil, true},
|
||||
|
||||
// Cute examples.
|
||||
{"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true},
|
||||
@ -737,6 +750,17 @@ func fVal2(i int) iter.Seq2[int, int] {
|
||||
}
|
||||
}
|
||||
|
||||
const rangeTestInt = `{{range $v := .}}{{printf "%T%d" $v $v}}{{end}}`
|
||||
|
||||
func rangeTestData[T int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr]() string {
|
||||
I := T(5)
|
||||
var buf strings.Builder
|
||||
for i := T(0); i < I; i++ {
|
||||
fmt.Fprintf(&buf, "%T%d", i, i)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func zeroArgs() string {
|
||||
return "zeroArgs"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user