This patch extends Clangd to allow the clients to specify the preference for how it wants to consume the fixes on the notes. If AllowNotesWithFixes is true in the DiagnosticOptions, then Clangd will keep the notes with the fixes instead of converting to fixes in the main diagnostic. This extension can be enabled by the client using the "clangdNotesWithFixSupport" capability.
Details
Diff Detail
- Repository
- rCTE Clang Tools Extra
Event Timeline
Why do we want an alternative mode for transferring fix-its and notes? Any reason why our current model is bad?
One thing that comes to mind is inconsistency between clang and our model, but I wonder where would it affect the user experience in a bad way?
Our client has a presentation layer with a Clang-based hierarchical model for diagnostics, so we need the original notes. This is a hard requirement in that sense.
Just to make sure I fully understand the use-case: could you elaborate a little more? Do you need to get exactly the same set of notes that clang provides?
Our current model seems to follow the clang's model, but it removes some notes and shows them as fix-its for the main diagnostic instead.
(We think it should provide a better user experience, because those notes do look like a way to present a fix-it to the user when you have only text-based output and they seem redundant when one has an editor-based UI with fix-its).
Not opposed to changing the model to meet other needs, but want to make sure what we're currently doing in clangd makes sense and understand your use-case better.
Yep. We are replacing libclang in a client that currently consumes diagnostics as provided by clang. We'd like to avoid regressions in the client, so we are looking to match the diagnostics provided by clangd, at least for now.
It might be possible to recreate the original hierarchy using the diagnostics that are currently provided by clangd using some heroics on the client-side. However, we'd like to avoid them for now and get the data from Clangd directly :)
Our current model seems to follow the clang's model, but it removes some notes and shows them as fix-its for the main diagnostic instead.
(We think it should provide a better user experience, because those notes do look like a way to present a fix-it to the user when you have only text-based output and they seem redundant when one has an editor-based UI with fix-its).
The current Clangd model certainly works well for newer clients who are built with LSP in mind from the get go. Sending diagnostics in a format similar to Clang's originals diagnostics would be helpful to clients that are transitioning though :)
Not opposed to changing the model to meet other needs, but want to make sure what we're currently doing in clangd makes sense and understand your use-case better.
Sorry for the delayed response. It seems we absolutely need this if mirroring libclang is an absolute requirement.
We seem to have multiple implementation options:
Which classes to use for representing diagnostics? We can:
- Reuse existing hierarchy for diagnostics. (current option)
- Have separate hierarchies for "flat" (fixits with notes) and "grouped" (fix-its are always attached to main diag). "flat" diagnostics can be stored exactly as they come from clang, with notes and main diags in the same vector, main diag should lack the "notes" field. I.e. if we choose to go with "raw" clang mode, we can as well avoid grouping the notes altogether instead of having code that does something in between the classical libclang and new clangd approach.
I think the added separation is worth it for code clarity, but also realize it's a bunch of boilerplate, so others may disagree. WDYT?
Another alternative that we might explore is always producing fix-its attached to notes at the lowest level (in Diagnostics.cpp) and reconstructing the current diagnostics hierarchy somewhere higher up the chain, e.g. at the LSPServer level.
This would allow to keep the option at the LSPServer level and would only require extracting a (seemingly simple) conversion function that can be called at the LSP Server level.
Having the option handled at the top-level seems like a win, since most of the code does not need to care about this option.
+@sammccall, who wanted to take a look at this issue.
I think having separate hierarchies would be more confusing and harder to test well. I'd prefer to use one hierarchy.
Another alternative that we might explore is always producing fix-its attached to notes at the lowest level (in Diagnostics.cpp) and reconstructing the current diagnostics hierarchy somewhere higher up the chain, e.g. at the LSPServer level.
This would allow to keep the option at the LSPServer level and would only require extracting a (seemingly simple) conversion function that can be called at the LSP Server level.
Having the option handled at the top-level seems like a win, since most of the code does not need to care about this option.\
That would be my personal preference. I will work on an updated patch that does that.
+@sammccall, who wanted to take a look at this issue.