| //===--- ClangdUnitStore.h - A ClangdUnits container -------------*-C++-*-===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===---------------------------------------------------------------------===// | 
 |  | 
 | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNITSTORE_H | 
 | #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNITSTORE_H | 
 |  | 
 | #include <mutex> | 
 |  | 
 | #include "ClangdUnit.h" | 
 | #include "GlobalCompilationDatabase.h" | 
 | #include "Path.h" | 
 | #include "clang/Tooling/CompilationDatabase.h" | 
 |  | 
 | namespace clang { | 
 | namespace clangd { | 
 |  | 
 | /// Thread-safe collection of ASTs built for specific files. Provides | 
 | /// synchronized access to ASTs. | 
 | class ClangdUnitStore { | 
 | public: | 
 |   /// Run specified \p Action on the ClangdUnit for \p File. | 
 |   /// If the file is not present in ClangdUnitStore, a new ClangdUnit will be | 
 |   /// created from the \p FileContents. If the file is already present in the | 
 |   /// store, ClangdUnit::reparse will be called with the new contents before | 
 |   /// running \p Action. | 
 |   template <class Func> | 
 |   void runOnUnit(PathRef File, StringRef FileContents, StringRef ResourceDir, | 
 |                  GlobalCompilationDatabase &CDB, | 
 |                  std::shared_ptr<PCHContainerOperations> PCHs, | 
 |                  IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) { | 
 |     runOnUnitImpl(File, FileContents, ResourceDir, CDB, PCHs, | 
 |                   /*ReparseBeforeAction=*/true, VFS, | 
 |                   std::forward<Func>(Action)); | 
 |   } | 
 |  | 
 |   /// Run specified \p Action on the ClangdUnit for \p File. | 
 |   /// If the file is not present in ClangdUnitStore, a new ClangdUnit will be | 
 |   /// created from the \p FileContents. If the file is already present in the | 
 |   /// store, the \p Action will be run directly on it. | 
 |   template <class Func> | 
 |   void runOnUnitWithoutReparse(PathRef File, StringRef FileContents, | 
 |                                StringRef ResourceDir, | 
 |                                GlobalCompilationDatabase &CDB, | 
 |                                std::shared_ptr<PCHContainerOperations> PCHs, | 
 |                                IntrusiveRefCntPtr<vfs::FileSystem> VFS, | 
 |                                Func Action) { | 
 |     runOnUnitImpl(File, FileContents, ResourceDir, CDB, PCHs, | 
 |                   /*ReparseBeforeAction=*/false, VFS, | 
 |                   std::forward<Func>(Action)); | 
 |   } | 
 |  | 
 |   /// Run the specified \p Action on the ClangdUnit for \p File. | 
 |   /// Unit for \p File should exist in the store. | 
 |   template <class Func> void runOnExistingUnit(PathRef File, Func Action) { | 
 |     std::lock_guard<std::mutex> Lock(Mutex); | 
 |  | 
 |     auto It = OpenedFiles.find(File); | 
 |     assert(It != OpenedFiles.end() && "File is not in OpenedFiles"); | 
 |  | 
 |     Action(It->second); | 
 |   } | 
 |  | 
 |   /// Remove ClangdUnit for \p File, if any | 
 |   void removeUnitIfPresent(PathRef File); | 
 |  | 
 | private: | 
 |   /// Run specified \p Action on the ClangdUnit for \p File. | 
 |   template <class Func> | 
 |   void runOnUnitImpl(PathRef File, StringRef FileContents, | 
 |                      StringRef ResourceDir, GlobalCompilationDatabase &CDB, | 
 |                      std::shared_ptr<PCHContainerOperations> PCHs, | 
 |                      bool ReparseBeforeAction, | 
 |                      IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) { | 
 |     std::lock_guard<std::mutex> Lock(Mutex); | 
 |  | 
 |     auto Commands = getCompileCommands(CDB, File); | 
 |     assert(!Commands.empty() && | 
 |            "getCompileCommands should add default command"); | 
 |     VFS->setCurrentWorkingDirectory(Commands.front().Directory); | 
 |  | 
 |     auto It = OpenedFiles.find(File); | 
 |     if (It == OpenedFiles.end()) { | 
 |       It = OpenedFiles | 
 |                .insert(std::make_pair(File, ClangdUnit(File, FileContents, | 
 |                                                        ResourceDir, PCHs, | 
 |                                                        Commands, VFS))) | 
 |                .first; | 
 |     } else if (ReparseBeforeAction) { | 
 |       It->second.reparse(FileContents, VFS); | 
 |     } | 
 |     return Action(It->second); | 
 |   } | 
 |  | 
 |   std::vector<tooling::CompileCommand> | 
 |   getCompileCommands(GlobalCompilationDatabase &CDB, PathRef File); | 
 |  | 
 |   std::mutex Mutex; | 
 |   llvm::StringMap<ClangdUnit> OpenedFiles; | 
 | }; | 
 | } // namespace clangd | 
 | } // namespace clang | 
 |  | 
 | #endif |