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 }