@@ -68,14 +68,7 @@ func hashDiagnostics(diags ...*source.Diagnostic) string {
6868func (s * Server ) diagnoseDetached (snapshot source.Snapshot ) {
6969 ctx := snapshot .BackgroundContext ()
7070 ctx = xcontext .Detach (ctx )
71- showWarning := s .diagnose (ctx , snapshot , false )
72- if showWarning {
73- // If a view has been created or the configuration changed, warn the user.
74- s .client .ShowMessage (ctx , & protocol.ShowMessageParams {
75- Type : protocol .Warning ,
76- Message : `You are neither in a module nor in your GOPATH. If you are using modules, please open your editor to a directory in your module. If you believe this warning is incorrect, please file an issue: https://github.com/golang/go/issues/new.` ,
77- })
78- }
71+ s .diagnose (ctx , snapshot , false )
7972 s .publishDiagnostics (ctx , true , snapshot )
8073}
8174
@@ -138,22 +131,22 @@ func (s *Server) diagnoseChangedFiles(ctx context.Context, snapshot source.Snaps
138131 go func (pkg source.Package ) {
139132 defer wg .Done ()
140133
141- _ = s .diagnosePkg (ctx , snapshot , pkg , false )
134+ s .diagnosePkg (ctx , snapshot , pkg , false )
142135 }(pkg )
143136 }
144137 wg .Wait ()
145138}
146139
147140// diagnose is a helper function for running diagnostics with a given context.
148141// Do not call it directly. forceAnalysis is only true for testing purposes.
149- func (s * Server ) diagnose (ctx context.Context , snapshot source.Snapshot , forceAnalysis bool ) bool {
142+ func (s * Server ) diagnose (ctx context.Context , snapshot source.Snapshot , forceAnalysis bool ) {
150143 ctx , done := event .Start (ctx , "Server.diagnose" )
151144 defer done ()
152145
153146 // Wait for a free diagnostics slot.
154147 select {
155148 case <- ctx .Done ():
156- return false
149+ return
157150 case s .diagnosticsSema <- struct {}{}:
158151 }
159152 defer func () {
@@ -163,7 +156,7 @@ func (s *Server) diagnose(ctx context.Context, snapshot source.Snapshot, forceAn
163156 // First, diagnose the go.mod file.
164157 modReports , modErr := mod .Diagnostics (ctx , snapshot )
165158 if ctx .Err () != nil {
166- return false
159+ return
167160 }
168161 if modErr != nil {
169162 event .Error (ctx , "warning: diagnose go.mod" , modErr , tag .Directory .Of (snapshot .View ().Folder ().Filename ()), tag .Snapshot .Of (snapshot .ID ()))
@@ -179,7 +172,14 @@ func (s *Server) diagnose(ctx context.Context, snapshot source.Snapshot, forceAn
179172 // Diagnose all of the packages in the workspace.
180173 wsPkgs , err := snapshot .WorkspacePackages (ctx )
181174 if s .shouldIgnoreError (ctx , snapshot , err ) {
182- return false
175+ return
176+ }
177+ // Even if packages didn't fail to load, we still may want to show
178+ // additional warnings.
179+ if err == nil {
180+ if msg := shouldShowAdHocPackagesWarning (snapshot , wsPkgs ); msg != "" {
181+ err = fmt .Errorf (msg )
182+ }
183183 }
184184
185185 // Even if workspace packages were returned, there still may be an error
@@ -198,16 +198,15 @@ func (s *Server) diagnose(ctx context.Context, snapshot source.Snapshot, forceAn
198198 // error progress reports will be closed.
199199 s .showCriticalErrorStatus (ctx , snapshot , err )
200200
201- if err != nil {
202- event .Error (ctx , "errors diagnosing workspace" , err , tag .Snapshot .Of (snapshot .ID ()), tag .Directory .Of (snapshot .View ().Folder ()))
203- return false
201+ // If there are no workspace packages, there is nothing to diagnose and
202+ // there are no orphaned files.
203+ if len (wsPkgs ) == 0 {
204+ return
204205 }
205206
206207 var (
207- wg sync.WaitGroup
208- shouldShowMsgMu sync.Mutex
209- shouldShowMsg bool
210- seen = map [span.URI ]struct {}{}
208+ wg sync.WaitGroup
209+ seen = map [span.URI ]struct {}{}
211210 )
212211 for _ , pkg := range wsPkgs {
213212 wg .Add (1 )
@@ -219,33 +218,26 @@ func (s *Server) diagnose(ctx context.Context, snapshot source.Snapshot, forceAn
219218 go func (pkg source.Package ) {
220219 defer wg .Done ()
221220
222- show := s .diagnosePkg (ctx , snapshot , pkg , forceAnalysis )
223- if show {
224- shouldShowMsgMu .Lock ()
225- shouldShowMsg = true
226- shouldShowMsgMu .Unlock ()
227- }
221+ s .diagnosePkg (ctx , snapshot , pkg , forceAnalysis )
228222 }(pkg )
229223 }
230224 wg .Wait ()
225+
231226 // Confirm that every opened file belongs to a package (if any exist in
232227 // the workspace). Otherwise, add a diagnostic to the file.
233- if len (wsPkgs ) > 0 {
234- for _ , o := range s .session .Overlays () {
235- if _ , ok := seen [o .URI ()]; ok {
236- continue
237- }
238- diagnostic := s .checkForOrphanedFile (ctx , snapshot , o )
239- if diagnostic == nil {
240- continue
241- }
242- s .storeDiagnostics (snapshot , o .URI (), orphanedSource , []* source.Diagnostic {diagnostic })
228+ for _ , o := range s .session .Overlays () {
229+ if _ , ok := seen [o .URI ()]; ok {
230+ continue
243231 }
232+ diagnostic := s .checkForOrphanedFile (ctx , snapshot , o )
233+ if diagnostic == nil {
234+ continue
235+ }
236+ s .storeDiagnostics (snapshot , o .URI (), orphanedSource , []* source.Diagnostic {diagnostic })
244237 }
245- return shouldShowMsg
246238}
247239
248- func (s * Server ) diagnosePkg (ctx context.Context , snapshot source.Snapshot , pkg source.Package , alwaysAnalyze bool ) bool {
240+ func (s * Server ) diagnosePkg (ctx context.Context , snapshot source.Snapshot , pkg source.Package , alwaysAnalyze bool ) {
249241 includeAnalysis := alwaysAnalyze // only run analyses for packages with open files
250242 var gcDetailsDir span.URI // find the package's optimization details, if available
251243 for _ , pgf := range pkg .CompiledGoFiles () {
@@ -271,7 +263,7 @@ func (s *Server) diagnosePkg(ctx context.Context, snapshot source.Snapshot, pkg
271263 reports , err := source .Analyze (ctx , snapshot , pkg , typeCheckResults )
272264 if err != nil {
273265 event .Error (ctx , "warning: diagnose package" , err , tag .Snapshot .Of (snapshot .ID ()), tag .Package .Of (pkg .ID ()))
274- return false
266+ return
275267 }
276268 for uri , diags := range reports {
277269 s .storeDiagnostics (snapshot , uri , analysisSource , diags )
@@ -294,7 +286,6 @@ func (s *Server) diagnosePkg(ctx context.Context, snapshot source.Snapshot, pkg
294286 s .storeDiagnostics (snapshot , id .URI , gcDetailsSource , diags )
295287 }
296288 }
297- return shouldWarn (snapshot , pkg )
298289}
299290
300291// storeDiagnostics stores results from a single diagnostic source. If merge is
@@ -329,21 +320,6 @@ func (s *Server) storeDiagnostics(snapshot source.Snapshot, uri span.URI, dsourc
329320 s .diagnostics [uri ].reports [dsource ] = report
330321}
331322
332- // shouldWarn reports whether we should warn the user about their build
333- // configuration.
334- func shouldWarn (snapshot source.Snapshot , pkg source.Package ) bool {
335- if snapshot .ValidBuildConfiguration () {
336- return false
337- }
338- if len (pkg .MissingDependencies ()) > 0 {
339- return true
340- }
341- if len (pkg .CompiledGoFiles ()) == 1 && hasUndeclaredErrors (pkg ) {
342- return true // The user likely opened a single file.
343- }
344- return false
345- }
346-
347323// clearDiagnosticSource clears all diagnostics for a given source type. It is
348324// necessary for cases where diagnostics have been invalidated by something
349325// other than a snapshot change, for example when gc_details is toggled.
@@ -355,22 +331,24 @@ func (s *Server) clearDiagnosticSource(dsource diagnosticSource) {
355331 }
356332}
357333
358- // hasUndeclaredErrors returns true if a package has a type error
359- // about an undeclared symbol .
360- //
361- // TODO(findleyr): switch to using error codes in 1.16
362- func hasUndeclaredErrors ( pkg source.Package ) bool {
363- for _ , err := range pkg . GetErrors () {
364- if err . Kind != source . TypeError {
365- continue
366- }
367- if strings . Contains ( err . Message , "undeclared name:" ) {
368- return true
334+ const adHocPackagesWarning = `You are outside of a module and outside of $GOPATH/src.
335+ If you are using modules, please open your editor to a directory in your module .
336+ If you believe this warning is incorrect, please file an issue: https://github.com/golang/go/issues/new.`
337+
338+ func shouldShowAdHocPackagesWarning ( snapshot source.Snapshot , pkgs []source. Package ) string {
339+ if snapshot . ValidBuildConfiguration () {
340+ return ""
341+ }
342+ for _ , pkg := range pkgs {
343+ if len ( pkg . MissingDependencies ()) > 0 {
344+ return adHocPackagesWarning
369345 }
370346 }
371- return false
347+ return ""
372348}
373349
350+ const WorkspaceLoadFailure = "Error loading workspace"
351+
374352// showCriticalErrorStatus shows the error as a progress report.
375353// If the error is nil, it clears any existing error progress report.
376354func (s * Server ) showCriticalErrorStatus (ctx context.Context , snapshot source.Snapshot , err error ) {
@@ -381,21 +359,18 @@ func (s *Server) showCriticalErrorStatus(ctx context.Context, snapshot source.Sn
381359 // status bar.
382360 var errMsg string
383361 if err != nil {
384- // Some error messages can also be displayed as diagnostics. But don't
385- // show source.ErrorLists as critical errors--only CriticalErrors
386- // should be shown .
362+ event . Error ( ctx , "errors loading workspace" , err , tag . Snapshot . Of ( snapshot . ID ()), tag . Directory . Of ( snapshot . View (). Folder ()))
363+
364+ // Some error messages can also be displayed as diagnostics .
387365 if criticalErr := (* source .CriticalError )(nil ); errors .As (err , & criticalErr ) {
388366 s .storeErrorDiagnostics (ctx , snapshot , typeCheckSource , criticalErr .ErrorList )
389- } else if srcErrList := (source .ErrorList )(nil ); errors .As (err , & srcErrList ) {
390- s .storeErrorDiagnostics (ctx , snapshot , typeCheckSource , srcErrList )
391- return
392367 }
393368 errMsg = strings .Replace (err .Error (), "\n " , " " , - 1 )
394369 }
395370
396371 if s .criticalErrorStatus == nil {
397372 if errMsg != "" {
398- s .criticalErrorStatus = s .progress .start (ctx , "Error loading workspace" , errMsg , nil , nil )
373+ s .criticalErrorStatus = s .progress .start (ctx , WorkspaceLoadFailure , errMsg , nil , nil )
399374 }
400375 return
401376 }
0 commit comments