usaxena95 created this revision. Herald added subscribers: cfe-commits, kadircet, arphaman. Herald added a project: clang. usaxena95 requested review of this revision. Herald added subscribers: MaskRay, ilya-biryukov.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D91626 Files: clang-tools-extra/clangd/ClangdLSPServer.cpp clang-tools-extra/clangd/ClangdLSPServer.h clang-tools-extra/clangd/ClangdServer.cpp clang-tools-extra/clangd/ClangdServer.h clang-tools-extra/clangd/Protocol.cpp clang-tools-extra/clangd/Protocol.h clang-tools-extra/clangd/XRefs.cpp clang-tools-extra/clangd/XRefs.h clang-tools-extra/clangd/unittests/XRefsTests.cpp
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -41,6 +41,7 @@ using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Matcher; +using ::testing::Not; using ::testing::UnorderedElementsAre; using ::testing::UnorderedElementsAreArray; @@ -1161,7 +1162,7 @@ )cpp", }; - for (const auto* Case : Tests) { + for (const auto *Case : Tests) { SCOPED_TRACE(Case); auto T = Annotations(Case); auto AST = TestTU::withCode(T.code()).build(); @@ -1464,6 +1465,69 @@ } } +// TEST(FindImplementations, Inheritance) { +// llvm::StringRef Test = R"cpp( +// struct Base { +// virtual void F$1^oo(); +// }; +// struct Sub1 : Base { +// void $1[[Foo]]() override; +// virtual void Bar(); +// }; +// struct Sub2 : Base { +// void $1[[Foo]]() override; +// virtual void Baz(); +// }; +// struct Sub12: Sub1, Sub2 { +// void $1[[Foo]]() override; +// void Bar() override; +// void Baz() override; +// }; + +// void FromReference() { +// Base* B; +// B->Fo$1^o(); +// } +// )cpp"; + +// Annotations Code(Test); +// auto TU = TestTU::withCode(Code.code()); +// auto AST = TU.build(); + +// std::vector<Matcher<Location>> ExpectedLocations; +// for (const auto &R : Code.ranges("1")) +// ExpectedLocations.push_back(RangeIs(R)); +// for (const auto &Point : Code.points("1")) { +// EXPECT_THAT(findImplementations(AST, Point, TU.index().get()).References, +// UnorderedElementsAreArray(ExpectedLocations)) +// << Test << " at" << Point; +// } +// } + +// TEST(FindImplementations, BaseTemplateDoesNotWork) { +// std::string Test = R"cpp( +// template <typename T> +// class Base { +// virtual void f^oo(); +// }; +// class Sub : public Base<int> { +// void [[foo]]() override; +// }; +// )cpp"; +// Annotations Code(Test); +// auto TU = TestTU::withCode(Code.code()); +// auto AST = TU.build(); + +// std::vector<Matcher<Location>> ExpectedLocations; +// for (const auto &R : Code.ranges()) +// ExpectedLocations.push_back(RangeIs(R)); +// // FIXME: No implementations for templated virtual functions. +// EXPECT_THAT( +// findImplementations(AST, Code.point(), TU.index().get()).References, +// Not(UnorderedElementsAreArray(ExpectedLocations))) +// << Test; +// } + TEST(FindReferences, WithinAST) { const char *Tests[] = { R"cpp(// Local variable Index: clang-tools-extra/clangd/XRefs.h =================================================================== --- clang-tools-extra/clangd/XRefs.h +++ clang-tools-extra/clangd/XRefs.h @@ -82,6 +82,11 @@ std::vector<Location> References; bool HasMore = false; }; + +/// Returns implementations of the virtual function at a specified \p Pos. +ReferencesResult findImplementations(ParsedAST &AST, Position Pos, + const SymbolIndex *Index = nullptr); + /// Returns references of the symbol at a specified \p Pos. /// \p Limit limits the number of results returned (0 means no limit). ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, Index: clang-tools-extra/clangd/XRefs.cpp =================================================================== --- clang-tools-extra/clangd/XRefs.cpp +++ clang-tools-extra/clangd/XRefs.cpp @@ -1124,6 +1124,40 @@ return Result; } +ReferencesResult findImplementations(ParsedAST &AST, Position Pos, + const SymbolIndex *Index) { + ReferencesResult Results; + // We rely on index to find the implementations in subclasses. + if (!Index) + return Results; + const SourceManager &SM = AST.getSourceManager(); + auto MainFilePath = + getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); + if (!MainFilePath) { + elog("Failed to get a path for the main file, so no implementations."); + return Results; + } + auto CurLoc = sourceLocationInMainFile(SM, Pos); + DeclRelationSet Relations = + DeclRelation::TemplatePattern | DeclRelation::Alias; + std::vector<const NamedDecl *> Decls = + getDeclAtPosition(AST, *CurLoc, Relations); + + const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(Decls[0]); + if (!CMD) + return Results; + + SymbolID ID = getSymbolID(CMD); + RelationsRequest Req; + Req.Subjects.insert(ID); + Req.Predicate = RelationKind::OverridenBy; + Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) { + if (auto Loc = symbolToLocation(Object, *MainFilePath)) + Results.References.push_back(*Loc); + }); + return Results; +} + ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index) { if (!Limit) Index: clang-tools-extra/clangd/Protocol.h =================================================================== --- clang-tools-extra/clangd/Protocol.h +++ clang-tools-extra/clangd/Protocol.h @@ -1402,6 +1402,10 @@ }; bool fromJSON(const llvm::json::Value &, ReferenceParams &, llvm::json::Path); +struct ImplementationParams : public TextDocumentPositionParams {}; +bool fromJSON(const llvm::json::Value &, ImplementationParams &, + llvm::json::Path); + /// Clangd extension: indicates the current state of the file in clangd, /// sent from server via the `textDocument/clangd.fileStatus` notification. struct FileStatus { Index: clang-tools-extra/clangd/Protocol.cpp =================================================================== --- clang-tools-extra/clangd/Protocol.cpp +++ clang-tools-extra/clangd/Protocol.cpp @@ -1209,6 +1209,12 @@ return fromJSON(Params, Base, P); } +bool fromJSON(const llvm::json::Value &Params, ImplementationParams &R, + llvm::json::Path P) { + TextDocumentPositionParams &Base = R; + return fromJSON(Params, Base, P); +} + static const char *toString(OffsetEncoding OE) { switch (OE) { case OffsetEncoding::UTF8: Index: clang-tools-extra/clangd/ClangdServer.h =================================================================== --- clang-tools-extra/clangd/ClangdServer.h +++ clang-tools-extra/clangd/ClangdServer.h @@ -253,6 +253,10 @@ /// Retrieve ranges that can be used to fold code within the specified file. void foldingRanges(StringRef File, Callback<std::vector<FoldingRange>> CB); + /// Retrieve implementations for virtual method. + void findImplementations(PathRef File, Position Pos, + Callback<ReferencesResult> CB); + /// Retrieve locations for symbol references. void findReferences(PathRef File, Position Pos, uint32_t Limit, Callback<ReferencesResult> CB); Index: clang-tools-extra/clangd/ClangdServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdServer.cpp +++ clang-tools-extra/clangd/ClangdServer.cpp @@ -717,6 +717,18 @@ TUScheduler::InvalidateOnUpdate); } +void ClangdServer::findImplementations(PathRef File, Position Pos, + Callback<ReferencesResult> CB) { + auto Action = [Pos, CB = std::move(CB), + this](llvm::Expected<InputsAndAST> InpAST) mutable { + if (!InpAST) + return CB(InpAST.takeError()); + CB(clangd::findImplementations(InpAST->AST, Pos, Index)); + }; + + WorkScheduler.runWithAST("Implementations", File, std::move(Action)); +} + void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit, Callback<ReferencesResult> CB) { auto Action = [Pos, Limit, CB = std::move(CB), Index: clang-tools-extra/clangd/ClangdLSPServer.h =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.h +++ clang-tools-extra/clangd/ClangdLSPServer.h @@ -114,6 +114,8 @@ Callback<std::vector<Location>>); void onGoToDefinition(const TextDocumentPositionParams &, Callback<std::vector<Location>>); + void onImplementation(const ImplementationParams &, + Callback<std::vector<Location>>); void onReference(const ReferenceParams &, Callback<std::vector<Location>>); void onSwitchSourceHeader(const TextDocumentIdentifier &, Callback<llvm::Optional<URIForFile>>); Index: clang-tools-extra/clangd/ClangdLSPServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.cpp +++ clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -612,6 +612,7 @@ {"selectionRangeProvider", true}, {"documentSymbolProvider", true}, {"workspaceSymbolProvider", true}, + {"implementationProvider", true}, {"referencesProvider", true}, {"executeCommandProvider", llvm::json::Object{ @@ -1288,6 +1289,18 @@ }); } +void ClangdLSPServer::onImplementation(const ImplementationParams &Params, + Callback<std::vector<Location>> Reply) { + Server->findImplementations( + Params.textDocument.uri.file(), Params.position, + [Reply = + std::move(Reply)](llvm::Expected<ReferencesResult> Impls) mutable { + if (!Impls) + return Reply(Impls.takeError()); + return Reply(std::move(Impls->References)); + }); +} + void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params, Callback<std::vector<SymbolDetails>> Reply) { Server->symbolInfo(Params.textDocument.uri.file(), Params.position, @@ -1424,6 +1437,7 @@ MsgHandler->bind("textDocument/definition", &ClangdLSPServer::onGoToDefinition); MsgHandler->bind("textDocument/declaration", &ClangdLSPServer::onGoToDeclaration); MsgHandler->bind("textDocument/references", &ClangdLSPServer::onReference); + MsgHandler->bind("textDocument/implementation", &ClangdLSPServer::onImplementation); MsgHandler->bind("textDocument/switchSourceHeader", &ClangdLSPServer::onSwitchSourceHeader); MsgHandler->bind("textDocument/prepareRename", &ClangdLSPServer::onPrepareRename); MsgHandler->bind("textDocument/rename", &ClangdLSPServer::onRename);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits