[clangd] Match AST and Index label for template Symbols
Summary: Previsouly, class completions items from the index were missing template parameters in both the snippet and the label. Reviewers: sammccall, hokein Reviewed By: sammccall Subscribers: klimek, jkorous-apple, ioeric, MaskRay, cfe-commits Differential Revision: https://reviews.llvm.org/D45482 llvm-svn: 330004
This commit is contained in:
parent
038d996c80
commit
cf124bd828
|
@ -14,6 +14,7 @@
|
|||
#include "../URI.h"
|
||||
#include "CanonicalIncludes.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Index/IndexSymbol.h"
|
||||
|
@ -26,6 +27,19 @@ namespace clang {
|
|||
namespace clangd {
|
||||
|
||||
namespace {
|
||||
/// If \p ND is a template specialization, returns the primary template.
|
||||
/// Otherwise, returns \p ND.
|
||||
const NamedDecl &getTemplateOrThis(const NamedDecl &ND) {
|
||||
if (auto Cls = dyn_cast<CXXRecordDecl>(&ND)) {
|
||||
if (auto T = Cls->getDescribedTemplate())
|
||||
return *T;
|
||||
} else if (auto Func = dyn_cast<FunctionDecl>(&ND)) {
|
||||
if (auto T = Func->getPrimaryTemplate())
|
||||
return *T;
|
||||
}
|
||||
return ND;
|
||||
}
|
||||
|
||||
// Returns a URI of \p Path. Firstly, this makes the \p Path absolute using the
|
||||
// current working directory of the given SourceManager if the Path is not an
|
||||
// absolute path. If failed, this resolves relative paths against \p FallbackDir
|
||||
|
@ -325,7 +339,8 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
|
|||
// Add completion info.
|
||||
// FIXME: we may want to choose a different redecl, or combine from several.
|
||||
assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
|
||||
CodeCompletionResult SymbolCompletion(&ND, 0);
|
||||
// We use the primary template, as clang does during code completion.
|
||||
CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0);
|
||||
const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
|
||||
*ASTCtx, *PP, CodeCompletionContext::CCC_Name, *CompletionAllocator,
|
||||
*CompletionTUInfo,
|
||||
|
|
|
@ -195,6 +195,44 @@ TEST(FileIndexTest, NoIncludeCollected) {
|
|||
EXPECT_TRUE(SeenSymbol);
|
||||
}
|
||||
|
||||
TEST(FileIndexTest, TemplateParamsInLabel) {
|
||||
auto Source = R"cpp(
|
||||
template <class Ty>
|
||||
class vector {
|
||||
};
|
||||
|
||||
template <class Ty>
|
||||
vector<Ty> make_vector(Ty* begin, Ty* end) {}
|
||||
)cpp";
|
||||
|
||||
FileIndex M;
|
||||
M.update("f", build("f", Source).getPointer());
|
||||
|
||||
FuzzyFindRequest Req;
|
||||
Req.Query = "";
|
||||
bool SeenVector = false;
|
||||
bool SeenMakeVector = false;
|
||||
M.fuzzyFind(Req, [&](const Symbol &Sym) {
|
||||
if (Sym.Name == "vector") {
|
||||
EXPECT_EQ(Sym.CompletionLabel, "vector<class Ty>");
|
||||
EXPECT_EQ(Sym.CompletionSnippetInsertText, "vector<${1:class Ty}>");
|
||||
EXPECT_EQ(Sym.CompletionPlainInsertText, "vector");
|
||||
SeenVector = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Sym.Name == "make_vector") {
|
||||
EXPECT_EQ(Sym.CompletionLabel, "make_vector(Ty *begin, Ty *end)");
|
||||
EXPECT_EQ(Sym.CompletionSnippetInsertText,
|
||||
"make_vector(${1:Ty *begin}, ${2:Ty *end})");
|
||||
EXPECT_EQ(Sym.CompletionPlainInsertText, "make_vector");
|
||||
SeenMakeVector = true;
|
||||
}
|
||||
});
|
||||
EXPECT_TRUE(SeenVector);
|
||||
EXPECT_TRUE(SeenMakeVector);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
|
Loading…
Reference in New Issue