From bb41e54b0444fcea3fd73bce906c8061f82650d4 Mon Sep 17 00:00:00 2001
From: Soichiro Kashima <soichiro.kashima@gmail.com>
Date: Mon, 27 Jan 2020 23:09:28 +0900
Subject: [PATCH 1/2] Fix failed_prerequisites error

---
 pkg/lint/runner.go | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go
index 56b02cce..8ce01c79 100644
--- a/pkg/lint/runner.go
+++ b/pkg/lint/runner.go
@@ -111,10 +111,29 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
 		}
 	}()
 
+	// pkgs will get dirty while analyzing, which affects to other linters' result.
+	// To avoid this issue, we clone the loaded packages rather than directly using them.
+	oldPackages := lintCtx.Packages
+	oldOriginalPackages := lintCtx.OriginalPackages
+	clone := func(pkgs []*gopackages.Package) []*gopackages.Package {
+		clonedPkgs := make([]*gopackages.Package, len(pkgs))
+		for i, pkg := range pkgs {
+			p := *pkg
+			clonedPkgs[i] = &p
+		}
+		return clonedPkgs
+	}
+	lintCtx.Packages = clone(lintCtx.Packages)
+	lintCtx.OriginalPackages = clone(lintCtx.OriginalPackages)
+
 	specificLintCtx := *lintCtx
 	specificLintCtx.Log = r.Log.Child(lc.Name())
 
 	issues, err := lc.Linter.Run(ctx, &specificLintCtx)
+
+	lintCtx.Packages = oldPackages
+	lintCtx.OriginalPackages = oldOriginalPackages
+
 	if err != nil {
 		return nil, err
 	}

From 796b4fffbe35d1a9fc4d36180d1911b5d14649da Mon Sep 17 00:00:00 2001
From: Soichiro Kashima <soichiro.kashima@gmail.com>
Date: Tue, 28 Jan 2020 16:04:43 +0900
Subject: [PATCH 2/2] Clear part of package fields before analysis

---
 pkg/lint/linter/context.go | 17 +++++++++++++++++
 pkg/lint/runner.go         | 23 ++++-------------------
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/pkg/lint/linter/context.go b/pkg/lint/linter/context.go
index 1c4902e1..a9f9d7d7 100644
--- a/pkg/lint/linter/context.go
+++ b/pkg/lint/linter/context.go
@@ -1,6 +1,8 @@
 package linter
 
 import (
+	"go/ast"
+
 	"golang.org/x/tools/go/packages"
 
 	"github.com/golangci/golangci-lint/internal/pkgcache"
@@ -30,3 +32,18 @@ type Context struct {
 func (c *Context) Settings() *config.LintersSettings {
 	return &c.Cfg.LintersSettings
 }
+
+func (c *Context) ClearTypesInPackages() {
+	for _, p := range c.Packages {
+		clearTypes(p)
+	}
+	for _, p := range c.OriginalPackages {
+		clearTypes(p)
+	}
+}
+
+func clearTypes(p *packages.Package) {
+	p.Types = nil
+	p.TypesInfo = nil
+	p.Syntax = []*ast.File{}
+}
diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go
index 8ce01c79..4dc40f3f 100644
--- a/pkg/lint/runner.go
+++ b/pkg/lint/runner.go
@@ -111,29 +111,14 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
 		}
 	}()
 
-	// pkgs will get dirty while analyzing, which affects to other linters' result.
-	// To avoid this issue, we clone the loaded packages rather than directly using them.
-	oldPackages := lintCtx.Packages
-	oldOriginalPackages := lintCtx.OriginalPackages
-	clone := func(pkgs []*gopackages.Package) []*gopackages.Package {
-		clonedPkgs := make([]*gopackages.Package, len(pkgs))
-		for i, pkg := range pkgs {
-			p := *pkg
-			clonedPkgs[i] = &p
-		}
-		return clonedPkgs
-	}
-	lintCtx.Packages = clone(lintCtx.Packages)
-	lintCtx.OriginalPackages = clone(lintCtx.OriginalPackages)
-
 	specificLintCtx := *lintCtx
 	specificLintCtx.Log = r.Log.Child(lc.Name())
 
+	// Packages in lintCtx might be dirty due to the last analysis,
+	// which affects to the next analysis.
+	// To avoid this issue, we clear type information from the packages.
+	specificLintCtx.ClearTypesInPackages()
 	issues, err := lc.Linter.Run(ctx, &specificLintCtx)
-
-	lintCtx.Packages = oldPackages
-	lintCtx.OriginalPackages = oldOriginalPackages
-
 	if err != nil {
 		return nil, err
 	}