diff --git a/private/buf/buflsp/file.go b/private/buf/buflsp/file.go index c835f82a23..2103dff795 100644 --- a/private/buf/buflsp/file.go +++ b/private/buf/buflsp/file.go @@ -169,7 +169,7 @@ func (f *file) Refresh(ctx context.Context) { progress.Begin(ctx, "Indexing") progress.Report(ctx, "Parsing AST", 1.0/6) - hasReport := f.RefreshAST(ctx) + f.RefreshAST(ctx) progress.Report(ctx, "Indexing Imports", 2.0/6) f.IndexImports(ctx) @@ -179,15 +179,17 @@ func (f *file) Refresh(ctx context.Context) { progress.Report(ctx, "Linking Descriptors", 4.0/6) f.BuildImage(ctx) - hasReport = f.RunLints(ctx) || hasReport // Avoid short-circuit here. + f.RunLints(ctx) progress.Report(ctx, "Indexing Symbols", 5.0/6) f.IndexSymbols(ctx) progress.Done(ctx) - if hasReport { - f.PublishDiagnostics(ctx) - } + + // NOTE: Diagnostics are published unconditionally. This is necessary even + // if we have zero diagnostics, so that the client correctly ticks over from + // n > 0 diagnostics to 0 diagnostics. + f.PublishDiagnostics(ctx) } // RefreshAST reparses the file and generates diagnostics if necessary. @@ -232,8 +234,11 @@ func (f *file) RefreshAST(ctx context.Context) bool { func (f *file) PublishDiagnostics(ctx context.Context) { defer slogext.DebugProfile(f.lsp.logger, slog.String("uri", string(f.uri)))() + // NOTE: We need to avoid sending a JSON null here, so we replace it with + // a non-nil empty slice when the diagnostics slice is nil. + diagnostics := f.diagnostics if f.diagnostics == nil { - return + diagnostics = []protocol.Diagnostic{} } // Publish the diagnostics. This error is automatically logged by the LSP framework. @@ -242,7 +247,7 @@ func (f *file) PublishDiagnostics(ctx context.Context) { // NOTE: For some reason, Version is int32 in the document struct, but uint32 here. // This seems like a bug in the LSP protocol package. Version: uint32(f.version), - Diagnostics: f.diagnostics, + Diagnostics: diagnostics, }) }