Repository: bombsimon/wsl (go)

Issue:
Allow defer statements after error checking
It is good practice to defer a close statement for a HTTP response body after the error check as discussed in https://stackoverflow.com/questions/33238518/what-could-happen-if-i-dont-close-response-body-in-golang#33238755

In my opinion, this defer statement should logically be part of the block where the body originates so I think we should allow the following:

```go
resp, err := client.Do(req)
if err != nil {
    return err
}
defer resp.Body.Close()
```

instead of enforcing the following:

```go
resp, err := client.Do(req)
if err != nil {
    return err
}

defer resp.Body.Close()
```

Pull request description:
Support cuddle http body close with error check
This resolves #31 

The implementation is **very** specific to this use case but I imagine this is the only way not already allowed which should be supported. If there are more cases needed to handle this we can add them later!

Patch:
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")
 


Test patch:
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 {