Skip to content

Commit

Permalink
fix: allow slice type definitions in templ expressions (#670)
Browse files Browse the repository at this point in the history
  • Loading branch information
joerdav authored Apr 19, 2024
1 parent 0b30dc5 commit f300746
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 19 deletions.
16 changes: 16 additions & 0 deletions parser/v2/goexpression/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,11 +452,27 @@ var templExpressionTests = []testInput{
{Name: "A"},
{Name: "B"},
})`,
},
{
name: "function call with function arg",
input: `componentA(func(y []int) string {
return "hi"
})`,
},
{
name: "function call with function called arg",
input: `componentA(func(y []int) string {
return "hi"
}())`,
},
{
name: "call with braces and brackets",
input: `templates.New(test{}, other())`,
},
{
name: "generic call",
input: `templates.New(toString[[]int](data))`,
},
{
name: "struct method call",
input: `typeName{}.Method()`,
Expand Down
26 changes: 7 additions & 19 deletions parser/v2/goexpression/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ type ExpressionParser struct {
End int
Previous token.Token
Fns Stack[int] // Stack of function depths.
Slices Stack[int] // Stack of slice depths.
}

func (ep *ExpressionParser) setEnd(pos token.Pos, tok token.Token, lit string) {
Expand All @@ -72,10 +71,14 @@ func (ep *ExpressionParser) hasSpaceBeforeCurrentToken(pos token.Pos) bool {
}

func (ep *ExpressionParser) isTopLevel() bool {
return len(ep.Fns) == 0 && len(ep.Slices) == 0 && len(ep.Stack) == 0
return len(ep.Fns) == 0 && len(ep.Stack) == 0
}

func (ep *ExpressionParser) Insert(pos token.Pos, tok token.Token, lit string) (stop bool, err error) {
func (ep *ExpressionParser) Insert(
pos token.Pos,
tok token.Token,
lit string,
) (stop bool, err error) {
defer func() {
ep.Previous = tok
}()
Expand All @@ -87,17 +90,6 @@ func (ep *ExpressionParser) Insert(pos token.Pos, tok token.Token, lit string) (
ep.setEnd(pos, tok, lit)
return false, nil
}
// Handle slice definitions e.g.: []string{"a", "b"}
// Similarly to functions, we push the current depth onto the stack,
// and prevent stopping until we've closed the slice.
if ep.Previous == token.LBRACK && tok == token.RBRACK {
// Pop a left square bracket from the stack.
ep.Stack.Pop()
// Push the current depth onto the slice stack.
ep.Slices.Push(len(ep.Stack))
ep.setEnd(pos, tok, lit)
return false, nil
}
// If we're opening a pair, we don't stop until we've closed it.
if _, isOpener := goTokenOpenToClose[tok]; isOpener {
// If we're at an open brace, at the top level, where a space has been used, stop.
Expand Down Expand Up @@ -134,16 +126,12 @@ func (ep *ExpressionParser) Insert(pos token.Pos, tok token.Token, lit string) (
if len(ep.Stack) == ep.Fns.Peek() {
ep.Fns.Pop()
}
// If we're closing a slice assignment, pop the slice depth.
if len(ep.Stack) == ep.Slices.Peek() {
ep.Slices.Pop()
}
}
ep.setEnd(pos, tok, lit)
return false, nil
}
// If we're in a function literal slice, or pair, we allow anything until we close it.
if len(ep.Fns) > 0 || len(ep.Slices) > 0 || len(ep.Stack) > 0 {
if len(ep.Fns) > 0 || len(ep.Stack) > 0 {
ep.setEnd(pos, tok, lit)
return false, nil
}
Expand Down

0 comments on commit f300746

Please sign in to comment.