mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-24 08:35:08 +00:00
Adjust FrontendOpts.Inputs[0] for inferred files
This commit is contained in:
parent
cbd36aeedb
commit
e8cacf1efa
@ -93,7 +93,7 @@ Range FromTokenRangeDefaulted(const SourceManager &SM, const LangOptions &Lang,
|
||||
}
|
||||
|
||||
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) {
|
||||
std::string save = "-resource-dir=" + g_config->clang.resourceDir;
|
||||
args.push_back(save.c_str());
|
||||
@ -106,6 +106,9 @@ BuildCompilerInvocation(std::vector<const char *> args,
|
||||
CI->getDiagnosticOpts().IgnoreWarnings = true;
|
||||
CI->getFrontendOpts().DisableFree = 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;
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ Range FromTokenRangeDefaulted(const clang::SourceManager &SM,
|
||||
Range range);
|
||||
|
||||
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);
|
||||
|
||||
const char *ClangBuiltinTypeName(int);
|
||||
|
@ -1230,14 +1230,15 @@ void Init() {
|
||||
|
||||
std::vector<std::unique_ptr<IndexFile>>
|
||||
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<std::pair<std::string, std::string>> &remapped,
|
||||
bool &ok) {
|
||||
ok = true;
|
||||
auto PCH = std::make_shared<PCHContainerOperations>();
|
||||
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
|
||||
if (!CI)
|
||||
return {};
|
||||
@ -1257,35 +1258,13 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
||||
// HSOpts.UseBuiltinIncludes)
|
||||
// HSOpts.ResourceDir = g_config->clang.resourceDir;
|
||||
}
|
||||
std::string buf = wfiles->GetContent(file);
|
||||
std::string buf = wfiles->GetContent(main);
|
||||
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Bufs;
|
||||
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
|
||||
if (buf.size())
|
||||
for (auto &[filename, content] : remapped) {
|
||||
if (filename == file && done_remap)
|
||||
continue;
|
||||
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content));
|
||||
CI->getPreprocessorOpts().addRemappedFile(
|
||||
filename == file ? CI->getFrontendOpts().Inputs[0].getFile()
|
||||
: StringRef(filename),
|
||||
Bufs.back().get());
|
||||
CI->getPreprocessorOpts().addRemappedFile(filename, Bufs.back().get());
|
||||
}
|
||||
}
|
||||
|
||||
DiagnosticConsumer DC;
|
||||
auto Clang = std::make_unique<CompilerInstance>(PCH);
|
||||
@ -1314,20 +1293,20 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
||||
{
|
||||
llvm::CrashRecoveryContext CRC;
|
||||
auto parse = [&]() {
|
||||
if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
|
||||
return;
|
||||
if (!Action->Execute())
|
||||
return;
|
||||
Action->EndSourceFile();
|
||||
ok = true;
|
||||
};
|
||||
if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
|
||||
return;
|
||||
if (!Action->Execute())
|
||||
return;
|
||||
Action->EndSourceFile();
|
||||
ok = true;
|
||||
};
|
||||
if (!CRC.RunSafely(parse)) {
|
||||
LOG_S(ERROR) << "clang crashed for " << file;
|
||||
LOG_S(ERROR) << "clang crashed for " << main;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
LOG_S(ERROR) << "failed to index " << file;
|
||||
LOG_S(ERROR) << "failed to index " << main;
|
||||
return {};
|
||||
}
|
||||
for (auto &Buf : Bufs)
|
||||
@ -1338,7 +1317,7 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
||||
if (!it.second.db)
|
||||
continue;
|
||||
std::unique_ptr<IndexFile> &entry = it.second.db;
|
||||
entry->import_file = file;
|
||||
entry->import_file = main;
|
||||
entry->args = args;
|
||||
for (auto &[_, it] : entry->uid2lid_and_path)
|
||||
entry->lid2path.emplace_back(it.first, std::move(it.second));
|
||||
|
@ -29,6 +29,7 @@ limitations under the License.
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/writer.h>
|
||||
|
||||
#include <llvm/Support/Path.h>
|
||||
#include <llvm/Support/Process.h>
|
||||
#include <llvm/Support/Threading.h>
|
||||
using namespace llvm;
|
||||
@ -122,9 +123,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();
|
||||
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;
|
||||
if (changed)
|
||||
LOG_S(INFO) << "args changed for " << path
|
||||
@ -207,7 +210,8 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
|
||||
}
|
||||
|
||||
// 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())
|
||||
return true;
|
||||
if (request.args.size())
|
||||
|
@ -423,17 +423,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) {
|
||||
Project::Folder *best_folder = nullptr;
|
||||
const Entry *best = nullptr;
|
||||
std::lock_guard lock(mtx);
|
||||
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);
|
||||
if (it != folder.path2entry_index.end()) {
|
||||
Project::Entry &entry = folder.entries[it->second];
|
||||
if (!must_exist || entry.filename == path)
|
||||
if (can_redirect || entry.filename == path)
|
||||
return entry;
|
||||
if (entry.compdb_size) {
|
||||
best_folder = &folder;
|
||||
best = &entry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -483,7 +490,7 @@ out:
|
||||
best_folder = &folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret.is_inferred = true;
|
||||
@ -497,14 +504,6 @@ out:
|
||||
ret.root = best->root;
|
||||
ret.directory = best->directory;
|
||||
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);
|
||||
if (extra && extra->size())
|
||||
ret.args.insert(ret.args.end(), extra->begin() + 1, extra->end());
|
||||
|
@ -68,7 +68,7 @@ struct Project {
|
||||
|
||||
// Lookup the CompilationEntry for |filename|. If no entry was found this
|
||||
// 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
|
||||
// that is not in the compilation_database.json make sure those changes
|
||||
|
@ -420,7 +420,7 @@ void *PreambleMain(void *manager_) {
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
||||
stat_cache->Producer(session->FS);
|
||||
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));
|
||||
|
||||
if (task.from_diag) {
|
||||
@ -460,7 +460,7 @@ void *CompletionMain(void *manager_) {
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
||||
preamble ? preamble->stat_cache->Consumer(session->FS) : session->FS;
|
||||
std::unique_ptr<CompilerInvocation> CI =
|
||||
BuildCompilerInvocation(session->file.args, FS);
|
||||
BuildCompilerInvocation(task->path, session->file.args, FS);
|
||||
if (!CI)
|
||||
continue;
|
||||
auto &FOpts = CI->getFrontendOpts();
|
||||
@ -562,7 +562,7 @@ void *DiagnosticMain(void *manager_) {
|
||||
}
|
||||
|
||||
std::unique_ptr<CompilerInvocation> CI =
|
||||
BuildCompilerInvocation(session->file.args, FS);
|
||||
BuildCompilerInvocation(task.path, session->file.args, FS);
|
||||
if (!CI)
|
||||
continue;
|
||||
// If main file is a header, add -Wno-unused-function
|
||||
@ -707,7 +707,7 @@ SemaManager::EnsureSession(const std::string &path, bool *created) {
|
||||
std::shared_ptr<ccls::Session> session = sessions.Get(path);
|
||||
if (!session) {
|
||||
session = std::make_shared<ccls::Session>(
|
||||
project_->FindEntry(path, true), wfiles, PCH);
|
||||
project_->FindEntry(path, false, false), wfiles, PCH);
|
||||
std::string line;
|
||||
if (LOG_V_ENABLED(1)) {
|
||||
line = "\n ";
|
||||
|
Loading…
Reference in New Issue
Block a user