This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Add option to use dirty file contents when building preambles.
ClosedPublic

Authored by njames93 on Jan 20 2021, 6:54 AM.

Details

Summary

Adds a option use-dirty-preambles to enable using unsaved in editor contents when building pre-ambles.
This enables a more seamless user experience when switching between header and implementation files and forgetting to save inbetween.
It's also in line with the LSP spec that states open files in the editor should be used instead of on the contents on disk - https://microsoft.github.io/language-server-protocol/overviews/lsp/overview/
For now the option is defaulted to off and hidden, Though I have a feeling it should be moved into the .clangd config and possibly defaulted to true.

Addresses https://github.com/clangd/clangd/issues/488

Diff Detail

Event Timeline

njames93 created this revision.Jan 20 2021, 6:54 AM
njames93 requested review of this revision.Jan 20 2021, 6:54 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 15 2022, 3:22 AM
njames93 edited the summary of this revision. (Show Details)Jan 15 2022, 3:24 AM

@sammccall What else is needed for this to go in?

nridge added a subscriber: nridge.Jan 15 2022, 3:35 PM
sammccall accepted this revision.Jan 17 2022, 1:28 AM

Sorry about letting this sit. I think this is good to go, with a naming tweak.

For the 14 cycle, it should be hidden: we may want to tweak the interactions with didSave reparsing etc, and there may be other unexpected wrinkles.

Regarding moving to config: we should do this, but there's some dumb bikeshedding of names (mostly: does this go at the top level or do we want a Parsing block or something, will other things fit in there, etc). So a hidden flag seems like the easiest thing for now.

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

Naming (here and throughout). On reflection the use of "preamble" isn't ideal:

  • it mostly affects the preamble, but not exclusively: #includes in the non-preamble region also use this FS.
  • it's jargony, and if we want to put this in config we should use a friendlier name. Might as well find one now.

I'd suggest a boolean UseDirtyHeaders for now, and if we move it to config then something like HeaderContents: Saved|Dirty.

This revision is now accepted and ready to land.Jan 17 2022, 1:28 AM

Sorry about letting this sit. I think this is good to go, with a naming tweak.

For the 14 cycle, it should be hidden: we may want to tweak the interactions with didSave reparsing etc, and there may be other unexpected wrinkles.

Regarding moving to config: we should do this, but there's some dumb bikeshedding of names (mostly: does this go at the top level or do we want a Parsing block or something, will other things fit in there, etc). So a hidden flag seems like the easiest thing for now.

I've been using this locally for months. The one nit i have is if you edit a header file then switch to a different file, diagnostics aren't updated until you force clangd to reparse the file (by editing it for example).
However I'm not sure of a nice way around this that doesn't involve trying to rebuild the world when you make an edit to a header.

njames93 updated this revision to Diff 400473.Jan 17 2022, 2:14 AM

Update name

Sorry about letting this sit. I think this is good to go, with a naming tweak.

For the 14 cycle, it should be hidden: we may want to tweak the interactions with didSave reparsing etc, and there may be other unexpected wrinkles.

Regarding moving to config: we should do this, but there's some dumb bikeshedding of names (mostly: does this go at the top level or do we want a Parsing block or something, will other things fit in there, etc). So a hidden flag seems like the easiest thing for now.

I've been using this locally for months. The one nit i have is if you edit a header file then switch to a different file, diagnostics aren't updated until you force clangd to reparse the file (by editing it for example).

That's the only real interaction I can think of too.
The didSave trigger for rebuild will still trigger the rebuild too I think. It doesn't make a great deal of sense in this mode, but it may still be a helpful workflow.

However I'm not sure of a nice way around this that doesn't involve trying to rebuild the world when you make an edit to a header.

Agree, this is tricky.

Maybe one idea is a large global debounce: we reparse all files when a header is saved *or* e.g. 30 seconds have passed with no edits to any file.

Exact details could vary, I think important aspects are: rebuilds should not scale with rate of edits, prefer the extra work to happen when relatively idle, clangd should still eventually reach a steady state where it's doing no work until it receives requests.

In any case I'd prefer to land in its current simple form, and land any further bits after the branch cut (soon).

clang-tools-extra/clangd/tool/ClangdMain.cpp
497

Nit: when parsing headers

This revision was landed with ongoing or failed builds.Jan 17 2022, 2:55 AM
This revision was automatically updated to reflect the committed changes.