@@ -26,8 +26,8 @@ import (
2626// idWithAnalysis is used to track if the diagnostics for a given file were
2727// computed with analyses.
2828type idWithAnalysis struct {
29- id source.VersionedFileIdentity
30- withAnalysis bool
29+ id source.VersionedFileIdentity
30+ includeAnalysis bool
3131}
3232
3333// A reportSet collects diagnostics for publication, sorting them by file and
@@ -38,15 +38,15 @@ type reportSet struct {
3838 reports map [idWithAnalysis ]map [string ]* source.Diagnostic
3939}
4040
41- func (s * reportSet ) add (id source.VersionedFileIdentity , withAnalysis bool , diags ... * source.Diagnostic ) {
41+ func (s * reportSet ) add (id source.VersionedFileIdentity , includeAnalysis bool , diags ... * source.Diagnostic ) {
4242 s .mu .Lock ()
4343 defer s .mu .Unlock ()
4444 if s .reports == nil {
4545 s .reports = make (map [idWithAnalysis ]map [string ]* source.Diagnostic )
4646 }
4747 key := idWithAnalysis {
48- id : id ,
49- withAnalysis : withAnalysis ,
48+ id : id ,
49+ includeAnalysis : includeAnalysis ,
5050 }
5151 if _ , ok := s .reports [key ]; ! ok {
5252 s .reports [key ] = map [string ]* source.Diagnostic {}
@@ -79,7 +79,7 @@ func (s *Server) diagnoseDetached(snapshot source.Snapshot) {
7979 // If a view has been created or the configuration changed, warn the user.
8080 s .client .ShowMessage (ctx , shows )
8181 }
82- s .publishReports (ctx , snapshot , reports )
82+ s .publishReports (ctx , snapshot , reports , false )
8383}
8484
8585func (s * Server ) diagnoseSnapshot (snapshot source.Snapshot , changedURIs []span.URI ) {
@@ -99,17 +99,17 @@ func (s *Server) diagnoseSnapshot(snapshot source.Snapshot, changedURIs []span.U
9999 event .Error (ctx , "diagnosing changed files" , err )
100100 }
101101 }
102- s .publishReports (ctx , snapshot , reports )
102+ s .publishReports (ctx , snapshot , reports , true )
103103 s .debouncer .debounce (snapshot .View ().Name (), snapshot .ID (), delay , func () {
104104 reports , _ := s .diagnose (ctx , snapshot , false )
105- s .publishReports (ctx , snapshot , reports )
105+ s .publishReports (ctx , snapshot , reports , false )
106106 })
107107 return
108108 }
109109
110110 // Ignore possible workspace configuration warnings in the normal flow.
111111 reports , _ := s .diagnose (ctx , snapshot , false )
112- s .publishReports (ctx , snapshot , reports )
112+ s .publishReports (ctx , snapshot , reports , false )
113113}
114114
115115func (s * Server ) diagnoseChangedFiles (ctx context.Context , snapshot source.Snapshot , uris []span.URI ) (* reportSet , error ) {
@@ -215,11 +215,11 @@ If you believe this is a mistake, please file an issue: https://github.com/golan
215215 go func (pkg source.Package ) {
216216 defer wg .Done ()
217217
218- withAnalysis := alwaysAnalyze // only run analyses for packages with open files
219- var gcDetailsDir span.URI // find the package's optimization details, if available
218+ includeAnalysis := alwaysAnalyze // only run analyses for packages with open files
219+ var gcDetailsDir span.URI // find the package's optimization details, if available
220220 for _ , pgf := range pkg .CompiledGoFiles () {
221221 if snapshot .IsOpen (pgf .URI ) {
222- withAnalysis = true
222+ includeAnalysis = true
223223 }
224224 if gcDetailsDir == "" {
225225 dirURI := span .URIFromPath (filepath .Dir (pgf .URI .Filename ()))
@@ -232,7 +232,7 @@ If you believe this is a mistake, please file an issue: https://github.com/golan
232232 }
233233 }
234234
235- pkgReports , warn , err := source .Diagnostics (ctx , snapshot , pkg , withAnalysis )
235+ pkgReports , warn , err := source .Diagnostics (ctx , snapshot , pkg , includeAnalysis )
236236
237237 // Check if might want to warn the user about their build configuration.
238238 // Our caller decides whether to send the message.
@@ -251,7 +251,7 @@ If you believe this is a mistake, please file an issue: https://github.com/golan
251251
252252 // Add all reports to the global map, checking for duplicates.
253253 for id , diags := range pkgReports {
254- reports .add (id , withAnalysis , diags ... )
254+ reports .add (id , includeAnalysis , diags ... )
255255 }
256256 // If gc optimization details are available, add them to the
257257 // diagnostic reports.
@@ -261,7 +261,7 @@ If you believe this is a mistake, please file an issue: https://github.com/golan
261261 event .Error (ctx , "warning: gc details" , err , tag .Snapshot .Of (snapshot .ID ()))
262262 }
263263 for id , diags := range gcReports {
264- reports .add (id , withAnalysis , diags ... )
264+ reports .add (id , includeAnalysis , diags ... )
265265 }
266266 }
267267 }(pkg )
@@ -274,10 +274,10 @@ If you believe this is a mistake, please file an issue: https://github.com/golan
274274 // Check if we already have diagnostic reports for the given file,
275275 // meaning that we have already seen its package.
276276 var seen bool
277- for _ , withAnalysis := range []bool {true , false } {
277+ for _ , includeAnalysis := range []bool {true , false } {
278278 _ , ok := reports .reports [idWithAnalysis {
279- id : o .VersionedFileIdentity (),
280- withAnalysis : withAnalysis ,
279+ id : o .VersionedFileIdentity (),
280+ includeAnalysis : includeAnalysis ,
281281 }]
282282 seen = seen || ok
283283 }
@@ -349,7 +349,7 @@ func errorsToDiagnostic(ctx context.Context, snapshot source.Snapshot, errors []
349349 return nil
350350}
351351
352- func (s * Server ) publishReports (ctx context.Context , snapshot source.Snapshot , reports * reportSet ) {
352+ func (s * Server ) publishReports (ctx context.Context , snapshot source.Snapshot , reports * reportSet , isFirstPass bool ) {
353353 // Check for context cancellation before publishing diagnostics.
354354 if ctx .Err () != nil || reports == nil {
355355 return
@@ -370,10 +370,10 @@ func (s *Server) publishReports(ctx context.Context, snapshot source.Snapshot, r
370370 }
371371 source .SortDiagnostics (diagnostics )
372372 toSend := sentDiagnostics {
373- id : key .id ,
374- sorted : diagnostics ,
375- withAnalysis : key .withAnalysis ,
376- snapshotID : snapshot .ID (),
373+ id : key .id ,
374+ sorted : diagnostics ,
375+ includeAnalysis : key .includeAnalysis ,
376+ snapshotID : snapshot .ID (),
377377 }
378378
379379 // We use the zero values if this is an unknown file.
@@ -382,10 +382,11 @@ func (s *Server) publishReports(ctx context.Context, snapshot source.Snapshot, r
382382 // Snapshot IDs are always increasing, so we use them instead of file
383383 // versions to create the correct order for diagnostics.
384384
385- // If we've already delivered diagnostics for a future snapshot for this file,
386- // do not deliver them.
385+ // If we've already delivered diagnostics for a future snapshot for
386+ // this file, do not deliver them.
387387 if delivered .snapshotID > toSend .snapshotID {
388- // Do not update the delivered map since it already contains newer diagnostics.
388+ // Do not update the delivered map since it already contains newer
389+ // diagnostics.
389390 continue
390391 }
391392
@@ -399,10 +400,18 @@ func (s *Server) publishReports(ctx context.Context, snapshot source.Snapshot, r
399400 // If we've already delivered diagnostics for this file, at this
400401 // snapshot, with analyses, do not send diagnostics without analyses.
401402 if delivered .snapshotID == toSend .snapshotID && delivered .id == toSend .id &&
402- delivered .withAnalysis && ! toSend .withAnalysis {
403+ delivered .includeAnalysis && ! toSend .includeAnalysis {
403404 // Do not update the delivered map since it already contains better diagnostics.
404405 continue
405406 }
407+
408+ // If we've previously delivered non-empty diagnostics and this is a
409+ // first diagnostic pass, wait for a subsequent pass to complete before
410+ // sending empty diagnostics to avoid flickering diagnostics.
411+ if isFirstPass && delivered .includeAnalysis && ! toSend .includeAnalysis && len (toSend .sorted ) == 0 {
412+ continue
413+ }
414+
406415 if err := s .client .PublishDiagnostics (ctx , & protocol.PublishDiagnosticsParams {
407416 Diagnostics : toProtocolDiagnostics (diagnostics ),
408417 URI : protocol .URIFromSpanURI (key .id .URI ),
0 commit comments