diff --git a/wsl.go b/wsl.go index 696ca6b..9bc0fe2 100644 --- a/wsl.go +++ b/wsl.go @@ -414,6 +414,25 @@ func (p *Processor) parseBlockStatements(statements []ast.Stmt) { continue } + // Special treatment of deferring body closes after error checking + // according to best practices. See + // https://github.com/bombsimon/wsl/issues/31 which links to + // discussion about error handling after HTTP requests. This is hard + // coded and very specific but for now this is to be seen as a + // special case. What this does is that it *only* allows a defer + // statement with `Close` on the right hand side to be cuddled with + // an if-statement to support this: + // resp, err := client.Do(req) + // if err != nil { + // return err + // } + // defer resp.Body.Close() + if _, ok := previousStatement.(*ast.IfStmt); ok { + if atLeastOneInListsMatch(rightHandSide, []string{"Close"}) { + continue + } + } + if moreThanOneStatementAbove() { p.addError(t.Pos(), "only one cuddle assignment allowed before defer statement") diff --git a/wsl_test.go b/wsl_test.go index f509d18..dcd2927 100644 --- a/wsl_test.go +++ b/wsl_test.go @@ -1055,6 +1055,18 @@ func TestShouldAddEmptyLines(t *testing.T) { "block should not end with a whitespace (or comment)", }, }, + { + description: "allow http body close best practice", + code: []byte(`package main + + func main() { + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + }`), + }, } for _, tc := range cases {