This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Introduce pullDiags endpoint
ClosedPublic

Authored by kadircet on Mar 15 2021, 2:37 AM.

Details

Summary

Implement initial support for pull-based diagnostics in ClangdServer.
This is planned for LSP 3.17, and initial proposal is in
https://github.com/microsoft/vscode-languageserver-node/blob/d15eb0671e0947d14e3548d13754104ee13aa56d/protocol/src/common/proposed.diagnostic.ts#L111.

We chose to serve the requests only when clangd has a fresh preamble
available. In case of a stale preamble we just drop the request on the
floor.

This patch doesn't plumb this to LSP layer yet, as pullDiags is still a
proposal with only an implementation in vscode.

Diff Detail

Event Timeline

kadircet created this revision.Mar 15 2021, 2:37 AM
kadircet requested review of this revision.Mar 15 2021, 2:37 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 15 2021, 2:37 AM
kadircet updated this revision to Diff 330585.Mar 15 2021, 2:38 AM
  • Add fixme for the error code.

Thanks, nice to see this isn't going to require deep changes, and looking forward to seeing the diagnostics performance improvements.
(I wonder if we'll end up in the perverse situation where clangd is faster for most operations when your preamble is stale :-D Probably not...)

This patch doesn't plumb this to LSP layer yet, as pullDiags is still a proposal with only an implementation in vscode.

Based on our experiences with LSP + VSCode, I don't think that should stop us - I think it's OK for us to make incompatible changes to a newly-added request that hasn't been in any major release yet.
That said, good to keep it out of this patch for size reasons alone :-)

clang-tools-extra/clangd/ClangdServer.cpp
85–87

Replace comment with assert(AST.getDiagnostics().hasValue() && "We issue callback only with fresh preambles")?

clang-tools-extra/clangd/ClangdServer.h
72

Describe the relationship with the pull diagnostic method? (e.g. opposite of comment suggested below)

353

nit: "busy" is very vague - server is busy (building a preamble)?

354

I assume you mean if retried here.
This isn't a great access pattern though, it creates a useless loop of creating ASTs (or fetching them from cache?) until the preamble is ready. We really want people to retry after onSemanticsMaybeChanged right? So we need to guarantee that will work.

Maybe "If it fails, clients should wait for onSemanticsMaybeChanged and then retry."

355

Naming:

  • "diagnostics" rather than "diags" (clangd::Diag is an awkward name to avoid a collision with the LSP struct).
  • the "pull" nature is already in the signature, and while the push/pull distinction is very important to us now, I'm not sure it's central enough to put in the name. Rather maybe explain the relationship between them in the doc comment: "These 'pulled' diagnostics do not interfere with the diagnostics 'pushed' to Callbacks::onDiagnosticsReady, and clients may use either or both."
clang-tools-extra/clangd/ParsedAST.cpp
270–271

This is a slightly confusing/strange structure, because the triviality is a property of the patch, and determined when creating, not when applying.

I'd consider instead something more explicit like:

Patch = PreamblePatch::create(...);
PatchedPreamble = Patch.preservesDiagnostics(); // and rename PatchedPreamble variable.
Patch->apply(*CI);

This conceptually separates the idea of "diagnostics are trusted" from "patch is a no-op". Maybe we want to keep these identical forever, but I think PreamblePatch is the right place to express that decision.

(This isn't a big deal though, up to you)

clang-tools-extra/clangd/ParsedAST.h
91–93

please don't declare API methods with auto if we can avoid it :-)

clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
138

This assumption now appears in a bunch of places without comment.
Maybe add The result will always have getDiagnostics() populated to build() in TestTU.h, and assert it inside TestTU.cpp?

clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
1

I think we want unit tests here or in PreambleTests.cpp to show that the diagnostics get not-set appropriately.

(I'm fine with not testing the ClangdServer layer as it's pretty trivial, as long as we plan to have at least a happy-path smoke lit test for the LSP layer)

clang-tools-extra/clangd/unittests/PreambleTests.cpp
282

this doesn't produce a useful failure message.
Maybe gather the ranges into a vector<Range> MacroRefRanges and ASSERT_THAT(MacroRefRanges, Contains(Modified.range())) ?

kadircet marked 10 inline comments as done.Mar 16 2021, 3:20 AM
kadircet added inline comments.
clang-tools-extra/clangd/ParsedAST.h
91–93

oops forgot to fix after testing :D

clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
1

i was hoping some indirect testing of EXPECT_FALSE(PatchedAST->getDiagnostics()) in arbitrary tests to be enough, but you are right. adding an explicit test.

kadircet updated this revision to Diff 330918.Mar 16 2021, 3:20 AM
kadircet marked 2 inline comments as done.
  • Update comments/names
  • Instead of using apply, have a separate preserveDiagnostics API in PreamblePatch.
sammccall accepted this revision.Mar 16 2021, 3:29 AM
sammccall added inline comments.
clang-tools-extra/clangd/ClangdServer.cpp
916

building diagnostics -> parsing includes?

920

nit: PullDiagnostics or Diagnostics

This revision is now accepted and ready to land.Mar 16 2021, 3:29 AM
kadircet updated this revision to Diff 330946.Mar 16 2021, 4:51 AM
kadircet marked 2 inline comments as done.
  • address comments
This revision was landed with ongoing or failed builds.Mar 16 2021, 4:57 AM
This revision was automatically updated to reflect the committed changes.