Skip to content

Commit

Permalink
text/template/parse: add a mode to skip func-check on parsing
Browse files Browse the repository at this point in the history
Following the discussion on #34652 and the proposal of #36911 (gopls),
this CL adds an option to skip the function declartion check on parsing,
in order to make it possible to parse arbitrary template text files and
get their AST.

Fixed #38627

Change-Id: Id1e0360fc726b49dcdd49716ce25563ebaae6c10
Reviewed-on: https://go-review.googlesource.com/c/go/+/301493
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
a8m authored and ianlancetaylor committed Apr 19, 2021
1 parent 6b8e3e2 commit 5780ab4
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/text/template/parse/parse.go
Expand Up @@ -38,7 +38,8 @@ type Tree struct {
type Mode uint

const (
ParseComments Mode = 1 << iota // parse comments and add them to AST
ParseComments Mode = 1 << iota // parse comments and add them to AST
DeferFuncCheck // defer type checking functions until template is executed
)

// Copy returns a copy of the Tree. Any parsing state is discarded.
Expand Down Expand Up @@ -689,7 +690,8 @@ func (t *Tree) operand() Node {
func (t *Tree) term() Node {
switch token := t.nextNonSpace(); token.typ {
case itemIdentifier:
if !t.hasFunction(token.val) {
checkFunc := t.Mode&DeferFuncCheck == 0
if checkFunc && !t.hasFunction(token.val) {
t.errorf("function %q not defined", token.val)
}
return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
Expand Down
16 changes: 16 additions & 0 deletions src/text/template/parse/parse_test.go
Expand Up @@ -379,6 +379,22 @@ func TestParseWithComments(t *testing.T) {
}
}

func TestDeferFuncCheck(t *testing.T) {
oldTextFormat := textFormat
textFormat = "%q"
defer func() { textFormat = oldTextFormat }()
tr := New("defer func check")
tr.Mode = DeferFuncCheck
tmpl, err := tr.Parse("{{fn 1 2}}", "", "", make(map[string]*Tree))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expected := "{{fn 1 2}}"
if result := tmpl.Root.String(); result != expected {
t.Errorf("got\n\t%v\nexpected\n\t%v", result, expected)
}
}

type isEmptyTest struct {
name string
input string
Expand Down

0 comments on commit 5780ab4

Please sign in to comment.