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 @@ -129,11 +129,8 @@ return Merged.CanonicalDeclaration; } -std::vector getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, - DeclRelationSet Relations) { - FileID FID; - unsigned Offset; - std::tie(FID, Offset) = AST.getSourceManager().getDecomposedSpellingLoc(Pos); +std::vector getDeclAtOffset(ParsedAST &AST, unsigned Offset, + DeclRelationSet Relations) { SelectionTree Selection(AST.getASTContext(), AST.getTokens(), Offset); std::vector Result; if (const SelectionTree::Node *N = Selection.commonAncestor()) { @@ -143,6 +140,22 @@ return Result; } +std::vector getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, + DeclRelationSet Relations) { + FileID FID; + unsigned Offset; + std::tie(FID, Offset) = AST.getSourceManager().getDecomposedSpellingLoc(Pos); + std::vector Result = getDeclAtOffset(AST, Offset, Relations); + // If no declaration was found at this offset, try the previous offset. + // This compensates for the fact that SelectionTree interprets an offset + // as applying to the character after rather than the character before, + // allowing go-to-definition to work at the end of an identifier. + if (Result.empty() && Offset > 0) { + Result = getDeclAtOffset(AST, Offset - 1, Relations); + } + return Result; +} + llvm::Optional makeLocation(ASTContext &AST, SourceLocation TokLoc, llvm::StringRef TUPath) { const SourceManager &SourceMgr = AST.getSourceManager(); 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 @@ -450,6 +450,17 @@ +^+x; } )cpp", + + R"cpp(// End of identifier (definition) + void [[func]]^() {} + )cpp", + + R"cpp(// End of identifier (reference) + void [[func]]() {} + void test() { + func^(); + } + )cpp", }; for (const char *Test : Tests) { Annotations T(Test);