diff options
Diffstat (limited to 'tpl/internal/go_templates/texttemplate/parse')
-rw-r--r-- | tpl/internal/go_templates/texttemplate/parse/lex.go | 2 | ||||
-rw-r--r-- | tpl/internal/go_templates/texttemplate/parse/parse.go | 10 | ||||
-rw-r--r-- | tpl/internal/go_templates/texttemplate/parse/parse_test.go | 30 |
3 files changed, 36 insertions, 6 deletions
diff --git a/tpl/internal/go_templates/texttemplate/parse/lex.go b/tpl/internal/go_templates/texttemplate/parse/lex.go index 3e60a1ece..70fc86b63 100644 --- a/tpl/internal/go_templates/texttemplate/parse/lex.go +++ b/tpl/internal/go_templates/texttemplate/parse/lex.go @@ -520,7 +520,7 @@ func lexVariable(l *lexer) stateFn { return lexFieldOrVariable(l, itemVariable) } -// lexVariable scans a field or variable: [.$]Alphanumeric. +// lexFieldOrVariable scans a field or variable: [.$]Alphanumeric. // The . or $ has been scanned. func lexFieldOrVariable(l *lexer, typ itemType) stateFn { if l.atTerminator() { // Nothing interesting follows -> "." or "$". diff --git a/tpl/internal/go_templates/texttemplate/parse/parse.go b/tpl/internal/go_templates/texttemplate/parse/parse.go index 87b7618f7..d43d5334b 100644 --- a/tpl/internal/go_templates/texttemplate/parse/parse.go +++ b/tpl/internal/go_templates/texttemplate/parse/parse.go @@ -223,6 +223,11 @@ func (t *Tree) startParse(funcs []map[string]any, lex *lexer, treeSet map[string t.vars = []string{"$"} t.funcs = funcs t.treeSet = treeSet + lex.options = lexOptions{ + emitComment: t.Mode&ParseComments != 0, + breakOK: !t.hasFunction("break"), + continueOK: !t.hasFunction("continue"), + } } // stopParse terminates parsing. @@ -241,11 +246,6 @@ func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tre defer t.recover(&err) t.ParseName = t.Name lexer := lex(t.Name, text, leftDelim, rightDelim) - lexer.options = lexOptions{ - emitComment: t.Mode&ParseComments != 0, - breakOK: !t.hasFunction("break"), - continueOK: !t.hasFunction("continue"), - } t.startParse(funcs, lexer, treeSet) t.text = text t.parse() diff --git a/tpl/internal/go_templates/texttemplate/parse/parse_test.go b/tpl/internal/go_templates/texttemplate/parse/parse_test.go index 6ab48b3f7..080eea2f9 100644 --- a/tpl/internal/go_templates/texttemplate/parse/parse_test.go +++ b/tpl/internal/go_templates/texttemplate/parse/parse_test.go @@ -394,6 +394,36 @@ func TestParseWithComments(t *testing.T) { } } +func TestKeywordsAndFuncs(t *testing.T) { + // Check collisions between functions and new keywords like 'break'. When a + // break function is provided, the parser should treat 'break' as a function, + // not a keyword. + textFormat = "%q" + defer func() { textFormat = "%s" }() + + inp := `{{range .X}}{{break 20}}{{end}}` + { + // 'break' is a defined function, don't treat it as a keyword: it should + // accept an argument successfully. + var funcsWithKeywordFunc = map[string]any{ + "break": func(in any) any { return in }, + } + tmpl, err := New("").Parse(inp, "", "", make(map[string]*Tree), funcsWithKeywordFunc) + if err != nil || tmpl == nil { + t.Errorf("with break func: unexpected error: %v", err) + } + } + + { + // No function called 'break'; treat it as a keyword. Results in a parse + // error. + tmpl, err := New("").Parse(inp, "", "", make(map[string]*Tree), make(map[string]any)) + if err == nil || tmpl != nil { + t.Errorf("without break func: expected error; got none") + } + } +} + func TestSkipFuncCheck(t *testing.T) { oldTextFormat := textFormat textFormat = "%q" |