]> Cypherpunks repositories - gostls13.git/commitdiff
exp/template: forgot to allow . as a function argument
authorRob Pike <r@golang.org>
Fri, 8 Jul 2011 08:25:46 +0000 (18:25 +1000)
committerRob Pike <r@golang.org>
Fri, 8 Jul 2011 08:25:46 +0000 (18:25 +1000)
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/4671053

src/pkg/exp/template/exec.go
src/pkg/exp/template/exec_test.go
src/pkg/exp/template/set_test.go

index 57012183cdf7b6247aba86a1ee5f6dfbabd075e1..64b9cdd0e876499a1f30da6f3ec06c037bb334e0 100644 (file)
@@ -284,7 +284,10 @@ isFirst, canBeMethod bool) reflect.Value {
                if canBeMethod {
                        // Need to get to a value of type *T to guarantee we see all
                        // methods of T and *T.
-                       ptr := data.Addr()
+                       ptr := data
+                       if ptr.CanAddr() {
+                               ptr = ptr.Addr()
+                       }
                        if method, ok := methodByName(ptr.Type(), fieldName); ok {
                                return s.evalCall(ptr, method.Func, fieldName, true, args, final)
                        }
@@ -382,8 +385,14 @@ func (s *state) evalCall(v, fun reflect.Value, name string, isMethod bool, args
 }
 
 func (s *state) evalArg(data reflect.Value, typ reflect.Type, n node) reflect.Value {
-       if field, ok := n.(*fieldNode); ok {
-               value := s.evalFieldNode(data, field, []node{n}, zero)
+       switch arg := n.(type) {
+       case *dotNode:
+               if !data.Type().AssignableTo(typ) {
+                       s.errorf("wrong type for value; expected %s; got %s", typ, data.Type())
+               }
+               return data
+       case *fieldNode:
+               value := s.evalFieldNode(data, arg, []node{n}, zero)
                if !value.Type().AssignableTo(typ) {
                        s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
                }
index 5d771a2b77500014433eabf4b86276be65916168..919c57408601f75205bab4ea9cbd2e61a7ca20ee 100644 (file)
@@ -161,7 +161,7 @@ var execTests = []execTest{
        {"*[]int[1]", "{{index .PSI 1}}", "22", tVal, true},
        {"NIL", "{{.NIL}}", "<nil>", tVal, true},
 
-       // Emtpy interfaces holding values.
+       // Empty interfaces holding values.
        {"empty nil", "{{.Empty0}}", "<no value>", tVal, true},
        {"empty with int", "{{.Empty1}}", "3", tVal, true},
        {"empty with string", "{{.Empty2}}", "empty2", tVal, true},
@@ -200,7 +200,7 @@ var execTests = []execTest{
        {"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true},
        {"printf complex", `{{printf "%g" 1+7i}}`, "(1+7i)", tVal, true},
        {"printf string", `{{printf "%s" "hello"}}`, "hello", tVal, true},
-       {"printf function", `{{printf "%#q" gopher}}`, "`gopher`", tVal, true},
+       {"printf function", `{{printf "%#q" zeroArgs}}`, "`zeroArgs`", tVal, true},
        {"printf field", `{{printf "%s" .U.V}}`, "v", tVal, true},
        {"printf method", `{{printf "%s" .Method0}}`, "M0", tVal, true},
        {"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) M0", tVal, true},
@@ -273,13 +273,17 @@ var execTests = []execTest{
        {"error method, no error", "{{.EPERM false}}", "false", tVal, true},
 }
 
-func gopher() string {
-       return "gopher"
+func zeroArgs() string {
+       return "zeroArgs"
+}
+
+func oneArg(a string) string {
+       return "oneArg=" + a
 }
 
 func testExecute(execTests []execTest, set *Set, t *testing.T) {
        b := new(bytes.Buffer)
-       funcs := FuncMap{"gopher": gopher}
+       funcs := FuncMap{"zeroArgs": zeroArgs, "oneArg": oneArg}
        for _, test := range execTests {
                tmpl := New(test.name).Funcs(funcs)
                err := tmpl.Parse(test.input)
index c0115ec0ade14a23f64ac72f1cf94717a5979f19..628839a724b4273f07babd3acf8cec2a6e920fb4 100644 (file)
@@ -81,6 +81,10 @@ var setExecTests = []execTest{
        {"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
        {"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
        {"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
+
+       // User-defined function: test argument evaluator.
+       {"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
+       {"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true},
 }
 
 const setText = `