@@ -16,6 +16,7 @@ import (
16
16
"golang.org/x/tools/internal/lsp/protocol"
17
17
"golang.org/x/tools/internal/lsp/source"
18
18
"golang.org/x/tools/internal/xcontext"
19
+ "golang.org/x/xerrors"
19
20
)
20
21
21
22
type diagnosticKey struct {
@@ -61,13 +62,13 @@ func (s *Server) diagnose(ctx context.Context, snapshot source.Snapshot, alwaysA
61
62
var wg sync.WaitGroup
62
63
63
64
// Diagnose the go.mod file.
64
- reports , err := mod .Diagnostics (ctx , snapshot )
65
- if err != nil {
66
- event .Error (ctx , "warning: diagnose go.mod" , err , tag .Directory .Of (snapshot .View ().Folder ().Filename ()))
67
- }
65
+ reports , modErr := mod .Diagnostics (ctx , snapshot )
68
66
if ctx .Err () != nil {
69
67
return nil , nil
70
68
}
69
+ if modErr != nil {
70
+ event .Error (ctx , "warning: diagnose go.mod" , modErr , tag .Directory .Of (snapshot .View ().Folder ().Filename ()))
71
+ }
71
72
for id , diags := range reports {
72
73
if id .URI == "" {
73
74
event .Error (ctx , "missing URI for module diagnostics" , fmt .Errorf ("empty URI" ), tag .Directory .Of (snapshot .View ().Folder ().Filename ()))
@@ -83,7 +84,19 @@ func (s *Server) diagnose(ctx context.Context, snapshot source.Snapshot, alwaysA
83
84
// Diagnose all of the packages in the workspace.
84
85
wsPackages , err := snapshot .WorkspacePackages (ctx )
85
86
if err != nil {
86
- s .handleFatalErrors (ctx , snapshot , err )
87
+ // Try constructing a more helpful error message out of this error.
88
+ if s .handleFatalErrors (ctx , snapshot , modErr , err ) {
89
+ return nil , nil
90
+ }
91
+ msg := `The code in the workspace failed to compile (see the error message below).
92
+ If you believe this is a mistake, please file an issue: https://github.com/golang/go/issues/new.`
93
+ event .Error (ctx , msg , err , tag .Snapshot .Of (snapshot .ID ()), tag .Directory .Of (snapshot .View ().Folder ()))
94
+ if err := s .client .ShowMessage (ctx , & protocol.ShowMessageParams {
95
+ Type : protocol .Error ,
96
+ Message : fmt .Sprintf ("%s\n %v" , msg , err ),
97
+ }); err != nil {
98
+ event .Error (ctx , "ShowMessage failed" , err , tag .Directory .Of (snapshot .View ().Folder ()))
99
+ }
87
100
return nil , nil
88
101
}
89
102
var shows * protocol.ShowMessageParams
@@ -229,8 +242,15 @@ func toProtocolDiagnostics(diagnostics []*source.Diagnostic) []protocol.Diagnost
229
242
return reports
230
243
}
231
244
232
- func (s * Server ) handleFatalErrors (ctx context.Context , snapshot source.Snapshot , err error ) {
233
- switch err {
245
+ func (s * Server ) handleFatalErrors (ctx context.Context , snapshot source.Snapshot , modErr , loadErr error ) bool {
246
+ modURI := snapshot .View ().ModFile ()
247
+
248
+ // We currently only have workarounds for errors associated with modules.
249
+ if modURI == "" {
250
+ return false
251
+ }
252
+
253
+ switch loadErr {
234
254
case source .InconsistentVendoring :
235
255
item , err := s .client .ShowMessageRequest (ctx , & protocol.ShowMessageRequestParams {
236
256
Type : protocol .Error ,
@@ -240,27 +260,45 @@ See https://github.com/golang/go/issues/39164 for more detail on this issue.`,
240
260
{Title : "go mod vendor" },
241
261
},
242
262
})
243
- if item == nil || err != nil {
263
+ // If the user closes the pop-up, don't show them further errors.
264
+ if item == nil {
265
+ return true
266
+ }
267
+ if err != nil {
244
268
event .Error (ctx , "go mod vendor ShowMessageRequest failed" , err , tag .Directory .Of (snapshot .View ().Folder ()))
245
- return
269
+ return true
246
270
}
247
- modURI := snapshot .View ().ModFile ()
248
271
if err := s .directGoModCommand (ctx , protocol .URIFromSpanURI (modURI ), "mod" , []string {"vendor" }... ); err != nil {
249
272
if err := s .client .ShowMessage (ctx , & protocol.ShowMessageParams {
250
273
Type : protocol .Error ,
251
274
Message : fmt .Sprintf (`"go mod vendor" failed with %v` , err ),
252
275
}); err != nil {
253
- event .Error (ctx , "ShowMessage failed" , err )
276
+ if err != nil {
277
+ event .Error (ctx , "go mod vendor ShowMessage failed" , err , tag .Directory .Of (snapshot .View ().Folder ()))
278
+ }
254
279
}
255
280
}
256
- default :
257
- msg := "failed to load workspace packages, skipping diagnostics"
258
- event .Error (ctx , msg , err , tag .Snapshot .Of (snapshot .ID ()), tag .Directory .Of (snapshot .View ().Folder ()))
259
- if err := s .client .ShowMessage (ctx , & protocol.ShowMessageParams {
260
- Type : protocol .Error ,
261
- Message : fmt .Sprintf ("%s: %v" , msg , err ),
262
- }); err != nil {
263
- event .Error (ctx , "ShowMessage failed" , err , tag .Directory .Of (snapshot .View ().Folder ()))
281
+ return true
282
+ }
283
+ // If there is a go.mod-related error, as well as a workspace load error,
284
+ // there is likely an issue with the go.mod file. Try to parse the error
285
+ // message and create a diagnostic.
286
+ if modErr == nil {
287
+ return false
288
+ }
289
+ if xerrors .Is (loadErr , source .PackagesLoadError ) {
290
+ fh , err := snapshot .GetFile (ctx , modURI )
291
+ if err != nil {
292
+ return false
264
293
}
294
+ diag , err := mod .ExtractGoCommandError (ctx , snapshot , fh , loadErr )
295
+ if err != nil {
296
+ return false
297
+ }
298
+ s .publishReports (ctx , snapshot , map [diagnosticKey ][]* source.Diagnostic {
299
+ {id : fh .Identity ()}: {diag },
300
+ })
301
+ return true
265
302
}
303
+ return false
266
304
}
0 commit comments