Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion texttemplate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ Options are per execution, so one parsed template can be shared by executions wi

## Upstream sync

Every deviation from upstream is tagged `gomplate:`; `rg "gomplate:" texttemplate` lists them. The additions themselves live in `values.go`. To sync, copy the upstream files over, re-apply the tagged hunks and run `go test ./texttemplate`.
Every deviation from upstream is tagged `gomplate:`; `rg "gomplate:" texttemplate` lists them. The additions themselves live in `values.go`. Changes tagged `gomplate: lint` only satisfy this repository's golangci-lint rules (error naming, camelCase, `else if`, no `log.Fatal` after `defer`) and do not change behaviour. To sync, copy the upstream files over, re-apply the tagged hunks and run `go test ./texttemplate`.
33 changes: 18 additions & 15 deletions texttemplate/examplefiles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ func createTestDir(files []templateFile) string {
if err != nil {
log.Fatal(err)
}
defer f.Close()
// gomplate: lint, close before a fatal exit instead of deferring
_, err = io.WriteString(f, file.contents)
if closeErr := f.Close(); err == nil {
err = closeErr
}
if err != nil {
log.Fatal(err)
}
Expand All @@ -51,7 +54,7 @@ func ExampleTemplate_glob() {
// T2.tmpl defines a template T2.
{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
})
// Clean up after the test; another quirk of running as an example.
// Clean up after the test; another quirk of running as an example. gomplate: lint, log.Panic below so this defer runs.
defer os.RemoveAll(dir)

// pattern is the glob pattern used to find all the template files.
Expand All @@ -64,7 +67,7 @@ func ExampleTemplate_glob() {

err := tmpl.Execute(os.Stdout, nil)
if err != nil {
log.Fatalf("template execution: %s", err)
log.Panicf("template execution: %s", err)
}
// Output:
// T0 invokes T1: (T1 invokes T2: (This is T2))
Expand All @@ -83,7 +86,7 @@ func ExampleTemplate_helpers() {
// T2.tmpl defines a template T2.
{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
})
// Clean up after the test; another quirk of running as an example.
// Clean up after the test; another quirk of running as an example. gomplate: lint, log.Panic below so this defer runs.
defer os.RemoveAll(dir)

// pattern is the glob pattern used to find all the template files.
Expand All @@ -95,22 +98,22 @@ func ExampleTemplate_helpers() {
// Add one driver template to the bunch; we do this with an explicit template definition.
_, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}")
if err != nil {
log.Fatal("parsing driver1: ", err)
log.Panic("parsing driver1: ", err)
}
// Add another driver template.
_, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}")
if err != nil {
log.Fatal("parsing driver2: ", err)
log.Panic("parsing driver2: ", err)
}
// We load all the templates before execution. This package does not require
// that behavior but html/template's escaping does, so it's a good habit.
err = templates.ExecuteTemplate(os.Stdout, "driver1", nil)
if err != nil {
log.Fatalf("driver1 execution: %s", err)
log.Panicf("driver1 execution: %s", err)
}
err = templates.ExecuteTemplate(os.Stdout, "driver2", nil)
if err != nil {
log.Fatalf("driver2 execution: %s", err)
log.Panicf("driver2 execution: %s", err)
}
// Output:
// Driver 1 calls T1: (T1 invokes T2: (This is T2))
Expand All @@ -129,7 +132,7 @@ func ExampleTemplate_share() {
// T1.tmpl defines a template, T1 that invokes T2. Note T2 is not defined
{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
})
// Clean up after the test; another quirk of running as an example.
// Clean up after the test; another quirk of running as an example. gomplate: lint, log.Panic below so this defer runs.
defer os.RemoveAll(dir)

// pattern is the glob pattern used to find all the template files.
Expand All @@ -145,35 +148,35 @@ func ExampleTemplate_share() {
// 1. Clone the helper set to create a new name space from which to run them.
first, err := drivers.Clone()
if err != nil {
log.Fatal("cloning helpers: ", err)
log.Panic("cloning helpers: ", err)
}
// 2. Define T2, version A, and parse it.
_, err = first.Parse("{{define `T2`}}T2, version A{{end}}")
if err != nil {
log.Fatal("parsing T2: ", err)
log.Panic("parsing T2: ", err)
}

// Now repeat the whole thing, using a different version of T2.
// 1. Clone the drivers.
second, err := drivers.Clone()
if err != nil {
log.Fatal("cloning drivers: ", err)
log.Panic("cloning drivers: ", err)
}
// 2. Define T2, version B, and parse it.
_, err = second.Parse("{{define `T2`}}T2, version B{{end}}")
if err != nil {
log.Fatal("parsing T2: ", err)
log.Panic("parsing T2: ", err)
}

// Execute the templates in the reverse order to verify the
// first is unaffected by the second.
err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second")
if err != nil {
log.Fatalf("second execution: %s", err)
log.Panicf("second execution: %s", err)
}
err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first")
if err != nil {
log.Fatalf("first: execution: %s", err)
log.Panicf("first: execution: %s", err)
}

// Output:
Expand Down
14 changes: 7 additions & 7 deletions texttemplate/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ func (t *Template) DefinedTemplates() string {

// Sentinel errors for use with panic to signal early exits from range loops.
var (
walkBreak = errors.New("break")
walkContinue = errors.New("continue")
errWalkBreak = errors.New("break") // gomplate: lint, renamed from walkBreak
errWalkContinue = errors.New("continue") // gomplate: lint, renamed from walkContinue
)

// Walk functions step through the major pieces of the template structure,
Expand All @@ -275,10 +275,10 @@ func (s *state) walk(dot reflect.Value, node parse.Node) {
s.printValue(node, s.consume(val)) // gomplate: consume
}
case *parse.BreakNode:
panic(walkBreak)
panic(errWalkBreak)
case *parse.CommentNode:
case *parse.ContinueNode:
panic(walkContinue)
panic(errWalkContinue)
case *parse.IfNode:
s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
case *parse.ListNode:
Expand Down Expand Up @@ -358,7 +358,7 @@ func isTrue(val reflect.Value) (truth, ok bool) {
func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
s.at(r)
defer func() {
if r := recover(); r != nil && r != walkBreak {
if r := recover(); r != nil && r != errWalkBreak {
panic(r)
}
}()
Expand Down Expand Up @@ -393,8 +393,8 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
}
defer s.pop(mark)
defer func() {
// Consume panic(walkContinue)
if r := recover(); r != nil && r != walkContinue {
// Consume panic(errWalkContinue)
if r := recover(); r != nil && r != errWalkContinue {
panic(r)
}
}()
Expand Down
37 changes: 20 additions & 17 deletions texttemplate/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ type T struct {
ErrFunc func() (string, error)
PanicFunc func() string
TooFewReturnCountFunc func()
TooManyReturnCountFunc func() (string, error, int)
TooManyReturnCountFunc func() (string, int, error) // gomplate: lint, error last
InvalidReturnTypeFunc func() (string, bool)
// Template to test evaluation of templates.
Tmpl *Template
Expand Down Expand Up @@ -179,7 +179,7 @@ var tVal = &T{
ErrFunc: func() (string, error) { return "bla", nil },
PanicFunc: func() string { panic("test panic") },
TooFewReturnCountFunc: func() {},
TooManyReturnCountFunc: func() (string, error, int) { return "", nil, 0 },
TooManyReturnCountFunc: func() (string, int, error) { return "", 0, nil },
InvalidReturnTypeFunc: func() (string, bool) { return "", false },
Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
}
Expand Down Expand Up @@ -244,12 +244,12 @@ func (t *T) MAdd(a int, b []int) []int {
return v
}

var myError = errors.New("my error")
var errMy = errors.New("my error") // gomplate: lint, renamed from myError

// MyError returns a value and an error according to its argument.
func (t *T) MyError(error bool) (bool, error) {
if error {
return true, myError
return true, errMy
}
return false, nil
}
Expand Down Expand Up @@ -975,11 +975,11 @@ func TestExecuteError(t *testing.T) {
err = tmpl.Execute(b, tVal)
if err == nil {
t.Errorf("expected error; got none")
} else if !strings.Contains(err.Error(), myError.Error()) {
} else if !strings.Contains(err.Error(), errMy.Error()) {
if *debug {
fmt.Printf("test execute error: %s\n", err)
}
t.Errorf("expected myError; got %s", err)
t.Errorf("expected errMy; got %s", err)
}
}

Expand Down Expand Up @@ -1439,12 +1439,12 @@ func TestUnterminatedStringError(t *testing.T) {

const alwaysErrorText = "always be failing"

var alwaysError = errors.New(alwaysErrorText)
var errAlways = errors.New(alwaysErrorText) // gomplate: lint, renamed from alwaysError

type ErrorWriter int

func (e ErrorWriter) Write(p []byte) (int, error) {
return 0, alwaysError
return 0, errAlways
}

func TestExecuteGivesExecError(t *testing.T) {
Expand Down Expand Up @@ -1515,8 +1515,8 @@ func TestBadFuncNames(t *testing.T) {
}

func TestIsTrue(t *testing.T) {
var nil_ptr *int
var nil_chan chan int
var nilPtr *int // gomplate: lint, camelCase names in TestIsTrue
var nilChan chan int
tests := []struct {
v any
want bool
Expand All @@ -1538,16 +1538,16 @@ func TestIsTrue(t *testing.T) {
{map[string]int{"a": 1, "b": 2}, true},
{map[string]int{}, false},
{make(chan int), true},
{nil_chan, false},
{nilChan, false},
{new(int), true},
{nil_ptr, false},
{nilPtr, false},
{unsafe.Pointer(new(int)), true},
{unsafe.Pointer(nil_ptr), false},
{unsafe.Pointer(nilPtr), false},
}
for _, test_case := range tests {
got, _ := IsTrue(test_case.v)
if got != test_case.want {
t.Fatalf("expect result %v, got %v", test_case.want, got)
for _, testCase := range tests {
got, _ := IsTrue(testCase.v)
if got != testCase.want {
t.Fatalf("expect result %v, got %v", testCase.want, got)
}
}
}
Expand Down Expand Up @@ -1937,6 +1937,9 @@ func TestIssue31810(t *testing.T) {
// Works if the function is explicitly called.
const textCall = "{{ (call .) }}"
tmpl, err = New("").Parse(textCall)
if err != nil { // gomplate: lint
t.Fatal(err)
}
b.Reset()
err = tmpl.Execute(&b, f)
if err != nil {
Expand Down
6 changes: 2 additions & 4 deletions texttemplate/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,10 +329,8 @@ func call(name string, fn reflect.Value, args ...reflect.Value) (reflect.Value,
return reflect.Value{}, fmt.Errorf("wrong number of args for %s: got %d want at least %d", name, len(args), numIn-1)
}
dddType = typ.In(numIn - 1).Elem()
} else {
if len(args) != numIn {
return reflect.Value{}, fmt.Errorf("wrong number of args for %s: got %d want %d", name, len(args), numIn)
}
} else if len(args) != numIn { // gomplate: lint
return reflect.Value{}, fmt.Errorf("wrong number of args for %s: got %d want %d", name, len(args), numIn)
}
argv := make([]reflect.Value, len(args))
for i, arg := range args {
Expand Down
Loading
Loading