Repository: go-critic/go-critic (go)

Issue:
exitAfterDefer: false positive
Using latest golangci-lint, found something which looks like false positive
Possibly related: #995

```go
        var Response *http.Response
	if Response, Error = client.Do(Request); Error == nil {
		defer Response.Body.Close()
	} else {
		fmt.Println("[client.Do]", Error)
		os.Exit(1)
	}
```
```
cmd\GitHubReleasesAssets\json.go:41:3: exitAfterDefer: os.Exit will exit, and `defer Response.Body.Close()` will not run (gocritic)
                os.Exit(1)
                ^
```
If snippet is not enough, source can be found [here](https://github.com/wipe2238/GitHubReleasesAssets/blob/0622654bf631128b994d76824336d164a27400bb/cmd/GitHubReleasesAssets/json.go#L36-L42)

Pull request description:
checkers/exitAfterDefer: handle optional `defer` properly
This will correct a false positive reported in https://github.com/go-critic/go-critic/issues/1421

Let me know if there are any other alterations needed.

Thank you!

Fixes #1421

Patch:
diff --git a/checkers/exitAfterDefer_checker.go b/checkers/exitAfterDefer_checker.go
index 9889f48..19b20e4 100644
--- a/checkers/exitAfterDefer_checker.go
+++ b/checkers/exitAfterDefer_checker.go
@@ -45,6 +45,12 @@ func (c *exitAfterDeferChecker) VisitFuncDecl(fn *ast.FuncDecl) {
 
 	var deferStmt *ast.DeferStmt
 	pre := func(cur *astutil.Cursor) bool {
+		// If we found a defer statement in the function post traversal.
+		// and are looking at the Else branch during a pre traversal, stop seeking as it could be false positive.
+		if deferStmt != nil && cur.Name() == "Else" {
+			return false
+		}
+
 		// Don't recurse into local anonymous functions.
 		return !astp.IsFuncLit(cur.Node())
 	}


Test patch:
diff --git a/checkers/testdata/exitAfterDefer/negative_tests.go b/checkers/testdata/exitAfterDefer/negative_tests.go
index 77074ea..5de7166 100644
--- a/checkers/testdata/exitAfterDefer/negative_tests.go
+++ b/checkers/testdata/exitAfterDefer/negative_tests.go
@@ -53,3 +53,11 @@ func justDefer() {
 func noDefers() {
 	println("")
 }
+
+func neverOsExitAndCallADefer() {
+	if true {
+		defer println("I'm deferred and will possibly run")
+	} else {
+		os.Exit(1)
+	}
+}