kadircet created this revision. kadircet added a reviewer: ilya-biryukov. Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous, MaskRay. Herald added a project: clang.
Clangd didn't fill documentation for `auto` when it wasn't available in index. Also it wasn't showing any documentations for implicit instantiations. This patch ensures auto and normal decl case behaves in the same way and also makes use of the explicit template specialization while fetching comments for implicit instantiations. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D71596 Files: clang-tools-extra/clangd/Hover.cpp clang-tools-extra/clangd/unittests/HoverTests.cpp
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HoverTests.cpp +++ clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "AST.h" #include "Annotations.h" #include "Hover.h" #include "TestIndex.h" @@ -1271,6 +1272,7 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = "auto function return with trailing type"; }}, { R"cpp(// trailing return type @@ -1282,6 +1284,7 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = "trailing return type"; }}, { R"cpp(// auto in function return @@ -1293,6 +1296,7 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = "auto in function return"; }}, { R"cpp(// auto& in function return @@ -1305,6 +1309,7 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = "auto& in function return"; }}, { R"cpp(// auto* in function return @@ -1317,6 +1322,7 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = "auto* in function return"; }}, { R"cpp(// const auto& in function return @@ -1329,6 +1335,7 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = "const auto& in function return"; }}, { R"cpp(// decltype(auto) in function return @@ -1340,6 +1347,7 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = "decltype(auto) in function return"; }}, { R"cpp(// decltype(auto) reference in function return @@ -1404,6 +1412,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.Documentation = + "decltype of function with trailing return type."; }}, { R"cpp(// decltype of var with decltype. @@ -1477,6 +1487,87 @@ } } +TEST(Hover, DocsFromIndex) { + Annotations T(R"cpp( + template <typename T> class X {}; + void foo() { + au^to t = X<int>(); + X^<int> w; + (void)w; + })cpp"); + + TestTU TU = TestTU::withCode(T.code()); + auto AST = TU.build(); + for (const auto &D : AST.getDiagnostics()) + ADD_FAILURE() << D; + ASSERT_TRUE(AST.getDiagnostics().empty()); + + Symbol IndexSym; + IndexSym.ID = *getSymbolID(&findDecl(AST, "X")); + IndexSym.Documentation = "comment from index"; + SymbolSlab::Builder Symbols; + Symbols.insert(IndexSym); + auto Index = + MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab()); + + for (const auto &P : T.points()) { + auto H = getHover(AST, P, format::getLLVMStyle(), Index.get()); + ASSERT_TRUE(H); + EXPECT_EQ(H->Documentation, IndexSym.Documentation); + } +} + +TEST(Hover, DocsFromAST) { + Annotations T(R"cpp( + // doc + template <typename T> class X {}; + void foo() { + au^to t = X<int>(); + X^<int> w; + (void)w; + })cpp"); + + TestTU TU = TestTU::withCode(T.code()); + auto AST = TU.build(); + for (const auto &D : AST.getDiagnostics()) + ADD_FAILURE() << D; + ASSERT_TRUE(AST.getDiagnostics().empty()); + + for (const auto &P : T.points()) { + auto H = getHover(AST, P, format::getLLVMStyle(), nullptr); + ASSERT_TRUE(H); + EXPECT_EQ(H->Documentation, "doc"); + } +} + +TEST(Hover, DocsFromMostSpecial) { + Annotations T(R"cpp( + // doc1 + template <typename T> class X {}; + // doc2 + template <> class X<int> {}; + // doc3 + template <typename T> class X<T*> {}; + void foo() { + X$doc1^<char>(); + X$doc2^<int>(); + X$doc3^<int*>(); + })cpp"); + + TestTU TU = TestTU::withCode(T.code()); + auto AST = TU.build(); + for (const auto &D : AST.getDiagnostics()) + ADD_FAILURE() << D; + ASSERT_TRUE(AST.getDiagnostics().empty()); + + for (auto Comment : {"doc1", "doc2", "doc3"}) { + for (const auto &P : T.points(Comment)) { + auto H = getHover(AST, P, format::getLLVMStyle(), nullptr); + ASSERT_TRUE(H); + EXPECT_EQ(H->Documentation, Comment); + } + } +} } // namespace } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/Hover.cpp =================================================================== --- clang-tools-extra/clangd/Hover.cpp +++ clang-tools-extra/clangd/Hover.cpp @@ -183,15 +183,24 @@ return D->getAsFunction(); } +// Returns the explicit specialization for implicit instantiations, otherwise +// returns D. +const NamedDecl *getExplicitSpec(const NamedDecl *D) { + if (auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) { + if (!CTSD->isExplicitInstantiationOrSpecialization()) + return CTSD->getSpecializedTemplate(); + } + return D; +} + // Look up information about D from the index, and add it to Hover. -void enhanceFromIndex(HoverInfo &Hover, const Decl *D, +void enhanceFromIndex(HoverInfo &Hover, const NamedDecl &ND, const SymbolIndex *Index) { - if (!Index || !llvm::isa<NamedDecl>(D)) - return; - const NamedDecl &ND = *cast<NamedDecl>(D); - // We only add documentation, so don't bother if we already have some. - if (!Hover.Documentation.empty()) + // We only add documentation, so don't bother if we already have some, or + // Index isn't supplied. + if (!Hover.Documentation.empty() || !Index) return; + // Skip querying for non-indexable symbols, there's no point. // We're searching for symbols that might be indexed outside this main file. if (!SymbolCollector::shouldCollectSymbol(ND, ND.getASTContext(), @@ -307,8 +316,10 @@ PrintingPolicy Policy = printingPolicyForDecls(Ctx.getPrintingPolicy()); if (const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D)) { - HI.Documentation = getDeclComment(Ctx, *ND); HI.Name = printName(Ctx, *ND); + ND = getExplicitSpec(ND); + HI.Documentation = getDeclComment(Ctx, *ND); + enhanceFromIndex(HI, *ND, Index); } HI.Kind = index::getSymbolInfo(D).Kind; @@ -346,7 +357,6 @@ } HI.Definition = printDefinition(D); - enhanceFromIndex(HI, D, Index); return HI; } @@ -358,10 +368,13 @@ D = T->getAsTagDecl(); if (D) { - if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) - HI.Name = printName(ASTCtx, *ND); HI.Kind = index::getSymbolInfo(D).Kind; - enhanceFromIndex(HI, D, Index); + if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) { + HI.Name = printName(ASTCtx, *ND); + ND = getExplicitSpec(ND); + HI.Documentation = getDeclComment(ASTCtx, *ND); + enhanceFromIndex(HI, *ND, Index); + } } if (HI.Name.empty()) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits