mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -04:00

Summary: Currently, changes *within* CDBs are not tracked (CDB has no facility to do so). However, discovery of new CDBs are tracked (all files are marked as modified). Also, files whose compilation commands are explicitly set are marked modified. The intent is to use this for auto-index. Newly discovered files will be indexed with low priority. Reviewers: ilya-biryukov Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D54475 llvm-svn: 347297
131 lines
4.4 KiB
C++
131 lines
4.4 KiB
C++
//===--- GlobalCompilationDatabase.cpp ---------------------------*- C++-*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "GlobalCompilationDatabase.h"
|
|
#include "Logger.h"
|
|
#include "clang/Tooling/CompilationDatabase.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
using namespace llvm;
|
|
namespace clang {
|
|
namespace clangd {
|
|
|
|
tooling::CompileCommand
|
|
GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
|
|
std::vector<std::string> Argv = {"clang"};
|
|
// Clang treats .h files as C by default, resulting in unhelpful diagnostics.
|
|
// Parsing as Objective C++ is friendly to more cases.
|
|
if (sys::path::extension(File) == ".h")
|
|
Argv.push_back("-xobjective-c++-header");
|
|
Argv.push_back(File);
|
|
return tooling::CompileCommand(sys::path::parent_path(File),
|
|
sys::path::filename(File), std::move(Argv),
|
|
/*Output=*/"");
|
|
}
|
|
|
|
DirectoryBasedGlobalCompilationDatabase::
|
|
DirectoryBasedGlobalCompilationDatabase(Optional<Path> CompileCommandsDir)
|
|
: CompileCommandsDir(std::move(CompileCommandsDir)) {}
|
|
|
|
DirectoryBasedGlobalCompilationDatabase::
|
|
~DirectoryBasedGlobalCompilationDatabase() = default;
|
|
|
|
Optional<tooling::CompileCommand>
|
|
DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const {
|
|
if (auto CDB = getCDBForFile(File)) {
|
|
auto Candidates = CDB->getCompileCommands(File);
|
|
if (!Candidates.empty())
|
|
return std::move(Candidates.front());
|
|
} else {
|
|
log("Failed to find compilation database for {0}", File);
|
|
}
|
|
return None;
|
|
}
|
|
|
|
std::pair<tooling::CompilationDatabase *, /*Cached*/ bool>
|
|
DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const {
|
|
// FIXME(ibiryukov): Invalidate cached compilation databases on changes
|
|
auto CachedIt = CompilationDatabases.find(Dir);
|
|
if (CachedIt != CompilationDatabases.end())
|
|
return {CachedIt->second.get(), true};
|
|
std::string Error = "";
|
|
auto CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error);
|
|
auto Result = CDB.get();
|
|
CompilationDatabases.insert(std::make_pair(Dir, std::move(CDB)));
|
|
return {Result, false};
|
|
}
|
|
|
|
tooling::CompilationDatabase *
|
|
DirectoryBasedGlobalCompilationDatabase::getCDBForFile(PathRef File) const {
|
|
namespace path = sys::path;
|
|
assert((path::is_absolute(File, path::Style::posix) ||
|
|
path::is_absolute(File, path::Style::windows)) &&
|
|
"path must be absolute");
|
|
|
|
tooling::CompilationDatabase *CDB = nullptr;
|
|
bool Cached = false;
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
if (CompileCommandsDir) {
|
|
std::tie(CDB, Cached) = getCDBInDirLocked(*CompileCommandsDir);
|
|
} else {
|
|
for (auto Path = path::parent_path(File); !CDB && !Path.empty();
|
|
Path = path::parent_path(Path)) {
|
|
std::tie(CDB, Cached) = getCDBInDirLocked(Path);
|
|
}
|
|
}
|
|
if (CDB && !Cached)
|
|
OnCommandChanged.broadcast(CDB->getAllFiles());
|
|
return CDB;
|
|
}
|
|
|
|
OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base,
|
|
std::vector<std::string> FallbackFlags)
|
|
: Base(Base), FallbackFlags(std::move(FallbackFlags)) {
|
|
if (Base)
|
|
BaseChanged = Base->watch([this](const std::vector<std::string> Changes) {
|
|
OnCommandChanged.broadcast(Changes);
|
|
});
|
|
}
|
|
|
|
Optional<tooling::CompileCommand>
|
|
OverlayCDB::getCompileCommand(PathRef File) const {
|
|
{
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
auto It = Commands.find(File);
|
|
if (It != Commands.end())
|
|
return It->second;
|
|
}
|
|
return Base ? Base->getCompileCommand(File) : None;
|
|
}
|
|
|
|
tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
|
|
auto Cmd = Base ? Base->getFallbackCommand(File)
|
|
: GlobalCompilationDatabase::getFallbackCommand(File);
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
|
|
FallbackFlags.end());
|
|
return Cmd;
|
|
}
|
|
|
|
void OverlayCDB::setCompileCommand(
|
|
PathRef File, llvm::Optional<tooling::CompileCommand> Cmd) {
|
|
{
|
|
std::unique_lock<std::mutex> Lock(Mutex);
|
|
if (Cmd)
|
|
Commands[File] = std::move(*Cmd);
|
|
else
|
|
Commands.erase(File);
|
|
}
|
|
OnCommandChanged.broadcast({File});
|
|
}
|
|
|
|
} // namespace clangd
|
|
} // namespace clang
|