Author: ibiryukov Date: Tue Jun 13 03:32:27 2017 New Revision: 305280 URL: http://llvm.org/viewvc/llvm-project?rev=305280&view=rev Log: [clangd] Allow to override contents of the file during completion.
Reviewers: krasimir Reviewed By: krasimir Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D34107 Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp clang-tools-extra/trunk/clangd/ClangdServer.h clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=305280&r1=305279&r2=305280&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original) +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Tue Jun 13 03:32:27 2017 @@ -184,17 +184,27 @@ void ClangdServer::forceReparse(PathRef addDocument(File, getDocument(File)); } -Tagged<std::vector<CompletionItem>> ClangdServer::codeComplete(PathRef File, - Position Pos) { - auto FileContents = DraftMgr.getDraft(File); - assert(FileContents.Draft && "codeComplete is called for non-added document"); +Tagged<std::vector<CompletionItem>> +ClangdServer::codeComplete(PathRef File, Position Pos, + llvm::Optional<StringRef> OverridenContents) { + if (!OverridenContents) { + auto FileContents = DraftMgr.getDraft(File); + assert(FileContents.Draft && + "codeComplete is called for non-added document"); + + OverridenContents = *FileContents.Draft; + } std::vector<CompletionItem> Result; auto TaggedFS = FSProvider->getTaggedFileSystem(); - Units.runOnUnitWithoutReparse( - File, *FileContents.Draft, *CDB, PCHs, TaggedFS.Value, [&](ClangdUnit &Unit) { - Result = Unit.codeComplete(*FileContents.Draft, Pos, TaggedFS.Value); - }); + // It would be nice to use runOnUnitWithoutReparse here, but we can't + // guarantee the correctness of code completion cache here if we don't do the + // reparse. + Units.runOnUnit(File, *OverridenContents, *CDB, PCHs, TaggedFS.Value, + [&](ClangdUnit &Unit) { + Result = Unit.codeComplete(*OverridenContents, Pos, + TaggedFS.Value); + }); return make_tagged(std::move(Result), TaggedFS.Tag); } Modified: clang-tools-extra/trunk/clangd/ClangdServer.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=305280&r1=305279&r2=305280&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.h (original) +++ clang-tools-extra/trunk/clangd/ClangdServer.h Tue Jun 13 03:32:27 2017 @@ -152,8 +152,15 @@ public: /// Force \p File to be reparsed using the latest contents. void forceReparse(PathRef File); - /// Run code completion for \p File at \p Pos. - Tagged<std::vector<CompletionItem>> codeComplete(PathRef File, Position Pos); + /// Run code completion for \p File at \p Pos. If \p OverridenContents is not + /// None, they will used only for code completion, i.e. no diagnostics update + /// will be scheduled and a draft for \p File will not be updated. + /// If \p OverridenContents is None, contents of the current draft for \p File + /// will be used. + /// This method should only be called for currently tracked files. + Tagged<std::vector<CompletionItem>> + codeComplete(PathRef File, Position Pos, + llvm::Optional<StringRef> OverridenContents = llvm::None); /// Run formatting for \p Rng inside \p File. std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng); Modified: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=305280&r1=305279&r2=305280&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Tue Jun 13 03:32:27 2017 @@ -398,5 +398,69 @@ TEST_F(ClangdVFSTest, CheckVersions) { EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).Tag, FS->Tag); } +class ClangdCompletionTest : public ClangdVFSTest { +protected: + bool ContainsItem(std::vector<CompletionItem> const &Items, StringRef Name) { + for (const auto &Item : Items) { + if (Item.insertText == Name) + return true; + } + return false; + } +}; + +TEST_F(ClangdCompletionTest, CheckContentsOverride) { + MockFSProvider *FS; + + ClangdServer Server(llvm::make_unique<MockCompilationDatabase>(), + llvm::make_unique<ErrorCheckingDiagConsumer>(), + getAndMove(llvm::make_unique<MockFSProvider>(), FS), + /*RunSynchronously=*/false); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( +int aba; +int b = ; +)cpp"; + + const auto OverridenSourceContents = R"cpp( +int cbc; +int b = ; +)cpp"; + // Complete after '=' sign. We need to be careful to keep the SourceContents' + // size the same. + // We complete on the 3rd line (2nd in zero-based numbering), because raw + // string literal of the SourceContents starts with a newline(it's easy to + // miss). + Position CompletePos = {2, 8}; + FS->Files[FooCpp] = SourceContents; + + Server.addDocument(FooCpp, SourceContents); + + { + auto CodeCompletionResults1 = + Server.codeComplete(FooCpp, CompletePos, None).Value; + EXPECT_TRUE(ContainsItem(CodeCompletionResults1, "aba")); + EXPECT_FALSE(ContainsItem(CodeCompletionResults1, "cbc")); + } + + { + auto CodeCompletionResultsOverriden = + Server + .codeComplete(FooCpp, CompletePos, + StringRef(OverridenSourceContents)) + .Value; + EXPECT_TRUE(ContainsItem(CodeCompletionResultsOverriden, "cbc")); + EXPECT_FALSE(ContainsItem(CodeCompletionResultsOverriden, "aba")); + } + + { + auto CodeCompletionResults2 = + Server.codeComplete(FooCpp, CompletePos, None).Value; + EXPECT_TRUE(ContainsItem(CodeCompletionResults2, "aba")); + EXPECT_FALSE(ContainsItem(CodeCompletionResults2, "cbc")); + } +} + } // namespace clangd } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits