Skip to content

Commit

Permalink
Merge pull request #32 from gobuffalo/fix-for-loop-error-numbers
Browse files Browse the repository at this point in the history
Line numbers for errors are wrongly reported inside of for loops fixes #30
  • Loading branch information
markbates authored Jan 9, 2018
2 parents 760a9e9 + af4b111 commit 586a6d1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
11 changes: 10 additions & 1 deletion compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var ErrUnknownIdentifier = errors.New("unknown identifier")
type compiler struct {
ctx *Context
program *ast.Program
curStmt ast.Statement
}

func (c *compiler) compile() (string, error) {
Expand All @@ -37,7 +38,11 @@ func (c *compiler) compile() (string, error) {
res, err = c.evalLetStatement(node)
}
if err != nil {
return "", errors.WithStack(errors.Wrapf(err, "line %d", stmt.T().LineNumber))
s := stmt
if c.curStmt != nil {
s = c.curStmt
}
return "", errors.WithStack(errors.Wrapf(err, "line %d", s.T().LineNumber))
}

c.write(bb, res)
Expand Down Expand Up @@ -239,6 +244,9 @@ func (c *compiler) evalIdentifier(node *ast.Identifier) (interface{}, error) {
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
if rv.Kind() != reflect.Struct {
return nil, errors.WithStack(errors.Errorf("'%s' does not have a field or method named '%s' (%s)", node.Callee.String(), node.Value, node))
}
f := rv.FieldByName(node.Value)
if !f.IsValid() {
m := rv.MethodByName(node.Value)
Expand Down Expand Up @@ -665,6 +673,7 @@ func (c *compiler) evalBlockStatement(node *ast.BlockStatement) (interface{}, er
}

func (c *compiler) evalStatement(node ast.Statement) (interface{}, error) {
c.curStmt = node
// fmt.Println("evalStatement")
switch t := node.(type) {
case *ast.ExpressionStatement:
Expand Down
38 changes: 38 additions & 0 deletions plush_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,44 @@ func Test_VariadicHelperWithWrongParam(t *testing.T) {
r.Contains(err.Error(), "test (string) is an invalid argument for foo at pos 2: expected (int)")
}

func Test_LineNumberErrors(t *testing.T) {
r := require.New(t)
input := `<p>
<%= f.Foo %>
</p>`

_, err := Render(input, NewContext())
r.Error(err)
r.Contains(err.Error(), "line 2:")
}

func Test_LineNumberErrors_ForLoop(t *testing.T) {
r := require.New(t)
input := `
<%= for (n) in numbers.Foo { %>
<%= n %>
<% } %>
`

_, err := Render(input, NewContext())
r.Error(err)
r.Contains(err.Error(), "line 2:")
}

func Test_LineNumberErrors_InsideForLoop(t *testing.T) {
r := require.New(t)
input := `
<%= for (n) in numbers { %>
<%= n.Foo %>
<% } %>
`
ctx := NewContext()
ctx.Set("numbers", []int{1, 2})
_, err := Render(input, ctx)
r.Error(err)
r.Contains(err.Error(), "line 3:")
}

func Test_RunScript(t *testing.T) {
r := require.New(t)
bb := &bytes.Buffer{}
Expand Down

0 comments on commit 586a6d1

Please sign in to comment.