forked from OSchip/llvm-project
[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
This commit is contained in:
parent
72e7575ffe
commit
220d850823
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue