Kirill Bobyrev | 8e35f1e | 2018-08-14 16:03:32 +0000 | [diff] [blame] | 1 | //===--- GlobalCompilationDatabase.cpp ---------------------------*- C++-*-===// |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 6 | // |
Kirill Bobyrev | 8e35f1e | 2018-08-14 16:03:32 +0000 | [diff] [blame] | 7 | //===----------------------------------------------------------------------===// |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 8 | |
| 9 | #include "GlobalCompilationDatabase.h" |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 10 | #include "FS.h" |
Ilya Biryukov | 0c1ca6b | 2017-10-02 15:13:20 +0000 | [diff] [blame] | 11 | #include "Logger.h" |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 12 | #include "Path.h" |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 13 | #include "clang/Frontend/CompilerInvocation.h" |
| 14 | #include "clang/Tooling/ArgumentsAdjusters.h" |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 15 | #include "clang/Tooling/CompilationDatabase.h" |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 16 | #include "llvm/ADT/None.h" |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 17 | #include "llvm/ADT/Optional.h" |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 18 | #include "llvm/ADT/STLExtras.h" |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 19 | #include "llvm/ADT/SmallString.h" |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 20 | #include "llvm/Support/FileSystem.h" |
| 21 | #include "llvm/Support/Path.h" |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 22 | #include <string> |
| 23 | #include <tuple> |
| 24 | #include <vector> |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 25 | |
Krasimir Georgiev | c2a16a3 | 2017-07-06 08:44:54 +0000 | [diff] [blame] | 26 | namespace clang { |
| 27 | namespace clangd { |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 28 | namespace { |
| 29 | |
| 30 | void adjustArguments(tooling::CompileCommand &Cmd, |
| 31 | llvm::StringRef ResourceDir) { |
Kadir Cetinkaya | 65944ab | 2019-03-08 08:38:25 +0000 | [diff] [blame] | 32 | tooling::ArgumentsAdjuster ArgsAdjuster = tooling::combineAdjusters( |
| 33 | // clangd should not write files to disk, including dependency files |
| 34 | // requested on the command line. |
| 35 | tooling::getClangStripDependencyFileAdjuster(), |
| 36 | // Strip plugin related command line arguments. Clangd does |
| 37 | // not support plugins currently. Therefore it breaks if |
| 38 | // compiler tries to load plugins. |
| 39 | tooling::combineAdjusters(tooling::getStripPluginsAdjuster(), |
| 40 | tooling::getClangSyntaxOnlyAdjuster())); |
| 41 | |
| 42 | Cmd.CommandLine = ArgsAdjuster(Cmd.CommandLine, Cmd.Filename); |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 43 | // Inject the resource dir. |
| 44 | // FIXME: Don't overwrite it if it's already there. |
| 45 | if (!ResourceDir.empty()) |
| 46 | Cmd.CommandLine.push_back(("-resource-dir=" + ResourceDir).str()); |
| 47 | } |
| 48 | |
| 49 | std::string getStandardResourceDir() { |
| 50 | static int Dummy; // Just an address in this process. |
| 51 | return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy); |
| 52 | } |
| 53 | |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 54 | // Runs the given action on all parent directories of filename, starting from |
| 55 | // deepest directory and going up to root. Stops whenever action succeeds. |
| 56 | void actOnAllParentDirectories(PathRef FileName, |
| 57 | llvm::function_ref<bool(PathRef)> Action) { |
| 58 | for (auto Path = llvm::sys::path::parent_path(FileName); |
| 59 | !Path.empty() && !Action(Path); |
| 60 | Path = llvm::sys::path::parent_path(Path)) |
| 61 | ; |
| 62 | } |
| 63 | |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 64 | } // namespace |
Krasimir Georgiev | c2a16a3 | 2017-07-06 08:44:54 +0000 | [diff] [blame] | 65 | |
Haojian Wu | e1ced5c | 2019-01-07 12:35:02 +0000 | [diff] [blame] | 66 | static std::string getFallbackClangPath() { |
| 67 | static int Dummy; |
| 68 | std::string ClangdExecutable = |
| 69 | llvm::sys::fs::getMainExecutable("clangd", (void *)&Dummy); |
| 70 | SmallString<128> ClangPath; |
| 71 | ClangPath = llvm::sys::path::parent_path(ClangdExecutable); |
| 72 | llvm::sys::path::append(ClangPath, "clang"); |
| 73 | return ClangPath.str(); |
| 74 | } |
| 75 | |
Sam McCall | ecbeab0 | 2017-12-04 10:08:45 +0000 | [diff] [blame] | 76 | tooling::CompileCommand |
| 77 | GlobalCompilationDatabase::getFallbackCommand(PathRef File) const { |
Haojian Wu | e1ced5c | 2019-01-07 12:35:02 +0000 | [diff] [blame] | 78 | std::vector<std::string> Argv = {getFallbackClangPath()}; |
Haojian Wu | 8ddf31b | 2019-06-18 11:54:17 +0000 | [diff] [blame] | 79 | // Clang treats .h files as C by default and files without extension as linker |
| 80 | // input, resulting in unhelpful diagnostics. |
Sam McCall | 690dcf1 | 2018-04-20 11:35:17 +0000 | [diff] [blame] | 81 | // Parsing as Objective C++ is friendly to more cases. |
Haojian Wu | 8ddf31b | 2019-06-18 11:54:17 +0000 | [diff] [blame] | 82 | auto FileExtension = llvm::sys::path::extension(File); |
| 83 | if (FileExtension.empty() || FileExtension == ".h") |
Sam McCall | 690dcf1 | 2018-04-20 11:35:17 +0000 | [diff] [blame] | 84 | Argv.push_back("-xobjective-c++-header"); |
| 85 | Argv.push_back(File); |
Eric Liu | 9ef03dd | 2019-04-15 12:32:28 +0000 | [diff] [blame] | 86 | tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File), |
| 87 | llvm::sys::path::filename(File), std::move(Argv), |
| 88 | /*Output=*/""); |
| 89 | Cmd.Heuristic = "clangd fallback"; |
| 90 | return Cmd; |
Krasimir Georgiev | c2a16a3 | 2017-07-06 08:44:54 +0000 | [diff] [blame] | 91 | } |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 92 | |
Ilya Biryukov | e5128f7 | 2017-09-20 07:24:15 +0000 | [diff] [blame] | 93 | DirectoryBasedGlobalCompilationDatabase:: |
Ilya Biryukov | f2001aa | 2019-01-07 15:45:19 +0000 | [diff] [blame] | 94 | DirectoryBasedGlobalCompilationDatabase( |
| 95 | llvm::Optional<Path> CompileCommandsDir) |
Ilya Biryukov | 940901e | 2017-12-13 12:51:22 +0000 | [diff] [blame] | 96 | : CompileCommandsDir(std::move(CompileCommandsDir)) {} |
Ilya Biryukov | e5128f7 | 2017-09-20 07:24:15 +0000 | [diff] [blame] | 97 | |
Sam McCall | 690dcf1 | 2018-04-20 11:35:17 +0000 | [diff] [blame] | 98 | DirectoryBasedGlobalCompilationDatabase:: |
| 99 | ~DirectoryBasedGlobalCompilationDatabase() = default; |
| 100 | |
Ilya Biryukov | f2001aa | 2019-01-07 15:45:19 +0000 | [diff] [blame] | 101 | llvm::Optional<tooling::CompileCommand> |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 102 | DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const { |
| 103 | CDBLookupRequest Req; |
| 104 | Req.FileName = File; |
| 105 | Req.ShouldBroadcast = true; |
| 106 | |
| 107 | auto Res = lookupCDB(Req); |
| 108 | if (!Res) { |
Sam McCall | bed5885 | 2018-07-11 10:35:11 +0000 | [diff] [blame] | 109 | log("Failed to find compilation database for {0}", File); |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 110 | return llvm::None; |
Krasimir Georgiev | c2a16a3 | 2017-07-06 08:44:54 +0000 | [diff] [blame] | 111 | } |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 112 | |
| 113 | auto Candidates = Res->CDB->getCompileCommands(File); |
| 114 | if (!Candidates.empty()) |
| 115 | return std::move(Candidates.front()); |
| 116 | |
Sam McCall | c008af6 | 2018-10-20 15:30:37 +0000 | [diff] [blame] | 117 | return None; |
Sam McCall | ecbeab0 | 2017-12-04 10:08:45 +0000 | [diff] [blame] | 118 | } |
Krasimir Georgiev | c2a16a3 | 2017-07-06 08:44:54 +0000 | [diff] [blame] | 119 | |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 120 | std::pair<tooling::CompilationDatabase *, /*SentBroadcast*/ bool> |
Sam McCall | c02ba72 | 2017-12-22 09:47:34 +0000 | [diff] [blame] | 121 | DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const { |
| 122 | // FIXME(ibiryukov): Invalidate cached compilation databases on changes |
| 123 | auto CachedIt = CompilationDatabases.find(Dir); |
| 124 | if (CachedIt != CompilationDatabases.end()) |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 125 | return {CachedIt->second.CDB.get(), CachedIt->second.SentBroadcast}; |
Sam McCall | c02ba72 | 2017-12-22 09:47:34 +0000 | [diff] [blame] | 126 | std::string Error = ""; |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 127 | |
| 128 | CachedCDB Entry; |
| 129 | Entry.CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error); |
| 130 | auto Result = Entry.CDB.get(); |
| 131 | CompilationDatabases[Dir] = std::move(Entry); |
| 132 | |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 133 | return {Result, false}; |
Sam McCall | c02ba72 | 2017-12-22 09:47:34 +0000 | [diff] [blame] | 134 | } |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 135 | |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 136 | llvm::Optional<DirectoryBasedGlobalCompilationDatabase::CDBLookupResult> |
| 137 | DirectoryBasedGlobalCompilationDatabase::lookupCDB( |
| 138 | CDBLookupRequest Request) const { |
| 139 | assert(llvm::sys::path::is_absolute(Request.FileName) && |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 140 | "path must be absolute"); |
| 141 | |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 142 | CDBLookupResult Result; |
| 143 | bool SentBroadcast = false; |
| 144 | |
| 145 | { |
| 146 | std::lock_guard<std::mutex> Lock(Mutex); |
| 147 | if (CompileCommandsDir) { |
| 148 | std::tie(Result.CDB, SentBroadcast) = |
| 149 | getCDBInDirLocked(*CompileCommandsDir); |
| 150 | Result.PI.SourceRoot = *CompileCommandsDir; |
| 151 | } else { |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 152 | // Traverse the canonical version to prevent false positives. i.e.: |
| 153 | // src/build/../a.cc can detect a CDB in /src/build if not canonicalized. |
| 154 | actOnAllParentDirectories(removeDots(Request.FileName), |
| 155 | [this, &SentBroadcast, &Result](PathRef Path) { |
| 156 | std::tie(Result.CDB, SentBroadcast) = |
| 157 | getCDBInDirLocked(Path); |
| 158 | Result.PI.SourceRoot = Path; |
| 159 | return Result.CDB != nullptr; |
| 160 | }); |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | if (!Result.CDB) |
| 164 | return llvm::None; |
| 165 | |
| 166 | // Mark CDB as broadcasted to make sure discovery is performed once. |
| 167 | if (Request.ShouldBroadcast && !SentBroadcast) |
| 168 | CompilationDatabases[Result.PI.SourceRoot].SentBroadcast = true; |
| 169 | } |
| 170 | |
| 171 | // FIXME: Maybe make the following part async, since this can block retrieval |
| 172 | // of compile commands. |
| 173 | if (Request.ShouldBroadcast && !SentBroadcast) |
| 174 | broadcastCDB(Result); |
| 175 | return Result; |
| 176 | } |
| 177 | |
| 178 | void DirectoryBasedGlobalCompilationDatabase::broadcastCDB( |
| 179 | CDBLookupResult Result) const { |
| 180 | assert(Result.CDB && "Trying to broadcast an invalid CDB!"); |
| 181 | |
| 182 | std::vector<std::string> AllFiles = Result.CDB->getAllFiles(); |
| 183 | // We assume CDB in CompileCommandsDir owns all of its entries, since we don't |
| 184 | // perform any search in parent paths whenever it is set. |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 185 | if (CompileCommandsDir) { |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 186 | assert(*CompileCommandsDir == Result.PI.SourceRoot && |
| 187 | "Trying to broadcast a CDB outside of CompileCommandsDir!"); |
| 188 | OnCommandChanged.broadcast(std::move(AllFiles)); |
| 189 | return; |
| 190 | } |
| 191 | |
| 192 | llvm::StringMap<bool> DirectoryHasCDB; |
| 193 | { |
| 194 | std::lock_guard<std::mutex> Lock(Mutex); |
| 195 | // Uniquify all parent directories of all files. |
| 196 | for (llvm::StringRef File : AllFiles) { |
| 197 | actOnAllParentDirectories(File, [&](PathRef Path) { |
| 198 | auto It = DirectoryHasCDB.try_emplace(Path); |
| 199 | // Already seen this path, and all of its parents. |
| 200 | if (!It.second) |
| 201 | return true; |
| 202 | |
| 203 | auto Res = getCDBInDirLocked(Path); |
| 204 | It.first->second = Res.first != nullptr; |
| 205 | return Path == Result.PI.SourceRoot; |
| 206 | }); |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 207 | } |
| 208 | } |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 209 | |
| 210 | std::vector<std::string> GovernedFiles; |
| 211 | for (llvm::StringRef File : AllFiles) { |
| 212 | // A file is governed by this CDB if lookup for the file would find it. |
| 213 | // Independent of whether it has an entry for that file or not. |
| 214 | actOnAllParentDirectories(File, [&](PathRef Path) { |
| 215 | if (DirectoryHasCDB.lookup(Path)) { |
| 216 | if (Path == Result.PI.SourceRoot) |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 217 | // Make sure listeners always get a canonical path for the file. |
| 218 | GovernedFiles.push_back(removeDots(File)); |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 219 | // Stop as soon as we hit a CDB. |
| 220 | return true; |
| 221 | } |
| 222 | return false; |
| 223 | }); |
| 224 | } |
| 225 | |
| 226 | OnCommandChanged.broadcast(std::move(GovernedFiles)); |
| 227 | } |
| 228 | |
| 229 | llvm::Optional<ProjectInfo> |
| 230 | DirectoryBasedGlobalCompilationDatabase::getProjectInfo(PathRef File) const { |
| 231 | CDBLookupRequest Req; |
| 232 | Req.FileName = File; |
| 233 | Req.ShouldBroadcast = false; |
| 234 | auto Res = lookupCDB(Req); |
| 235 | if (!Res) |
| 236 | return llvm::None; |
| 237 | return Res->PI; |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base, |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 241 | std::vector<std::string> FallbackFlags, |
| 242 | llvm::Optional<std::string> ResourceDir) |
| 243 | : Base(Base), ResourceDir(ResourceDir ? std::move(*ResourceDir) |
| 244 | : getStandardResourceDir()), |
| 245 | FallbackFlags(std::move(FallbackFlags)) { |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 246 | if (Base) |
| 247 | BaseChanged = Base->watch([this](const std::vector<std::string> Changes) { |
| 248 | OnCommandChanged.broadcast(Changes); |
| 249 | }); |
Ilya Biryukov | 38d7977 | 2017-05-16 09:38:59 +0000 | [diff] [blame] | 250 | } |
Krasimir Georgiev | c2a16a3 | 2017-07-06 08:44:54 +0000 | [diff] [blame] | 251 | |
Ilya Biryukov | f2001aa | 2019-01-07 15:45:19 +0000 | [diff] [blame] | 252 | llvm::Optional<tooling::CompileCommand> |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 253 | OverlayCDB::getCompileCommand(PathRef File) const { |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 254 | llvm::Optional<tooling::CompileCommand> Cmd; |
Sam McCall | c55d09a | 2018-11-02 13:09:36 +0000 | [diff] [blame] | 255 | { |
| 256 | std::lock_guard<std::mutex> Lock(Mutex); |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 257 | auto It = Commands.find(removeDots(File)); |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 258 | if (It != Commands.end()) |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 259 | Cmd = It->second; |
Sam McCall | c55d09a | 2018-11-02 13:09:36 +0000 | [diff] [blame] | 260 | } |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 261 | if (!Cmd && Base) |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 262 | Cmd = Base->getCompileCommand(File); |
Kadir Cetinkaya | be6b35d | 2019-01-22 09:10:20 +0000 | [diff] [blame] | 263 | if (!Cmd) |
| 264 | return llvm::None; |
| 265 | adjustArguments(*Cmd, ResourceDir); |
| 266 | return Cmd; |
Alex Lorenz | f808786 | 2018-08-01 17:39:29 +0000 | [diff] [blame] | 267 | } |
| 268 | |
Sam McCall | c55d09a | 2018-11-02 13:09:36 +0000 | [diff] [blame] | 269 | tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const { |
| 270 | auto Cmd = Base ? Base->getFallbackCommand(File) |
| 271 | : GlobalCompilationDatabase::getFallbackCommand(File); |
| 272 | std::lock_guard<std::mutex> Lock(Mutex); |
| 273 | Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(), |
| 274 | FallbackFlags.end()); |
Kadir Cetinkaya | a7f9f42 | 2019-06-04 13:38:36 +0000 | [diff] [blame] | 275 | adjustArguments(Cmd, ResourceDir); |
Sam McCall | c55d09a | 2018-11-02 13:09:36 +0000 | [diff] [blame] | 276 | return Cmd; |
| 277 | } |
| 278 | |
| 279 | void OverlayCDB::setCompileCommand( |
| 280 | PathRef File, llvm::Optional<tooling::CompileCommand> Cmd) { |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 281 | // We store a canonical version internally to prevent mismatches between set |
| 282 | // and get compile commands. Also it assures clients listening to broadcasts |
| 283 | // doesn't receive different names for the same file. |
| 284 | std::string CanonPath = removeDots(File); |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 285 | { |
| 286 | std::unique_lock<std::mutex> Lock(Mutex); |
| 287 | if (Cmd) |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 288 | Commands[CanonPath] = std::move(*Cmd); |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 289 | else |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 290 | Commands.erase(CanonPath); |
Sam McCall | 2bebc3d | 2018-11-20 10:56:03 +0000 | [diff] [blame] | 291 | } |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 292 | OnCommandChanged.broadcast({CanonPath}); |
Alex Lorenz | f808786 | 2018-08-01 17:39:29 +0000 | [diff] [blame] | 293 | } |
| 294 | |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 295 | llvm::Optional<ProjectInfo> OverlayCDB::getProjectInfo(PathRef File) const { |
| 296 | { |
| 297 | std::lock_guard<std::mutex> Lock(Mutex); |
Kadir Cetinkaya | 6d53adf | 2019-07-18 16:13:23 +0000 | [diff] [blame^] | 298 | auto It = Commands.find(removeDots(File)); |
Kadir Cetinkaya | ad54935 | 2019-07-11 09:54:31 +0000 | [diff] [blame] | 299 | if (It != Commands.end()) |
| 300 | return ProjectInfo{}; |
| 301 | } |
| 302 | if (Base) |
| 303 | return Base->getProjectInfo(File); |
| 304 | |
| 305 | return llvm::None; |
| 306 | } |
Krasimir Georgiev | c2a16a3 | 2017-07-06 08:44:54 +0000 | [diff] [blame] | 307 | } // namespace clangd |
| 308 | } // namespace clang |