Skip to content

Commit

Permalink
ast: clarify property name parser (#228)
Browse files Browse the repository at this point in the history
The property access parser has been getting increasingly gnarly, and
will continue to do so as it evolves to handle accessor ranges. These
changes refactor the parser for simplicity and clarity. As a nice
side-effect, they also improve some error reporting.
  • Loading branch information
pgavlin authored Feb 1, 2024
1 parent ba2d384 commit a1e0bbb
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 232 deletions.
1 change: 1 addition & 0 deletions ast/interpolation.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func parseInterpolate(node syntax.Node, value string) ([]Interpolation, syntax.D
value = value[2:]
case strings.HasPrefix(value, "${"):
rest, access, accessDiags := parsePropertyAccess(node, value[2:])

diags.Extend(accessDiags...)
parts = append(parts, Interpolation{
Text: str.String(),
Expand Down
107 changes: 33 additions & 74 deletions ast/interpolation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,115 +21,74 @@ import (
"github.com/stretchr/testify/assert"
)

func mkInterp(text string, accessors ...PropertyAccessor) Interpolation {
return Interpolation{
Text: text,
Value: mkAccess(accessors...),
}
}

func mkAccess(accessors ...PropertyAccessor) *PropertyAccess {
if len(accessors) == 0 {
return nil
}
return &PropertyAccess{Accessors: accessors}
}

func mkPropertyName(name string) *PropertyName {
return &PropertyName{Name: name}
}

func mkPropertySubscript[T string | int](index T) *PropertySubscript {
return &PropertySubscript{Index: index}
}

func TestInvalidInterpolations(t *testing.T) {
cases := []struct {
text string
parts []Interpolation
}{
{
text: "${foo",
parts: []Interpolation{
{
Text: "",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertyName{Name: "foo"},
},
},
},
},
text: "${foo",
parts: []Interpolation{mkInterp("", mkPropertyName("foo"))},
},
{
text: "${foo ",
parts: []Interpolation{
{
Text: "",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertyName{Name: "foo"},
},
},
},
{
Text: " ",
},
mkInterp("", mkPropertyName("foo")),
mkInterp(" "),
},
},
{
text: `${foo} ${["baz} bar`,
parts: []Interpolation{
{
Text: "",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertyName{Name: "foo"},
},
},
},
{
Text: " ",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertySubscript{Index: "baz} bar"},
},
},
},
mkInterp("", mkPropertyName("foo")),
mkInterp(" ", mkPropertySubscript("baz} bar")),
},
},
{
text: `missing ${property[} subscript`,
parts: []Interpolation{
{
Text: "missing ",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertyName{Name: "property"},
},
},
},
{
Text: " subscript",
},
mkInterp("missing ", mkPropertyName("property"), mkPropertySubscript("")),
mkInterp(" subscript"),
},
},
{
text: `${[bar].baz}`,
parts: []Interpolation{
{
Text: "",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertySubscript{Index: 0},
&PropertyName{Name: "baz"},
},
},
},
mkInterp("", mkPropertySubscript("bar"), mkPropertyName("baz")),
},
},
{
text: `${foo.`,
parts: []Interpolation{
{
Text: "",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertyName{Name: "foo"},
},
},
},
mkInterp("", mkPropertyName("foo"), mkPropertyName("")),
},
},
{
text: `${foo[`,
parts: []Interpolation{
{
Text: "",
Value: &PropertyAccess{
Accessors: []PropertyAccessor{
&PropertyName{Name: "foo"},
},
},
},
mkInterp("", mkPropertyName("foo"), mkPropertySubscript("")),
},
},
}
Expand Down
Loading

0 comments on commit a1e0bbb

Please sign in to comment.