This is an archive of the discontinued LLVM Phabricator instance.

[clangd] go-to-definition on auto unwraps array/pointer types
Changes PlannedPublic

Authored by sammccall on Dec 15 2020, 9:27 AM.

Details

Reviewers
qchateau

Diff Detail

Event Timeline

sammccall created this revision.Dec 15 2020, 9:27 AM
sammccall requested review of this revision.Dec 15 2020, 9:27 AM

We don't do this kind of unwrapping in targetDecl() because it seems a bit sloppy/approximate, but in this case the full type isn't written, so you can't choose to target the Foo rather than the * in Foo *.

Do you think we should try to handle unique_ptr/shared_ptr too? (Today they'd go to the unique_ptr template)

nridge added a subscriber: nridge.Dec 15 2020, 11:08 AM

Ah good catch, I agree this is the behavior we want.

Concerning cases like unique_ptr<T>, the only generic behavior I can think of would be to suggest multiple LocatedSymbol when auto is deduced to a template class: the template class itself, and all its template type parameters.

class A {};
class B {};

template<typename T, typename U>
class C {};

auto x = C<A, B>();

go-to-definition on auto could suggest jumping to C, A or B.

In a way, when you explicitly have C<A, B> x; you can go-to-def to either A, B or C in one click, it is simply made easier because all these types are visible in the code and you make the choice by choosing on where you click.

sammccall planned changes to this revision.Dec 16 2020, 3:31 AM

Ah good catch, I agree this is the behavior we want.

Concerning cases like unique_ptr<T>, the only generic behavior I can think of would be to suggest multiple LocatedSymbol when auto is deduced to a template class: the template class itself, and all its template type parameters.

Right. There are not-completely-generic options too though :-)

I'm inclined to agree that unique_ptr<MemoryBuffer> should resolve to both unique_ptr and MemoryBuffer.
But not std::default_deleter, and probably not even a custom deleter.

Similarly, maybe vector<MemoryBuffer> should resolve to both, but I'm not sure that holds for all templates (e.g. lock_guard).

So I'm leaning towards defining these behaviors for pointers and containers rather than templates per se. There's a nice symmetry with the raw pointer and array types that this patch.
(We have some precedent and code for detecting smart pointers, see getPointeeType() in FindTarget.cpp.)

We could land this as-is (just handling the built-in types) but it will need some structural changes for dealing with multiple results (including recursive cases like vector<Foo*>) so I'll take a stab at doing all that at once.

So I'm leaning towards defining these behaviors for pointers and containers rather than templates per se. There's a nice symmetry with the raw pointer and array types that this patch.
(We have some precedent and code for detecting smart pointers, see getPointeeType() in FindTarget.cpp.)

If you think it's fine to have specific code using heuristics to try to find what the user expects, then pointers and containers sounds like a good target.