diff options
Diffstat (limited to 'llgo/third_party/gofrontend/libgo/go/text/template/exec.go')
| -rw-r--r-- | llgo/third_party/gofrontend/libgo/go/text/template/exec.go | 77 |
1 files changed, 56 insertions, 21 deletions
diff --git a/llgo/third_party/gofrontend/libgo/go/text/template/exec.go b/llgo/third_party/gofrontend/libgo/go/text/template/exec.go index b00e10c7e41..daba788b55b 100644 --- a/llgo/third_party/gofrontend/libgo/go/text/template/exec.go +++ b/llgo/third_party/gofrontend/libgo/go/text/template/exec.go @@ -113,7 +113,10 @@ func errRecover(errp *error) { // the output writer. // A template may be executed safely in parallel. func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { - tmpl := t.tmpl[name] + var tmpl *Template + if t.common != nil { + tmpl = t.tmpl[name] + } if tmpl == nil { return fmt.Errorf("template: no template %q associated with template %q", name, t.name) } @@ -134,26 +137,36 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) { wr: wr, vars: []variable{{"$", value}}, } - t.init() if t.Tree == nil || t.Root == nil { - var b bytes.Buffer - for name, tmpl := range t.tmpl { - if tmpl.Tree == nil || tmpl.Root == nil { - continue - } - if b.Len() > 0 { - b.WriteString(", ") - } - fmt.Fprintf(&b, "%q", name) + state.errorf("%q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates()) + } + state.walk(value, t.Root) + return +} + +// DefinedTemplates returns a string listing the defined templates, +// prefixed by the string "defined templates are: ". If there are none, +// it returns the empty string. For generating an error message here +// and in html/template. +func (t *Template) DefinedTemplates() string { + if t.common == nil { + return "" + } + var b bytes.Buffer + for name, tmpl := range t.tmpl { + if tmpl.Tree == nil || tmpl.Root == nil { + continue } - var s string if b.Len() > 0 { - s = "; defined templates are: " + b.String() + b.WriteString(", ") } - state.errorf("%q is an incomplete or empty template%s", t.Name(), s) + fmt.Fprintf(&b, "%q", name) } - state.walk(value, t.Root) - return + var s string + if b.Len() > 0 { + s = "; defined templates are: " + b.String() + } + return s } // Walk functions step through the major pieces of the template structure, @@ -418,11 +431,14 @@ func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args [] func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value { s.at(chain) - // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields. - pipe := s.evalArg(dot, nil, chain.Node) if len(chain.Field) == 0 { s.errorf("internal error: no fields in evalChainNode") } + if chain.Node.Type() == parse.NodeNil { + s.errorf("indirection through explicit nil in %s", chain) + } + // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields. + pipe := s.evalArg(dot, nil, chain.Node) return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final) } @@ -505,7 +521,18 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, if hasArgs { s.errorf("%s is not a method but has arguments", fieldName) } - return receiver.MapIndex(nameVal) + result := receiver.MapIndex(nameVal) + if !result.IsValid() { + switch s.tmpl.option.missingKey { + case mapInvalid: + // Just use the invalid value. + case mapZeroValue: + result = reflect.Zero(receiver.Type().Elem()) + case mapError: + s.errorf("map has no entry for key %q", fieldName) + } + } + return result } } s.errorf("can't evaluate field %s in type %s", fieldName, typ) @@ -560,7 +587,15 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a if final.IsValid() { t := typ.In(typ.NumIn() - 1) if typ.IsVariadic() { - t = t.Elem() + if numIn-1 < numFixed { + // The added final argument corresponds to a fixed parameter of the function. + // Validate against the type of the actual parameter. + t = typ.In(numIn - 1) + } else { + // The added final argument corresponds to the variadic part. + // Validate against the type of the elements of the variadic slice. + t = t.Elem() + } } argv[i] = s.validateType(final, t) } @@ -635,7 +670,7 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle case *parse.PipeNode: return s.validateType(s.evalPipeline(dot, arg), typ) case *parse.IdentifierNode: - return s.evalFunction(dot, arg, arg, nil, zero) + return s.validateType(s.evalFunction(dot, arg, arg, nil, zero), typ) case *parse.ChainNode: return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ) } |

