This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Add support TextDocumentEdit.
ClosedPublic

Authored by hokein on Apr 20 2023, 12:13 AM.

Details

Summary

This is an initial patch to add TextDocumentEdit (versioned edits) support in
clangd, the scope is minimal:

  • add and extend the corresponding protocol structures
  • propagate the documentChanges for diagnostic codeactions (our motivated case)

Diff Detail

Event Timeline

hokein created this revision.Apr 20 2023, 12:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 20 2023, 12:13 AM
Herald added a subscriber: arphaman. · View Herald Transcript
hokein requested review of this revision.Apr 20 2023, 12:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 20 2023, 12:13 AM
hokein added inline comments.Apr 20 2023, 12:16 AM
clang-tools-extra/clangd/ClangdLSPServer.cpp
1722

This part of code is moved from the toLSPDiags, we can keep it unchanged then we have to pass the Version and SupportsDocumentChanges to toLSPDiags which makes the API ugly. Open for ideas.

hokein updated this revision to Diff 515230.Apr 20 2023, 12:16 AM

add missing test.

can you also have a version of the clang-tools-extra/clangd/test/fixits-command.test with documentChanges support? it's unlikely to have clients in that configuration but i believe the deserialization issue i mentioned above would be discoverable by such a test.

clang-tools-extra/clangd/ClangdLSPServer.cpp
1722

no i think it makes more sense in LSP layer, as it's an LSP extension. I believe we had it in the guts because i believe we were using it internally with a client that doesn't use LSPServer at some point.

it would be better to drop the extension but i see that qt-creator & sourcekit-lsp has mentions of this :/ so as I mentioned above, we can convert the fixes to CodeActions here unconditionally (it's not more expensive than the copy we perform today). afterwards we only make copying those CodeActions into the Diag conditioned on the capability.

clang-tools-extra/clangd/ClangdLSPServer.h
201–202

instead of a pair maybe a:

struct VersionedFixes {
  std::optional<int64_t> DocumentVersion;
  std::vector<Fix> Fixes;
};
236

can we instead have a:

std::map<clangd::Diagnostic, std::vector<CodeAction>, LSPDiagnosticCompare> Fixes;

We'll make sure we store code actions with necessary version information.
That way FixItsMap can stay the same, and rest of the code will look more uniform; we'll do the conversion from Fixes to CodeActions during onDiagnosticsReady

clang-tools-extra/clangd/Diagnostics.cpp
426–428

we can now move this into clangdlsperver.cpp

clang-tools-extra/clangd/Protocol.cpp
735

we actually want O.mapOptional for both "changes" and "documentChanges".

hokein updated this revision to Diff 515671.Apr 21 2023, 3:31 AM
hokein marked 2 inline comments as done.

address review comments

can you also have a version of the clang-tools-extra/clangd/test/fixits-command.test with documentChanges support? it's unlikely to have clients in that configuration but i believe the deserialization issue i mentioned above would be discoverable by such a test.

I'm happy to add a test for that, but I'm not sure the deserialization issue you mentioned in the comment, is the one to use mapOptional?

clang-tools-extra/clangd/ClangdLSPServer.h
201–202

we don't need this struct now, as we switch to store the CodeAction.

236

good idea!

clang-tools-extra/clangd/Protocol.cpp
735

I think map is a better fit here, it has a specific version of std::optional, see https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Support/JSON.h#L852.

mapOptional doesn't set the field when missing the key in json object,

nridge added a subscriber: nridge.Apr 22 2023, 3:45 PM

can you also have a version of the clang-tools-extra/clangd/test/fixits-command.test with documentChanges support? it's unlikely to have clients in that configuration but i believe the deserialization issue i mentioned above would be discoverable by such a test.

I'm happy to add a test for that, but I'm not sure the deserialization issue you mentioned in the comment, is the one to use mapOptional?

yes it was for mapOptional, which turns out not to be an issue as there's a specialization for optional<T>.

but still having that test to verify deserialization logic wouldn't hurt.

clang-tools-extra/clangd/ClangdLSPServer.cpp
1728

we didn't have the empty check before, let's not introduce it now (i.e. we'll still reply with an empty set of code actions rather than "none" when there are no fixes known to clangd)

1731–1734

i am not sure why this logic was appending to the vector rather than just overwriting. but we shouldn't receive the same diagnostics from the callback here, am i missing something? so what about just:

LocalFixIts[Diag] = std::move(CodeActions);
clang-tools-extra/clangd/Protocol.cpp
735

yeah you're right, i missed the specialization of map for optional<T>

hokein updated this revision to Diff 516702.Apr 25 2023, 1:23 AM

address review comments, added one more test for command code-actions

clang-tools-extra/clangd/ClangdLSPServer.cpp
1728

yeah, I added this empty check to keep fixits-embed-in-diagnostic.test unchanged (we don't emit code-action for diagnostic notes), but I think it is fair enough to change it.

1731–1734

Agreed, changed to overwriting.

kadircet accepted this revision.Apr 25 2023, 3:10 AM

thanks!

clang-tools-extra/clangd/ClangdLSPServer.cpp
1680

nit: let's keep llvm::StringRef

This revision is now accepted and ready to land.Apr 25 2023, 3:10 AM
hokein updated this revision to Diff 516734.Apr 25 2023, 3:52 AM
hokein marked an inline comment as done.

update and rebase

This revision was landed with ongoing or failed builds.Apr 25 2023, 4:07 AM
This revision was automatically updated to reflect the committed changes.

Hi, these tests are failing on our (Linaro's) Windows on Arm buildbot. First appearance here https://lab.llvm.org/buildbot/#/builders/65/builds/9346

Still failing as of a few hours ago https://lab.llvm.org/buildbot/#/builders/65/builds/9360 (maybe you have fixed this already, I am checking in infrequently over the next few days).

If you need any help debugging it let me know. It appears there is a drive letter on Windows:

# CHECK-NEXT:              "uri": "file:///clangd-test/foo.c",
                           ^
<stdin>:224:30: note: scanning from here
            "textDocument": {
                             ^
<stdin>:225:15: note: possible intended match here
              "uri": "file:///C:/clangd-test/foo.c",
              ^

Hi, these tests are failing on our (Linaro's) Windows on Arm buildbot. First appearance here https://lab.llvm.org/buildbot/#/builders/65/builds/9346

Still failing as of a few hours ago https://lab.llvm.org/buildbot/#/builders/65/builds/9360 (maybe you have fixed this already, I am checking in infrequently over the next few days).

If you need any help debugging it let me know. It appears there is a drive letter on Windows:

# CHECK-NEXT:              "uri": "file:///clangd-test/foo.c",
                           ^
<stdin>:224:30: note: scanning from here
            "textDocument": {
                             ^
<stdin>:225:15: note: possible intended match here
              "uri": "file:///C:/clangd-test/foo.c",
              ^

sorry for the breakage, looking now.