mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 17:11:59 +00:00
Adjust FrontendOpts.Inputs[0] for inferred files
This commit is contained in:
parent
52e0289245
commit
dd74d03cfc
@ -81,7 +81,7 @@ Range FromTokenRangeDefaulted(const SourceManager &SM, const LangOptions &Lang,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CompilerInvocation>
|
std::unique_ptr<CompilerInvocation>
|
||||||
BuildCompilerInvocation(std::vector<const char *> args,
|
BuildCompilerInvocation(const std::string &main, std::vector<const char *> args,
|
||||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
|
||||||
std::string save = "-resource-dir=" + g_config->clang.resourceDir;
|
std::string save = "-resource-dir=" + g_config->clang.resourceDir;
|
||||||
args.push_back(save.c_str());
|
args.push_back(save.c_str());
|
||||||
@ -94,6 +94,9 @@ BuildCompilerInvocation(std::vector<const char *> args,
|
|||||||
CI->getDiagnosticOpts().IgnoreWarnings = true;
|
CI->getDiagnosticOpts().IgnoreWarnings = true;
|
||||||
CI->getFrontendOpts().DisableFree = false;
|
CI->getFrontendOpts().DisableFree = false;
|
||||||
CI->getLangOpts()->SpellChecking = false;
|
CI->getLangOpts()->SpellChecking = false;
|
||||||
|
auto &IS = CI->getFrontendOpts().Inputs;
|
||||||
|
if (IS.size())
|
||||||
|
IS[0] = FrontendInputFile(main, IS[0].getKind(), IS[0].isSystem());
|
||||||
}
|
}
|
||||||
return CI;
|
return CI;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,8 @@ Range FromTokenRangeDefaulted(const clang::SourceManager &SM,
|
|||||||
Range range);
|
Range range);
|
||||||
|
|
||||||
std::unique_ptr<clang::CompilerInvocation>
|
std::unique_ptr<clang::CompilerInvocation>
|
||||||
BuildCompilerInvocation(std::vector<const char *> args,
|
BuildCompilerInvocation(const std::string &main,
|
||||||
|
std::vector<const char *> args,
|
||||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
|
||||||
|
|
||||||
const char *ClangBuiltinTypeName(int);
|
const char *ClangBuiltinTypeName(int);
|
||||||
|
@ -1217,14 +1217,15 @@ void Init() {
|
|||||||
|
|
||||||
std::vector<std::unique_ptr<IndexFile>>
|
std::vector<std::unique_ptr<IndexFile>>
|
||||||
Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
||||||
const std::string &opt_wdir, const std::string &file,
|
const std::string &opt_wdir, const std::string &main,
|
||||||
const std::vector<const char *> &args,
|
const std::vector<const char *> &args,
|
||||||
const std::vector<std::pair<std::string, std::string>> &remapped,
|
const std::vector<std::pair<std::string, std::string>> &remapped,
|
||||||
bool &ok) {
|
bool &ok) {
|
||||||
ok = true;
|
ok = true;
|
||||||
auto PCH = std::make_shared<PCHContainerOperations>();
|
auto PCH = std::make_shared<PCHContainerOperations>();
|
||||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getRealFileSystem();
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getRealFileSystem();
|
||||||
std::shared_ptr<CompilerInvocation> CI = BuildCompilerInvocation(args, FS);
|
std::shared_ptr<CompilerInvocation> CI =
|
||||||
|
BuildCompilerInvocation(main, args, FS);
|
||||||
// e.g. .s
|
// e.g. .s
|
||||||
if (!CI)
|
if (!CI)
|
||||||
return {};
|
return {};
|
||||||
@ -1234,35 +1235,13 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
|||||||
CI->getLangOpts()->CommentOpts.ParseAllComments =
|
CI->getLangOpts()->CommentOpts.ParseAllComments =
|
||||||
g_config->index.comments > 1;
|
g_config->index.comments > 1;
|
||||||
CI->getLangOpts()->RetainCommentsFromSystemHeaders = true;
|
CI->getLangOpts()->RetainCommentsFromSystemHeaders = true;
|
||||||
std::string buf = wfiles->GetContent(file);
|
std::string buf = wfiles->GetContent(main);
|
||||||
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Bufs;
|
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Bufs;
|
||||||
if (buf.size()) {
|
if (buf.size())
|
||||||
// If there is a completion session, reuse its preamble if exists.
|
|
||||||
bool done_remap = false;
|
|
||||||
#if 0
|
|
||||||
std::shared_ptr<CompletionSession> session =
|
|
||||||
manager->TryGetSession(file, false, false);
|
|
||||||
if (session)
|
|
||||||
if (auto preamble = session->GetPreamble()) {
|
|
||||||
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(buf));
|
|
||||||
auto Bounds = ComputePreambleBounds(*CI->getLangOpts(), Bufs.back().get(), 0);
|
|
||||||
if (preamble->Preamble.CanReuse(*CI, Bufs.back().get(), Bounds,
|
|
||||||
FS.get())) {
|
|
||||||
preamble->Preamble.AddImplicitPreamble(*CI, FS, Bufs.back().get());
|
|
||||||
done_remap = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for (auto &[filename, content] : remapped) {
|
for (auto &[filename, content] : remapped) {
|
||||||
if (filename == file && done_remap)
|
|
||||||
continue;
|
|
||||||
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content));
|
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content));
|
||||||
CI->getPreprocessorOpts().addRemappedFile(
|
CI->getPreprocessorOpts().addRemappedFile(filename, Bufs.back().get());
|
||||||
filename == file ? CI->getFrontendOpts().Inputs[0].getFile()
|
|
||||||
: StringRef(filename),
|
|
||||||
Bufs.back().get());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DiagnosticConsumer DC;
|
DiagnosticConsumer DC;
|
||||||
auto Clang = std::make_unique<CompilerInstance>(PCH);
|
auto Clang = std::make_unique<CompilerInstance>(PCH);
|
||||||
@ -1291,20 +1270,20 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
|||||||
{
|
{
|
||||||
llvm::CrashRecoveryContext CRC;
|
llvm::CrashRecoveryContext CRC;
|
||||||
auto parse = [&]() {
|
auto parse = [&]() {
|
||||||
if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
|
if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
|
||||||
return;
|
return;
|
||||||
if (!Action->Execute())
|
if (!Action->Execute())
|
||||||
return;
|
return;
|
||||||
Action->EndSourceFile();
|
Action->EndSourceFile();
|
||||||
ok = true;
|
ok = true;
|
||||||
};
|
};
|
||||||
if (!CRC.RunSafely(parse)) {
|
if (!CRC.RunSafely(parse)) {
|
||||||
LOG_S(ERROR) << "clang crashed for " << file;
|
LOG_S(ERROR) << "clang crashed for " << main;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOG_S(ERROR) << "failed to index " << file;
|
LOG_S(ERROR) << "failed to index " << main;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
for (auto &Buf : Bufs)
|
for (auto &Buf : Bufs)
|
||||||
@ -1315,7 +1294,7 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
|||||||
if (!it.second.db)
|
if (!it.second.db)
|
||||||
continue;
|
continue;
|
||||||
std::unique_ptr<IndexFile> &entry = it.second.db;
|
std::unique_ptr<IndexFile> &entry = it.second.db;
|
||||||
entry->import_file = file;
|
entry->import_file = main;
|
||||||
entry->args = args;
|
entry->args = args;
|
||||||
for (auto &[_, it] : entry->uid2lid_and_path)
|
for (auto &[_, it] : entry->uid2lid_and_path)
|
||||||
entry->lid2path.emplace_back(it.first, std::move(it.second));
|
entry->lid2path.emplace_back(it.first, std::move(it.second));
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <rapidjson/writer.h>
|
#include <rapidjson/writer.h>
|
||||||
|
|
||||||
|
#include <llvm/Support/Path.h>
|
||||||
#include <llvm/Support/Process.h>
|
#include <llvm/Support/Process.h>
|
||||||
#include <llvm/Support/Threading.h>
|
#include <llvm/Support/Threading.h>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -110,9 +111,11 @@ bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For inferred files, allow -o a a.cc -> -o b b.cc
|
||||||
|
std::string stem = sys::path::stem(path);
|
||||||
bool changed = prev->args.size() != args.size();
|
bool changed = prev->args.size() != args.size();
|
||||||
for (size_t i = 0; !changed && i < args.size(); i++)
|
for (size_t i = 0; !changed && i < args.size(); i++)
|
||||||
if (strcmp(prev->args[i], args[i]))
|
if (strcmp(prev->args[i], args[i]) && sys::path::stem(args[i]) != stem)
|
||||||
changed = true;
|
changed = true;
|
||||||
if (changed)
|
if (changed)
|
||||||
LOG_S(INFO) << "args changed for " << path
|
LOG_S(INFO) << "args changed for " << path
|
||||||
@ -195,7 +198,8 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// must_exist is currently unused.
|
// must_exist is currently unused.
|
||||||
Project::Entry entry = project->FindEntry(request.path, false);
|
Project::Entry entry =
|
||||||
|
project->FindEntry(request.path, true, request.must_exist);
|
||||||
if (request.must_exist && entry.filename.empty())
|
if (request.must_exist && entry.filename.empty())
|
||||||
return true;
|
return true;
|
||||||
if (request.args.size())
|
if (request.args.size())
|
||||||
|
@ -411,17 +411,24 @@ void Project::Load(const std::string &root) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::Entry Project::FindEntry(const std::string &path,
|
Project::Entry Project::FindEntry(const std::string &path, bool can_redirect,
|
||||||
bool must_exist) {
|
bool must_exist) {
|
||||||
Project::Folder *best_folder = nullptr;
|
Project::Folder *best_folder = nullptr;
|
||||||
const Entry *best = nullptr;
|
const Entry *best = nullptr;
|
||||||
std::lock_guard lock(mtx);
|
std::lock_guard lock(mtx);
|
||||||
for (auto &[root, folder] : root2folder) {
|
for (auto &[root, folder] : root2folder) {
|
||||||
|
// The entry may have different filename but it doesn't matter when building
|
||||||
|
// CompilerInvocation. The main filename is specified separately.
|
||||||
auto it = folder.path2entry_index.find(path);
|
auto it = folder.path2entry_index.find(path);
|
||||||
if (it != folder.path2entry_index.end()) {
|
if (it != folder.path2entry_index.end()) {
|
||||||
Project::Entry &entry = folder.entries[it->second];
|
Project::Entry &entry = folder.entries[it->second];
|
||||||
if (!must_exist || entry.filename == path)
|
if (can_redirect || entry.filename == path)
|
||||||
return entry;
|
return entry;
|
||||||
|
if (entry.compdb_size) {
|
||||||
|
best_folder = &folder;
|
||||||
|
best = &entry;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +478,7 @@ out:
|
|||||||
best_folder = &folder;
|
best_folder = &folder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.is_inferred = true;
|
ret.is_inferred = true;
|
||||||
@ -485,14 +492,6 @@ out:
|
|||||||
ret.root = best->root;
|
ret.root = best->root;
|
||||||
ret.directory = best->directory;
|
ret.directory = best->directory;
|
||||||
ret.args = best->args;
|
ret.args = best->args;
|
||||||
std::string base_name = sys::path::filename(best->filename);
|
|
||||||
for (const char *&arg : ret.args) {
|
|
||||||
try {
|
|
||||||
if (arg == best->filename || sys::path::filename(arg) == base_name)
|
|
||||||
arg = Intern(path);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret.args.resize(best->compdb_size);
|
ret.args.resize(best->compdb_size);
|
||||||
if (extra && extra->size())
|
if (extra && extra->size())
|
||||||
ret.args.insert(ret.args.end(), extra->begin() + 1, extra->end());
|
ret.args.insert(ret.args.end(), extra->begin() + 1, extra->end());
|
||||||
|
@ -56,7 +56,7 @@ struct Project {
|
|||||||
|
|
||||||
// Lookup the CompilationEntry for |filename|. If no entry was found this
|
// Lookup the CompilationEntry for |filename|. If no entry was found this
|
||||||
// will infer one based on existing project structure.
|
// will infer one based on existing project structure.
|
||||||
Entry FindEntry(const std::string &path, bool can_be_inferred);
|
Entry FindEntry(const std::string &path, bool can_redirect, bool must_exist);
|
||||||
|
|
||||||
// If the client has overridden the flags, or specified them for a file
|
// If the client has overridden the flags, or specified them for a file
|
||||||
// that is not in the compilation_database.json make sure those changes
|
// that is not in the compilation_database.json make sure those changes
|
||||||
|
@ -409,7 +409,7 @@ void *PreambleMain(void *manager_) {
|
|||||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
||||||
stat_cache->Producer(session->FS);
|
stat_cache->Producer(session->FS);
|
||||||
if (std::unique_ptr<CompilerInvocation> CI =
|
if (std::unique_ptr<CompilerInvocation> CI =
|
||||||
BuildCompilerInvocation(session->file.args, FS))
|
BuildCompilerInvocation(task.path, session->file.args, FS))
|
||||||
BuildPreamble(*session, *CI, FS, task, std::move(stat_cache));
|
BuildPreamble(*session, *CI, FS, task, std::move(stat_cache));
|
||||||
|
|
||||||
if (task.from_diag) {
|
if (task.from_diag) {
|
||||||
@ -449,7 +449,7 @@ void *CompletionMain(void *manager_) {
|
|||||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
||||||
preamble ? preamble->stat_cache->Consumer(session->FS) : session->FS;
|
preamble ? preamble->stat_cache->Consumer(session->FS) : session->FS;
|
||||||
std::unique_ptr<CompilerInvocation> CI =
|
std::unique_ptr<CompilerInvocation> CI =
|
||||||
BuildCompilerInvocation(session->file.args, FS);
|
BuildCompilerInvocation(task->path, session->file.args, FS);
|
||||||
if (!CI)
|
if (!CI)
|
||||||
continue;
|
continue;
|
||||||
auto &FOpts = CI->getFrontendOpts();
|
auto &FOpts = CI->getFrontendOpts();
|
||||||
@ -551,7 +551,7 @@ void *DiagnosticMain(void *manager_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CompilerInvocation> CI =
|
std::unique_ptr<CompilerInvocation> CI =
|
||||||
BuildCompilerInvocation(session->file.args, FS);
|
BuildCompilerInvocation(task.path, session->file.args, FS);
|
||||||
if (!CI)
|
if (!CI)
|
||||||
continue;
|
continue;
|
||||||
// If main file is a header, add -Wno-unused-function
|
// If main file is a header, add -Wno-unused-function
|
||||||
@ -696,7 +696,7 @@ SemaManager::EnsureSession(const std::string &path, bool *created) {
|
|||||||
std::shared_ptr<ccls::Session> session = sessions.Get(path);
|
std::shared_ptr<ccls::Session> session = sessions.Get(path);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
session = std::make_shared<ccls::Session>(
|
session = std::make_shared<ccls::Session>(
|
||||||
project_->FindEntry(path, true), wfiles, PCH);
|
project_->FindEntry(path, false, false), wfiles, PCH);
|
||||||
std::string line;
|
std::string line;
|
||||||
if (LOG_V_ENABLED(1)) {
|
if (LOG_V_ENABLED(1)) {
|
||||||
line = "\n ";
|
line = "\n ";
|
||||||
|
Loading…
Reference in New Issue
Block a user