This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Improve hover and goToDefinition on auto and dectype
ClosedPublic

Authored by qchateau on Dec 9 2020, 3:31 PM.

Details

Reviewers
sammccall
Group Reviewers
Restricted Project
Commits
rGbda7d0af9707: [clangd] Improve goToDefinition on auto and dectype
Summary

Make the hover content on auto and decltype
look like the hover content we would get on the
deduced type.

locateSymbolAt (used in goToDeclaration) follows the
deduced type instead of failing to locate the declaration.


I took a screenshot of what happens when you hover over an 'auto' keyword in VSCode with clangd-10 and with the one integrating my patch (see below). Concerning the goToDefinition feature, it did not work at all for 'auto', not it goes to the same definition as the one shown on hover.

PS: This is the first time I submit a patch to LLVM, please let me know what I need to change and what I could improve, both concerning the patch itself and my submission to Phabricator.

Diff Detail

Event Timeline

qchateau created this revision.Dec 9 2020, 3:31 PM
qchateau requested review of this revision.Dec 9 2020, 3:31 PM
qchateau edited the summary of this revision. (Show Details)Dec 9 2020, 3:37 PM
qchateau added reviewers: Restricted Project, sammccall.
qchateau edited projects, added Restricted Project; removed Restricted Project.
Herald added a project: Restricted Project. · View Herald TranscriptDec 9 2020, 3:37 PM
nridge added a subscriber: nridge.Dec 9 2020, 5:00 PM
qchateau updated this revision to Diff 310872.EditedDec 10 2020, 6:09 AM

I've fixed the failing unittests, added some more
to test the new behavior, and fixed some bugs in
the new code.

Not sure what's wrong with the unit test "x64 windows > LLVM.CodeGen/XCore::threads.ll", I don't see how it's related to my patch

Thanks for doing this! Go-to-def-on-auto has been bugging me, it'll be great to have it :-)
Overall the patch looks really solid, with nice tests. The one thing I'd suggest is splitting the two features (hover and go-to-def) into separate patches.
e.g. here, I'm not totally sure about the hover change yet, and want to think and get some input from others. But I don't want to delay the go-to-definition part. So I've left comments on the go-to-definition changes, and if you want to drop hover from this patch and upload it as a separate review, that'd be really helpful.


My concern with hover is mostly around consistency and clarity. In isolation, the new hover certainly looks better than the old one for structs (e.g. syntax highligthing!).
However now we have a different style for struct vs non-struct types, and it's not just a surface thing: for structs we show the declaration, but many types have no declaration to show. I'm not sure how you can show a hover for auto = char *const* or so that feels consistent with this one.

We should also consider consistency and clarity with different types of auto. Currently our hover for undeduced auto is just "auto", and our hover for auto params is a mess. It would be nice about this distinction, as when the same keyword has multiple meanings people can conflate them.

One solution would be to make auto the name, and the type the definition. This provides less information (but I suspect that information is often noise):

### deduced-type `auto`

---

struct cv::Ptr<cv::detail::ChannelsCompensator>

