diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -171,22 +171,33 @@ return Merged.CanonicalDeclaration; } +std::vector> +getDeclAtPositionWithRelations(ParsedAST &AST, SourceLocation Pos, + DeclRelationSet Relations, + ASTNodeKind *NodeKind = nullptr) { + unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(Pos).second; + std::vector> Result; + auto ResultFromTree = [&](SelectionTree ST) { + if (const SelectionTree::Node *N = ST.commonAncestor()) { + if (NodeKind) + *NodeKind = N->ASTNode.getNodeKind(); + llvm::copy_if(allTargetDecls(N->ASTNode), std::back_inserter(Result), + [&](auto &Entry) { return !(Entry.second & ~Relations); }); + } + return !Result.empty(); + }; + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset, + Offset, ResultFromTree); + return Result; +} + std::vector getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, DeclRelationSet Relations, ASTNodeKind *NodeKind = nullptr) { - unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(Pos).second; std::vector Result; - SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset, - Offset, [&](SelectionTree ST) { - if (const SelectionTree::Node *N = - ST.commonAncestor()) { - if (NodeKind) - *NodeKind = N->ASTNode.getNodeKind(); - llvm::copy(targetDecl(N->ASTNode, Relations), - std::back_inserter(Result)); - } - return !Result.empty(); - }); + for (auto &Entry : + getDeclAtPositionWithRelations(AST, Pos, Relations, NodeKind)) + Result.push_back(Entry.first); return Result; } @@ -316,8 +327,10 @@ // Emit all symbol locations (declaration or definition) from AST. DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias; - for (const NamedDecl *D : - getDeclAtPosition(AST, CurLoc, Relations, NodeKind)) { + auto Candidates = + getDeclAtPositionWithRelations(AST, CurLoc, Relations, NodeKind); + for (const auto &E : Candidates) { + const NamedDecl *D = E.first; // Special case: void foo() ^override: jump to the overridden method. if (const auto *CMD = llvm::dyn_cast(D)) { const InheritableAttr *Attr = D->getAttr(); @@ -333,6 +346,18 @@ } } + // Special case: the cursor is on an alias, prefer other results. + // This targets "using ns::^Foo", where the target is more interesting. + // This does not trigger on renaming aliases: + // `using Foo = ^Bar` already targets Bar via a TypeLoc + // `using ^Foo = Bar` has no other results, as Underlying is filtered. + if (E.second & DeclRelation::Alias && Candidates.size() > 1 && + // beginLoc/endLoc are a token range, so rewind the identifier we're in. + SM.isPointWithin(TouchedIdentifier ? TouchedIdentifier->location() + : CurLoc, + D->getBeginLoc(), D->getEndLoc())) + continue; + // Special case: the point of declaration of a template specialization, // it's more useful to navigate to the template declaration. if (auto *CTSD = dyn_cast(D)) { diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -1118,13 +1118,12 @@ // decls. R"cpp( namespace ns { class [[Foo]] {}; } - // FIXME: don't return the using decl if it touches the cursor position. - using ns::[[F^oo]]; + using ns::F^oo; )cpp", R"cpp( namespace ns { int [[x]](char); int [[x]](double); } - using ns::[[^x]]; + using ns::^x; )cpp", R"cpp( @@ -1157,7 +1156,7 @@ }; template struct Derived : Base { - using Base::[[w^aldo]]; + using Base::w^aldo; }; )cpp", };