bou.ke/statictemplate@v0.0.0-20180821122055-510411a5e7dd/statictemplate/translate_typed_test.go (about)

     1  package statictemplate
     2  
     3  import (
     4  	"go/types"
     5  	"testing"
     6  	"text/template"
     7  
     8  	"gopkg.in/stretchr/testify.v1/assert"
     9  )
    10  
    11  func TestComplexInput(t *testing.T) {
    12  	stringSlice := types.NewSlice(types.Typ[types.String])
    13  	structA := types.NewStruct([]*types.Var{types.NewVar(0, nil, "A", types.Typ[types.String])}, nil)
    14  	structASlice := types.NewStruct([]*types.Var{types.NewVar(0, nil, "A", types.NewSlice(types.Typ[types.Int]))}, nil)
    15  	structABool := types.NewStruct([]*types.Var{types.NewVar(0, nil, "A", types.Typ[types.Bool])}, nil)
    16  	p := types.NewPackage("bou.ke/statictemplate/statictemplate", "statictemplate")
    17  	emptyStruct := types.NewStruct(nil, nil)
    18  	testStruct := types.NewNamed(types.NewTypeName(0, p, "testStruct", emptyStruct), emptyStruct, []*types.Func{
    19  		types.NewFunc(0, p, "Hello", types.NewSignature(types.NewVar(0, p, "t", emptyStruct), types.NewTuple(), types.NewTuple(
    20  			types.NewVar(0, p, "", types.Typ[types.String]),
    21  		), false)),
    22  		types.NewFunc(0, p, "Upcase", types.NewSignature(types.NewVar(0, p, "t", emptyStruct), types.NewTuple(
    23  			types.NewVar(0, p, "input", types.Typ[types.String]),
    24  		), types.NewTuple(
    25  			types.NewVar(0, p, "", types.Typ[types.String]),
    26  		), false)),
    27  		types.NewFunc(0, p, "Bla", types.NewSignature(types.NewVar(0, p, "t", emptyStruct), types.NewTuple(), types.NewTuple(
    28  			types.NewVar(0, p, "", types.Typ[types.Int]),
    29  			types.NewVar(0, p, "", types.Typ[types.String]),
    30  		), false)),
    31  	})
    32  
    33  	testStruct.AddMethod(
    34  		types.NewFunc(0, p, "Recursive", types.NewSignature(types.NewVar(0, p, "t", emptyStruct), types.NewTuple(), types.NewTuple(
    35  			types.NewVar(0, p, "", types.NewPointer(testStruct)),
    36  		), false)),
    37  	)
    38  
    39  	for _, c := range []struct {
    40  		input, expected string
    41  		typ             types.Type
    42  	}{
    43  		{"{{ .A }}", `
    44  package main
    45  
    46  import (
    47    "io"
    48  )
    49  
    50  func Name(w io.Writer, dot struct{ A string }) (err error) {
    51    defer func() {
    52      if recovered := recover(); recovered != nil {
    53        var ok bool
    54        if err, ok = recovered.(error); !ok {
    55          panic(recovered)
    56        }
    57      }
    58    }()
    59    return fun0(w, dot)
    60  }
    61  
    62  // template.tmpl(struct{A string})
    63  func fun0(w io.Writer, dot struct{ A string }) error {
    64    _, _ = io.WriteString(w, dot.A)
    65    return nil
    66  }`, structA},
    67  		{"{{ range . }}Hello{{ end }}", `
    68  package main
    69  
    70  import (
    71    "io"
    72  )
    73  
    74  func Name(w io.Writer, dot []string) (err error) {
    75    defer func() {
    76      if recovered := recover(); recovered != nil {
    77        var ok bool
    78        if err, ok = recovered.(error); !ok {
    79          panic(recovered)
    80        }
    81      }
    82    }()
    83    return fun0(w, dot)
    84  }
    85  
    86  // template.tmpl([]string)
    87  func fun0(w io.Writer, dot []string) error {
    88    if eval := dot; len(eval) != 0 {
    89  		for _, dot := range eval {
    90  			_ = dot
    91        _, _ = io.WriteString(w, "Hello")
    92      }
    93    }
    94    return nil
    95  }`, stringSlice},
    96  		{"{{ range $a := . }}{{ $a }}{{ end }}", `
    97  package main
    98  
    99  import (
   100    "io"
   101  )
   102  
   103  func Name(w io.Writer, dot []string) (err error) {
   104    defer func() {
   105      if recovered := recover(); recovered != nil {
   106        var ok bool
   107        if err, ok = recovered.(error); !ok {
   108          panic(recovered)
   109        }
   110      }
   111    }()
   112    return fun0(w, dot)
   113  }
   114  
   115  // template.tmpl([]string)
   116  func fun0(w io.Writer, dot []string) error {
   117    if eval := dot; len(eval) != 0 {
   118      for _, _Vara := range eval {
   119  			dot := _Vara
   120  			_ = dot
   121        _, _ = io.WriteString(w, _Vara)
   122      }
   123    }
   124    return nil
   125  }`, stringSlice},
   126  		{"{{ range $i, $a := . }}{{ $i }}{{ $a }}{{ end }}", `
   127  package main
   128  
   129  import (
   130    "fmt"
   131    "io"
   132  )
   133  
   134  func Name(w io.Writer, dot []string) (err error) {
   135    defer func() {
   136      if recovered := recover(); recovered != nil {
   137        var ok bool
   138        if err, ok = recovered.(error); !ok {
   139          panic(recovered)
   140        }
   141      }
   142    }()
   143    return fun0(w, dot)
   144  }
   145  
   146  // template.tmpl([]string)
   147  func fun0(w io.Writer, dot []string) error {
   148    if eval := dot; len(eval) != 0 {
   149      for _Vari, _Vara := range eval {
   150  			_ = _Vari
   151  			dot := _Vara
   152  			_ = dot
   153        _, _ = fmt.Fprint(w, _Vari)
   154        _, _ = io.WriteString(w, _Vara)
   155      }
   156    }
   157    return nil
   158  }`, stringSlice},
   159  		{"{{ print .A }}", `
   160  package main
   161  
   162  import (
   163    "bou.ke/statictemplate/funcs"
   164    "io"
   165  )
   166  
   167  func Name(w io.Writer, dot struct{ A string }) (err error) {
   168    defer func() {
   169      if recovered := recover(); recovered != nil {
   170        var ok bool
   171        if err, ok = recovered.(error); !ok {
   172          panic(recovered)
   173        }
   174      }
   175    }()
   176    return fun0(w, dot)
   177  }
   178  
   179  // template.tmpl(struct{A string})
   180  func fun0(w io.Writer, dot struct{ A string }) error {
   181    _, _ = io.WriteString(w, funcs.Print(dot.A))
   182    return nil
   183  }`, structA},
   184  		{"{{ (.).A }}", `
   185  package main
   186  
   187  import (
   188    "io"
   189  )
   190  
   191  func Name(w io.Writer, dot struct{ A string }) (err error) {
   192    defer func() {
   193      if recovered := recover(); recovered != nil {
   194        var ok bool
   195        if err, ok = recovered.(error); !ok {
   196          panic(recovered)
   197        }
   198      }
   199    }()
   200    return fun0(w, dot)
   201  }
   202  
   203  // template.tmpl(struct{A string})
   204  func fun0(w io.Writer, dot struct{ A string }) error {
   205    _, _ = io.WriteString(w, dot.A)
   206    return nil
   207  }`, structA},
   208  		{"{{ (.A) }}", `
   209  package main
   210  
   211  import (
   212    "io"
   213  )
   214  
   215  func Name(w io.Writer, dot struct{ A string }) (err error) {
   216    defer func() {
   217      if recovered := recover(); recovered != nil {
   218        var ok bool
   219        if err, ok = recovered.(error); !ok {
   220          panic(recovered)
   221        }
   222      }
   223    }()
   224    return fun0(w, dot)
   225  }
   226  
   227  // template.tmpl(struct{A string})
   228  func fun0(w io.Writer, dot struct{ A string }) error {
   229    _, _ = io.WriteString(w, dot.A)
   230    return nil
   231  }`, structA},
   232  		{"{{ with .A }} {{ . }} {{else}} {{ .A }} {{end}}", `
   233  package main
   234  
   235  import (
   236    "fmt"
   237    "io"
   238  )
   239  
   240  func Name(w io.Writer, dot struct{ A string }) (err error) {
   241    defer func() {
   242      if recovered := recover(); recovered != nil {
   243        var ok bool
   244        if err, ok = recovered.(error); !ok {
   245          panic(recovered)
   246        }
   247      }
   248    }()
   249    return fun0(w, dot)
   250  }
   251  
   252  // template.tmpl(struct{A string})
   253  func fun0(w io.Writer, dot struct{ A string }) error {
   254    if eval := dot.A; len(eval) != 0 {
   255      dot := eval
   256  		_ = dot
   257      _, _ = io.WriteString(w, " ")
   258      _, _ = fmt.Fprint(w, dot)
   259      _, _ = io.WriteString(w, " ")
   260    } else {
   261      _, _ = io.WriteString(w, " ")
   262      _, _ = io.WriteString(w, dot.A)
   263      _, _ = io.WriteString(w, " ")
   264    }
   265    return nil
   266  }`, structA},
   267  		{"{{ with .A }} {{ . }} {{else}} {{ .A }} {{end}}", `
   268  package main
   269  
   270  import (
   271    "fmt"
   272    "io"
   273  )
   274  
   275  func Name(w io.Writer, dot struct{ A bool }) (err error) {
   276    defer func() {
   277      if recovered := recover(); recovered != nil {
   278        var ok bool
   279        if err, ok = recovered.(error); !ok {
   280          panic(recovered)
   281        }
   282      }
   283    }()
   284    return fun0(w, dot)
   285  }
   286  
   287  // template.tmpl(struct{A bool})
   288  func fun0(w io.Writer, dot struct{ A bool }) error {
   289    if eval := dot.A; eval {
   290      dot := eval
   291  		_ = dot
   292      _, _ = io.WriteString(w, " ")
   293      _, _ = fmt.Fprint(w, dot)
   294      _, _ = io.WriteString(w, " ")
   295    } else {
   296      _, _ = io.WriteString(w, " ")
   297      _, _ = fmt.Fprint(w, dot.A)
   298      _, _ = io.WriteString(w, " ")
   299    }
   300    return nil
   301  }`, structABool},
   302  		{"{{ with .A }} {{ . }} {{else}} {{ .A }} {{end}}", `
   303  package main
   304  
   305  import (
   306    "fmt"
   307    "io"
   308  )
   309  
   310  func Name(w io.Writer, dot struct{ A []int }) (err error) {
   311    defer func() {
   312      if recovered := recover(); recovered != nil {
   313        var ok bool
   314        if err, ok = recovered.(error); !ok {
   315          panic(recovered)
   316        }
   317      }
   318    }()
   319    return fun0(w, dot)
   320  }
   321  
   322  // template.tmpl(struct{A []int})
   323  func fun0(w io.Writer, dot struct{ A []int }) error {
   324    if eval := dot.A; len(eval) != 0 {
   325      dot := eval
   326  		_ = dot
   327      _, _ = io.WriteString(w, " ")
   328      _, _ = fmt.Fprint(w, dot)
   329      _, _ = io.WriteString(w, " ")
   330    } else {
   331      _, _ = io.WriteString(w, " ")
   332      _, _ = fmt.Fprint(w, dot.A)
   333      _, _ = io.WriteString(w, " ")
   334    }
   335    return nil
   336  }`, structASlice},
   337  		{"{{ if $b := .A }}{{ $b }}{{end}}", `
   338  package main
   339  
   340  import (
   341    "fmt"
   342    "io"
   343  )
   344  
   345  func Name(w io.Writer, dot struct{ A []int }) (err error) {
   346    defer func() {
   347      if recovered := recover(); recovered != nil {
   348        var ok bool
   349        if err, ok = recovered.(error); !ok {
   350          panic(recovered)
   351        }
   352      }
   353    }()
   354    return fun0(w, dot)
   355  }
   356  
   357  // template.tmpl(struct{A []int})
   358  func fun0(w io.Writer, dot struct{ A []int }) error {
   359    if eval := dot.A; len(eval) != 0 {
   360      _Varb := eval
   361  		_ = _Varb
   362      _, _ = fmt.Fprint(w, _Varb)
   363    }
   364    return nil
   365  }`, structASlice},
   366  		{`{{ .Hello }}`, `
   367  package main
   368  
   369  import (
   370    pkg1 "bou.ke/statictemplate/statictemplate"
   371    "io"
   372  )
   373  
   374  func Name(w io.Writer, dot pkg1.testStruct) (err error) {
   375    defer func() {
   376      if recovered := recover(); recovered != nil {
   377        var ok bool
   378        if err, ok = recovered.(error); !ok {
   379          panic(recovered)
   380        }
   381      }
   382    }()
   383    return fun0(w, dot)
   384  }
   385  
   386  // template.tmpl(pkg1.testStruct)
   387  func fun0(w io.Writer, dot pkg1.testStruct) error {
   388    _, _ = io.WriteString(w, dot.Hello())
   389    return nil
   390  }`, testStruct},
   391  		{`{{ .Hello }}`, `
   392  package main
   393  
   394  import (
   395    pkg1 "bou.ke/statictemplate/statictemplate"
   396    "io"
   397  )
   398  
   399  func Name(w io.Writer, dot *pkg1.testStruct) (err error) {
   400    defer func() {
   401      if recovered := recover(); recovered != nil {
   402        var ok bool
   403        if err, ok = recovered.(error); !ok {
   404          panic(recovered)
   405        }
   406      }
   407    }()
   408    return fun0(w, dot)
   409  }
   410  
   411  // template.tmpl(*pkg1.testStruct)
   412  func fun0(w io.Writer, dot *pkg1.testStruct) error {
   413    _, _ = io.WriteString(w, dot.Hello())
   414    return nil
   415  }`, types.NewPointer(testStruct)},
   416  		{`{{ .Recursive.Recursive.Recursive.Upcase "whatup" }}`, `
   417  package main
   418  
   419  import (
   420    pkg1 "bou.ke/statictemplate/statictemplate"
   421    "io"
   422  )
   423  
   424  func Name(w io.Writer, dot pkg1.testStruct) (err error) {
   425    defer func() {
   426      if recovered := recover(); recovered != nil {
   427        var ok bool
   428        if err, ok = recovered.(error); !ok {
   429          panic(recovered)
   430        }
   431      }
   432    }()
   433    return fun0(w, dot)
   434  }
   435  
   436  // template.tmpl(pkg1.testStruct)
   437  func fun0(w io.Writer, dot pkg1.testStruct) error {
   438    _, _ = io.WriteString(w, dot.Recursive().Recursive().Recursive().Upcase("whatup"))
   439    return nil
   440  }`, testStruct},
   441  		{`{{ ( .Recursive.Recursive ).Recursive.Upcase "whatup" }}`, `
   442  package main
   443  
   444  import (
   445    pkg1 "bou.ke/statictemplate/statictemplate"
   446    "io"
   447  )
   448  
   449  func Name(w io.Writer, dot pkg1.testStruct) (err error) {
   450    defer func() {
   451      if recovered := recover(); recovered != nil {
   452        var ok bool
   453        if err, ok = recovered.(error); !ok {
   454          panic(recovered)
   455        }
   456      }
   457    }()
   458    return fun0(w, dot)
   459  }
   460  
   461  // template.tmpl(pkg1.testStruct)
   462  func fun0(w io.Writer, dot pkg1.testStruct) error {
   463    _, _ = io.WriteString(w, dot.Recursive().Recursive().Recursive().Upcase("whatup"))
   464    return nil
   465  }`, testStruct},
   466  		{`{{ .Hello | printf "%q" }}`, `
   467  package main
   468  
   469  import (
   470    "bou.ke/statictemplate/funcs"
   471    pkg1 "bou.ke/statictemplate/statictemplate"
   472    "io"
   473  )
   474  
   475  func Name(w io.Writer, dot pkg1.testStruct) (err error) {
   476    defer func() {
   477      if recovered := recover(); recovered != nil {
   478        var ok bool
   479        if err, ok = recovered.(error); !ok {
   480          panic(recovered)
   481        }
   482      }
   483    }()
   484    return fun0(w, dot)
   485  }
   486  
   487  // template.tmpl(pkg1.testStruct)
   488  func fun0(w io.Writer, dot pkg1.testStruct) error {
   489    _, _ = io.WriteString(w, funcs.Printf("%q", dot.Hello()))
   490    return nil
   491  }`, testStruct},
   492  		{`{{ .Upcase "whatup" }}`, `
   493  package main
   494  
   495  import (
   496    pkg1 "bou.ke/statictemplate/statictemplate"
   497    "io"
   498  )
   499  
   500  func Name(w io.Writer, dot pkg1.testStruct) (err error) {
   501    defer func() {
   502      if recovered := recover(); recovered != nil {
   503        var ok bool
   504        if err, ok = recovered.(error); !ok {
   505          panic(recovered)
   506        }
   507      }
   508    }()
   509    return fun0(w, dot)
   510  }
   511  
   512  // template.tmpl(pkg1.testStruct)
   513  func fun0(w io.Writer, dot pkg1.testStruct) error {
   514    _, _ = io.WriteString(w, dot.Upcase("whatup"))
   515    return nil
   516  }`, testStruct},
   517  		{`{{ "whatup" | .Upcase  }}`, `
   518  package main
   519  
   520  import (
   521    pkg1 "bou.ke/statictemplate/statictemplate"
   522    "io"
   523  )
   524  
   525  func Name(w io.Writer, dot pkg1.testStruct) (err error) {
   526    defer func() {
   527      if recovered := recover(); recovered != nil {
   528        var ok bool
   529        if err, ok = recovered.(error); !ok {
   530          panic(recovered)
   531        }
   532      }
   533    }()
   534    return fun0(w, dot)
   535  }
   536  
   537  // template.tmpl(pkg1.testStruct)
   538  func fun0(w io.Writer, dot pkg1.testStruct) error {
   539    _, _ = io.WriteString(w, dot.Upcase("whatup"))
   540    return nil
   541  }`, testStruct},
   542  		{`{{ .Bla }}`, `
   543  package main
   544  
   545  import (
   546    pkg1 "bou.ke/statictemplate/statictemplate"
   547    "fmt"
   548    "io"
   549  )
   550  
   551  func Name(w io.Writer, dot pkg1.testStruct) (err error) {
   552    defer func() {
   553      if recovered := recover(); recovered != nil {
   554        var ok bool
   555        if err, ok = recovered.(error); !ok {
   556          panic(recovered)
   557        }
   558      }
   559    }()
   560    return fun0(w, dot)
   561  }
   562  
   563  func fun2(value int, err error) int {
   564    if err != nil {
   565      panic(err)
   566    }
   567    return value
   568  }
   569  
   570  // template.tmpl(pkg1.testStruct)
   571  func fun0(w io.Writer, dot pkg1.testStruct) error {
   572    _, _ = fmt.Fprint(w, fun2(dot.Bla()))
   573    return nil
   574  }
   575  `, testStruct},
   576  		{`{{define "T1"}}{{ . }}{{end}}
   577  {{define "T2"}}TWO {{template "T1" .Hello}}{{end}}
   578  {{define "T3"}}{{template "T1" .}} {{template "T2" .}}{{end}}
   579  {{template "T3" .}}`, `
   580  package main
   581  
   582  import (
   583    pkg1 "bou.ke/statictemplate/statictemplate"
   584    "fmt"
   585    "io"
   586  )
   587  
   588  func Name(w io.Writer, dot *pkg1.testStruct) (err error) {
   589    defer func() {
   590      if recovered := recover(); recovered != nil {
   591        var ok bool
   592        if err, ok = recovered.(error); !ok {
   593          panic(recovered)
   594        }
   595      }
   596    }()
   597    return fun0(w, dot)
   598  }
   599  
   600  // T1(*pkg1.testStruct)
   601  func fun3(w io.Writer, dot *pkg1.testStruct) error {
   602    _, _ = fmt.Fprint(w, dot)
   603    return nil
   604  }
   605  
   606  // T1(string)
   607  func fun5(w io.Writer, dot string) error {
   608    _, _ = io.WriteString(w, dot)
   609    return nil
   610  }
   611  
   612  // T2(*pkg1.testStruct)
   613  func fun4(w io.Writer, dot *pkg1.testStruct) error {
   614    _, _ = io.WriteString(w, "TWO ")
   615    if err := fun5(w, dot.Hello()); err != nil {
   616      return err
   617    }
   618    return nil
   619  }
   620  
   621  // T3(*pkg1.testStruct)
   622  func fun2(w io.Writer, dot *pkg1.testStruct) error {
   623    if err := fun3(w, dot); err != nil {
   624      return err
   625    }
   626    _, _ = io.WriteString(w, " ")
   627    if err := fun4(w, dot); err != nil {
   628      return err
   629    }
   630    return nil
   631  }
   632  
   633  // template.tmpl(*pkg1.testStruct)
   634  func fun0(w io.Writer, dot *pkg1.testStruct) error {
   635    _, _ = io.WriteString(w, "\n")
   636    _, _ = io.WriteString(w, "\n")
   637    _, _ = io.WriteString(w, "\n")
   638    if err := fun2(w, dot); err != nil {
   639      return err
   640    }
   641    return nil
   642  }`, types.NewPointer(testStruct)},
   643  	} {
   644  		temp := template.Must(template.New("template.tmpl").Parse(c.input))
   645  		actual, err := Translate(temp, "main", []TranslateInstruction{
   646  			{"Name", "template.tmpl", c.typ},
   647  		})
   648  		if assert.NoError(t, err, c.input) {
   649  			equalish(t, c.expected, actual, c.input)
   650  		}
   651  	}
   652  }