This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Provide excuses for bad code completions, based on diagnostics. C++ API only.
Needs ReviewPublic

Authored by sammccall on Oct 18 2018, 10:50 AM.

Details

Reviewers
ilya-biryukov
Summary

In some circumstances we provide bad completions or no completions, because of
problems in the code. This can be puzzling and opaque to users.
If we can tell the user that this is the case and why, they'll be happy.
Experiments with go language servers have shown this to be a big win.

Two major problems:

  • Sema doesn't provide the information we need
  • LSP provides no protocol mechanims, and editors don't have UI for this

This patch attempts to guess the information, looking at diagnostics on the line.
Other heuristics are possible (e.g. using completion context). It's unclear how
useful or successful they will be. This is mostly a quick hack to test viability.

This is exposed as an extension of the C++ API only (not bound to LSP).
The idea is to test viability with a non-public editor that happens to have the
right UI already (and doesn't use LSP), and experiment with approaches.
If something fairly simple works well, we'll keep this and expose an LSP extension.
If it's not useful, we should drop this idea.

Event Timeline

sammccall created this revision.Oct 18 2018, 10:50 AM

Since we're showing the diagnostics in the editors anyway, how crucial do we think it is to actually add that to the procotol?
Having more concrete reasons for misbehaving completions sounds more useful, though, e.g. "cannot complete members of the incomplete type", etc.

Totally fine to have this in the C++ API for experiments, of course.

  • LSP provides no protocol mechanims, and editors don't have UI for this

Have we tried returning an error in addition to the results? How do the clients behave in that case?

clangd/CodeComplete.cpp
674

It took some time to figure out what "excuse" means here.
Maybe be more straightforward in naming/comments about what this class does? I.e. finds a last diagnostic on the same line.
It's private to this file, so it's easy to rename if we'll want to expand the heuristics.

686

Maybe use a getLineNumber helper from the SourceManager instead?
It needs a FileID, but it shouldn't be hard to get one.

1040

Maybe replace an out parameter with returning a struct of two members?
Is there any use for calling code completion without providing an "excuse"?

kadircet added inline comments.Oct 22 2018, 9:30 AM
clangd/CodeComplete.cpp
700

There are also a lot of cases where we can't find an include file(usually due to confused compile commands) and fail miserably. Maybe in addition to checking current line, we could also check for lines that are starting with #include or diags of type diag::err_pp_file_not_found ?

ilya-biryukov added inline comments.Oct 24 2018, 2:37 AM
clangd/CodeComplete.cpp
700

Good point!
It's even more complicated than that: some of those missing files might be in preamble.
This will lead to preamble being incomplete. The problem with that is that DiagnosticsConsumer we create for completion will not see those errors (we have a separate consumer instance for preamble).
So we also need to a way to keep the reason why preamble is broken in the preamble itself.

All these things are good ideas - I'm not addressing comments yet because I'm waiting for feedback from the team that's trying this out - maybe this needs patches, or maybe it'll never work.