[clang-tools-extra] 220d850 - [clangd] Fix hover on symbol introduced by using declaration
Tom Praschan via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 15 02:03:38 PDT 2022
Author: Tom Praschan
Date: 2022-09-15T13:02:58+02:00
New Revision: 220d850823494aad48d984395512e2ac74c666de
URL: https://github.com/llvm/llvm-project/commit/220d850823494aad48d984395512e2ac74c666de
DIFF: https://github.com/llvm/llvm-project/commit/220d850823494aad48d984395512e2ac74c666de.diff
LOG: [clangd] Fix hover on symbol introduced by using declaration
This fixes https://github.com/clangd/clangd/issues/1284. The example
there was C++20's "using enum", but I noticed that we had the same issue
for other using-declarations.
Differential Revision: https://reviews.llvm.org/D133664
Added:
Modified:
clang-tools-extra/clangd/Hover.cpp
clang-tools-extra/clangd/unittests/HoverTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 2ef6104e3a43..b587d9c5f1e7 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -1006,6 +1006,37 @@ void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
HI.CallPassType.emplace(PassType);
}
+const NamedDecl *pickDeclToUse(llvm::ArrayRef<const NamedDecl *> Candidates) {
+ if (Candidates.empty())
+ return nullptr;
+
+ // This is e.g the case for
+ // namespace ns { void foo(); }
+ // void bar() { using ns::foo; f^oo(); }
+ // One declaration in Candidates will refer to the using declaration,
+ // which isn't really useful for Hover. So use the other one,
+ // which in this example would be the actual declaration of foo.
+ if (Candidates.size() <= 2) {
+ if (llvm::isa<BaseUsingDecl>(Candidates.front()))
+ return Candidates.back();
+ return Candidates.front();
+ }
+
+ // For something like
+ // namespace ns { void foo(int); void foo(char); }
+ // using ns::foo;
+ // template <typename T> void bar() { fo^o(T{}); }
+ // we actually want to show the using declaration,
+ // it's not clear which declaration to pick otherwise.
+ auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
+ return llvm::isa<BaseUsingDecl>(D);
+ });
+ if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
+ return *BaseDecls.begin();
+
+ return Candidates.front();
+}
+
} // namespace
llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
@@ -1081,11 +1112,11 @@ llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
// FIXME: Fill in HighlightRange with range coming from N->ASTNode.
auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias,
AST.getHeuristicResolver());
- if (!Decls.empty()) {
- HI = getHoverContents(Decls.front(), PP, Index, TB);
+ if (const auto *DeclToUse = pickDeclToUse(Decls)) {
+ HI = getHoverContents(DeclToUse, PP, Index, TB);
// Layout info only shown when hovering on the field/class itself.
- if (Decls.front() == N->ASTNode.get<Decl>())
- addLayoutInfo(*Decls.front(), *HI);
+ if (DeclToUse == N->ASTNode.get<Decl>())
+ addLayoutInfo(*DeclToUse, *HI);
// Look for a close enclosing expression to show the value of.
if (!HI->Value)
HI->Value = printExprValue(N, AST.getASTContext());
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index d4000f31a5f7..d2ad2c69c4e7 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1630,6 +1630,38 @@ TEST(Hover, All) {
HI.Type = "int";
HI.Definition = "int foo";
}},
+ {
+ R"cpp(// Function definition via using declaration
+ namespace ns {
+ void foo();
+ }
+ int main() {
+ using ns::foo;
+ ^[[foo]]();
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "foo";
+ HI.Kind = index::SymbolKind::Function;
+ HI.NamespaceScope = "ns::";
+ HI.Type = "void ()";
+ HI.Definition = "void foo()";
+ HI.Documentation = "";
+ HI.ReturnType = "void";
+ HI.Parameters = std::vector<HoverInfo::Param>{};
+ }},
+ {
+ R"cpp( // using declaration and two possible function declarations
+ namespace ns { void foo(int); void foo(char); }
+ using ns::foo;
+ template <typename T> void bar() { [[f^oo]](T{}); }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "foo";
+ HI.Kind = index::SymbolKind::Using;
+ HI.NamespaceScope = "";
+ HI.Definition = "using ns::foo";
+ }},
{
R"cpp(// Macro
#define MACRO 0
@@ -1734,6 +1766,25 @@ TEST(Hover, All) {
HI.Definition = "ONE";
HI.Value = "0";
}},
+ {
+ R"cpp(// C++20's using enum
+ enum class Hello {
+ ONE, TWO, THREE,
+ };
+ void foo() {
+ using enum Hello;
+ Hello hello = [[O^NE]];
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "ONE";
+ HI.Kind = index::SymbolKind::EnumConstant;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Hello::";
+ HI.Type = "enum Hello";
+ HI.Definition = "ONE";
+ HI.Value = "0";
+ }},
{
R"cpp(// Enumerator in anonymous enum
enum {
More information about the cfe-commits
mailing list