(For context, the auto hover was one of the first implemented. Later we went back and added some structure (type/name/definition/documentation) but the old auto hover was mostly shoehorned into this. So if we're going to change auto hover, we shuold consider trying to make it fit this schema, too)

clang-tools-extra/clangd/XRefs.cpp
684

This deserves a high-level comment: // go-to-definition on auto should find the definition of the deduced type, if possible

685

I think we should pull the contents of this if() into a function findSymbolForType or so.

LSP has a textDocument/typeDefinition request that could also make use of this logic.
(You don't need to implement that, and I'm very much in favor of having this textDocument/definition be the do-what-i-mean swiss army knife like this patch does. But I'd just like to factor this code with potential reuse in mind)

688

there are many other types we could resolve to a decl: TypedefType, TemplateTypeParmtype, ...
If we're only going to handle tag types, it deserves a FIXME comment.

But we do have a helper for this. Can you try calling targetDecl(DynTypedNode::create(Deduced), DeclRelation::TemplatePattern | DeclRelation::Alias) instead of Deduced->getTypePtr()->getAsTagDecl()?

That should handle more cases, at a minimum, this case sholud pass:

using [[T]] = int;
T x;
^auto y = x;

(I see you have a test case that aliases backed by tag types are resolved to the underlying tag decl, this change would offer the alias instead, which is more consistent with our current go-to-definition. You could also offer both by passing DeclRelation::TemplatePattern | DeclRelation::Alias | DeclRelation::Underlying... but I think we should value consistency here)

clang-tools-extra/clangd/unittests/XRefsTests.cpp
669 ↗(On Diff #310872)

There's a scalability problem with testing every corner of the C++ language (there are lots!) with every feature. Generally I prefer to cover some important/weird/bugfix cases here, but to cover as much as possible with unittests of the underlying functions.

In this case, that would mean

  • moving tests that are about auto in different contexts to ASTTests.cpp (current test coverage there is poor).
  • (assuming we can use targetDecl()) moving tests that are about which decl a type should resolve to to FindTargetTests.cpp - but current coverage there is pretty good so we can probably just drop many of them.
qchateau updated this revision to Diff 311219.Dec 11 2020, 7:04 AM
  • Remove the patches affecting hover
  • Add tests in ASTTests.cpp to test the behavior of getDeducedType for auto and decltype
  • Add missing comment
  • Create a locateSymbolForType function (which uses targetDecl)
  • Remove the unit tests that were testing undesirable behaviors
qchateau marked 3 inline comments as done.Dec 11 2020, 7:19 AM
qchateau added inline comments.
clang-tools-extra/clangd/XRefs.cpp
688

locateSymbolForType uses targetDecl. Thanks for the tip, that's exactly what I was looking for.

I also agree with you that go-to-definition should go to the alias instead of the underlying type for consistency, but using targetDecl(DynTypedNode::create(Deduced), DeclRelation::TemplatePattern | DeclRelation::Alias) is not enough to resolve this consistency issue: getDeducedType already returns the underlying type. My current knowledge of the clangd code is nou sufficient to understand why, but the root of the problem seem to lie in the DeducedTypeVisitor class.

I removed the test that tested the undesirable behavior, should I open a bug report for getDeducedType that should not "go through" aliases ? In which case, what's the right place for that ? Github ?

clang-tools-extra/clangd/unittests/XRefsTests.cpp
669 ↗(On Diff #310872)

I added the relevant tests to ASTTests.cpp but I did not remove the tests here for the moment. I've always had the habit to keep tests that are already written, even if redundant.

If you'd like me to remove some of them, I'd say the only tests that are not redundant with the ones in ASTTests.cpp are the ones that test template specializations. Shoud I keep only these ?

sammccall accepted this revision.Dec 11 2020, 7:45 AM

Looks good, thanks again!
If you don't yet have LLVM commit access, I can commit this for you, let me know which email address to associate it with.
(https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access describes how you can get commit access if you're contributing regularly)

clang-tools-extra/clangd/XRefs.cpp
442

nit: we do often just use the first element (there's almost always just one), but here we can actually return multiple LocatedSymbols (client shows some sort of selector widget for them) so I'd suggest we loop and return all

688

Great!
Marginally better than removing a test is keeping it with a comment // FIXME: it'd be nice if this resolved to the alias instead or something like that

Github is the right place to file a bug, though I don't think this is really a big deal, so sometimes we just leave the comment.

(I'm not sure offhand if the AST actually preserves the sugar type or just the underlying one)

clang-tools-extra/clangd/unittests/XRefsTests.cpp
669 ↗(On Diff #310872)

Keeping them around is fine too, we're not strict about this.

Thanks for adding all the tests for deduced types!

This revision is now accepted and ready to land.Dec 11 2020, 7:46 AM
qchateau updated this revision to Diff 311247.Dec 11 2020, 9:10 AM
qchateau marked an inline comment as done.
  • Reintroduce test with a FIXME comment
  • locateSymbolForType returns a vector instead of an optional

I've updated the patch with your latest comments.

Please commit this patch for me, using "quentin.chateau@gmail.com", I'll probably ask for commit access after a few successful reviews

This revision was landed with ongoing or failed builds.Dec 15 2020, 7:37 AM
This revision was automatically updated to reflect the committed changes.

I sent you D93314 to extend the getNonReferenceType() a bit... curious what you think