summaryrefslogtreecommitdiffstats
path: root/llgo/third_party/gofrontend/libgo/go/text/template/exec.go
diff options
context:
space:
mode:
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.go77
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)
}
OpenPOWER on IntegriCloud