1 //===--- GlobalCompilationDatabase.h -----------------------------*- C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H 11 12 #include "CompileCommands.h" 13 #include "support/Function.h" 14 #include "support/Path.h" 15 #include "clang/Tooling/ArgumentsAdjusters.h" 16 #include "clang/Tooling/CompilationDatabase.h" 17 #include "llvm/ADT/Optional.h" 18 #include "llvm/ADT/StringMap.h" 19 #include <memory> 20 #include <mutex> 21 #include <vector> 22 23 namespace clang { 24 namespace clangd { 25 26 class Logger; 27 28 struct ProjectInfo { 29 // The directory in which the compilation database was discovered. 30 // Empty if directory-based compilation database discovery was not used. 31 std::string SourceRoot; 32 }; 33 34 /// Provides compilation arguments used for parsing C and C++ files. 35 class GlobalCompilationDatabase { 36 public: 37 virtual ~GlobalCompilationDatabase() = default; 38 39 /// If there are any known-good commands for building this file, returns one. 40 virtual llvm::Optional<tooling::CompileCommand> 41 getCompileCommand(PathRef File) const = 0; 42 43 /// Finds the closest project to \p File. getProjectInfo(PathRef File)44 virtual llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const { 45 return llvm::None; 46 } 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 /// Might trigger OnCommandChanged, if CDB wasn't broadcasted yet. 76 llvm::Optional<tooling::CompileCommand> 77 getCompileCommand(PathRef File) const override; 78 79 /// Returns the path to first directory containing a compilation database in 80 /// \p File's parents. 81 llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override; 82 83 private: 84 class DirectoryCache; 85 // If there's an explicit CompileCommandsDir, cache of the CDB found there. 86 mutable std::unique_ptr<DirectoryCache> OnlyDirCache; 87 88 // Keyed by possibly-case-folded directory path. 89 // We can hand out pointers as they're stable and entries are never removed. 90 // Empty if CompileCommandsDir is given (OnlyDirCache is used instead). 91 mutable llvm::StringMap<DirectoryCache> DirCaches; 92 // DirCaches access must be locked (unlike OnlyDirCache, which is threadsafe). 93 mutable std::mutex DirCachesMutex; 94 95 std::vector<DirectoryCache *> 96 getDirectoryCaches(llvm::ArrayRef<llvm::StringRef> Dirs) const; 97 98 struct CDBLookupRequest { 99 PathRef FileName; 100 // Whether this lookup should trigger discovery of the CDB found. 101 bool ShouldBroadcast = false; 102 }; 103 struct CDBLookupResult { 104 std::shared_ptr<const tooling::CompilationDatabase> CDB; 105 ProjectInfo PI; 106 }; 107 llvm::Optional<CDBLookupResult> lookupCDB(CDBLookupRequest Request) const; 108 109 // Performs broadcast on governed files. 110 void broadcastCDB(CDBLookupResult Res) const; 111 }; 112 113 /// Extracts system include search path from drivers matching QueryDriverGlobs 114 /// and adds them to the compile flags. Base may not be nullptr. 115 /// Returns Base when \p QueryDriverGlobs is empty. 116 std::unique_ptr<GlobalCompilationDatabase> 117 getQueryDriverDatabase(llvm::ArrayRef<std::string> QueryDriverGlobs, 118 std::unique_ptr<GlobalCompilationDatabase> Base); 119 120 /// Wraps another compilation database, and supports overriding the commands 121 /// using an in-memory mapping. 122 class OverlayCDB : public GlobalCompilationDatabase { 123 public: 124 // Base may be null, in which case no entries are inherited. 125 // FallbackFlags are added to the fallback compile command. 126 // Adjuster is applied to all commands, fallback or not. 127 OverlayCDB(const GlobalCompilationDatabase *Base, 128 std::vector<std::string> FallbackFlags = {}, 129 tooling::ArgumentsAdjuster Adjuster = nullptr); 130 131 llvm::Optional<tooling::CompileCommand> 132 getCompileCommand(PathRef File) const override; 133 tooling::CompileCommand getFallbackCommand(PathRef File) const override; 134 /// Project info is gathered purely from the inner compilation database to 135 /// ensure consistency. 136 llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override; 137 138 /// Sets or clears the compilation command for a particular file. 139 void 140 setCompileCommand(PathRef File, 141 llvm::Optional<tooling::CompileCommand> CompilationCommand); 142 143 private: 144 mutable std::mutex Mutex; 145 llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */ 146 const GlobalCompilationDatabase *Base; 147 tooling::ArgumentsAdjuster ArgsAdjuster; 148 std::vector<std::string> FallbackFlags; 149 CommandChanged::Subscription BaseChanged; 150 }; 151 152 } // namespace clangd 153 } // namespace clang 154 155 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H 156