<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="" applecontenteditable="true">Hi Ilya,<div class=""><br class=""></div><div class="">The unit test introduced by this commit hits an assertion failure on our bots. Could you please take a look at the issue?</div><div class=""><br class=""></div><div class=""> <a href="http://lab.llvm.org:8080/green/job/clang-stage1-cmake-RA-expensive/6733" class="">lab.llvm.org:8080/green/job/clang-stage1-cmake-RA-expensive/6733</a></div><div class=""><br class=""></div><div class="">I see:</div><div class=""><br class=""></div><span class=""><div class="">[ RUN ] ClangdVFSTest.Reparse</div><br class="Apple-interchange-newline"><div class="">Assertion failed: (Unit && "Unit wasn't created"), function ClangdUnit, file /Users/buildslave/jenkins/sharedspace/clang-stage1-cmake-RA_workspace/llvm/tools/clang/tools/extra/clangd/ClangdUnit.cpp, line 58.</div><br class="Apple-interchange-newline"><div class="">0 ClangdTests 0x0000000102fec2f8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40</div><div class="">1 ClangdTests 0x0000000102fec9e6 SignalHandler(int) + 454</div><div class="">2 libsystem_platform.dylib 0x00007fff97ed352a _sigtramp + 26</div><div class="">3 libsystem_platform.dylib 000000000000000000 _sigtramp + 1746062064</div><div class="">4 libsystem_c.dylib 0x00007fff97d776df abort + 129</div><div class="">5 libsystem_c.dylib 0x00007fff97d3edd8 basename + 0</div><div class="">6 ClangdTests 0x00000001030c95dd clang::clangd::ClangdUnit::ClangdUnit(llvm::StringRef, llvm::StringRef, std::__1::shared_ptr<clang::PCHContainerOperations>, std::__1::vector<clang::tooling::CompileCommand, std::__1::allocator<clang::tooling::CompileCommand> >, llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem>) + 1837</div><div class="">7 ClangdTests 0x00000001030c824f std::__1::__function::__func<clang::clangd::ClangdServer::addDocument(llvm::StringRef, llvm::StringRef)::$_1, std::__1::allocator<clang::clangd::ClangdServer::addDocument(llvm::StringRef, llvm::StringRef)::$_1>, void ()>::operator()() + 975</div><div class="">8 ClangdTests 0x00000001030c6e03 void* std::__1::__thread_proxy<std::__1::tuple<clang::clangd::ClangdScheduler::ClangdScheduler(bool)::$_0> >(void*) + 579</div><div class="">9 libsystem_pthread.dylib 0x00007fff8e26099d _pthread_body + 131</div><div class="">10 libsystem_pthread.dylib 0x00007fff8e26091a _pthread_body + 0</div><div class="">11 libsystem_pthread.dylib 0x00007fff8e25e351 thread_start + 13</div><div class=""><br class=""></div><div class="">********************</div><div class="">FAIL: Extra Tools Unit Tests :: clangd/ClangdTests/ClangdVFSTest.ReparseOnHeaderChange (13778 of 37955)</div><div class="">******************** TEST 'Extra Tools Unit Tests :: clangd/ClangdTests/ClangdVFSTest.ReparseOnHeaderChange' FAILED ********************</div><div class="">Note: Google Test filter = ClangdVFSTest.ReparseOnHeaderChange</div><div class="">[==========] Running 1 test from 1 test case.</div><div class="">[----------] Global test environment set-up.</div><div class="">[----------] 1 test from ClangdVFSTest</div><div class="">[ RUN ] ClangdVFSTest.ReparseOnHeaderChange</div><br class="Apple-interchange-newline"><div class="">Assertion failed: (Unit && "Unit wasn't created"), function ClangdUnit, file /Users/buildslave/jenkins/sharedspace/clang-stage1-cmake-RA_workspace/llvm/tools/clang/tools/extra/clangd/ClangdUnit.cpp, line 58.</div><br class="Apple-interchange-newline"><div class="">0 ClangdTests 0x00000001005b72f8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40</div><div class="">1 ClangdTests 0x00000001005b79e6 SignalHandler(int) + 454</div><div class="">2 libsystem_platform.dylib 0x00007fff97ed352a _sigtramp + 26</div><div class="">3 libsystem_platform.dylib 000000000000000000 _sigtramp + 1746062064</div><div class="">4 libsystem_c.dylib 0x00007fff97d776df abort + 129</div><div class="">5 libsystem_c.dylib 0x00007fff97d3edd8 basename + 0</div><div class="">6 ClangdTests 0x00000001006945dd clang::clangd::ClangdUnit::ClangdUnit(llvm::StringRef, llvm::StringRef, std::__1::shared_ptr<clang::PCHContainerOperations>, std::__1::vector<clang::tooling::CompileCommand, std::__1::allocator<clang::tooling::CompileCommand> >, llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem>) + 1837</div><div class="">7 ClangdTests 0x000000010069324f std::__1::__function::__func<clang::clangd::ClangdServer::addDocument(llvm::StringRef, llvm::StringRef)::$_1, std::__1::allocator<clang::clangd::ClangdServer::addDocument(llvm::StringRef, llvm::StringRef)::$_1>, void ()>::operator()() + 975</div><div class="">8 ClangdTests 0x0000000100691e03 void* std::__1::__thread_proxy<std::__1::tuple<clang::clangd::ClangdScheduler::ClangdScheduler(bool)::$_0> >(void*) + 579</div><div class="">9 libsystem_pthread.dylib 0x00007fff8e26099d _pthread_body + 131</div><div class="">10 libsystem_pthread.dylib 0x00007fff8e26091a _pthread_body + 0</div><div class="">11 libsystem_pthread.dylib 0x00007fff8e25e351 thread_start + 13</div></span><span class=""><br class=""></span><div class="">thanks,</div><div class="">vedant</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On May 26, 2017, at 5:26 AM, Ilya Biryukov via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Author: ibiryukov<br class="">Date: Fri May 26 07:26:51 2017<br class="">New Revision: 303977<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=303977&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=303977&view=rev</a><br class="">Log:<br class="">[clangd] Allow to use vfs::FileSystem for file accesses.<br class=""><br class="">Summary:<br class="">Custom vfs::FileSystem is currently used for unit tests.<br class="">This revision depends on <a href="https://reviews.llvm.org/D33397" class="">https://reviews.llvm.org/D33397</a>.<br class=""><br class="">Reviewers: bkramer, krasimir<br class=""><br class="">Reviewed By: bkramer, krasimir<br class=""><br class="">Subscribers: klimek, cfe-commits, mgorny<br class=""><br class="">Differential Revision: <a href="https://reviews.llvm.org/D33416" class="">https://reviews.llvm.org/D33416</a><br class=""><br class="">Added:<br class=""> clang-tools-extra/trunk/unittests/clangd/<br class=""> clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt<br class=""> clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp<br class="">Modified:<br class=""> clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp<br class=""> clang-tools-extra/trunk/clangd/ClangdServer.cpp<br class=""> clang-tools-extra/trunk/clangd/ClangdServer.h<br class=""> clang-tools-extra/trunk/clangd/ClangdUnit.cpp<br class=""> clang-tools-extra/trunk/clangd/ClangdUnit.h<br class=""> clang-tools-extra/trunk/clangd/ClangdUnitStore.h<br class=""> clang-tools-extra/trunk/unittests/CMakeLists.txt<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=303977&r1=303976&r2=303977&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=303977&r1=303976&r2=303977&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Fri May 26 07:26:51 2017<br class="">@@ -199,6 +199,7 @@ ClangdLSPServer::ClangdLSPServer(JSONOut<br class=""> : Out(Out),<br class=""> Server(llvm::make_unique<DirectoryBasedGlobalCompilationDatabase>(),<br class=""> llvm::make_unique<LSPDiagnosticsConsumer>(*this),<br class="">+ llvm::make_unique<RealFileSystemProvider>(),<br class=""> RunSynchronously) {}<br class=""><br class=""> void ClangdLSPServer::run(std::istream &In) {<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=303977&r1=303976&r2=303977&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=303977&r1=303976&r2=303977&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Fri May 26 07:26:51 2017<br class="">@@ -58,6 +58,10 @@ Position clangd::offsetToPosition(String<br class=""> return {Lines, Cols};<br class=""> }<br class=""><br class="">+IntrusiveRefCntPtr<vfs::FileSystem> RealFileSystemProvider::getFileSystem() {<br class="">+ return vfs::getRealFileSystem();<br class="">+}<br class="">+<br class=""> ClangdScheduler::ClangdScheduler(bool RunSynchronously)<br class=""> : RunSynchronously(RunSynchronously) {<br class=""> if (RunSynchronously) {<br class="">@@ -135,8 +139,10 @@ void ClangdScheduler::addToEnd(std::func<br class=""><br class=""> ClangdServer::ClangdServer(std::unique_ptr<GlobalCompilationDatabase> CDB,<br class=""> std::unique_ptr<DiagnosticsConsumer> DiagConsumer,<br class="">+ std::unique_ptr<FileSystemProvider> FSProvider,<br class=""> bool RunSynchronously)<br class=""> : CDB(std::move(CDB)), DiagConsumer(std::move(DiagConsumer)),<br class="">+ FSProvider(std::move(FSProvider)),<br class=""> PCHs(std::make_shared<PCHContainerOperations>()),<br class=""> WorkScheduler(RunSynchronously) {}<br class=""><br class="">@@ -150,10 +156,11 @@ void ClangdServer::addDocument(PathRef F<br class=""><br class=""> assert(FileContents.Draft &&<br class=""> "No contents inside a file that was scheduled for reparse");<br class="">- Units.runOnUnit(<br class="">- FileStr, *FileContents.Draft, *CDB, PCHs, [&](ClangdUnit const &Unit) {<br class="">- DiagConsumer->onDiagnosticsReady(FileStr, Unit.getLocalDiagnostics());<br class="">- });<br class="">+ Units.runOnUnit(FileStr, *FileContents.Draft, *CDB, PCHs,<br class="">+ FSProvider->getFileSystem(), [&](ClangdUnit const &Unit) {<br class="">+ DiagConsumer->onDiagnosticsReady(<br class="">+ FileStr, Unit.getLocalDiagnostics());<br class="">+ });<br class=""> });<br class=""> }<br class=""><br class="">@@ -168,15 +175,22 @@ void ClangdServer::removeDocument(PathRe<br class=""> });<br class=""> }<br class=""><br class="">+void ClangdServer::forceReparse(PathRef File) {<br class="">+ // The addDocument schedules the reparse even if the contents of the file<br class="">+ // never changed, so we just call it here.<br class="">+ addDocument(File, getDocument(File));<br class="">+}<br class="">+<br class=""> std::vector<CompletionItem> ClangdServer::codeComplete(PathRef File,<br class=""> Position Pos) {<br class=""> auto FileContents = DraftMgr.getDraft(File);<br class=""> assert(FileContents.Draft && "codeComplete is called for non-added document");<br class=""><br class=""> std::vector<CompletionItem> Result;<br class="">+ auto VFS = FSProvider->getFileSystem();<br class=""> Units.runOnUnitWithoutReparse(<br class="">- File, *FileContents.Draft, *CDB, PCHs, [&](ClangdUnit &Unit) {<br class="">- Result = Unit.codeComplete(*FileContents.Draft, Pos);<br class="">+ File, *FileContents.Draft, *CDB, PCHs, VFS, [&](ClangdUnit &Unit) {<br class="">+ Result = Unit.codeComplete(*FileContents.Draft, Pos, VFS);<br class=""> });<br class=""> return Result;<br class=""> }<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ClangdServer.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=303977&r1=303976&r2=303977&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=303977&r1=303976&r2=303977&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdServer.h Fri May 26 07:26:51 2017<br class="">@@ -50,6 +50,17 @@ public:<br class=""> std::vector<DiagWithFixIts> Diagnostics) = 0;<br class=""> };<br class=""><br class="">+class FileSystemProvider {<br class="">+public:<br class="">+ virtual ~FileSystemProvider() = default;<br class="">+ virtual IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() = 0;<br class="">+};<br class="">+<br class="">+class RealFileSystemProvider : public FileSystemProvider {<br class="">+public:<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() override;<br class="">+};<br class="">+<br class=""> class ClangdServer;<br class=""><br class=""> /// Handles running WorkerRequests of ClangdServer on a separate threads.<br class="">@@ -94,6 +105,7 @@ class ClangdServer {<br class=""> public:<br class=""> ClangdServer(std::unique_ptr<GlobalCompilationDatabase> CDB,<br class=""> std::unique_ptr<DiagnosticsConsumer> DiagConsumer,<br class="">+ std::unique_ptr<FileSystemProvider> FSProvider,<br class=""> bool RunSynchronously);<br class=""><br class=""> /// Add a \p File to the list of tracked C++ files or update the contents if<br class="">@@ -104,6 +116,8 @@ public:<br class=""> /// Remove \p File from list of tracked files, schedule a request to free<br class=""> /// resources associated with it.<br class=""> void removeDocument(PathRef File);<br class="">+ /// Force \p File to be reparsed using the latest contents.<br class="">+ void forceReparse(PathRef File);<br class=""><br class=""> /// Run code completion for \p File at \p Pos.<br class=""> std::vector<CompletionItem> codeComplete(PathRef File, Position Pos);<br class="">@@ -129,6 +143,7 @@ public:<br class=""> private:<br class=""> std::unique_ptr<GlobalCompilationDatabase> CDB;<br class=""> std::unique_ptr<DiagnosticsConsumer> DiagConsumer;<br class="">+ std::unique_ptr<FileSystemProvider> FSProvider;<br class=""> DraftStore DraftMgr;<br class=""> ClangdUnitStore Units;<br class=""> std::shared_ptr<PCHContainerOperations> PCHs;<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=303977&r1=303976&r2=303977&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=303977&r1=303976&r2=303977&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Fri May 26 07:26:51 2017<br class="">@@ -11,6 +11,7 @@<br class=""> #include "clang/Frontend/ASTUnit.h"<br class=""> #include "clang/Frontend/CompilerInstance.h"<br class=""> #include "clang/Frontend/CompilerInvocation.h"<br class="">+#include "clang/Frontend/Utils.h"<br class=""> #include "clang/Tooling/CompilationDatabase.h"<br class=""><br class=""> using namespace clang::clangd;<br class="">@@ -18,7 +19,8 @@ using namespace clang;<br class=""><br class=""> ClangdUnit::ClangdUnit(PathRef FileName, StringRef Contents,<br class=""> std::shared_ptr<PCHContainerOperations> PCHs,<br class="">- std::vector<tooling::CompileCommand> Commands)<br class="">+ std::vector<tooling::CompileCommand> Commands,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS)<br class=""> : FileName(FileName), PCHs(PCHs) {<br class=""> assert(!Commands.empty() && "No compile commands provided");<br class=""><br class="">@@ -48,10 +50,16 @@ ClangdUnit::ClangdUnit(PathRef FileName,<br class=""> /*PrecompilePreambleAfterNParses=*/1, /*TUKind=*/TU_Prefix,<br class=""> /*CacheCodeCompletionResults=*/true,<br class=""> /*IncludeBriefCommentsInCodeCompletion=*/true,<br class="">- /*AllowPCHWithCompilerErrors=*/true));<br class="">+ /*AllowPCHWithCompilerErrors=*/true,<br class="">+ /*SkipFunctionBodies=*/false,<br class="">+ /*UserFilesAreVolatile=*/false, /*ForSerialization=*/false,<br class="">+ /*ModuleFormat=*/llvm::None,<br class="">+ /*ErrAST=*/nullptr, VFS));<br class="">+ assert(Unit && "Unit wasn't created");<br class=""> }<br class=""><br class="">-void ClangdUnit::reparse(StringRef Contents) {<br class="">+void ClangdUnit::reparse(StringRef Contents,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS) {<br class=""> // Do a reparse if this wasn't the first parse.<br class=""> // FIXME: This might have the wrong working directory if it changed in the<br class=""> // meantime.<br class="">@@ -59,7 +67,7 @@ void ClangdUnit::reparse(StringRef Conte<br class=""> FileName,<br class=""> llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());<br class=""><br class="">- Unit->Reparse(PCHs, RemappedSource);<br class="">+ Unit->Reparse(PCHs, RemappedSource, VFS);<br class=""> }<br class=""><br class=""> namespace {<br class="">@@ -146,8 +154,9 @@ public:<br class=""> };<br class=""> } // namespace<br class=""><br class="">-std::vector<CompletionItem> ClangdUnit::codeComplete(StringRef Contents,<br class="">- Position Pos) {<br class="">+std::vector<CompletionItem><br class="">+ClangdUnit::codeComplete(StringRef Contents, Position Pos,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS) {<br class=""> CodeCompleteOptions CCO;<br class=""> CCO.IncludeBriefComments = 1;<br class=""> // This is where code completion stores dirty buffers. Need to free after<br class="">@@ -163,8 +172,10 @@ std::vector<CompletionItem> ClangdUnit::<br class=""> FileName,<br class=""> llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName).release());<br class=""><br class="">+ IntrusiveRefCntPtr<FileManager> FileMgr(<br class="">+ new FileManager(Unit->getFileSystemOpts(), VFS));<br class=""> IntrusiveRefCntPtr<SourceManager> SourceMgr(<br class="">- new SourceManager(*DiagEngine, Unit->getFileManager()));<br class="">+ new SourceManager(*DiagEngine, *FileMgr));<br class=""> // CodeComplete seems to require fresh LangOptions.<br class=""> LangOptions LangOpts = Unit->getLangOpts();<br class=""> // The language server protocol uses zero-based line and column numbers.<br class="">@@ -172,8 +183,8 @@ std::vector<CompletionItem> ClangdUnit::<br class=""> Unit->CodeComplete(FileName, Pos.line + 1, Pos.character + 1, RemappedSource,<br class=""> CCO.IncludeMacros, CCO.IncludeCodePatterns,<br class=""> CCO.IncludeBriefComments, Collector, PCHs, *DiagEngine,<br class="">- LangOpts, *SourceMgr, Unit->getFileManager(),<br class="">- StoredDiagnostics, OwnedBuffers);<br class="">+ LangOpts, *SourceMgr, *FileMgr, StoredDiagnostics,<br class="">+ OwnedBuffers);<br class=""> for (const llvm::MemoryBuffer *Buffer : OwnedBuffers)<br class=""> delete Buffer;<br class=""> return Items;<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=303977&r1=303976&r2=303977&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=303977&r1=303976&r2=303977&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdUnit.h Fri May 26 07:26:51 2017<br class="">@@ -10,8 +10,8 @@<br class=""> #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H<br class=""> #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H<br class=""><br class="">-#include "Protocol.h"<br class=""> #include "Path.h"<br class="">+#include "Protocol.h"<br class=""> #include "clang/Frontend/ASTUnit.h"<br class=""> #include "clang/Tooling/Core/Replacement.h"<br class=""> #include <memory><br class="">@@ -24,6 +24,10 @@ namespace clang {<br class=""> class ASTUnit;<br class=""> class PCHContainerOperations;<br class=""><br class="">+namespace vfs {<br class="">+class FileSystem;<br class="">+}<br class="">+<br class=""> namespace tooling {<br class=""> struct CompileCommand;<br class=""> }<br class="">@@ -42,16 +46,19 @@ class ClangdUnit {<br class=""> public:<br class=""> ClangdUnit(PathRef FileName, StringRef Contents,<br class=""> std::shared_ptr<PCHContainerOperations> PCHs,<br class="">- std::vector<tooling::CompileCommand> Commands);<br class="">+ std::vector<tooling::CompileCommand> Commands,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS);<br class=""><br class=""> /// Reparse with new contents.<br class="">- void reparse(StringRef Contents);<br class="">+ void reparse(StringRef Contents, IntrusiveRefCntPtr<vfs::FileSystem> VFS);<br class=""><br class=""> /// Get code completions at a specified \p Line and \p Column in \p File.<br class=""> ///<br class=""> /// This function is thread-safe and returns completion items that own the<br class=""> /// data they contain.<br class="">- std::vector<CompletionItem> codeComplete(StringRef Contents, Position Pos);<br class="">+ std::vector<CompletionItem><br class="">+ codeComplete(StringRef Contents, Position Pos,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS);<br class=""> /// Returns diagnostics and corresponding FixIts for each diagnostic that are<br class=""> /// located in the current file.<br class=""> std::vector<DiagWithFixIts> getLocalDiagnostics() const;<br class=""><br class="">Modified: clang-tools-extra/trunk/clangd/ClangdUnitStore.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnitStore.h?rev=303977&r1=303976&r2=303977&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnitStore.h?rev=303977&r1=303976&r2=303977&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/clangd/ClangdUnitStore.h (original)<br class="">+++ clang-tools-extra/trunk/clangd/ClangdUnitStore.h Fri May 26 07:26:51 2017<br class="">@@ -32,9 +32,10 @@ public:<br class=""> template <class Func><br class=""> void runOnUnit(PathRef File, StringRef FileContents,<br class=""> GlobalCompilationDatabase &CDB,<br class="">- std::shared_ptr<PCHContainerOperations> PCHs, Func Action) {<br class="">+ std::shared_ptr<PCHContainerOperations> PCHs,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) {<br class=""> runOnUnitImpl(File, FileContents, CDB, PCHs, /*ReparseBeforeAction=*/true,<br class="">- std::forward<Func>(Action));<br class="">+ VFS, std::forward<Func>(Action));<br class=""> }<br class=""><br class=""> /// Run specified \p Action on the ClangdUnit for \p File.<br class="">@@ -45,9 +46,10 @@ public:<br class=""> void runOnUnitWithoutReparse(PathRef File, StringRef FileContents,<br class=""> GlobalCompilationDatabase &CDB,<br class=""> std::shared_ptr<PCHContainerOperations> PCHs,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS,<br class=""> Func Action) {<br class=""> runOnUnitImpl(File, FileContents, CDB, PCHs, /*ReparseBeforeAction=*/false,<br class="">- std::forward<Func>(Action));<br class="">+ VFS, std::forward<Func>(Action));<br class=""> }<br class=""><br class=""> /// Run the specified \p Action on the ClangdUnit for \p File.<br class="">@@ -71,24 +73,23 @@ private:<br class=""> void runOnUnitImpl(PathRef File, StringRef FileContents,<br class=""> GlobalCompilationDatabase &CDB,<br class=""> std::shared_ptr<PCHContainerOperations> PCHs,<br class="">- bool ReparseBeforeAction, Func Action) {<br class="">+ bool ReparseBeforeAction,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) {<br class=""> std::lock_guard<std::mutex> Lock(Mutex);<br class=""><br class=""> auto Commands = getCompileCommands(CDB, File);<br class=""> assert(!Commands.empty() &&<br class=""> "getCompileCommands should add default command");<br class="">- // chdir. This is thread hostile.<br class="">- // FIXME(ibiryukov): get rid of this<br class="">- llvm::sys::fs::set_current_path(Commands.front().Directory);<br class="">+ VFS->setCurrentWorkingDirectory(Commands.front().Directory);<br class=""><br class=""> auto It = OpenedFiles.find(File);<br class=""> if (It == OpenedFiles.end()) {<br class=""> It = OpenedFiles<br class=""> .insert(std::make_pair(<br class="">- File, ClangdUnit(File, FileContents, PCHs, Commands)))<br class="">+ File, ClangdUnit(File, FileContents, PCHs, Commands, VFS)))<br class=""> .first;<br class=""> } else if (ReparseBeforeAction) {<br class="">- It->second.reparse(FileContents);<br class="">+ It->second.reparse(FileContents, VFS);<br class=""> }<br class=""> return Action(It->second);<br class=""> }<br class=""><br class="">Modified: clang-tools-extra/trunk/unittests/CMakeLists.txt<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/CMakeLists.txt?rev=303977&r1=303976&r2=303977&view=diff" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/CMakeLists.txt?rev=303977&r1=303976&r2=303977&view=diff</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/unittests/CMakeLists.txt (original)<br class="">+++ clang-tools-extra/trunk/unittests/CMakeLists.txt Fri May 26 07:26:51 2017<br class="">@@ -11,4 +11,5 @@ add_subdirectory(clang-move)<br class=""> add_subdirectory(clang-query)<br class=""> add_subdirectory(clang-tidy)<br class=""> add_subdirectory(clang-rename)<br class="">+add_subdirectory(clangd)<br class=""> add_subdirectory(include-fixer)<br class=""><br class="">Added: clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt?rev=303977&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt?rev=303977&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt (added)<br class="">+++ clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt Fri May 26 07:26:51 2017<br class="">@@ -0,0 +1,24 @@<br class="">+set(LLVM_LINK_COMPONENTS<br class="">+ support<br class="">+ )<br class="">+<br class="">+get_filename_component(CLANGD_SOURCE_DIR<br class="">+ ${CMAKE_CURRENT_SOURCE_DIR}/../../clangd REALPATH)<br class="">+include_directories(<br class="">+ ${CLANGD_SOURCE_DIR}<br class="">+ )<br class="">+<br class="">+add_extra_unittest(ClangdTests<br class="">+ ClangdTests.cpp<br class="">+ )<br class="">+<br class="">+target_link_libraries(ClangdTests<br class="">+ clangBasic<br class="">+ clangDaemon<br class="">+ clangFormat<br class="">+ clangFrontend<br class="">+ clangSema<br class="">+ clangTooling<br class="">+ clangToolingCore<br class="">+ LLVMSupport<br class="">+ )<br class=""><br class="">Added: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=303977&view=auto" class="">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=303977&view=auto</a><br class="">==============================================================================<br class="">--- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (added)<br class="">+++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Fri May 26 07:26:51 2017<br class="">@@ -0,0 +1,364 @@<br class="">+//===-- ClangdTests.cpp - Clangd unit tests ---------------------*- C++ -*-===//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#include "ClangdServer.h"<br class="">+#include "clang/Basic/VirtualFileSystem.h"<br class="">+#include "llvm/ADT/SmallVector.h"<br class="">+#include "llvm/ADT/StringMap.h"<br class="">+#include "llvm/Config/config.h"<br class="">+#include "llvm/Support/Errc.h"<br class="">+#include "llvm/Support/Path.h"<br class="">+#include "llvm/Support/Regex.h"<br class="">+#include "gtest/gtest.h"<br class="">+#include <algorithm><br class="">+#include <iostream><br class="">+#include <string><br class="">+#include <vector><br class="">+<br class="">+namespace clang {<br class="">+namespace vfs {<br class="">+<br class="">+/// An implementation of vfs::FileSystem that only allows access to<br class="">+/// files and folders inside a set of whitelisted directories.<br class="">+///<br class="">+/// FIXME(ibiryukov): should it also emulate access to parents of whitelisted<br class="">+/// directories with only whitelisted contents?<br class="">+class FilteredFileSystem : public vfs::FileSystem {<br class="">+public:<br class="">+ /// The paths inside \p WhitelistedDirs should be absolute<br class="">+ FilteredFileSystem(std::vector<std::string> WhitelistedDirs,<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> InnerFS)<br class="">+ : WhitelistedDirs(std::move(WhitelistedDirs)), InnerFS(InnerFS) {<br class="">+ assert(std::all_of(WhitelistedDirs.begin(), WhitelistedDirs.end(),<br class="">+ [](const std::string &Path) -> bool {<br class="">+ return llvm::sys::path::is_absolute(Path);<br class="">+ }) &&<br class="">+ "Not all WhitelistedDirs are absolute");<br class="">+ }<br class="">+<br class="">+ virtual llvm::ErrorOr<Status> status(const Twine &Path) {<br class="">+ if (!isInsideWhitelistedDir(Path))<br class="">+ return llvm::errc::no_such_file_or_directory;<br class="">+ return InnerFS->status(Path);<br class="">+ }<br class="">+<br class="">+ virtual llvm::ErrorOr<std::unique_ptr<File>><br class="">+ openFileForRead(const Twine &Path) {<br class="">+ if (!isInsideWhitelistedDir(Path))<br class="">+ return llvm::errc::no_such_file_or_directory;<br class="">+ return InnerFS->openFileForRead(Path);<br class="">+ }<br class="">+<br class="">+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>><br class="">+ getBufferForFile(const Twine &Name, int64_t FileSize = -1,<br class="">+ bool RequiresNullTerminator = true,<br class="">+ bool IsVolatile = false) {<br class="">+ if (!isInsideWhitelistedDir(Name))<br class="">+ return llvm::errc::no_such_file_or_directory;<br class="">+ return InnerFS->getBufferForFile(Name, FileSize, RequiresNullTerminator,<br class="">+ IsVolatile);<br class="">+ }<br class="">+<br class="">+ virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) {<br class="">+ if (!isInsideWhitelistedDir(Dir)) {<br class="">+ EC = llvm::errc::no_such_file_or_directory;<br class="">+ return directory_iterator();<br class="">+ }<br class="">+ return InnerFS->dir_begin(Dir, EC);<br class="">+ }<br class="">+<br class="">+ virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) {<br class="">+ return InnerFS->setCurrentWorkingDirectory(Path);<br class="">+ }<br class="">+<br class="">+ virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const {<br class="">+ return InnerFS->getCurrentWorkingDirectory();<br class="">+ }<br class="">+<br class="">+ bool exists(const Twine &Path) {<br class="">+ if (!isInsideWhitelistedDir(Path))<br class="">+ return false;<br class="">+ return InnerFS->exists(Path);<br class="">+ }<br class="">+<br class="">+ std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const {<br class="">+ return InnerFS->makeAbsolute(Path);<br class="">+ }<br class="">+<br class="">+private:<br class="">+ bool isInsideWhitelistedDir(const Twine &InputPath) const {<br class="">+ SmallString<128> Path;<br class="">+ InputPath.toVector(Path);<br class="">+<br class="">+ if (makeAbsolute(Path))<br class="">+ return false;<br class="">+<br class="">+ for (const auto &Dir : WhitelistedDirs) {<br class="">+ if (Path.startswith(Dir))<br class="">+ return true;<br class="">+ }<br class="">+ return false;<br class="">+ }<br class="">+<br class="">+ std::vector<std::string> WhitelistedDirs;<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> InnerFS;<br class="">+};<br class="">+<br class="">+/// Create a vfs::FileSystem that has access only to temporary directories<br class="">+/// (obtained by calling system_temp_directory).<br class="">+IntrusiveRefCntPtr<vfs::FileSystem> getTempOnlyFS() {<br class="">+ llvm::SmallString<128> TmpDir1;<br class="">+ llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, TmpDir1);<br class="">+ llvm::SmallString<128> TmpDir2;<br class="">+ llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/true, TmpDir2);<br class="">+<br class="">+ std::vector<std::string> TmpDirs;<br class="">+ TmpDirs.push_back(TmpDir1.str());<br class="">+ if (TmpDir2 != TmpDir2)<br class="">+ TmpDirs.push_back(TmpDir2.str());<br class="">+ return new vfs::FilteredFileSystem(std::move(TmpDirs),<br class="">+ vfs::getRealFileSystem());<br class="">+}<br class="">+} // namespace vfs<br class="">+<br class="">+namespace clangd {<br class="">+namespace {<br class="">+<br class="">+class ErrorCheckingDiagConsumer : public DiagnosticsConsumer {<br class="">+public:<br class="">+ void onDiagnosticsReady(PathRef File,<br class="">+ std::vector<DiagWithFixIts> Diagnostics) override {<br class="">+ bool HadError = false;<br class="">+ for (const auto &DiagAndFixIts : Diagnostics) {<br class="">+ // FIXME: severities returned by clangd should have a descriptive<br class="">+ // diagnostic severity enum<br class="">+ const int ErrorSeverity = 1;<br class="">+ HadError = DiagAndFixIts.Diag.severity == ErrorSeverity;<br class="">+ }<br class="">+<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+ HadErrorInLastDiags = HadError;<br class="">+ }<br class="">+<br class="">+ bool hadErrorInLastDiags() {<br class="">+ std::lock_guard<std::mutex> Lock(Mutex);<br class="">+ return HadErrorInLastDiags;<br class="">+ }<br class="">+<br class="">+private:<br class="">+ std::mutex Mutex;<br class="">+ bool HadErrorInLastDiags = false;<br class="">+};<br class="">+<br class="">+class MockCompilationDatabase : public GlobalCompilationDatabase {<br class="">+public:<br class="">+ std::vector<tooling::CompileCommand><br class="">+ getCompileCommands(PathRef File) override {<br class="">+ return {};<br class="">+ }<br class="">+};<br class="">+<br class="">+class MockFSProvider : public FileSystemProvider {<br class="">+public:<br class="">+ IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() override {<br class="">+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> MemFS(<br class="">+ new vfs::InMemoryFileSystem);<br class="">+ for (auto &FileAndContents : Files)<br class="">+ MemFS->addFile(FileAndContents.first(), time_t(),<br class="">+ llvm::MemoryBuffer::getMemBuffer(FileAndContents.second,<br class="">+ FileAndContents.first()));<br class="">+<br class="">+ auto OverlayFS = IntrusiveRefCntPtr<vfs::OverlayFileSystem>(<br class="">+ new vfs::OverlayFileSystem(vfs::getTempOnlyFS()));<br class="">+ OverlayFS->pushOverlay(std::move(MemFS));<br class="">+ return OverlayFS;<br class="">+ }<br class="">+<br class="">+ llvm::StringMap<std::string> Files;<br class="">+};<br class="">+<br class="">+/// Replaces all patterns of the form 0x123abc with spaces<br class="">+void replacePtrsInDump(std::string &Dump) {<br class="">+ llvm::Regex RE("0x[0-9a-fA-F]+");<br class="">+ llvm::SmallVector<StringRef, 1> Matches;<br class="">+ while (RE.match(Dump, &Matches)) {<br class="">+ assert(Matches.size() == 1 && "Exactly one match expected");<br class="">+ auto MatchPos = Matches[0].data() - Dump.data();<br class="">+ std::fill(Dump.begin() + MatchPos,<br class="">+ Dump.begin() + MatchPos + Matches[0].size(), ' ');<br class="">+ }<br class="">+}<br class="">+<br class="">+std::string dumpASTWithoutMemoryLocs(ClangdServer &Server, PathRef File) {<br class="">+ auto Dump = Server.dumpAST(File);<br class="">+ replacePtrsInDump(Dump);<br class="">+ return Dump;<br class="">+}<br class="">+<br class="">+template <class T><br class="">+std::unique_ptr<T> getAndMove(std::unique_ptr<T> Ptr, T *&Output) {<br class="">+ Output = Ptr.get();<br class="">+ return Ptr;<br class="">+}<br class="">+} // namespace<br class="">+<br class="">+class ClangdVFSTest : public ::testing::Test {<br class="">+protected:<br class="">+ SmallString<16> getVirtualTestRoot() {<br class="">+#ifdef LLVM_ON_WIN32<br class="">+ return SmallString<16>("C:\\clangd-test");<br class="">+#else<br class="">+ return SmallString<16>("/clangd-test");<br class="">+#endif<br class="">+ }<br class="">+<br class="">+ llvm::SmallString<32> getVirtualTestFilePath(PathRef File) {<br class="">+ assert(llvm::sys::path::is_relative(File) && "FileName should be relative");<br class="">+<br class="">+ llvm::SmallString<32> Path;<br class="">+ llvm::sys::path::append(Path, getVirtualTestRoot(), File);<br class="">+ return Path;<br class="">+ }<br class="">+<br class="">+ std::string parseSourceAndDumpAST(<br class="">+ PathRef SourceFileRelPath, StringRef SourceContents,<br class="">+ std::vector<std::pair<PathRef, StringRef>> ExtraFiles = {},<br class="">+ bool ExpectErrors = false) {<br class="">+ MockFSProvider *FS;<br class="">+ ErrorCheckingDiagConsumer *DiagConsumer;<br class="">+ ClangdServer Server(<br class="">+ llvm::make_unique<MockCompilationDatabase>(),<br class="">+ getAndMove(llvm::make_unique<ErrorCheckingDiagConsumer>(),<br class="">+ DiagConsumer),<br class="">+ getAndMove(llvm::make_unique<MockFSProvider>(), FS),<br class="">+ /*RunSynchronously=*/false);<br class="">+ for (const auto &FileWithContents : ExtraFiles)<br class="">+ FS->Files[getVirtualTestFilePath(FileWithContents.first)] =<br class="">+ FileWithContents.second;<br class="">+<br class="">+ auto SourceFilename = getVirtualTestFilePath(SourceFileRelPath);<br class="">+ Server.addDocument(SourceFilename, SourceContents);<br class="">+ auto Result = dumpASTWithoutMemoryLocs(Server, SourceFilename);<br class="">+ EXPECT_EQ(ExpectErrors, DiagConsumer->hadErrorInLastDiags());<br class="">+ return Result;<br class="">+ }<br class="">+};<br class="">+<br class="">+TEST_F(ClangdVFSTest, Parse) {<br class="">+ // FIXME: figure out a stable format for AST dumps, so that we can check the<br class="">+ // output of the dump itself is equal to the expected one, not just that it's<br class="">+ // different.<br class="">+ auto Empty = parseSourceAndDumpAST("foo.cpp", "", {});<br class="">+ auto OneDecl = parseSourceAndDumpAST("foo.cpp", "int a;", {});<br class="">+ auto SomeDecls = parseSourceAndDumpAST("foo.cpp", "int a; int b; int c;", {});<br class="">+ EXPECT_NE(Empty, OneDecl);<br class="">+ EXPECT_NE(Empty, SomeDecls);<br class="">+ EXPECT_NE(SomeDecls, OneDecl);<br class="">+<br class="">+ auto Empty2 = parseSourceAndDumpAST("foo.cpp", "");<br class="">+ auto OneDecl2 = parseSourceAndDumpAST("foo.cpp", "int a;");<br class="">+ auto SomeDecls2 = parseSourceAndDumpAST("foo.cpp", "int a; int b; int c;");<br class="">+ EXPECT_EQ(Empty, Empty2);<br class="">+ EXPECT_EQ(OneDecl, OneDecl2);<br class="">+ EXPECT_EQ(SomeDecls, SomeDecls2);<br class="">+}<br class="">+<br class="">+TEST_F(ClangdVFSTest, ParseWithHeader) {<br class="">+ parseSourceAndDumpAST("foo.cpp", "#include \"foo.h\"", {},<br class="">+ /*ExpectErrors=*/true);<br class="">+ parseSourceAndDumpAST("foo.cpp", "#include \"foo.h\"", {{"foo.h", ""}},<br class="">+ /*ExpectErrors=*/false);<br class="">+<br class="">+ const auto SourceContents = R"cpp(<br class="">+#include "foo.h"<br class="">+int b = a;<br class="">+)cpp";<br class="">+ parseSourceAndDumpAST("foo.cpp", SourceContents, {{"foo.h", ""}},<br class="">+ /*ExpectErrors=*/true);<br class="">+ parseSourceAndDumpAST("foo.cpp", SourceContents, {{"foo.h", "int a;"}},<br class="">+ /*ExpectErrors=*/false);<br class="">+}<br class="">+<br class="">+TEST_F(ClangdVFSTest, Reparse) {<br class="">+ MockFSProvider *FS;<br class="">+ ErrorCheckingDiagConsumer *DiagConsumer;<br class="">+ ClangdServer Server(<br class="">+ llvm::make_unique<MockCompilationDatabase>(),<br class="">+ getAndMove(llvm::make_unique<ErrorCheckingDiagConsumer>(), DiagConsumer),<br class="">+ getAndMove(llvm::make_unique<MockFSProvider>(), FS),<br class="">+ /*RunSynchronously=*/false);<br class="">+<br class="">+ const auto SourceContents = R"cpp(<br class="">+#include "foo.h"<br class="">+int b = a;<br class="">+)cpp";<br class="">+<br class="">+ auto FooCpp = getVirtualTestFilePath("foo.cpp");<br class="">+ auto FooH = getVirtualTestFilePath("foo.h");<br class="">+<br class="">+ FS->Files[FooH] = "int a;";<br class="">+ FS->Files[FooCpp] = SourceContents;<br class="">+<br class="">+ Server.addDocument(FooCpp, SourceContents);<br class="">+ auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);<br class="">+ EXPECT_FALSE(DiagConsumer->hadErrorInLastDiags());<br class="">+<br class="">+ Server.addDocument(FooCpp, "");<br class="">+ auto DumpParseEmpty = dumpASTWithoutMemoryLocs(Server, FooCpp);<br class="">+ EXPECT_FALSE(DiagConsumer->hadErrorInLastDiags());<br class="">+<br class="">+ Server.addDocument(FooCpp, SourceContents);<br class="">+ auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);<br class="">+ EXPECT_FALSE(DiagConsumer->hadErrorInLastDiags());<br class="">+<br class="">+ EXPECT_EQ(DumpParse1, DumpParse2);<br class="">+ EXPECT_NE(DumpParse1, DumpParseEmpty);<br class="">+}<br class="">+<br class="">+TEST_F(ClangdVFSTest, ReparseOnHeaderChange) {<br class="">+ MockFSProvider *FS;<br class="">+ ErrorCheckingDiagConsumer *DiagConsumer;<br class="">+<br class="">+ ClangdServer Server(<br class="">+ llvm::make_unique<MockCompilationDatabase>(),<br class="">+ getAndMove(llvm::make_unique<ErrorCheckingDiagConsumer>(), DiagConsumer),<br class="">+ getAndMove(llvm::make_unique<MockFSProvider>(), FS),<br class="">+ /*RunSynchronously=*/false);<br class="">+<br class="">+ const auto SourceContents = R"cpp(<br class="">+#include "foo.h"<br class="">+int b = a;<br class="">+)cpp";<br class="">+<br class="">+ auto FooCpp = getVirtualTestFilePath("foo.cpp");<br class="">+ auto FooH = getVirtualTestFilePath("foo.h");<br class="">+<br class="">+ FS->Files[FooH] = "int a;";<br class="">+ FS->Files[FooCpp] = SourceContents;<br class="">+<br class="">+ Server.addDocument(FooCpp, SourceContents);<br class="">+ auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);<br class="">+ EXPECT_FALSE(DiagConsumer->hadErrorInLastDiags());<br class="">+<br class="">+ FS->Files[FooH] = "";<br class="">+ Server.forceReparse(FooCpp);<br class="">+ auto DumpParseDifferent = dumpASTWithoutMemoryLocs(Server, FooCpp);<br class="">+ EXPECT_TRUE(DiagConsumer->hadErrorInLastDiags());<br class="">+<br class="">+ FS->Files[FooH] = "int a;";<br class="">+ Server.forceReparse(FooCpp);<br class="">+ auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);<br class="">+ EXPECT_FALSE(DiagConsumer->hadErrorInLastDiags());<br class="">+<br class="">+ EXPECT_EQ(DumpParse1, DumpParse2);<br class="">+ EXPECT_NE(DumpParse1, DumpParseDifferent);<br class="">+}<br class="">+<br class="">+} // namespace clangd<br class="">+} // namespace clang<br class=""><br class=""><br class="">_______________________________________________<br class="">cfe-commits mailing list<br class=""><a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits<br class=""></div></div></blockquote></div><br class=""></div></body></html>