forked from OSchip/llvm-project
[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:
parent
661cc1e104
commit
8fd44bb915
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue