1 //===--- GlobalCompilationDatabase.h -----------------------------*- C++-*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H 11 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H 12 13 #include "Function.h" 14 #include "Path.h" 15 #include "llvm/ADT/Optional.h" 16 #include "llvm/ADT/StringMap.h" 17 #include <memory> 18 #include <mutex> 19 #include <vector> 20 21 namespace clang { 22 23 namespace tooling { 24 class CompilationDatabase; 25 struct CompileCommand; 26 } // namespace tooling 27 28 namespace clangd { 29 30 class Logger; 31 32 struct ProjectInfo { 33 // The directory in which the compilation database was discovered. 34 // Empty if directory-based compilation database discovery was not used. 35 std::string SourceRoot; 36 }; 37 38 /// Provides compilation arguments used for parsing C and C++ files. 39 class GlobalCompilationDatabase { 40 public: 41 virtual ~GlobalCompilationDatabase() = default; 42 43 /// If there are any known-good commands for building this file, returns one. 44 /// If the ProjectInfo pointer is set, it will also be populated. 45 virtual llvm::Optional<tooling::CompileCommand> 46 getCompileCommand(PathRef File, ProjectInfo * = nullptr) const = 0; 47 48 /// Makes a guess at how to build a file. 49 /// The default implementation just runs clang on the file. 50 /// Clangd should treat the results as unreliable. 51 virtual tooling::CompileCommand getFallbackCommand(PathRef File) const; 52 53 using CommandChanged = Event<std::vector<std::string>>; 54 /// The callback is notified when files may have new compile commands. 55 /// The argument is a list of full file paths. watch(CommandChanged::Listener L)56 CommandChanged::Subscription watch(CommandChanged::Listener L) const { 57 return OnCommandChanged.observe(std::move(L)); 58 } 59 60 protected: 61 mutable CommandChanged OnCommandChanged; 62 }; 63 64 /// Gets compile args from tooling::CompilationDatabases built for parent 65 /// directories. 66 class DirectoryBasedGlobalCompilationDatabase 67 : public GlobalCompilationDatabase { 68 public: 69 DirectoryBasedGlobalCompilationDatabase( 70 llvm::Optional<Path> CompileCommandsDir); 71 ~DirectoryBasedGlobalCompilationDatabase() override; 72 73 /// Scans File's parents looking for compilation databases. 74 /// Any extra flags will be added. 75 llvm::Optional<tooling::CompileCommand> 76 getCompileCommand(PathRef File, ProjectInfo * = nullptr) const override; 77 78 private: 79 tooling::CompilationDatabase *getCDBForFile(PathRef File, 80 ProjectInfo *) const; 81 std::pair<tooling::CompilationDatabase *, /*Cached*/ bool> 82 getCDBInDirLocked(PathRef File) const; 83 84 mutable std::mutex Mutex; 85 /// Caches compilation databases loaded from directories(keys are 86 /// directories). 87 mutable llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>> 88 CompilationDatabases; 89 90 /// Used for command argument pointing to folder where compile_commands.json 91 /// is located. 92 llvm::Optional<Path> CompileCommandsDir; 93 }; 94 95 /// Wraps another compilation database, and supports overriding the commands 96 /// using an in-memory mapping. 97 class OverlayCDB : public GlobalCompilationDatabase { 98 public: 99 // Base may be null, in which case no entries are inherited. 100 // FallbackFlags are added to the fallback compile command. 101 OverlayCDB(const GlobalCompilationDatabase *Base, 102 std::vector<std::string> FallbackFlags = {}, 103 llvm::Optional<std::string> ResourceDir = llvm::None); 104 105 llvm::Optional<tooling::CompileCommand> 106 getCompileCommand(PathRef File, ProjectInfo * = nullptr) const override; 107 tooling::CompileCommand getFallbackCommand(PathRef File) const override; 108 109 /// Sets or clears the compilation command for a particular file. 110 void 111 setCompileCommand(PathRef File, 112 llvm::Optional<tooling::CompileCommand> CompilationCommand); 113 114 private: 115 mutable std::mutex Mutex; 116 llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */ 117 const GlobalCompilationDatabase *Base; 118 std::string ResourceDir; 119 std::vector<std::string> FallbackFlags; 120 CommandChanged::Subscription BaseChanged; 121 }; 122 123 } // namespace clangd 124 } // namespace clang 125 126 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H 127