token := t.peekNonSpace()
pos := token.pos
// Are there declarations or assignments?
+ // TODO(mvdan): simplify the loop break/continue logic
for {
if v := t.peekNonSpace(); v.typ == itemVariable {
t.next()
}
if next.typ == itemChar && next.val == "," {
if context == "range" && len(vars) < 2 {
- continue
+ switch t.peekNonSpace().typ {
+ case itemVariable, itemRightDelim, itemRightParen:
+ continue
+ default:
+ t.errorf("range can only initialize variables")
+ }
}
t.errorf("too many declarations in %s", context)
}
{"multilinerawstring",
"{{ $v := `\n` }} {{",
hasError, `multilinerawstring:2: unexpected unclosed action`},
+ {"rangeundefvar",
+ "{{range $k}}{{end}}",
+ hasError, `undefined variable`},
+ {"rangeundefvars",
+ "{{range $k, $v}}{{end}}",
+ hasError, `undefined variable`},
+ {"rangemissingvalue1",
+ "{{range $k,}}{{end}}",
+ hasError, `missing value for range`},
+ {"rangemissingvalue2",
+ "{{range $k, $v := }}{{end}}",
+ hasError, `missing value for range`},
+ {"rangenotvariable1",
+ "{{range $k, .}}{{end}}",
+ hasError, `range can only initialize variables`},
+ {"rangenotvariable2",
+ "{{range $k, 123 := .}}{{end}}",
+ hasError, `range can only initialize variables`},
}
func TestErrors(t *testing.T) {
for _, test := range errorTests {
- _, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree))
- if err == nil {
- t.Errorf("%q: expected error", test.name)
- continue
- }
- if !strings.Contains(err.Error(), test.result) {
- t.Errorf("%q: error %q does not contain %q", test.name, err, test.result)
- }
+ t.Run(test.name, func(t *testing.T) {
+ _, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree))
+ if err == nil {
+ t.Fatalf("expected error %q, got nil", test.result)
+ }
+ if !strings.Contains(err.Error(), test.result) {
+ t.Fatalf("error %q does not contain %q", err, test.result)
+ }
+ })
}
}