[clangd] Show non-instantiated decls in signatureHelp

Summary:
To avoid producing very verbose output in substitutions involving
typedefs, e.g.
  T -> std::vector<std::string>::iterator
gets turned into an unreadable mess when printed out for libstdc++,
result contains internal types (std::__Vector_iterator<...>) and
expanded well-defined typedefs (std::basic_string<char>).

Until we improve the presentation code in clang, going with
non-instantiated decls looks like a better UX trade-off.

Reviewers: hokein, ioeric, kadircet

Reviewed By: hokein

Subscribers: MaskRay, jkorous, arphaman, cfe-commits

Differential Revision: https://reviews.llvm.org/D50645

llvm-svn: 339665
This commit is contained in:
Ilya Biryukov 2018-08-14 09:36:32 +00:00
parent 661cc1e104
commit 8fd44bb915
2 changed files with 62 additions and 1 deletions

View File

@ -714,7 +714,15 @@ public:
"too many arguments");
SigHelp.activeParameter = static_cast<int>(CurrentArg);
for (unsigned I = 0; I < NumCandidates; ++I) {
const auto &Candidate = Candidates[I];
OverloadCandidate Candidate = Candidates[I];
// We want to avoid showing instantiated signatures, because they may be
// long in some cases (e.g. when 'T' is substituted with 'std::string', we
// would get 'std::basic_string<char>').
if (auto *Func = Candidate.getFunction()) {
if (auto *Pattern = Func->getTemplateInstantiationPattern())
Candidate = OverloadCandidate(Pattern);
}
const auto *CCS = Candidate.CreateSignatureString(
CurrentArg, S, *Allocator, CCTUInfo, true);
assert(CCS && "Expected the CodeCompletionString to be non-null");

View File

@ -1537,6 +1537,59 @@ TEST(SignatureHelpTest, OverloadsOrdering) {
EXPECT_EQ(0, Results.activeParameter);
}
TEST(SignatureHelpTest, InstantiatedSignatures) {
EXPECT_THAT(signatures(R"cpp(
template <class T>
void foo(T, T, T);
int main() {
foo<int>(^);
}
)cpp")
.signatures,
ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
EXPECT_THAT(signatures(R"cpp(
template <class T>
void foo(T, T, T);
int main() {
foo(10, ^);
})cpp")
.signatures,
ElementsAre(Sig("foo(T, T, T) -> void", {"T", "T", "T"})));
EXPECT_THAT(signatures(R"cpp(
template <class ...T>
void foo(T...);
int main() {
foo<int>(^);
}
)cpp")
.signatures,
ElementsAre(Sig("foo(T...) -> void", {"T..."})));
// It is debatable whether we should substitute the outer template parameter
// ('T') in that case. Currently we don't substitute it in signature help, but
// do substitute in code complete.
// FIXME: make code complete and signature help consistent, figure out which
// way is better.
EXPECT_THAT(signatures(R"cpp(
template <class T>
struct X {
template <class U>
void foo(T, U);
};
int main() {
X<int>().foo<double>(^)
}
)cpp")
.signatures,
ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
}
} // namespace
} // namespace clangd
} // namespace clang