Skip to content

Commit

Permalink
syntax: recover binary commands properly
Browse files Browse the repository at this point in the history
I wasn't paying close enough attention to the code;
the returned statement is the parent containing both branches,
not just the right branch which is recovered.

Teach the tests to spot when the result is empty or all recovered,
which caught these mistakes.
  • Loading branch information
mvdan committed Dec 21, 2024
1 parent c6175e6 commit 51f18f3
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 6 deletions.
14 changes: 8 additions & 6 deletions syntax/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1721,10 +1721,11 @@ func (p *Parser) getStmt(readEnd, binCmd, fnBody bool) *Stmt {
b.Y = p.getStmt(false, true, false)
if b.Y == nil || p.err != nil {
if p.recoverError() {
return &Stmt{Position: recoveredPos}
b.Y = &Stmt{Position: recoveredPos}
} else {
p.followErr(b.OpPos, b.Op.String(), "a statement")
return nil
}
p.followErr(b.OpPos, b.Op.String(), "a statement")
return nil
}
s = &Stmt{Position: s.Position}
s.Cmd = b
Expand Down Expand Up @@ -1897,10 +1898,11 @@ func (p *Parser) gotStmtPipe(s *Stmt, binCmd bool) *Stmt {
p.got(_Newl)
if b.Y = p.gotStmtPipe(&Stmt{Position: p.pos}, true); b.Y == nil || p.err != nil {
if p.recoverError() {
return &Stmt{Position: recoveredPos}
b.Y = &Stmt{Position: recoveredPos}
} else {
p.followErr(b.OpPos, b.Op.String(), "a statement")
break
}
p.followErr(b.OpPos, b.Op.String(), "a statement")
break
}
s = &Stmt{Position: s.Position}
s.Cmd = b
Expand Down
9 changes: 9 additions & 0 deletions syntax/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2618,12 +2618,21 @@ func TestParseRecoverErrors(t *testing.T) {
printer := NewPrinter()
for _, tc := range tests {
t.Run("", func(t *testing.T) {
t.Logf("input: %s", tc.src)
r := strings.NewReader(tc.src)
f, err := parser.Parse(r, "")
if tc.wantErr {
qt.Assert(t, qt.Not(qt.IsNil(err)))
} else {
qt.Assert(t, qt.IsNil(err))
switch len(f.Stmts) {
case 0:
t.Fatalf("result has no statements")
case 1:
if f.Stmts[0].Pos().IsRecovered() {
t.Fatalf("result is only a recovered statement")
}
}
}
qt.Assert(t, qt.Equals(countRecoveredPositions(reflect.ValueOf(f)), tc.wantMissing))

Expand Down

0 comments on commit 51f18f3

Please sign in to comment.