@@ -11,6 +11,8 @@ import (
11
11
"strings"
12
12
"time"
13
13
14
+ "github.com/golangci/golangci-lint/pkg/logutils"
15
+
14
16
"github.com/golangci/go-tools/ssa"
15
17
"github.com/golangci/go-tools/ssa/ssautil"
16
18
"github.com/golangci/golangci-lint/pkg/config"
@@ -21,6 +23,8 @@ import (
21
23
"golang.org/x/tools/go/loader"
22
24
)
23
25
26
+ var loadDebugf = logutils .Debug ("load" )
27
+
24
28
func isFullImportNeeded (linters []linter.Config ) bool {
25
29
for _ , linter := range linters {
26
30
if linter .NeedsProgramLoading () {
@@ -64,6 +68,89 @@ func normalizePaths(paths []string) ([]string, error) {
64
68
return ret , nil
65
69
}
66
70
71
+ func getCurrentProjectImportPath () (string , error ) {
72
+ gopath := os .Getenv ("GOPATH" )
73
+ if gopath == "" {
74
+ return "" , fmt .Errorf ("no GOPATH env variable" )
75
+ }
76
+
77
+ wd , err := os .Getwd ()
78
+ if err != nil {
79
+ return "" , fmt .Errorf ("can't get workind directory: %s" , err )
80
+ }
81
+
82
+ if ! strings .HasPrefix (wd , gopath ) {
83
+ return "" , fmt .Errorf ("currently no in gopath: %q isn't a prefix of %q" , gopath , wd )
84
+ }
85
+
86
+ path := strings .TrimPrefix (wd , gopath )
87
+ path = strings .TrimPrefix (path , string (os .PathSeparator )) // if GOPATH contains separator at the end
88
+ src := "src" + string (os .PathSeparator )
89
+ if ! strings .HasPrefix (path , src ) {
90
+ return "" , fmt .Errorf ("currently no in gopath/src: %q isn't a prefix of %q" , src , path )
91
+ }
92
+
93
+ path = strings .TrimPrefix (path , src )
94
+ path = strings .Replace (path , string (os .PathSeparator ), "/" , - 1 )
95
+ return path , nil
96
+ }
97
+
98
+ func isLocalProjectAnalysis (args []string ) bool {
99
+ for _ , arg := range args {
100
+ if strings .HasPrefix (arg , ".." ) || filepath .IsAbs (arg ) {
101
+ return false
102
+ }
103
+ }
104
+
105
+ return true
106
+ }
107
+
108
+ func getTypeCheckFuncBodies (cfg * config.Run , linters []linter.Config , pkgProg * packages.Program ) func (string ) bool {
109
+ if ! isLocalProjectAnalysis (cfg .Args ) {
110
+ loadDebugf ("analysis in nonlocal, don't optimize loading by not typechecking func bodies" )
111
+ return nil
112
+ }
113
+
114
+ if isSSAReprNeeded (linters ) {
115
+ loadDebugf ("ssa repr is needed, don't optimize loading by not typechecking func bodies" )
116
+ return nil
117
+ }
118
+
119
+ if len (pkgProg .Dirs ()) == 0 {
120
+ // files run, in this mode packages are fake: can't check their path properly
121
+ return nil
122
+ }
123
+
124
+ projPath , err := getCurrentProjectImportPath ()
125
+ if err != nil {
126
+ logrus .Infof ("can't get cur project path: %s" , err )
127
+ return nil
128
+ }
129
+
130
+ return func (path string ) bool {
131
+ if strings .HasPrefix (path , "." ) {
132
+ loadDebugf ("%s: dot import: typecheck func bodies" , path )
133
+ return true
134
+ }
135
+
136
+ isLocalPath := strings .HasPrefix (path , projPath )
137
+ if isLocalPath {
138
+ localPath := strings .TrimPrefix (path , projPath )
139
+ localPath = strings .TrimPrefix (localPath , "/" )
140
+ if strings .HasPrefix (localPath , "vendor/" ) {
141
+ loadDebugf ("%s: local vendor import: DO NOT typecheck func bodies" , path )
142
+ return false
143
+ }
144
+
145
+ loadDebugf ("%s: local import: typecheck func bodies" , path )
146
+ return true
147
+ }
148
+
149
+ loadDebugf ("%s: not local import: DO NOT typecheck func bodies" , path )
150
+ return false
151
+ }
152
+ }
153
+
67
154
func loadWholeAppIfNeeded (ctx context.Context , linters []linter.Config , cfg * config.Run , pkgProg * packages.Program ) (* loader.Program , * loader.Config , error ) {
68
155
if ! isFullImportNeeded (linters ) {
69
156
return nil , nil , nil
@@ -76,9 +163,10 @@ func loadWholeAppIfNeeded(ctx context.Context, linters []linter.Config, cfg *con
76
163
77
164
bctx := pkgProg .BuildContext ()
78
165
loadcfg := & loader.Config {
79
- Build : bctx ,
80
- AllowErrors : true , // Try to analyze partially
81
- ParserMode : parser .ParseComments , // AST will be reused by linters
166
+ Build : bctx ,
167
+ AllowErrors : true , // Try to analyze partially
168
+ ParserMode : parser .ParseComments , // AST will be reused by linters
169
+ TypeCheckFuncBodies : getTypeCheckFuncBodies (cfg , linters , pkgProg ),
82
170
}
83
171
84
172
var loaderArgs []string
0 commit comments