mirror of
https://github.com/golang/go
synced 2024-11-19 01:04:40 -07:00
text/template: emit field error over nil pointer error where appropriate
When evaluating "{{.MissingField}}" on a nil *T, Exec returns "can't evaluate field MissingField in type *T" instead of "nil pointer evaluating *T.MissingField". Fixes golang/go#15125 Change-Id: I6e73f61b8a72c694179c1f8cdc808766c90b6f57 Reviewed-on: https://go-review.googlesource.com/21705 Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
0004f34cef
commit
0fd270ab7a
@ -538,14 +538,14 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
|
|||||||
return s.evalCall(dot, method, node, fieldName, args, final)
|
return s.evalCall(dot, method, node, fieldName, args, final)
|
||||||
}
|
}
|
||||||
hasArgs := len(args) > 1 || final.IsValid()
|
hasArgs := len(args) > 1 || final.IsValid()
|
||||||
// It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
|
// It's not a method; must be a field of a struct or an element of a map.
|
||||||
if isNil {
|
|
||||||
s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
|
|
||||||
}
|
|
||||||
switch receiver.Kind() {
|
switch receiver.Kind() {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
tField, ok := receiver.Type().FieldByName(fieldName)
|
tField, ok := receiver.Type().FieldByName(fieldName)
|
||||||
if ok {
|
if ok {
|
||||||
|
if isNil {
|
||||||
|
s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
|
||||||
|
}
|
||||||
field := receiver.FieldByIndex(tField.Index)
|
field := receiver.FieldByIndex(tField.Index)
|
||||||
if tField.PkgPath != "" { // field is unexported
|
if tField.PkgPath != "" { // field is unexported
|
||||||
s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
|
s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
|
||||||
@ -556,8 +556,10 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
|
|||||||
}
|
}
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
s.errorf("%s is not a field of struct type %s", fieldName, typ)
|
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
|
if isNil {
|
||||||
|
s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
|
||||||
|
}
|
||||||
// If it's a map, attempt to use the field name as a key.
|
// If it's a map, attempt to use the field name as a key.
|
||||||
nameVal := reflect.ValueOf(fieldName)
|
nameVal := reflect.ValueOf(fieldName)
|
||||||
if nameVal.Type().AssignableTo(receiver.Type().Key()) {
|
if nameVal.Type().AssignableTo(receiver.Type().Key()) {
|
||||||
|
@ -1280,3 +1280,20 @@ func TestBlock(t *testing.T) {
|
|||||||
t.Errorf("got %q, want %q", got, want2)
|
t.Errorf("got %q, want %q", got, want2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that calling an invalid field on nil pointer prints
|
||||||
|
// a field error instead of a distracting nil pointer error.
|
||||||
|
// https://golang.org/issue/15125
|
||||||
|
func TestMissingFieldOnNil(t *testing.T) {
|
||||||
|
tmpl := Must(New("tmpl").Parse("{{.MissingField}}"))
|
||||||
|
var d *T
|
||||||
|
err := tmpl.Execute(ioutil.Discard, d)
|
||||||
|
got := "<nil>"
|
||||||
|
if err != nil {
|
||||||
|
got = err.Error()
|
||||||
|
}
|
||||||
|
want := "can't evaluate field MissingField in type *template.T"
|
||||||
|
if !strings.HasSuffix(got, want) {
|
||||||
|
t.Errorf("got error %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user