mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-23 08:05:07 +00:00
Drop support for LLVM 7, 8, and 9
This commit is contained in:
parent
192a82ba85
commit
50fd8d069e
@ -201,7 +201,6 @@ target_sources(ccls PRIVATE
|
||||
src/filesystem.cc
|
||||
src/fuzzy_match.cc
|
||||
src/main.cc
|
||||
src/include_complete.cc
|
||||
src/indexer.cc
|
||||
src/log.cc
|
||||
src/lsp.cc
|
||||
|
@ -163,12 +163,7 @@ buildCompilerInvocation(const std::string &main, std::vector<const char *> args,
|
||||
return nullptr;
|
||||
const llvm::opt::ArgStringList &cc_args = cmd.getArguments();
|
||||
auto ci = std::make_unique<CompilerInvocation>();
|
||||
#if LLVM_VERSION_MAJOR >= 10 // rC370122
|
||||
if (!CompilerInvocation::CreateFromArgs(*ci, cc_args, *diags))
|
||||
#else
|
||||
if (!CompilerInvocation::CreateFromArgs(
|
||||
*ci, cc_args.data(), cc_args.data() + cc_args.size(), *diags))
|
||||
#endif
|
||||
return nullptr;
|
||||
|
||||
ci->getDiagnosticOpts().IgnoreWarnings = true;
|
||||
@ -189,9 +184,7 @@ buildCompilerInvocation(const std::string &main, std::vector<const char *> args,
|
||||
auto &isec = ci->getFrontendOpts().Inputs;
|
||||
if (isec.size())
|
||||
isec[0] = FrontendInputFile(main, isec[0].getKind(), isec[0].isSystem());
|
||||
#if LLVM_VERSION_MAJOR >= 10 // llvmorg-11-init-2414-g75f09b54429
|
||||
ci->getPreprocessorOpts().DisablePragmaDebugCrash = true;
|
||||
#endif
|
||||
// clangSerialization has an unstable format. Disable PCH reading/writing
|
||||
// to work around PCH mismatch problems.
|
||||
ci->getPreprocessorOpts().ImplicitPCHInclude.clear();
|
||||
|
@ -10,13 +10,6 @@
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 8
|
||||
// D52783 Lift VFS from clang to llvm
|
||||
namespace llvm {
|
||||
namespace vfs = clang::vfs;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 14 // llvmorg-14-init-3863-g601102d282d5
|
||||
#define isAsciiIdentifierContinue isIdentifierBody
|
||||
#endif
|
||||
|
@ -1,185 +0,0 @@
|
||||
// Copyright 2017-2018 ccls Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "include_complete.hh"
|
||||
|
||||
#include "filesystem.hh"
|
||||
#include "platform.hh"
|
||||
#include "project.hh"
|
||||
|
||||
#include <llvm/ADT/Twine.h>
|
||||
#include <llvm/Support/Threading.h>
|
||||
#include <llvm/Support/Timer.h>
|
||||
|
||||
#include <unordered_set>
|
||||
using namespace llvm;
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace ccls {
|
||||
namespace {
|
||||
|
||||
struct CompletionCandidate {
|
||||
std::string absolute_path;
|
||||
CompletionItem completion_item;
|
||||
};
|
||||
|
||||
std::string elideLongPath(const std::string &path) {
|
||||
if (g_config->completion.include.maxPathSize <= 0 ||
|
||||
(int)path.size() <= g_config->completion.include.maxPathSize)
|
||||
return path;
|
||||
|
||||
size_t start = path.size() - g_config->completion.include.maxPathSize;
|
||||
return ".." + path.substr(start + 2);
|
||||
}
|
||||
|
||||
size_t trimCommonPathPrefix(const std::string &result,
|
||||
const std::string &trimmer) {
|
||||
#ifdef _WIN32
|
||||
std::string s = result, t = trimmer;
|
||||
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||
std::transform(t.begin(), t.end(), t.begin(), ::tolower);
|
||||
if (s.compare(0, t.size(), t) == 0)
|
||||
return t.size();
|
||||
#else
|
||||
if (result.compare(0, trimmer.size(), trimmer) == 0)
|
||||
return trimmer.size();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trimPath(Project *project, std::string &path) {
|
||||
size_t pos = 0;
|
||||
int kind = 0;
|
||||
for (auto &[root, folder] : project->root2folder)
|
||||
for (auto &[search, search_dir_kind] : folder.search_dir2kind)
|
||||
if (int t = trimCommonPathPrefix(path, search); t > pos)
|
||||
pos = t, kind = search_dir_kind;
|
||||
path = path.substr(pos);
|
||||
return kind;
|
||||
}
|
||||
|
||||
CompletionItem buildCompletionItem(const std::string &path, int kind) {
|
||||
CompletionItem item;
|
||||
item.label = elideLongPath(path);
|
||||
item.detail = path; // the include path, used in de-duplicating
|
||||
item.textEdit.newText = path;
|
||||
item.insertTextFormat = InsertTextFormat::PlainText;
|
||||
item.kind = CompletionItemKind::File;
|
||||
item.quote_kind_ = kind;
|
||||
item.priority_ = 0;
|
||||
return item;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
IncludeComplete::IncludeComplete(Project *project)
|
||||
: is_scanning(false), project_(project) {}
|
||||
|
||||
IncludeComplete::~IncludeComplete() {
|
||||
// Spin until the scanning has completed.
|
||||
while (is_scanning.load())
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
void IncludeComplete::rescan() {
|
||||
if (is_scanning || LLVM_VERSION_MAJOR >= 8)
|
||||
return;
|
||||
|
||||
completion_items.clear();
|
||||
absolute_path_to_completion_item.clear();
|
||||
inserted_paths.clear();
|
||||
|
||||
if (!match_ && (g_config->completion.include.whitelist.size() ||
|
||||
g_config->completion.include.blacklist.size()))
|
||||
match_ =
|
||||
std::make_unique<GroupMatch>(g_config->completion.include.whitelist,
|
||||
g_config->completion.include.blacklist);
|
||||
|
||||
is_scanning = true;
|
||||
std::thread([this]() {
|
||||
set_thread_name("include");
|
||||
for (auto &[root, folder] : project_->root2folder) {
|
||||
for (auto &search_kind : folder.search_dir2kind) {
|
||||
const std::string &search = search_kind.first;
|
||||
int kind = search_kind.second;
|
||||
assert(search.back() == '/');
|
||||
if (match_ && !match_->matches(search))
|
||||
return;
|
||||
bool include_cpp = search.find("include/c++") != std::string::npos;
|
||||
|
||||
std::vector<CompletionCandidate> results;
|
||||
getFilesInFolder(
|
||||
search, true /*recursive*/, false /*add_folder_to_path*/,
|
||||
[&](const std::string &path) {
|
||||
bool ok = include_cpp;
|
||||
for (StringRef suffix :
|
||||
g_config->completion.include.suffixWhitelist)
|
||||
if (StringRef(path).endswith(suffix))
|
||||
ok = true;
|
||||
if (!ok)
|
||||
return;
|
||||
if (match_ && !match_->matches(search + path))
|
||||
return;
|
||||
|
||||
CompletionCandidate candidate;
|
||||
candidate.absolute_path = search + path;
|
||||
candidate.completion_item = buildCompletionItem(path, kind);
|
||||
results.push_back(candidate);
|
||||
});
|
||||
|
||||
std::lock_guard lock(completion_items_mutex);
|
||||
for (CompletionCandidate &result : results)
|
||||
insertCompletionItem(result.absolute_path,
|
||||
std::move(result.completion_item));
|
||||
}
|
||||
}
|
||||
|
||||
is_scanning = false;
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void IncludeComplete::insertCompletionItem(const std::string &absolute_path,
|
||||
CompletionItem &&item) {
|
||||
if (inserted_paths.try_emplace(item.detail, inserted_paths.size()).second) {
|
||||
completion_items.push_back(item);
|
||||
// insert if not found or with shorter include path
|
||||
auto it = absolute_path_to_completion_item.find(absolute_path);
|
||||
if (it == absolute_path_to_completion_item.end() ||
|
||||
completion_items[it->second].detail.length() > item.detail.length()) {
|
||||
absolute_path_to_completion_item[absolute_path] =
|
||||
completion_items.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IncludeComplete::addFile(const std::string &path) {
|
||||
bool ok = false;
|
||||
for (StringRef suffix : g_config->completion.include.suffixWhitelist)
|
||||
if (StringRef(path).endswith(suffix))
|
||||
ok = true;
|
||||
if (!ok)
|
||||
return;
|
||||
if (match_ && !match_->matches(path))
|
||||
return;
|
||||
|
||||
std::string trimmed_path = path;
|
||||
int kind = trimPath(project_, trimmed_path);
|
||||
CompletionItem item = buildCompletionItem(trimmed_path, kind);
|
||||
|
||||
std::unique_lock<std::mutex> lock(completion_items_mutex, std::defer_lock);
|
||||
if (is_scanning)
|
||||
lock.lock();
|
||||
insertCompletionItem(path, std::move(item));
|
||||
}
|
||||
|
||||
std::optional<CompletionItem>
|
||||
IncludeComplete::findCompletionItemForAbsolutePath(
|
||||
const std::string &absolute_path) {
|
||||
std::lock_guard<std::mutex> lock(completion_items_mutex);
|
||||
|
||||
auto it = absolute_path_to_completion_item.find(absolute_path);
|
||||
if (it == absolute_path_to_completion_item.end())
|
||||
return std::nullopt;
|
||||
return completion_items[it->second];
|
||||
}
|
||||
} // namespace ccls
|
@ -1,49 +0,0 @@
|
||||
// Copyright 2017-2018 ccls Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "message_handler.hh"
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
namespace ccls {
|
||||
struct GroupMatch;
|
||||
struct Project;
|
||||
|
||||
struct IncludeComplete {
|
||||
IncludeComplete(Project *project);
|
||||
~IncludeComplete();
|
||||
|
||||
// Starts scanning directories. Clears existing cache.
|
||||
void rescan();
|
||||
|
||||
// Ensures the one-off file is inside |completion_items|.
|
||||
void addFile(const std::string &absolute_path);
|
||||
|
||||
std::optional<ccls::CompletionItem>
|
||||
findCompletionItemForAbsolutePath(const std::string &absolute_path);
|
||||
|
||||
// Insert item to |completion_items|.
|
||||
// Update |absolute_path_to_completion_item| and |inserted_paths|.
|
||||
void insertCompletionItem(const std::string &absolute_path,
|
||||
ccls::CompletionItem &&item);
|
||||
|
||||
// Guards |completion_items| when |is_scanning| is true.
|
||||
std::mutex completion_items_mutex;
|
||||
std::atomic<bool> is_scanning;
|
||||
std::vector<ccls::CompletionItem> completion_items;
|
||||
|
||||
// Absolute file path to the completion item in |completion_items|.
|
||||
// Keep the one with shortest include path.
|
||||
std::unordered_map<std::string, int> absolute_path_to_completion_item;
|
||||
|
||||
// Only one completion item per include path.
|
||||
std::unordered_map<std::string, int> inserted_paths;
|
||||
|
||||
// Cached references
|
||||
Project *project_;
|
||||
std::unique_ptr<GroupMatch> match_;
|
||||
};
|
||||
} // namespace ccls
|
@ -710,9 +710,6 @@ public:
|
||||
public:
|
||||
IndexDataConsumer(IndexParam ¶m) : param(param) {}
|
||||
void initialize(ASTContext &ctx) override { this->ctx = param.ctx = &ctx; }
|
||||
#if LLVM_VERSION_MAJOR < 10 // llvmorg-10-init-12036-g3b9715cb219
|
||||
# define handleDeclOccurrence handleDeclOccurence
|
||||
#endif
|
||||
bool handleDeclOccurrence(const Decl *d, index::SymbolRoleSet roles,
|
||||
ArrayRef<index::SymbolRelation> relations,
|
||||
SourceLocation src_loc,
|
||||
@ -899,31 +896,6 @@ public:
|
||||
if (!isa<EnumConstantDecl>(d))
|
||||
db->toType(usr1).instances.push_back(usr);
|
||||
} else if (const Decl *d1 = getAdjustedDecl(getTypeDecl(t))) {
|
||||
#if LLVM_VERSION_MAJOR < 9
|
||||
if (isa<TemplateTypeParmDecl>(d1)) {
|
||||
// e.g. TemplateTypeParmDecl is not handled by
|
||||
// handleDeclOccurence.
|
||||
SourceRange sr1 = d1->getSourceRange();
|
||||
if (sm.getFileID(sr1.getBegin()) == fid) {
|
||||
IndexParam::DeclInfo *info1;
|
||||
Usr usr1 = getUsr(d1, &info1);
|
||||
IndexType &type1 = db->toType(usr1);
|
||||
SourceLocation sl1 = d1->getLocation();
|
||||
type1.def.spell = {
|
||||
Use{{fromTokenRange(sm, lang, {sl1, sl1}), Role::Definition},
|
||||
lid},
|
||||
fromTokenRange(sm, lang, sr1)};
|
||||
type1.def.detailed_name = intern(info1->short_name);
|
||||
type1.def.short_name_size = int16_t(info1->short_name.size());
|
||||
type1.def.kind = SymbolKind::TypeParameter;
|
||||
type1.def.parent_kind = SymbolKind::Class;
|
||||
var->def.type = usr1;
|
||||
type1.instances.push_back(usr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
IndexParam::DeclInfo *info1;
|
||||
Usr usr1 = getUsr(d1, &info1);
|
||||
var->def.type = usr1;
|
||||
@ -1237,10 +1209,8 @@ public:
|
||||
std::make_unique<IndexPPCallbacks>(pp->getSourceManager(), param));
|
||||
std::vector<std::unique_ptr<ASTConsumer>> consumers;
|
||||
consumers.push_back(std::make_unique<SkipProcessed>(param));
|
||||
#if LLVM_VERSION_MAJOR >= 10 // rC370337
|
||||
consumers.push_back(index::createIndexingASTConsumer(
|
||||
dataConsumer, indexOpts, std::move(pp)));
|
||||
#endif
|
||||
return std::make_unique<MultiplexConsumer>(std::move(consumers));
|
||||
}
|
||||
};
|
||||
@ -1349,12 +1319,7 @@ index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
||||
if (!clang->hasTarget())
|
||||
return {};
|
||||
clang->getPreprocessorOpts().RetainRemappedFileBuffers = true;
|
||||
#if LLVM_VERSION_MAJOR >= 9 // rC357037
|
||||
clang->createFileManager(fs);
|
||||
#else
|
||||
clang->setVirtualFileSystem(fs);
|
||||
clang->createFileManager();
|
||||
#endif
|
||||
clang->setSourceManager(new SourceManager(clang->getDiagnostics(),
|
||||
clang->getFileManager(), true));
|
||||
|
||||
@ -1366,39 +1331,23 @@ index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
||||
if (no_linkage) {
|
||||
indexOpts.IndexFunctionLocals = true;
|
||||
indexOpts.IndexImplicitInstantiation = true;
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
|
||||
indexOpts.IndexParametersInDeclarations =
|
||||
g_config->index.parametersInDeclarations;
|
||||
indexOpts.IndexTemplateParameters = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 10 // rC370337
|
||||
auto action = std::make_unique<IndexFrontendAction>(
|
||||
std::make_shared<IndexDataConsumer>(param), indexOpts, param);
|
||||
#else
|
||||
auto dataConsumer = std::make_shared<IndexDataConsumer>(param);
|
||||
auto action = createIndexingAction(
|
||||
dataConsumer, indexOpts,
|
||||
std::make_unique<IndexFrontendAction>(dataConsumer, indexOpts, param));
|
||||
#endif
|
||||
|
||||
std::string reason;
|
||||
{
|
||||
llvm::CrashRecoveryContext crc;
|
||||
auto parse = [&]() {
|
||||
if (!action->BeginSourceFile(*clang, clang->getFrontendOpts().Inputs[0]))
|
||||
return;
|
||||
#if LLVM_VERSION_MAJOR >= 9 // rL364464
|
||||
if (llvm::Error e = action->Execute()) {
|
||||
reason = llvm::toString(std::move(e));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!action->Execute())
|
||||
return;
|
||||
#endif
|
||||
action->EndSourceFile();
|
||||
ok = true;
|
||||
};
|
||||
|
@ -14,7 +14,6 @@
|
||||
namespace ccls {
|
||||
struct SemaManager;
|
||||
struct VFS;
|
||||
struct IncludeComplete;
|
||||
struct Project;
|
||||
struct WorkingFile;
|
||||
struct WorkingFiles;
|
||||
@ -239,7 +238,6 @@ struct ReplyOnce {
|
||||
struct MessageHandler {
|
||||
SemaManager *manager = nullptr;
|
||||
DB *db = nullptr;
|
||||
IncludeComplete *include_complete = nullptr;
|
||||
Project *project = nullptr;
|
||||
VFS *vfs = nullptr;
|
||||
WorkingFiles *wfiles = nullptr;
|
||||
|
@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "filesystem.hh"
|
||||
#include "include_complete.hh"
|
||||
#include "log.hh"
|
||||
#include "message_handler.hh"
|
||||
#include "pipeline.hh"
|
||||
@ -261,7 +260,7 @@ void *indexer(void *arg_) {
|
||||
// Don't lower priority on __APPLE__. getpriority(2) says "When setting a
|
||||
// thread into background state the scheduling priority is set to lowest
|
||||
// value, disk and network IO are throttled."
|
||||
#if LLVM_ENABLE_THREADS && LLVM_VERSION_MAJOR >= 9 && !defined(__APPLE__)
|
||||
#if LLVM_ENABLE_THREADS && !defined(__APPLE__)
|
||||
set_thread_priority(ThreadPriority::Background);
|
||||
#endif
|
||||
pipeline::indexer_Main(h->manager, h->vfs, h->project, h->wfiles);
|
||||
@ -389,10 +388,6 @@ void do_initialize(MessageHandler *m, InitializeParam ¶m,
|
||||
for (int i = 0; i < g_config->index.threads; i++)
|
||||
spawnThread(indexer, new std::pair<MessageHandler *, int>{m, i});
|
||||
|
||||
// Start scanning include directories before dispatching project
|
||||
// files, because that takes a long time.
|
||||
m->include_complete->rescan();
|
||||
|
||||
LOG_S(INFO) << "dispatch initial index requests";
|
||||
m->project->index(m->wfiles, reply.id);
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "fuzzy_match.hh"
|
||||
#include "include_complete.hh"
|
||||
#include "log.hh"
|
||||
#include "message_handler.hh"
|
||||
#include "pipeline.hh"
|
||||
@ -13,10 +12,6 @@
|
||||
#include <clang/Sema/Sema.h>
|
||||
#include <llvm/ADT/Twine.h>
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 8
|
||||
#include <regex>
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 18 // llvmorg-18-init-10631-gedd690b02e16
|
||||
#define TTK_Struct TagTypeKind::Struct
|
||||
#endif
|
||||
@ -52,54 +47,6 @@ struct CompletionList {
|
||||
};
|
||||
REFLECT_STRUCT(CompletionList, isIncomplete, items);
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 8
|
||||
void decorateIncludePaths(const std::smatch &match,
|
||||
std::vector<CompletionItem> *items, char quote) {
|
||||
std::string spaces_after_include = " ";
|
||||
if (match[3].compare("include") == 0 && quote != '\0')
|
||||
spaces_after_include = match[4].str();
|
||||
|
||||
std::string prefix =
|
||||
match[1].str() + '#' + match[2].str() + "include" + spaces_after_include;
|
||||
std::string suffix = match[7].str();
|
||||
|
||||
for (CompletionItem &item : *items) {
|
||||
char quote0, quote1;
|
||||
if (quote != '"')
|
||||
quote0 = '<', quote1 = '>';
|
||||
else
|
||||
quote0 = quote1 = '"';
|
||||
|
||||
item.textEdit.newText =
|
||||
prefix + quote0 + item.textEdit.newText + quote1 + suffix;
|
||||
item.label = prefix + quote0 + item.label + quote1 + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
struct ParseIncludeLineResult {
|
||||
bool ok;
|
||||
std::string keyword;
|
||||
std::string quote;
|
||||
std::string pattern;
|
||||
std::smatch match;
|
||||
};
|
||||
|
||||
ParseIncludeLineResult ParseIncludeLine(const std::string &line) {
|
||||
static const std::regex pattern("(\\s*)" // [1]: spaces before '#'
|
||||
"#" //
|
||||
"(\\s*)" // [2]: spaces after '#'
|
||||
"([^\\s\"<]*)" // [3]: "include"
|
||||
"(\\s*)" // [4]: spaces before quote
|
||||
"([\"<])?" // [5]: the first quote char
|
||||
"([^\\s\">]*)" // [6]: path of file
|
||||
"[\">]?" //
|
||||
"(.*)"); // [7]: suffix after quote char
|
||||
std::smatch match;
|
||||
bool ok = std::regex_match(line, match, pattern);
|
||||
return {ok, match[3], match[5], match[6], match};
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pre-filters completion responses before sending to vscode. This results in a
|
||||
// significantly snappier completion experience as vscode is easily overloaded
|
||||
// when given 1000+ completion items.
|
||||
@ -309,10 +256,8 @@ CompletionItemKind getCompletionKind(CodeCompletionContext::Kind k,
|
||||
case CodeCompletionResult::RK_Macro:
|
||||
return CompletionItemKind::Reference;
|
||||
case CodeCompletionResult::RK_Pattern:
|
||||
#if LLVM_VERSION_MAJOR >= 8
|
||||
if (k == CodeCompletionContext::CCC_IncludedFile)
|
||||
return CompletionItemKind::File;
|
||||
#endif
|
||||
return CompletionItemKind::Snippet;
|
||||
}
|
||||
}
|
||||
@ -402,11 +347,7 @@ public:
|
||||
|
||||
CompletionConsumer(const CodeCompleteOptions &opts, bool from_cache)
|
||||
:
|
||||
#if LLVM_VERSION_MAJOR >= 9 // rC358696
|
||||
CodeCompleteConsumer(opts),
|
||||
#else
|
||||
CodeCompleteConsumer(opts, false),
|
||||
#endif
|
||||
alloc(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
|
||||
cctu_info(alloc), from_cache(from_cache) {
|
||||
}
|
||||
@ -544,31 +485,6 @@ void MessageHandler::textDocument_completion(CompletionParam ¶m,
|
||||
Position end_pos = param.position;
|
||||
Position begin_pos = wf->getCompletionPosition(param.position, &filter);
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 8
|
||||
ParseIncludeLineResult preprocess = ParseIncludeLine(buffer_line);
|
||||
if (preprocess.ok && preprocess.keyword.compare("include") == 0) {
|
||||
CompletionList result;
|
||||
char quote = std::string(preprocess.match[5])[0];
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(
|
||||
include_complete->completion_items_mutex, std::defer_lock);
|
||||
if (include_complete->is_scanning)
|
||||
lock.lock();
|
||||
for (auto &item : include_complete->completion_items)
|
||||
if (quote == '\0' || (item.quote_kind_ & 1 && quote == '"') ||
|
||||
(item.quote_kind_ & 2 && quote == '<'))
|
||||
result.items.push_back(item);
|
||||
}
|
||||
begin_pos.character = 0;
|
||||
end_pos.character = (int)buffer_line.size();
|
||||
filterCandidates(result, preprocess.pattern, begin_pos, end_pos,
|
||||
buffer_line);
|
||||
decorateIncludePaths(preprocess.match, &result.items, quote);
|
||||
reply(result);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SemaManager::OnComplete callback =
|
||||
[filter, path, begin_pos, end_pos, reply,
|
||||
buffer_line](CodeCompleteConsumer *optConsumer) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright 2017-2018 ccls Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "include_complete.hh"
|
||||
#include "message_handler.hh"
|
||||
#include "pipeline.hh"
|
||||
#include "project.hh"
|
||||
@ -38,7 +37,6 @@ void MessageHandler::textDocument_didOpen(DidOpenTextDocumentParam ¶m) {
|
||||
emitSkippedRanges(wf, *file);
|
||||
emitSemanticHighlight(db, wf, *file);
|
||||
}
|
||||
include_complete->addFile(wf->filename);
|
||||
|
||||
// Submit new index request if it is not a header file or there is no
|
||||
// pending index request.
|
||||
|
@ -65,22 +65,10 @@ public:
|
||||
bool from_cache;
|
||||
SignatureHelp ls_sighelp;
|
||||
SignatureHelpConsumer(const clang::CodeCompleteOptions &opts, bool from_cache)
|
||||
:
|
||||
#if LLVM_VERSION_MAJOR >= 9 // rC358696
|
||||
CodeCompleteConsumer(opts),
|
||||
#else
|
||||
CodeCompleteConsumer(opts, false),
|
||||
#endif
|
||||
alloc(std::make_shared<GlobalCodeCompletionAllocator>()),
|
||||
cCTUInfo(alloc), from_cache(from_cache) {
|
||||
}
|
||||
void ProcessOverloadCandidates(Sema &s, unsigned currentArg,
|
||||
OverloadCandidate *candidates,
|
||||
unsigned numCandidates
|
||||
#if LLVM_VERSION_MAJOR >= 8
|
||||
,
|
||||
: CodeCompleteConsumer(opts), alloc(std::make_shared<GlobalCodeCompletionAllocator>()), cCTUInfo(alloc),
|
||||
from_cache(from_cache) {}
|
||||
void ProcessOverloadCandidates(Sema &s, unsigned currentArg, OverloadCandidate *candidates, unsigned numCandidates,
|
||||
SourceLocation openParLoc
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 14
|
||||
,
|
||||
bool braced
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "pipeline.hh"
|
||||
|
||||
#include "config.hh"
|
||||
#include "include_complete.hh"
|
||||
#include "log.hh"
|
||||
#include "lsp.hh"
|
||||
#include "message_handler.hh"
|
||||
@ -657,7 +656,6 @@ void mainLoop() {
|
||||
}
|
||||
});
|
||||
|
||||
IncludeComplete include_complete(&project);
|
||||
DB db;
|
||||
|
||||
// Setup shared references.
|
||||
@ -667,7 +665,6 @@ void mainLoop() {
|
||||
handler.vfs = &vfs;
|
||||
handler.wfiles = &wfiles;
|
||||
handler.manager = &manager;
|
||||
handler.include_complete = &include_complete;
|
||||
|
||||
bool work_done_created = false, in_progress = false;
|
||||
bool has_indexed = false;
|
||||
@ -787,14 +784,12 @@ void standalone(const std::string &root) {
|
||||
nullptr, nullptr,
|
||||
[](const std::string &, const std::vector<Diagnostic> &) {},
|
||||
[](const RequestId &id) {});
|
||||
IncludeComplete complete(&project);
|
||||
|
||||
MessageHandler handler;
|
||||
handler.project = &project;
|
||||
handler.wfiles = &wfiles;
|
||||
handler.vfs = &vfs;
|
||||
handler.manager = &manager;
|
||||
handler.include_complete = &complete;
|
||||
|
||||
standaloneInitialize(handler, root);
|
||||
bool tty = sys::Process::StandardOutIsDisplayed();
|
||||
|
@ -134,88 +134,6 @@ struct ProjectProcessor {
|
||||
}
|
||||
}
|
||||
entry.args = args;
|
||||
getSearchDirs(entry);
|
||||
}
|
||||
|
||||
void getSearchDirs(Project::Entry &entry) {
|
||||
#if LLVM_VERSION_MAJOR < 8
|
||||
const std::string base_name = sys::path::filename(entry.filename);
|
||||
size_t hash = std::hash<std::string>{}(entry.directory);
|
||||
bool OPT_o = false;
|
||||
for (auto &arg : entry.args) {
|
||||
bool last_o = OPT_o;
|
||||
OPT_o = false;
|
||||
if (arg[0] == '-') {
|
||||
OPT_o = arg[1] == 'o' && arg[2] == '\0';
|
||||
if (OPT_o || arg[1] == 'D' || arg[1] == 'W')
|
||||
continue;
|
||||
} else if (last_o) {
|
||||
continue;
|
||||
} else if (sys::path::filename(arg) == base_name) {
|
||||
LanguageId lang = lookupExtension(arg).first;
|
||||
if (lang != LanguageId::Unknown) {
|
||||
hash_combine(hash, (size_t)lang);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
hash_combine(hash, std::hash<std::string_view>{}(arg));
|
||||
}
|
||||
if (!command_set.insert(hash).second)
|
||||
return;
|
||||
auto args = entry.args;
|
||||
args.push_back("-fsyntax-only");
|
||||
for (const std::string &arg : g_config->clang.extraArgs)
|
||||
args.push_back(intern(arg));
|
||||
args.push_back(intern("-working-directory=" + entry.directory));
|
||||
args.push_back(intern("-resource-dir=" + g_config->clang.resourceDir));
|
||||
|
||||
// a weird C++ deduction guide heap-use-after-free causes libclang to crash.
|
||||
IgnoringDiagConsumer DiagC;
|
||||
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
|
||||
DiagnosticsEngine Diags(
|
||||
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
|
||||
&DiagC, false);
|
||||
|
||||
driver::Driver Driver(args[0], llvm::sys::getDefaultTargetTriple(), Diags);
|
||||
auto TargetAndMode =
|
||||
driver::ToolChain::getTargetAndModeFromProgramName(args[0]);
|
||||
if (!TargetAndMode.TargetPrefix.empty()) {
|
||||
const char *arr[] = {"-target", TargetAndMode.TargetPrefix.c_str()};
|
||||
args.insert(args.begin() + 1, std::begin(arr), std::end(arr));
|
||||
Driver.setTargetAndMode(TargetAndMode);
|
||||
}
|
||||
Driver.setCheckInputsExist(false);
|
||||
|
||||
std::unique_ptr<driver::Compilation> C(Driver.BuildCompilation(args));
|
||||
const driver::JobList &Jobs = C->getJobs();
|
||||
if (Jobs.size() != 1)
|
||||
return;
|
||||
const auto &CCArgs = Jobs.begin()->getArguments();
|
||||
|
||||
auto CI = std::make_unique<CompilerInvocation>();
|
||||
CompilerInvocation::CreateFromArgs(*CI, CCArgs.data(),
|
||||
CCArgs.data() + CCArgs.size(), Diags);
|
||||
CI->getFrontendOpts().DisableFree = false;
|
||||
CI->getCodeGenOpts().DisableFree = false;
|
||||
|
||||
HeaderSearchOptions &HeaderOpts = CI->getHeaderSearchOpts();
|
||||
for (auto &E : HeaderOpts.UserEntries) {
|
||||
std::string path =
|
||||
normalizePath(resolveIfRelative(entry.directory, E.Path));
|
||||
ensureEndsInSlash(path);
|
||||
switch (E.Group) {
|
||||
default:
|
||||
folder.search_dir2kind[path] |= 2;
|
||||
break;
|
||||
case frontend::Quoted:
|
||||
folder.search_dir2kind[path] |= 1;
|
||||
break;
|
||||
case frontend::Angled:
|
||||
folder.search_dir2kind[path] |= 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@ -452,7 +370,6 @@ void Project::loadDirectory(const std::string &root, Project::Folder &folder) {
|
||||
entry.args.push_back(intern(args[i]));
|
||||
}
|
||||
entry.compdb_size = entry.args.size();
|
||||
proc.getSearchDirs(entry);
|
||||
if (seen.insert(entry.filename).second)
|
||||
folder.entries.push_back(entry);
|
||||
}
|
||||
|
@ -26,39 +26,6 @@ using namespace llvm;
|
||||
#include <thread>
|
||||
namespace chrono = std::chrono;
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 8
|
||||
namespace clang::vfs {
|
||||
struct ProxyFileSystem : FileSystem {
|
||||
explicit ProxyFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
|
||||
: FS(std::move(FS)) {}
|
||||
llvm::ErrorOr<Status> status(const Twine &Path) override {
|
||||
return FS->status(Path);
|
||||
}
|
||||
llvm::ErrorOr<std::unique_ptr<File>>
|
||||
openFileForRead(const Twine &Path) override {
|
||||
return FS->openFileForRead(Path);
|
||||
}
|
||||
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
|
||||
return FS->dir_begin(Dir, EC);
|
||||
}
|
||||
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
|
||||
return FS->getCurrentWorkingDirectory();
|
||||
}
|
||||
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
|
||||
return FS->setCurrentWorkingDirectory(Path);
|
||||
}
|
||||
#if LLVM_VERSION_MAJOR == 7
|
||||
std::error_code getRealPath(const Twine &Path,
|
||||
SmallVectorImpl<char> &Output) const override {
|
||||
return FS->getRealPath(Path, Output);
|
||||
}
|
||||
#endif
|
||||
FileSystem &getUnderlyingFS() { return *FS; }
|
||||
IntrusiveRefCntPtr<FileSystem> FS;
|
||||
};
|
||||
} // namespace clang::vfs
|
||||
#endif
|
||||
|
||||
namespace ccls {
|
||||
|
||||
TextEdit toTextEdit(const clang::SourceManager &sm, const clang::LangOptions &l,
|
||||
@ -330,12 +297,7 @@ buildCompilerInstance(Session &session, std::unique_ptr<CompilerInvocation> ci,
|
||||
// Construct SourceManager with UserFilesAreVolatile: true because otherwise
|
||||
// RequiresNullTerminator: true may cause out-of-bounds read when a file is
|
||||
// mmap'ed but is saved concurrently.
|
||||
#if LLVM_VERSION_MAJOR >= 9 // rC357037
|
||||
clang->createFileManager(fs);
|
||||
#else
|
||||
clang->setVirtualFileSystem(fs);
|
||||
clang->createFileManager();
|
||||
#endif
|
||||
clang->setSourceManager(new SourceManager(clang->getDiagnostics(),
|
||||
clang->getFileManager(), true));
|
||||
auto &isec = clang->getFrontendOpts().Inputs;
|
||||
@ -353,15 +315,10 @@ bool parse(CompilerInstance &clang) {
|
||||
auto run = [&]() {
|
||||
if (!action.BeginSourceFile(clang, clang.getFrontendOpts().Inputs[0]))
|
||||
return;
|
||||
#if LLVM_VERSION_MAJOR >= 9 // rL364464
|
||||
if (llvm::Error e = action.Execute()) {
|
||||
llvm::consumeError(std::move(e));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!action.Execute())
|
||||
return;
|
||||
#endif
|
||||
action.EndSourceFile();
|
||||
ok = true;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user