mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 15:45:08 +00:00
Simplify pipeline
This commit is contained in:
parent
cf0d16fa0c
commit
a962061698
@ -189,11 +189,8 @@ file(GLOB SOURCES src/*.cc src/*.h src/serializers/*.cc src/serializers/*.h
|
|||||||
target_sources(ccls PRIVATE third_party/siphash.cc)
|
target_sources(ccls PRIVATE third_party/siphash.cc)
|
||||||
|
|
||||||
target_sources(ccls PRIVATE
|
target_sources(ccls PRIVATE
|
||||||
src/cache_manager.cc
|
|
||||||
src/clang_complete.cc
|
src/clang_complete.cc
|
||||||
src/clang_cursor.cc
|
src/clang_tu.cc
|
||||||
src/clang_indexer.cc
|
|
||||||
src/clang_translation_unit.cc
|
|
||||||
src/clang_utils.cc
|
src/clang_utils.cc
|
||||||
src/config.cc
|
src/config.cc
|
||||||
src/diagnostics_engine.cc
|
src/diagnostics_engine.cc
|
||||||
@ -202,6 +199,7 @@ target_sources(ccls PRIVATE
|
|||||||
src/fuzzy_match.cc
|
src/fuzzy_match.cc
|
||||||
src/main.cc
|
src/main.cc
|
||||||
src/include_complete.cc
|
src/include_complete.cc
|
||||||
|
src/indexer.cc
|
||||||
src/method.cc
|
src/method.cc
|
||||||
src/language.cc
|
src/language.cc
|
||||||
src/lex_utils.cc
|
src/lex_utils.cc
|
||||||
@ -212,12 +210,10 @@ target_sources(ccls PRIVATE
|
|||||||
src/pipeline.cc
|
src/pipeline.cc
|
||||||
src/platform_posix.cc
|
src/platform_posix.cc
|
||||||
src/platform_win.cc
|
src/platform_win.cc
|
||||||
src/port.cc
|
|
||||||
src/position.cc
|
src/position.cc
|
||||||
src/project.cc
|
src/project.cc
|
||||||
src/query_utils.cc
|
src/query_utils.cc
|
||||||
src/query.cc
|
src/query.cc
|
||||||
src/queue_manager.cc
|
|
||||||
src/serializer.cc
|
src/serializer.cc
|
||||||
src/test.cc
|
src/test.cc
|
||||||
src/third_party_impl.cc
|
src/third_party_impl.cc
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "indexer.h"
|
|
||||||
#include "lsp.h"
|
|
||||||
#include "platform.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
std::string GetCachePath(const std::string& source_file) {
|
|
||||||
assert(!g_config->cacheDirectory.empty());
|
|
||||||
std::string cache_file;
|
|
||||||
size_t len = g_config->projectRoot.size();
|
|
||||||
if (StartsWith(source_file, g_config->projectRoot)) {
|
|
||||||
cache_file = EscapeFileName(g_config->projectRoot) +
|
|
||||||
EscapeFileName(source_file.substr(len));
|
|
||||||
} else {
|
|
||||||
cache_file = '@' + EscapeFileName(g_config->projectRoot) +
|
|
||||||
EscapeFileName(source_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_config->cacheDirectory + cache_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AppendSerializationFormat(const std::string& base) {
|
|
||||||
switch (g_config->cacheFormat) {
|
|
||||||
case SerializeFormat::Binary:
|
|
||||||
return base + ".blob";
|
|
||||||
case SerializeFormat::Json:
|
|
||||||
return base + ".json";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manages loading caches from file paths for the indexer process.
|
|
||||||
void ICacheManager::WriteToCache(IndexFile& file) {
|
|
||||||
std::string cache_path = GetCachePath(file.path);
|
|
||||||
WriteToFile(cache_path, file.file_contents);
|
|
||||||
|
|
||||||
std::string indexed_content = Serialize(g_config->cacheFormat, file);
|
|
||||||
WriteToFile(AppendSerializationFormat(cache_path), indexed_content);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::string> ICacheManager::LoadCachedFileContents(
|
|
||||||
const std::string& path) {
|
|
||||||
return ReadContent(GetCachePath(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<IndexFile> ICacheManager::RawCacheLoad(
|
|
||||||
const std::string& path) {
|
|
||||||
std::string cache_path = GetCachePath(path);
|
|
||||||
std::optional<std::string> file_content = ReadContent(cache_path);
|
|
||||||
std::optional<std::string> serialized_indexed_content =
|
|
||||||
ReadContent(AppendSerializationFormat(cache_path));
|
|
||||||
if (!file_content || !serialized_indexed_content)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return Deserialize(g_config->cacheFormat, path, *serialized_indexed_content,
|
|
||||||
*file_content, IndexFile::kMajorVersion);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct IndexFile;
|
|
||||||
|
|
||||||
struct ICacheManager {
|
|
||||||
void WriteToCache(IndexFile& file);
|
|
||||||
|
|
||||||
std::optional<std::string> LoadCachedFileContents(const std::string& path);
|
|
||||||
|
|
||||||
template <typename Fn>
|
|
||||||
void IterateLoadedCaches(Fn fn) {
|
|
||||||
for (const auto& cache : caches_)
|
|
||||||
fn(cache.second.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<IndexFile> RawCacheLoad(const std::string& path);
|
|
||||||
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<IndexFile>> caches_;
|
|
||||||
};
|
|
@ -21,14 +21,8 @@ unsigned Flags() {
|
|||||||
CXTranslationUnit_CacheCompletionResults |
|
CXTranslationUnit_CacheCompletionResults |
|
||||||
CXTranslationUnit_PrecompiledPreamble |
|
CXTranslationUnit_PrecompiledPreamble |
|
||||||
CXTranslationUnit_IncludeBriefCommentsInCodeCompletion |
|
CXTranslationUnit_IncludeBriefCommentsInCodeCompletion |
|
||||||
CXTranslationUnit_DetailedPreprocessingRecord
|
CXTranslationUnit_DetailedPreprocessingRecord |
|
||||||
#if !defined(_WIN32)
|
CXTranslationUnit_CreatePreambleOnFirstParse;
|
||||||
// For whatever reason, CreatePreambleOnFirstParse causes clang to
|
|
||||||
// become very crashy on windows.
|
|
||||||
// TODO: do more investigation, submit fixes to clang.
|
|
||||||
| CXTranslationUnit_CreatePreambleOnFirstParse
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StripFileType(const std::string& path) {
|
std::string StripFileType(const std::string& path) {
|
||||||
@ -57,23 +51,6 @@ unsigned GetCompletionPriority(const CXCompletionString& str,
|
|||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
bool IsCallKind(CXCursorKind kind) {
|
|
||||||
switch (kind) {
|
|
||||||
case CXCursor_ObjCInstanceMethodDecl:
|
|
||||||
case CXCursor_CXXMethod:
|
|
||||||
case CXCursor_FunctionTemplate:
|
|
||||||
case CXCursor_FunctionDecl:
|
|
||||||
case CXCursor_Constructor:
|
|
||||||
case CXCursor_Destructor:
|
|
||||||
case CXCursor_ConversionFunction:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) {
|
lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) {
|
||||||
switch (cursor_kind) {
|
switch (cursor_kind) {
|
||||||
case CXCursor_UnexposedDecl:
|
case CXCursor_UnexposedDecl:
|
||||||
@ -383,8 +360,8 @@ void TryEnsureDocumentParsed(ClangCompleteManager* manager,
|
|||||||
std::vector<std::string> args = session->file.args;
|
std::vector<std::string> args = session->file.args;
|
||||||
|
|
||||||
// -fspell-checking enables FixIts for, ie, misspelled types.
|
// -fspell-checking enables FixIts for, ie, misspelled types.
|
||||||
if (!AnyStartsWith(args, "-fno-spell-checking") &&
|
if (!std::count(args.begin(), args.end(), "-fno-spell-checking") &&
|
||||||
!AnyStartsWith(args, "-fspell-checking")) {
|
!std::count(args.begin(), args.end(), "-fspell-checking")) {
|
||||||
args.push_back("-fspell-checking");
|
args.push_back("-fspell-checking");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "clang_cursor.h"
|
#include "clang_tu.h"
|
||||||
#include "clang_translation_unit.h"
|
|
||||||
#include "lru_cache.h"
|
#include "lru_cache.h"
|
||||||
#include "lsp_completion.h"
|
#include "lsp_completion.h"
|
||||||
#include "lsp_diagnostic.h"
|
#include "lsp_diagnostic.h"
|
||||||
|
@ -1,155 +0,0 @@
|
|||||||
#include "clang_translation_unit.h"
|
|
||||||
|
|
||||||
#include "clang_utils.h"
|
|
||||||
#include "log.hh"
|
|
||||||
#include "platform.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void EmitDiagnostics(std::string path,
|
|
||||||
std::vector<const char*> args,
|
|
||||||
CXTranslationUnit tu) {
|
|
||||||
std::string output = "Fatal errors while trying to parse " + path + "\n";
|
|
||||||
output +=
|
|
||||||
"Args: " +
|
|
||||||
StringJoinMap(args, [](const char* arg) { return std::string(arg); }) +
|
|
||||||
"\n";
|
|
||||||
|
|
||||||
size_t num_diagnostics = clang_getNumDiagnostics(tu);
|
|
||||||
for (unsigned i = 0; i < num_diagnostics; ++i) {
|
|
||||||
output += " - ";
|
|
||||||
|
|
||||||
CXDiagnostic diagnostic = clang_getDiagnostic(tu, i);
|
|
||||||
|
|
||||||
// Location.
|
|
||||||
CXFile file;
|
|
||||||
unsigned int line, column;
|
|
||||||
clang_getSpellingLocation(clang_getDiagnosticLocation(diagnostic), &file,
|
|
||||||
&line, &column, nullptr);
|
|
||||||
std::string path = FileName(file);
|
|
||||||
output += path + ":" + std::to_string(line - 1) + ":" +
|
|
||||||
std::to_string(column) + " ";
|
|
||||||
|
|
||||||
// Severity
|
|
||||||
switch (clang_getDiagnosticSeverity(diagnostic)) {
|
|
||||||
case CXDiagnostic_Ignored:
|
|
||||||
case CXDiagnostic_Note:
|
|
||||||
output += "[info]";
|
|
||||||
break;
|
|
||||||
case CXDiagnostic_Warning:
|
|
||||||
output += "[warning]";
|
|
||||||
break;
|
|
||||||
case CXDiagnostic_Error:
|
|
||||||
output += "[error]";
|
|
||||||
break;
|
|
||||||
case CXDiagnostic_Fatal:
|
|
||||||
output += "[fatal]";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Content.
|
|
||||||
output += " " + ToString(clang_getDiagnosticSpelling(diagnostic));
|
|
||||||
|
|
||||||
clang_disposeDiagnostic(diagnostic);
|
|
||||||
|
|
||||||
output += "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_S(WARNING) << output;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// static
|
|
||||||
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
|
|
||||||
ClangIndex* index,
|
|
||||||
const std::string& filepath,
|
|
||||||
const std::vector<std::string>& arguments,
|
|
||||||
std::vector<CXUnsavedFile>& unsaved_files,
|
|
||||||
unsigned flags) {
|
|
||||||
std::vector<const char*> args;
|
|
||||||
for (auto& arg : arguments)
|
|
||||||
args.push_back(arg.c_str());
|
|
||||||
|
|
||||||
CXTranslationUnit cx_tu;
|
|
||||||
CXErrorCode error_code;
|
|
||||||
{
|
|
||||||
error_code = clang_parseTranslationUnit2FullArgv(
|
|
||||||
index->cx_index, nullptr, args.data(), (int)args.size(),
|
|
||||||
unsaved_files.data(), (unsigned)unsaved_files.size(), flags, &cx_tu);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error_code != CXError_Success && cx_tu)
|
|
||||||
EmitDiagnostics(filepath, args, cx_tu);
|
|
||||||
|
|
||||||
// We sometimes dump the command to logs and ask the user to run it. Include
|
|
||||||
// -fsyntax-only so they don't do a full compile.
|
|
||||||
auto make_msg = [&]() {
|
|
||||||
return "Please try running the following, identify which flag causes the "
|
|
||||||
"issue, and report a bug. ccls will then filter the flag for you "
|
|
||||||
" automatically:\n " +
|
|
||||||
StringJoin(args, " ") + " -fsyntax-only";
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (error_code) {
|
|
||||||
case CXError_Success:
|
|
||||||
return std::make_unique<ClangTranslationUnit>(cx_tu);
|
|
||||||
case CXError_Failure:
|
|
||||||
LOG_S(ERROR) << "libclang generic failure for " << filepath << ". "
|
|
||||||
<< make_msg();
|
|
||||||
return nullptr;
|
|
||||||
case CXError_Crashed:
|
|
||||||
LOG_S(ERROR) << "libclang crashed for " << filepath << ". " << make_msg();
|
|
||||||
return nullptr;
|
|
||||||
case CXError_InvalidArguments:
|
|
||||||
LOG_S(ERROR) << "libclang had invalid arguments for " << filepath << ". "
|
|
||||||
<< make_msg();
|
|
||||||
return nullptr;
|
|
||||||
case CXError_ASTReadError:
|
|
||||||
LOG_S(ERROR) << "libclang had ast read error for " << filepath << ". "
|
|
||||||
<< make_msg();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Reparse(
|
|
||||||
std::unique_ptr<ClangTranslationUnit> tu,
|
|
||||||
std::vector<CXUnsavedFile>& unsaved) {
|
|
||||||
int error_code;
|
|
||||||
{
|
|
||||||
error_code = clang_reparseTranslationUnit(
|
|
||||||
tu->cx_tu, (unsigned)unsaved.size(), unsaved.data(),
|
|
||||||
clang_defaultReparseOptions(tu->cx_tu));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error_code != CXError_Success && tu->cx_tu)
|
|
||||||
EmitDiagnostics("<unknown>", {}, tu->cx_tu);
|
|
||||||
|
|
||||||
switch (error_code) {
|
|
||||||
case CXError_Success:
|
|
||||||
return tu;
|
|
||||||
case CXError_Failure:
|
|
||||||
LOG_S(ERROR) << "libclang reparse generic failure";
|
|
||||||
return nullptr;
|
|
||||||
case CXError_Crashed:
|
|
||||||
LOG_S(ERROR) << "libclang reparse crashed";
|
|
||||||
return nullptr;
|
|
||||||
case CXError_InvalidArguments:
|
|
||||||
LOG_S(ERROR) << "libclang reparse had invalid arguments";
|
|
||||||
return nullptr;
|
|
||||||
case CXError_ASTReadError:
|
|
||||||
LOG_S(ERROR) << "libclang reparse had ast read error";
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClangTranslationUnit::ClangTranslationUnit(CXTranslationUnit tu) : cx_tu(tu) {}
|
|
||||||
|
|
||||||
ClangTranslationUnit::~ClangTranslationUnit() {
|
|
||||||
clang_disposeTranslationUnit(cx_tu);
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "clang_cursor.h"
|
|
||||||
|
|
||||||
#include <clang-c/Index.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// RAII wrapper around CXTranslationUnit which also makes it much more
|
|
||||||
// challenging to use a CXTranslationUnit instance that is not correctly
|
|
||||||
// initialized.
|
|
||||||
struct ClangTranslationUnit {
|
|
||||||
static std::unique_ptr<ClangTranslationUnit> Create(
|
|
||||||
ClangIndex* index,
|
|
||||||
const std::string& filepath,
|
|
||||||
const std::vector<std::string>& arguments,
|
|
||||||
std::vector<CXUnsavedFile>& unsaved_files,
|
|
||||||
unsigned flags);
|
|
||||||
|
|
||||||
static std::unique_ptr<ClangTranslationUnit> Reparse(
|
|
||||||
std::unique_ptr<ClangTranslationUnit> tu,
|
|
||||||
std::vector<CXUnsavedFile>& unsaved);
|
|
||||||
|
|
||||||
explicit ClangTranslationUnit(CXTranslationUnit tu);
|
|
||||||
~ClangTranslationUnit();
|
|
||||||
|
|
||||||
CXTranslationUnit cx_tu;
|
|
||||||
};
|
|
@ -1,12 +1,70 @@
|
|||||||
#include "clang_cursor.h"
|
#include "clang_tu.h"
|
||||||
|
|
||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
|
#include "log.hh"
|
||||||
|
#include "platform.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void EmitDiagnostics(std::string path,
|
||||||
|
std::vector<const char*> args,
|
||||||
|
CXTranslationUnit tu) {
|
||||||
|
std::string output = "Fatal errors while trying to parse " + path + "\n";
|
||||||
|
output +=
|
||||||
|
"Args: " +
|
||||||
|
StringJoinMap(args, [](const char* arg) { return std::string(arg); }) +
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
size_t num_diagnostics = clang_getNumDiagnostics(tu);
|
||||||
|
for (unsigned i = 0; i < num_diagnostics; ++i) {
|
||||||
|
output += " - ";
|
||||||
|
|
||||||
|
CXDiagnostic diagnostic = clang_getDiagnostic(tu, i);
|
||||||
|
|
||||||
|
// Location.
|
||||||
|
CXFile file;
|
||||||
|
unsigned int line, column;
|
||||||
|
clang_getSpellingLocation(clang_getDiagnosticLocation(diagnostic), &file,
|
||||||
|
&line, &column, nullptr);
|
||||||
|
std::string path = FileName(file);
|
||||||
|
output += path + ":" + std::to_string(line - 1) + ":" +
|
||||||
|
std::to_string(column) + " ";
|
||||||
|
|
||||||
|
// Severity
|
||||||
|
switch (clang_getDiagnosticSeverity(diagnostic)) {
|
||||||
|
case CXDiagnostic_Ignored:
|
||||||
|
case CXDiagnostic_Note:
|
||||||
|
output += "[info]";
|
||||||
|
break;
|
||||||
|
case CXDiagnostic_Warning:
|
||||||
|
output += "[warning]";
|
||||||
|
break;
|
||||||
|
case CXDiagnostic_Error:
|
||||||
|
output += "[error]";
|
||||||
|
break;
|
||||||
|
case CXDiagnostic_Fatal:
|
||||||
|
output += "[fatal]";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content.
|
||||||
|
output += " " + ToString(clang_getDiagnosticSpelling(diagnostic));
|
||||||
|
|
||||||
|
clang_disposeDiagnostic(diagnostic);
|
||||||
|
|
||||||
|
output += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_S(WARNING) << output;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
Range ResolveCXSourceRange(const CXSourceRange& range, CXFile* cx_file) {
|
Range ResolveCXSourceRange(const CXSourceRange& range, CXFile* cx_file) {
|
||||||
CXSourceLocation start = clang_getRangeStart(range);
|
CXSourceLocation start = clang_getRangeStart(range);
|
||||||
CXSourceLocation end = clang_getRangeEnd(range);
|
CXSourceLocation end = clang_getRangeEnd(range);
|
||||||
@ -284,3 +342,97 @@ ClangIndex::ClangIndex(int exclude_declarations_from_pch,
|
|||||||
ClangIndex::~ClangIndex() {
|
ClangIndex::~ClangIndex() {
|
||||||
clang_disposeIndex(cx_index);
|
clang_disposeIndex(cx_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
|
||||||
|
ClangIndex* index,
|
||||||
|
const std::string& filepath,
|
||||||
|
const std::vector<std::string>& arguments,
|
||||||
|
std::vector<CXUnsavedFile>& unsaved_files,
|
||||||
|
unsigned flags) {
|
||||||
|
std::vector<const char*> args;
|
||||||
|
for (auto& arg : arguments)
|
||||||
|
args.push_back(arg.c_str());
|
||||||
|
|
||||||
|
CXTranslationUnit cx_tu;
|
||||||
|
CXErrorCode error_code;
|
||||||
|
{
|
||||||
|
error_code = clang_parseTranslationUnit2FullArgv(
|
||||||
|
index->cx_index, nullptr, args.data(), (int)args.size(),
|
||||||
|
unsaved_files.data(), (unsigned)unsaved_files.size(), flags, &cx_tu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error_code != CXError_Success && cx_tu)
|
||||||
|
EmitDiagnostics(filepath, args, cx_tu);
|
||||||
|
|
||||||
|
// We sometimes dump the command to logs and ask the user to run it. Include
|
||||||
|
// -fsyntax-only so they don't do a full compile.
|
||||||
|
auto make_msg = [&]() {
|
||||||
|
return "Please try running the following, identify which flag causes the "
|
||||||
|
"issue, and report a bug. ccls will then filter the flag for you "
|
||||||
|
" automatically:\n " +
|
||||||
|
StringJoin(args, " ") + " -fsyntax-only";
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (error_code) {
|
||||||
|
case CXError_Success:
|
||||||
|
return std::make_unique<ClangTranslationUnit>(cx_tu);
|
||||||
|
case CXError_Failure:
|
||||||
|
LOG_S(ERROR) << "libclang generic failure for " << filepath << ". "
|
||||||
|
<< make_msg();
|
||||||
|
return nullptr;
|
||||||
|
case CXError_Crashed:
|
||||||
|
LOG_S(ERROR) << "libclang crashed for " << filepath << ". " << make_msg();
|
||||||
|
return nullptr;
|
||||||
|
case CXError_InvalidArguments:
|
||||||
|
LOG_S(ERROR) << "libclang had invalid arguments for " << filepath << ". "
|
||||||
|
<< make_msg();
|
||||||
|
return nullptr;
|
||||||
|
case CXError_ASTReadError:
|
||||||
|
LOG_S(ERROR) << "libclang had ast read error for " << filepath << ". "
|
||||||
|
<< make_msg();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Reparse(
|
||||||
|
std::unique_ptr<ClangTranslationUnit> tu,
|
||||||
|
std::vector<CXUnsavedFile>& unsaved) {
|
||||||
|
int error_code;
|
||||||
|
{
|
||||||
|
error_code = clang_reparseTranslationUnit(
|
||||||
|
tu->cx_tu, (unsigned)unsaved.size(), unsaved.data(),
|
||||||
|
clang_defaultReparseOptions(tu->cx_tu));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error_code != CXError_Success && tu->cx_tu)
|
||||||
|
EmitDiagnostics("<unknown>", {}, tu->cx_tu);
|
||||||
|
|
||||||
|
switch (error_code) {
|
||||||
|
case CXError_Success:
|
||||||
|
return tu;
|
||||||
|
case CXError_Failure:
|
||||||
|
LOG_S(ERROR) << "libclang reparse generic failure";
|
||||||
|
return nullptr;
|
||||||
|
case CXError_Crashed:
|
||||||
|
LOG_S(ERROR) << "libclang reparse crashed";
|
||||||
|
return nullptr;
|
||||||
|
case CXError_InvalidArguments:
|
||||||
|
LOG_S(ERROR) << "libclang reparse had invalid arguments";
|
||||||
|
return nullptr;
|
||||||
|
case CXError_ASTReadError:
|
||||||
|
LOG_S(ERROR) << "libclang reparse had ast read error";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangTranslationUnit::ClangTranslationUnit(CXTranslationUnit tu) : cx_tu(tu) {}
|
||||||
|
|
||||||
|
ClangTranslationUnit::~ClangTranslationUnit() {
|
||||||
|
clang_disposeTranslationUnit(cx_tu);
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nt_string.h"
|
#include "nt_string.h"
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
|
|
||||||
#include <clang-c/Index.h>
|
#include <clang-c/Index.h>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include <array>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -119,3 +117,24 @@ class ClangIndex {
|
|||||||
~ClangIndex();
|
~ClangIndex();
|
||||||
CXIndex cx_index;
|
CXIndex cx_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// RAII wrapper around CXTranslationUnit which also makes it much more
|
||||||
|
// challenging to use a CXTranslationUnit instance that is not correctly
|
||||||
|
// initialized.
|
||||||
|
struct ClangTranslationUnit {
|
||||||
|
static std::unique_ptr<ClangTranslationUnit> Create(
|
||||||
|
ClangIndex* index,
|
||||||
|
const std::string& filepath,
|
||||||
|
const std::vector<std::string>& arguments,
|
||||||
|
std::vector<CXUnsavedFile>& unsaved_files,
|
||||||
|
unsigned flags);
|
||||||
|
|
||||||
|
static std::unique_ptr<ClangTranslationUnit> Reparse(
|
||||||
|
std::unique_ptr<ClangTranslationUnit> tu,
|
||||||
|
std::vector<CXUnsavedFile>& unsaved);
|
||||||
|
|
||||||
|
explicit ClangTranslationUnit(CXTranslationUnit tu);
|
||||||
|
~ClangTranslationUnit();
|
||||||
|
|
||||||
|
CXTranslationUnit cx_tu;
|
||||||
|
};
|
@ -1,6 +1,7 @@
|
|||||||
#include "diagnostics_engine.h"
|
#include "diagnostics_engine.h"
|
||||||
|
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@ -30,6 +31,6 @@ void DiagnosticsEngine::Publish(WorkingFiles* working_files,
|
|||||||
Out_TextDocumentPublishDiagnostics out;
|
Out_TextDocumentPublishDiagnostics out;
|
||||||
out.params.uri = lsDocumentUri::FromPath(path);
|
out.params.uri = lsDocumentUri::FromPath(path);
|
||||||
out.params.diagnostics = diagnostics;
|
out.params.diagnostics = diagnostics;
|
||||||
QueueManager::WriteStdout(kMethodType_TextDocumentPublishDiagnostics, out);
|
pipeline::WriteStdout(kMethodType_TextDocumentPublishDiagnostics, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ void IncludeComplete::Rescan() {
|
|||||||
|
|
||||||
is_scanning = true;
|
is_scanning = true;
|
||||||
std::thread([this]() {
|
std::thread([this]() {
|
||||||
set_thread_name("scan_includes");
|
set_thread_name("include");
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
|
||||||
for (const std::string& dir : project_->quote_include_directories)
|
for (const std::string& dir : project_->quote_include_directories)
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "indexer.h"
|
#include "indexer.h"
|
||||||
|
|
||||||
#include "clang_cursor.h"
|
|
||||||
#include "clang_utils.h"
|
|
||||||
#include "log.hh"
|
#include "log.hh"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "clang_cursor.h"
|
#include "clang_tu.h"
|
||||||
#include "clang_translation_unit.h"
|
|
||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
#include "file_consumer.h"
|
#include "file_consumer.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
|
10
src/main.cc
10
src/main.cc
@ -5,6 +5,7 @@
|
|||||||
#include "serializers/json.h"
|
#include "serializers/json.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <llvm/Support/CommandLine.h>
|
#include <llvm/Support/CommandLine.h>
|
||||||
#include <llvm/Support/Process.h>
|
#include <llvm/Support/Process.h>
|
||||||
@ -56,8 +57,7 @@ int main(int argc, char** argv) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiQueueWaiter querydb_waiter, indexer_waiter, stdout_waiter;
|
pipeline::Init();
|
||||||
QueueManager::Init(&querydb_waiter, &indexer_waiter, &stdout_waiter);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// We need to write to stdout in binary mode because in Windows, writing
|
// We need to write to stdout in binary mode because in Windows, writing
|
||||||
@ -132,11 +132,11 @@ int main(int argc, char** argv) {
|
|||||||
std::unordered_map<MethodType, Timer> request_times;
|
std::unordered_map<MethodType, Timer> request_times;
|
||||||
|
|
||||||
// The thread that reads from stdin and dispatchs commands to the main thread.
|
// The thread that reads from stdin and dispatchs commands to the main thread.
|
||||||
LaunchStdinLoop(&request_times);
|
pipeline::LaunchStdin(&request_times);
|
||||||
// The thread that writes responses from the main thread to stdout.
|
// The thread that writes responses from the main thread to stdout.
|
||||||
LaunchStdoutThread(&request_times, &stdout_waiter);
|
pipeline::LaunchStdout(&request_times);
|
||||||
// Main thread which also spawns indexer threads upon the "initialize" request.
|
// Main thread which also spawns indexer threads upon the "initialize" request.
|
||||||
MainLoop(&querydb_waiter, &indexer_waiter);
|
pipeline::MainLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "match.h"
|
#include "match.h"
|
||||||
|
|
||||||
#include "lsp.h"
|
#include "lsp.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <doctest/doctest.h>
|
#include <doctest/doctest.h>
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ std::optional<Matcher> Matcher::Create(const std::string& search) {
|
|||||||
out.params.type = lsMessageType::Error;
|
out.params.type = lsMessageType::Error;
|
||||||
out.params.message = "ccls: Parsing EMCAScript regex \"" + search +
|
out.params.message = "ccls: Parsing EMCAScript regex \"" + search +
|
||||||
"\" failed; " + e.what();
|
"\" failed; " + e.what();
|
||||||
QueueManager::WriteStdout(kMethodType_Unknown, out);
|
pipeline::WriteStdout(kMethodType_Unknown, out);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
#include "log.hh"
|
#include "log.hh"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -167,7 +168,7 @@ bool FindFileOrFail(QueryDatabase* db,
|
|||||||
out.error.code = lsErrorCodes::InternalError;
|
out.error.code = lsErrorCodes::InternalError;
|
||||||
out.error.message = "Unable to find file " + absolute_path;
|
out.error.message = "Unable to find file " + absolute_path;
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(kMethodType_Unknown, out);
|
pipeline::WriteStdout(kMethodType_Unknown, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -182,7 +183,7 @@ void EmitInactiveLines(WorkingFile* working_file,
|
|||||||
if (ls_skipped)
|
if (ls_skipped)
|
||||||
out.params.inactiveRegions.push_back(*ls_skipped);
|
out.params.inactiveRegions.push_back(*ls_skipped);
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(kMethodType_CclsPublishInactiveRegions, out);
|
pipeline::WriteStdout(kMethodType_CclsPublishInactiveRegions, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSemanticHighlighting(QueryDatabase* db,
|
void EmitSemanticHighlighting(QueryDatabase* db,
|
||||||
@ -343,5 +344,5 @@ void EmitSemanticHighlighting(QueryDatabase* db,
|
|||||||
for (auto& entry : grouped_symbols)
|
for (auto& entry : grouped_symbols)
|
||||||
if (entry.second.ranges.size())
|
if (entry.second.ranges.size())
|
||||||
out.params.symbols.push_back(entry.second);
|
out.params.symbols.push_back(entry.second);
|
||||||
QueueManager::WriteStdout(kMethodType_CclsPublishSemanticHighlighting, out);
|
pipeline::WriteStdout(kMethodType_CclsPublishSemanticHighlighting, out);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ struct Handler_CclsBase : BaseMessageHandler<In_CclsBase> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsBase);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsBase);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -225,7 +227,7 @@ struct Handler_CclsCallHierarchy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsCallHierarchy);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsCallHierarchy);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "$ccls/callers";
|
MethodType kMethodType = "$ccls/callers";
|
||||||
@ -39,7 +40,7 @@ struct Handler_CclsCallers : BaseMessageHandler<In_CclsCallers> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsCallers);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsCallers);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
MAKE_REFLECT_STRUCT(QueryFile::Def,
|
MAKE_REFLECT_STRUCT(QueryFile::Def,
|
||||||
path,
|
path,
|
||||||
@ -49,7 +50,7 @@ struct Handler_CclsFileInfo : BaseMessageHandler<In_CclsFileInfo> {
|
|||||||
out.result.language = file->def->language;
|
out.result.language = file->def->language;
|
||||||
out.result.includes = file->def->includes;
|
out.result.includes = file->def->includes;
|
||||||
out.result.inactive_regions = file->def->inactive_regions;
|
out.result.inactive_regions = file->def->inactive_regions;
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsFileInfo);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsFileInfo);
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "pipeline.hh"
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@ -79,7 +78,7 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler<In_CclsFreshenIndex> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send index requests for every file.
|
// Send index requests for every file.
|
||||||
project->Index(QueueManager::instance(), working_files, lsRequestId());
|
project->Index(working_files, lsRequestId());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsFreshenIndex);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsFreshenIndex);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -95,7 +96,7 @@ bool ExpandHelper(MessageHandler* m,
|
|||||||
if (derived) {
|
if (derived) {
|
||||||
if (levels > 0) {
|
if (levels > 0) {
|
||||||
for (auto usr : entity.derived) {
|
for (auto usr : entity.derived) {
|
||||||
if (seen.insert(usr).second)
|
if (!seen.insert(usr).second)
|
||||||
continue;
|
continue;
|
||||||
Out_CclsInheritanceHierarchy::Entry entry1;
|
Out_CclsInheritanceHierarchy::Entry entry1;
|
||||||
entry1.id = std::to_string(usr);
|
entry1.id = std::to_string(usr);
|
||||||
@ -110,7 +111,7 @@ bool ExpandHelper(MessageHandler* m,
|
|||||||
} else {
|
} else {
|
||||||
if (levels > 0) {
|
if (levels > 0) {
|
||||||
for (auto usr : def->bases) {
|
for (auto usr : def->bases) {
|
||||||
if (seen.insert(usr).second)
|
if (!seen.insert(usr).second)
|
||||||
continue;
|
continue;
|
||||||
Out_CclsInheritanceHierarchy::Entry entry1;
|
Out_CclsInheritanceHierarchy::Entry entry1;
|
||||||
entry1.id = std::to_string(usr);
|
entry1.id = std::to_string(usr);
|
||||||
@ -180,17 +181,15 @@ struct Handler_CclsInheritanceHierarchy
|
|||||||
WorkingFile* wfile =
|
WorkingFile* wfile =
|
||||||
working_files->GetFileByFilename(file->def->path);
|
working_files->GetFileByFilename(file->def->path);
|
||||||
|
|
||||||
for (SymbolRef sym :
|
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, params.position))
|
||||||
FindSymbolsAtLocation(wfile, file, params.position)) {
|
|
||||||
if (sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) {
|
if (sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) {
|
||||||
out.result = BuildInitial(sym, params.derived, params.qualified,
|
out.result = BuildInitial(sym, params.derived, params.qualified,
|
||||||
params.levels);
|
params.levels);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsInheritanceHierarchy);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsInheritanceHierarchy);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -264,7 +265,7 @@ struct Handler_CclsMemberHierarchy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsMemberHierarchy);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsMemberHierarchy);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -126,7 +127,7 @@ struct Handler_CclsRandom : BaseMessageHandler<In_CclsRandom> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsRandom);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsRandom);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "$ccls/vars";
|
MethodType kMethodType = "$ccls/vars";
|
||||||
@ -48,7 +49,7 @@ struct Handler_CclsVars : BaseMessageHandler<In_CclsVars> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_CclsVars);
|
REGISTER_MESSAGE_HANDLER(Handler_CclsVars);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
#include "diagnostics_engine.h"
|
#include "diagnostics_engine.h"
|
||||||
#include "filesystem.hh"
|
#include "filesystem.hh"
|
||||||
#include "include_complete.h"
|
#include "include_complete.h"
|
||||||
@ -7,10 +6,10 @@
|
|||||||
#include "pipeline.hh"
|
#include "pipeline.hh"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "queue_manager.h"
|
|
||||||
#include "serializers/json.h"
|
#include "serializers/json.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <llvm/ADT/Twine.h>
|
#include <llvm/ADT/Twine.h>
|
||||||
#include <llvm/Support/Threading.h>
|
#include <llvm/Support/Threading.h>
|
||||||
@ -482,7 +481,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
Out_InitializeResponse out;
|
Out_InitializeResponse out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
|
|
||||||
// Set project root.
|
// Set project root.
|
||||||
EnsureEndsInSlash(project_path);
|
EnsureEndsInSlash(project_path);
|
||||||
@ -515,7 +514,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
g_thread_id = i + 1;
|
g_thread_id = i + 1;
|
||||||
std::string name = "indexer" + std::to_string(i);
|
std::string name = "indexer" + std::to_string(i);
|
||||||
set_thread_name(name.c_str());
|
set_thread_name(name.c_str());
|
||||||
Indexer_Main(diag_engine, vfs, project, working_files, waiter);
|
pipeline::Indexer_Main(diag_engine, vfs, project, working_files);
|
||||||
}).detach();
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +523,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
include_complete->Rescan();
|
include_complete->Rescan();
|
||||||
|
|
||||||
time.Reset();
|
time.Reset();
|
||||||
project->Index(QueueManager::instance(), working_files, request->id);
|
project->Index(working_files, request->id);
|
||||||
// We need to support multiple concurrent index processes.
|
// We need to support multiple concurrent index processes.
|
||||||
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "shutdown";
|
MethodType kMethodType = "shutdown";
|
||||||
@ -21,7 +22,7 @@ struct Handler_Shutdown : BaseMessageHandler<In_Shutdown> {
|
|||||||
void Run(In_Shutdown* request) override {
|
void Run(In_Shutdown* request) override {
|
||||||
Out_Shutdown out;
|
Out_Shutdown out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_Shutdown);
|
REGISTER_MESSAGE_HANDLER(Handler_Shutdown);
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#include "lsp_code_action.h"
|
#include "lsp_code_action.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/codeLens";
|
MethodType kMethodType = "textDocument/codeLens";
|
||||||
@ -225,7 +226,7 @@ struct Handler_TextDocumentCodeLens
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentCodeLens);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentCodeLens);
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
#include "fuzzy_match.h"
|
#include "fuzzy_match.h"
|
||||||
#include "include_complete.h"
|
#include "include_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include "lex_utils.h"
|
#include "lex_utils.h"
|
||||||
|
|
||||||
@ -270,7 +271,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
|||||||
auto write_empty_result = [request]() {
|
auto write_empty_result = [request]() {
|
||||||
Out_TextDocumentComplete out;
|
Out_TextDocumentComplete out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string path = request->params.textDocument.uri.GetPath();
|
std::string path = request->params.textDocument.uri.GetPath();
|
||||||
@ -377,7 +378,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
|||||||
item.textEdit->range.end.character = (int)buffer_line.size();
|
item.textEdit->range.end.character = (int)buffer_line.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
} else {
|
} else {
|
||||||
ClangCompleteManager::OnComplete callback = std::bind(
|
ClangCompleteManager::OnComplete callback = std::bind(
|
||||||
[this, request, is_global_completion, existing_completion,
|
[this, request, is_global_completion, existing_completion,
|
||||||
@ -389,7 +390,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
|||||||
|
|
||||||
// Emit completion results.
|
// Emit completion results.
|
||||||
FilterAndSortCompletionResponse(&out, existing_completion, has_open_paren);
|
FilterAndSortCompletionResponse(&out, existing_completion, has_open_paren);
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
|
|
||||||
// Cache completion results.
|
// Cache completion results.
|
||||||
if (!is_cached_result) {
|
if (!is_cached_result) {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "lex_utils.h"
|
#include "lex_utils.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -173,7 +174,7 @@ struct Handler_TextDocumentDefinition
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDefinition);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDefinition);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/didChange";
|
MethodType kMethodType = "textDocument/didChange";
|
||||||
@ -25,9 +25,7 @@ struct Handler_TextDocumentDidChange
|
|||||||
working_files->OnChange(request->params);
|
working_files->OnChange(request->params);
|
||||||
if (g_config->index.onDidChange) {
|
if (g_config->index.onDidChange) {
|
||||||
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
||||||
QueueManager::instance()->index_request.PushBack(
|
pipeline::Index(entry.filename, entry.args, true);
|
||||||
Index_Request(entry.filename, entry.args, true /*is_interactive*/),
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
clang_complete->NotifyEdit(path);
|
clang_complete->NotifyEdit(path);
|
||||||
clang_complete->DiagnosticsUpdate(
|
clang_complete->DiagnosticsUpdate(
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/didClose";
|
MethodType kMethodType = "textDocument/didClose";
|
||||||
@ -27,7 +28,7 @@ struct Handler_TextDocumentDidClose
|
|||||||
// Clear any diagnostics for the file.
|
// Clear any diagnostics for the file.
|
||||||
Out_TextDocumentPublishDiagnostics out;
|
Out_TextDocumentPublishDiagnostics out;
|
||||||
out.params.uri = request->params.textDocument.uri;
|
out.params.uri = request->params.textDocument.uri;
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
|
|
||||||
// Remove internal state.
|
// Remove internal state.
|
||||||
working_files->OnClose(request->params.textDocument);
|
working_files->OnClose(request->params.textDocument);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "include_complete.h"
|
#include "include_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
|
||||||
@ -38,11 +38,9 @@ struct Handler_TextDocumentDidOpen
|
|||||||
const auto& params = request->params;
|
const auto& params = request->params;
|
||||||
std::string path = params.textDocument.uri.GetPath();
|
std::string path = params.textDocument.uri.GetPath();
|
||||||
|
|
||||||
ICacheManager cache;
|
|
||||||
WorkingFile* working_file = working_files->OnOpen(params.textDocument);
|
WorkingFile* working_file = working_files->OnOpen(params.textDocument);
|
||||||
std::optional<std::string> cached_file_contents =
|
if (std::optional<std::string> cached_file_contents =
|
||||||
cache.LoadCachedFileContents(path);
|
pipeline::LoadCachedFileContents(path))
|
||||||
if (cached_file_contents)
|
|
||||||
working_file->SetIndexContent(*cached_file_contents);
|
working_file->SetIndexContent(*cached_file_contents);
|
||||||
|
|
||||||
QueryFile* file = nullptr;
|
QueryFile* file = nullptr;
|
||||||
@ -60,11 +58,8 @@ struct Handler_TextDocumentDidOpen
|
|||||||
// Submit new index request if it is not a header file.
|
// Submit new index request if it is not a header file.
|
||||||
if (SourceFileLanguage(path) != LanguageId::Unknown) {
|
if (SourceFileLanguage(path) != LanguageId::Unknown) {
|
||||||
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
||||||
QueueManager::instance()->index_request.PushBack(
|
pipeline::Index(entry.filename,
|
||||||
Index_Request(entry.filename,
|
params.args.size() ? params.args : entry.args, true);
|
||||||
params.args.size() ? params.args : entry.args,
|
|
||||||
true /*is_interactive*/),
|
|
||||||
true /* priority */);
|
|
||||||
|
|
||||||
clang_complete->FlushSession(entry.filename);
|
clang_complete->FlushSession(entry.filename);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/didSave";
|
MethodType kMethodType = "textDocument/didSave";
|
||||||
@ -29,7 +29,8 @@ struct Handler_TextDocumentDidSave
|
|||||||
MethodType GetMethodType() const override { return kMethodType; }
|
MethodType GetMethodType() const override { return kMethodType; }
|
||||||
|
|
||||||
void Run(In_TextDocumentDidSave* request) override {
|
void Run(In_TextDocumentDidSave* request) override {
|
||||||
std::string path = request->params.textDocument.uri.GetPath();
|
const auto& params = request->params;
|
||||||
|
std::string path = params.textDocument.uri.GetPath();
|
||||||
|
|
||||||
// Send out an index request, and copy the current buffer state so we
|
// Send out an index request, and copy the current buffer state so we
|
||||||
// can update the cached index contents when the index is done.
|
// can update the cached index contents when the index is done.
|
||||||
@ -47,9 +48,7 @@ struct Handler_TextDocumentDidSave
|
|||||||
// TODO: send as priority request
|
// TODO: send as priority request
|
||||||
if (!g_config->index.onDidChange) {
|
if (!g_config->index.onDidChange) {
|
||||||
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
||||||
QueueManager::instance()->index_request.PushBack(
|
pipeline::Index(entry.filename, entry.args, true);
|
||||||
Index_Request(entry.filename, entry.args, true /*is_interactive*/),
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clang_complete->NotifySave(path);
|
clang_complete->NotifySave(path);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
|
||||||
#include "symbol.h"
|
#include "symbol.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/documentHighlight";
|
MethodType kMethodType = "textDocument/documentHighlight";
|
||||||
@ -61,7 +62,7 @@ struct Handler_TextDocumentDocumentHighlight
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentHighlight);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentHighlight);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/documentSymbol";
|
MethodType kMethodType = "textDocument/documentSymbol";
|
||||||
@ -64,7 +65,7 @@ struct Handler_TextDocumentDocumentSymbol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentSymbol);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentSymbol);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/hover";
|
MethodType kMethodType = "textDocument/hover";
|
||||||
@ -99,7 +100,7 @@ struct Handler_TextDocumentHover : BaseMessageHandler<In_TextDocumentHover> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentHover);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentHover);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/implementation";
|
MethodType kMethodType = "textDocument/implementation";
|
||||||
@ -41,7 +42,7 @@ struct Handler_TextDocumentImplementation
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentImplementation);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentImplementation);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "clang_format.h"
|
#include "clang_format.h"
|
||||||
#include "lex_utils.h"
|
#include "lex_utils.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
@ -64,7 +65,7 @@ struct Handler_TextDocumentRangeFormatting
|
|||||||
response.result = {};
|
response.result = {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, response);
|
pipeline::WriteStdout(kMethodType, response);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRangeFormatting);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRangeFormatting);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -135,7 +136,7 @@ struct Handler_TextDocumentReferences
|
|||||||
|
|
||||||
if ((int)out.result.size() >= g_config->xref.maxNum)
|
if ((int)out.result.size() >= g_config->xref.maxNum)
|
||||||
out.result.resize(g_config->xref.maxNum);
|
out.result.resize(g_config->xref.maxNum);
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentReferences);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentReferences);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/rename";
|
MethodType kMethodType = "textDocument/rename";
|
||||||
@ -102,7 +103,7 @@ struct Handler_TextDocumentRename : BaseMessageHandler<In_TextDocumentRename> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRename);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRename);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -142,7 +143,7 @@ struct Handler_TextDocumentSignatureHelp : MessageHandler {
|
|||||||
out.result.activeParameter = active_param;
|
out.result.activeParameter = active_param;
|
||||||
|
|
||||||
Timer timer;
|
Timer timer;
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
|
|
||||||
if (!is_cached_result) {
|
if (!is_cached_result) {
|
||||||
signature_cache->WithLock([&]() {
|
signature_cache->WithLock([&]() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/typeDefinition";
|
MethodType kMethodType = "textDocument/typeDefinition";
|
||||||
@ -60,7 +61,7 @@ struct Handler_TextDocumentTypeDefinition
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentTypeDefinition);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentTypeDefinition);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ struct Handler_WorkspaceDidChangeConfiguration
|
|||||||
std::to_string(project->entries.size()) + " files)");
|
std::to_string(project->entries.size()) + " files)");
|
||||||
|
|
||||||
time.Reset();
|
time.Reset();
|
||||||
project->Index(QueueManager::instance(), working_files, lsRequestId());
|
project->Index(working_files, lsRequestId());
|
||||||
time.ResetAndPrint(
|
time.ResetAndPrint(
|
||||||
"[perf] Dispatched workspace/didChangeConfiguration index requests");
|
"[perf] Dispatched workspace/didChangeConfiguration index requests");
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "cache_manager.h"
|
|
||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "workspace/didChangeWatchedFiles";
|
MethodType kMethodType = "workspace/didChangeWatchedFiles";
|
||||||
@ -52,15 +52,13 @@ struct Handler_WorkspaceDidChangeWatchedFiles
|
|||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case lsFileChangeType::Created:
|
case lsFileChangeType::Created:
|
||||||
case lsFileChangeType::Changed: {
|
case lsFileChangeType::Changed: {
|
||||||
QueueManager::instance()->index_request.PushBack(
|
pipeline::Index(path, entry.args, is_interactive);
|
||||||
Index_Request(path, entry.args, is_interactive));
|
|
||||||
if (is_interactive)
|
if (is_interactive)
|
||||||
clang_complete->NotifySave(path);
|
clang_complete->NotifySave(path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lsFileChangeType::Deleted:
|
case lsFileChangeType::Deleted:
|
||||||
QueueManager::instance()->index_request.PushBack(
|
pipeline::Index(path, entry.args, is_interactive);
|
||||||
Index_Request(path, entry.args, is_interactive));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "lsp_code_action.h"
|
#include "lsp_code_action.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "workspace/executeCommand";
|
MethodType kMethodType = "workspace/executeCommand";
|
||||||
@ -34,7 +35,7 @@ struct Handler_WorkspaceExecuteCommand
|
|||||||
out.result = params.arguments.locations;
|
out.result = params.arguments.locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceExecuteCommand);
|
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceExecuteCommand);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "fuzzy_match.h"
|
#include "fuzzy_match.h"
|
||||||
#include "lex_utils.h"
|
#include "lex_utils.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
|
#include "pipeline.hh"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
using namespace ccls;
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -124,7 +125,7 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
|
|||||||
out.result.push_back(std::get<0>(entry));
|
out.result.push_back(std::get<0>(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
pipeline::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceSymbol);
|
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceSymbol);
|
||||||
|
181
src/pipeline.cc
181
src/pipeline.cc
@ -1,6 +1,5 @@
|
|||||||
#include "pipeline.hh"
|
#include "pipeline.hh"
|
||||||
|
|
||||||
#include "cache_manager.h"
|
|
||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "diagnostics_engine.h"
|
#include "diagnostics_engine.h"
|
||||||
@ -11,18 +10,43 @@
|
|||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
#include <llvm/ADT/Twine.h>
|
#include <llvm/ADT/Twine.h>
|
||||||
#include <llvm/Support/Threading.h>
|
#include <llvm/Support/Threading.h>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
struct Index_Request {
|
||||||
|
std::string path;
|
||||||
|
std::vector<std::string> args;
|
||||||
|
bool is_interactive;
|
||||||
|
lsRequestId id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Index_OnIndexed {
|
||||||
|
IndexUpdate update;
|
||||||
|
PerformanceImportFile perf;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stdout_Request {
|
||||||
|
MethodType method;
|
||||||
|
std::string content;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ccls::pipeline {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
MultiQueueWaiter* main_waiter;
|
||||||
|
MultiQueueWaiter* indexer_waiter;
|
||||||
|
MultiQueueWaiter* stdout_waiter;
|
||||||
|
ThreadedQueue<std::unique_ptr<InMessage>>* on_request;
|
||||||
|
ThreadedQueue<Index_Request>* index_request;
|
||||||
|
ThreadedQueue<Index_OnIndexed>* on_indexed;
|
||||||
|
ThreadedQueue<Stdout_Request>* for_stdout;
|
||||||
|
|
||||||
// Checks if |path| needs to be reparsed. This will modify cached state
|
// Checks if |path| needs to be reparsed. This will modify cached state
|
||||||
// such that calling this function twice with the same path may return true
|
// such that calling this function twice with the same path may return true
|
||||||
// the first time but will return false the second.
|
// the first time but will return false the second.
|
||||||
@ -64,24 +88,57 @@ bool FileNeedsParse(int64_t write_time,
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string AppendSerializationFormat(const std::string& base) {
|
||||||
|
switch (g_config->cacheFormat) {
|
||||||
|
case SerializeFormat::Binary:
|
||||||
|
return base + ".blob";
|
||||||
|
case SerializeFormat::Json:
|
||||||
|
return base + ".json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetCachePath(const std::string& source_file) {
|
||||||
|
std::string cache_file;
|
||||||
|
size_t len = g_config->projectRoot.size();
|
||||||
|
if (StartsWith(source_file, g_config->projectRoot)) {
|
||||||
|
cache_file = EscapeFileName(g_config->projectRoot) +
|
||||||
|
EscapeFileName(source_file.substr(len));
|
||||||
|
} else {
|
||||||
|
cache_file = '@' + EscapeFileName(g_config->projectRoot) +
|
||||||
|
EscapeFileName(source_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_config->cacheDirectory + cache_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<IndexFile> RawCacheLoad(
|
||||||
|
const std::string& path) {
|
||||||
|
std::string cache_path = GetCachePath(path);
|
||||||
|
std::optional<std::string> file_content = ReadContent(cache_path);
|
||||||
|
std::optional<std::string> serialized_indexed_content =
|
||||||
|
ReadContent(AppendSerializationFormat(cache_path));
|
||||||
|
if (!file_content || !serialized_indexed_content)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return Deserialize(g_config->cacheFormat, path, *serialized_indexed_content,
|
||||||
|
*file_content, IndexFile::kMajorVersion);
|
||||||
|
}
|
||||||
|
|
||||||
bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
Project* project,
|
Project* project,
|
||||||
VFS* vfs,
|
VFS* vfs,
|
||||||
ClangIndexer* indexer) {
|
ClangIndexer* indexer) {
|
||||||
auto* queue = QueueManager::instance();
|
std::optional<Index_Request> opt_request = index_request->TryPopFront();
|
||||||
std::optional<Index_Request> opt_request = queue->index_request.TryPopFront();
|
|
||||||
if (!opt_request)
|
if (!opt_request)
|
||||||
return false;
|
return false;
|
||||||
auto& request = *opt_request;
|
auto& request = *opt_request;
|
||||||
ICacheManager cache;
|
|
||||||
|
|
||||||
// Dummy one to trigger refresh semantic highlight.
|
// Dummy one to trigger refresh semantic highlight.
|
||||||
if (request.path.empty()) {
|
if (request.path.empty()) {
|
||||||
IndexUpdate dummy;
|
IndexUpdate dummy;
|
||||||
dummy.refresh = true;
|
dummy.refresh = true;
|
||||||
queue->on_indexed.PushBack(
|
on_indexed->PushBack({std::move(dummy), PerformanceImportFile()}, false);
|
||||||
Index_OnIndexed(std::move(dummy), PerformanceImportFile()), false);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +165,7 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
int reparse; // request.is_interactive;
|
int reparse; // request.is_interactive;
|
||||||
prev = cache.RawCacheLoad(path_to_index);
|
prev = RawCacheLoad(path_to_index);
|
||||||
if (!prev)
|
if (!prev)
|
||||||
reparse = 2;
|
reparse = 2;
|
||||||
else {
|
else {
|
||||||
@ -132,15 +189,13 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
|||||||
auto dependencies = prev->dependencies;
|
auto dependencies = prev->dependencies;
|
||||||
if (reparse) {
|
if (reparse) {
|
||||||
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
|
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
|
||||||
queue->on_indexed.PushBack(Index_OnIndexed(std::move(update), perf),
|
on_indexed->PushBack({std::move(update), perf}, request.is_interactive);
|
||||||
request.is_interactive);
|
|
||||||
}
|
}
|
||||||
for (const auto& dep : dependencies)
|
for (const auto& dep : dependencies)
|
||||||
if (vfs->Mark(dep.first().str(), 0, 2)) {
|
if (vfs->Mark(dep.first().str(), 0, 2)) {
|
||||||
prev = cache.RawCacheLoad(dep.first().str());
|
prev = RawCacheLoad(dep.first().str());
|
||||||
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
|
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
|
||||||
queue->on_indexed.PushBack(Index_OnIndexed(std::move(update), perf),
|
on_indexed->PushBack({std::move(update), perf}, request.is_interactive);
|
||||||
request.is_interactive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(vfs->mutex);
|
std::lock_guard<std::mutex> lock(vfs->mutex);
|
||||||
@ -152,7 +207,6 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
|||||||
|
|
||||||
LOG_S(INFO) << "parse " << path_to_index;
|
LOG_S(INFO) << "parse " << path_to_index;
|
||||||
|
|
||||||
std::vector<Index_OnIdMapped> result;
|
|
||||||
PerformanceImportFile perf;
|
PerformanceImportFile perf;
|
||||||
auto indexes = indexer->Index(vfs, path_to_index, entry.args, {}, &perf);
|
auto indexes = indexer->Index(vfs, path_to_index, entry.args, {}, &perf);
|
||||||
|
|
||||||
@ -162,7 +216,7 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
|||||||
out.id = request.id;
|
out.id = request.id;
|
||||||
out.error.code = lsErrorCodes::InternalError;
|
out.error.code = lsErrorCodes::InternalError;
|
||||||
out.error.message = "Failed to index " + path_to_index;
|
out.error.message = "Failed to index " + path_to_index;
|
||||||
QueueManager::WriteStdout(kMethodType_Unknown, out);
|
pipeline::WriteStdout(kMethodType_Unknown, out);
|
||||||
}
|
}
|
||||||
vfs->Reset(path_to_index);
|
vfs->Reset(path_to_index);
|
||||||
return true;
|
return true;
|
||||||
@ -179,12 +233,17 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
|||||||
if (!(vfs->Stamp(path, curr->last_write_time) || path == path_to_index))
|
if (!(vfs->Stamp(path, curr->last_write_time) || path == path_to_index))
|
||||||
continue;
|
continue;
|
||||||
LOG_S(INFO) << "emit index for " << path;
|
LOG_S(INFO) << "emit index for " << path;
|
||||||
prev = cache.RawCacheLoad(path);
|
prev = RawCacheLoad(path);
|
||||||
|
|
||||||
// Write current index to disk if requested.
|
// Write current index to disk if requested.
|
||||||
LOG_S(INFO) << "store index for " << path;
|
LOG_S(INFO) << "store index for " << path;
|
||||||
Timer time;
|
Timer time;
|
||||||
cache.WriteToCache(*curr);
|
{
|
||||||
|
std::string cache_path = GetCachePath(path);
|
||||||
|
WriteToFile(cache_path, curr->file_contents);
|
||||||
|
WriteToFile(AppendSerializationFormat(cache_path),
|
||||||
|
Serialize(g_config->cacheFormat, *curr));
|
||||||
|
}
|
||||||
perf.index_save_to_disk = time.ElapsedMicrosecondsAndReset();
|
perf.index_save_to_disk = time.ElapsedMicrosecondsAndReset();
|
||||||
|
|
||||||
vfs->Reset(path_to_index);
|
vfs->Reset(path_to_index);
|
||||||
@ -199,8 +258,7 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
|
|||||||
perf.index_make_delta = time.ElapsedMicrosecondsAndReset();
|
perf.index_make_delta = time.ElapsedMicrosecondsAndReset();
|
||||||
LOG_S(INFO) << "built index for " << path << " (is_delta=" << !!prev << ")";
|
LOG_S(INFO) << "built index for " << path << " (is_delta=" << !!prev << ")";
|
||||||
|
|
||||||
Index_OnIndexed reply(std::move(update), perf);
|
on_indexed->PushBack({std::move(update), perf}, request.is_interactive);
|
||||||
queue->on_indexed.PushBack(std::move(reply), request.is_interactive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -217,26 +275,34 @@ bool ShouldDisplayMethodTiming(MethodType type) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
main_waiter = new MultiQueueWaiter;
|
||||||
|
on_request = new ThreadedQueue<std::unique_ptr<InMessage>>(main_waiter);
|
||||||
|
on_indexed = new ThreadedQueue<Index_OnIndexed>(main_waiter);
|
||||||
|
|
||||||
|
indexer_waiter = new MultiQueueWaiter;
|
||||||
|
index_request = new ThreadedQueue<Index_Request>(indexer_waiter);
|
||||||
|
|
||||||
|
stdout_waiter = new MultiQueueWaiter;
|
||||||
|
for_stdout = new ThreadedQueue<Stdout_Request>(stdout_waiter);
|
||||||
|
}
|
||||||
|
|
||||||
void Indexer_Main(DiagnosticsEngine* diag_engine,
|
void Indexer_Main(DiagnosticsEngine* diag_engine,
|
||||||
VFS* vfs,
|
VFS* vfs,
|
||||||
Project* project,
|
Project* project,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files) {
|
||||||
MultiQueueWaiter* waiter) {
|
|
||||||
auto* queue = QueueManager::instance();
|
|
||||||
// Build one index per-indexer, as building the index acquires a global lock.
|
// Build one index per-indexer, as building the index acquires a global lock.
|
||||||
ClangIndexer indexer;
|
ClangIndexer indexer;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
if (!Indexer_Parse(diag_engine, working_files, project, vfs, &indexer))
|
if (!Indexer_Parse(diag_engine, working_files, project, vfs, &indexer))
|
||||||
waiter->Wait(&queue->index_request);
|
indexer_waiter->Wait(index_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryDb_OnIndexed(QueueManager* queue,
|
void Main_OnIndexed(QueryDatabase* db,
|
||||||
QueryDatabase* db,
|
|
||||||
SemanticHighlightSymbolCache* semantic_cache,
|
SemanticHighlightSymbolCache* semantic_cache,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
Index_OnIndexed* response) {
|
Index_OnIndexed* response) {
|
||||||
|
|
||||||
if (response->update.refresh) {
|
if (response->update.refresh) {
|
||||||
LOG_S(INFO) << "Loaded project. Refresh semantic highlight for all working file.";
|
LOG_S(INFO) << "Loaded project. Refresh semantic highlight for all working file.";
|
||||||
std::lock_guard<std::mutex> lock(working_files->files_mutex);
|
std::lock_guard<std::mutex> lock(working_files->files_mutex);
|
||||||
@ -257,9 +323,8 @@ void QueryDb_OnIndexed(QueueManager* queue,
|
|||||||
if (response->update.files_def_update) {
|
if (response->update.files_def_update) {
|
||||||
auto& update = *response->update.files_def_update;
|
auto& update = *response->update.files_def_update;
|
||||||
time.ResetAndPrint("apply index for " + update.value.path);
|
time.ResetAndPrint("apply index for " + update.value.path);
|
||||||
WorkingFile* working_file =
|
if (WorkingFile* working_file =
|
||||||
working_files->GetFileByFilename(update.value.path);
|
working_files->GetFileByFilename(update.value.path)) {
|
||||||
if (working_file) {
|
|
||||||
// Update indexed content.
|
// Update indexed content.
|
||||||
working_file->SetIndexContent(update.file_content);
|
working_file->SetIndexContent(update.file_content);
|
||||||
|
|
||||||
@ -275,10 +340,9 @@ void QueryDb_OnIndexed(QueueManager* queue,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaunchStdinLoop(std::unordered_map<MethodType, Timer>* request_times) {
|
void LaunchStdin(std::unordered_map<MethodType, Timer>* request_times) {
|
||||||
std::thread([request_times]() {
|
std::thread([request_times]() {
|
||||||
set_thread_name("stdin");
|
set_thread_name("stdin");
|
||||||
auto* queue = QueueManager::instance();
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::unique_ptr<InMessage> message;
|
std::unique_ptr<InMessage> message;
|
||||||
std::optional<std::string> err =
|
std::optional<std::string> err =
|
||||||
@ -295,7 +359,7 @@ void LaunchStdinLoop(std::unordered_map<MethodType, Timer>* request_times) {
|
|||||||
out.id = id;
|
out.id = id;
|
||||||
out.error.code = lsErrorCodes::InvalidParams;
|
out.error.code = lsErrorCodes::InvalidParams;
|
||||||
out.error.message = std::move(*err);
|
out.error.message = std::move(*err);
|
||||||
queue->WriteStdout(kMethodType_Unknown, out);
|
WriteStdout(kMethodType_Unknown, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -305,7 +369,7 @@ void LaunchStdinLoop(std::unordered_map<MethodType, Timer>* request_times) {
|
|||||||
MethodType method_type = message->GetMethodType();
|
MethodType method_type = message->GetMethodType();
|
||||||
(*request_times)[method_type] = Timer();
|
(*request_times)[method_type] = Timer();
|
||||||
|
|
||||||
queue->for_querydb.PushBack(std::move(message));
|
on_request->PushBack(std::move(message));
|
||||||
|
|
||||||
// If the message was to exit then querydb will take care of the actual
|
// If the message was to exit then querydb will take care of the actual
|
||||||
// exit. Stop reading from stdin since it might be detached.
|
// exit. Stop reading from stdin since it might be detached.
|
||||||
@ -315,16 +379,14 @@ void LaunchStdinLoop(std::unordered_map<MethodType, Timer>* request_times) {
|
|||||||
}).detach();
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaunchStdoutThread(std::unordered_map<MethodType, Timer>* request_times,
|
void LaunchStdout(std::unordered_map<MethodType, Timer>* request_times) {
|
||||||
MultiQueueWaiter* waiter) {
|
|
||||||
std::thread([=]() {
|
std::thread([=]() {
|
||||||
set_thread_name("stdout");
|
set_thread_name("stdout");
|
||||||
auto* queue = QueueManager::instance();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::vector<Stdout_Request> messages = queue->for_stdout.DequeueAll();
|
std::vector<Stdout_Request> messages = for_stdout->DequeueAll();
|
||||||
if (messages.empty()) {
|
if (messages.empty()) {
|
||||||
waiter->Wait(&queue->for_stdout);
|
stdout_waiter->Wait(for_stdout);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,8 +403,7 @@ void LaunchStdoutThread(std::unordered_map<MethodType, Timer>* request_times,
|
|||||||
}).detach();
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainLoop(MultiQueueWaiter* querydb_waiter,
|
void MainLoop() {
|
||||||
MultiQueueWaiter* indexer_waiter) {
|
|
||||||
Project project;
|
Project project;
|
||||||
SemanticHighlightSymbolCache semantic_cache;
|
SemanticHighlightSymbolCache semantic_cache;
|
||||||
WorkingFiles working_files;
|
WorkingFiles working_files;
|
||||||
@ -362,7 +423,7 @@ void MainLoop(MultiQueueWaiter* querydb_waiter,
|
|||||||
out.error.message =
|
out.error.message =
|
||||||
"Dropping completion request; a newer request "
|
"Dropping completion request; a newer request "
|
||||||
"has come in that will be serviced instead.";
|
"has come in that will be serviced instead.";
|
||||||
QueueManager::WriteStdout(kMethodType_Unknown, out);
|
pipeline::WriteStdout(kMethodType_Unknown, out);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -389,11 +450,8 @@ void MainLoop(MultiQueueWaiter* querydb_waiter,
|
|||||||
handler->signature_cache = signature_cache.get();
|
handler->signature_cache = signature_cache.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run query db main loop.
|
|
||||||
auto* queue = QueueManager::instance();
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::vector<std::unique_ptr<InMessage>> messages =
|
std::vector<std::unique_ptr<InMessage>> messages = on_request->DequeueAll();
|
||||||
queue->for_querydb.DequeueAll();
|
|
||||||
bool did_work = messages.size();
|
bool did_work = messages.size();
|
||||||
for (auto& message : messages) {
|
for (auto& message : messages) {
|
||||||
// TODO: Consider using std::unordered_map to lookup the handler
|
// TODO: Consider using std::unordered_map to lookup the handler
|
||||||
@ -409,19 +467,40 @@ void MainLoop(MultiQueueWaiter* querydb_waiter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 80; i--;) {
|
for (int i = 80; i--;) {
|
||||||
std::optional<Index_OnIndexed> response = queue->on_indexed.TryPopFront();
|
std::optional<Index_OnIndexed> response = on_indexed->TryPopFront();
|
||||||
if (!response)
|
if (!response)
|
||||||
break;
|
break;
|
||||||
did_work = true;
|
did_work = true;
|
||||||
QueryDb_OnIndexed(queue, &db, &semantic_cache, &working_files, &*response);
|
Main_OnIndexed(&db, &semantic_cache, &working_files, &*response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup and free any unused memory.
|
// Cleanup and free any unused memory.
|
||||||
FreeUnusedMemory();
|
FreeUnusedMemory();
|
||||||
|
|
||||||
if (!did_work) {
|
if (!did_work)
|
||||||
auto* queue = QueueManager::instance();
|
main_waiter->Wait(on_indexed, on_request);
|
||||||
querydb_waiter->Wait(&queue->on_indexed, &queue->for_querydb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Index(const std::string& path,
|
||||||
|
const std::vector<std::string>& args,
|
||||||
|
bool interactive,
|
||||||
|
lsRequestId id) {
|
||||||
|
index_request->PushBack({path, args, interactive, id}, interactive);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> LoadCachedFileContents(const std::string& path) {
|
||||||
|
return ReadContent(GetCachePath(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteStdout(MethodType method, lsBaseOutMessage& response) {
|
||||||
|
std::ostringstream sstream;
|
||||||
|
response.Write(sstream);
|
||||||
|
|
||||||
|
Stdout_Request out;
|
||||||
|
out.content = sstream.str();
|
||||||
|
out.method = method;
|
||||||
|
for_stdout->PushBack(std::move(out));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "queue_manager.h"
|
#include "method.h"
|
||||||
|
#include "query.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct ClangTranslationUnit;
|
|
||||||
class DiagnosticsEngine;
|
class DiagnosticsEngine;
|
||||||
struct VFS;
|
struct VFS;
|
||||||
struct ICacheManager;
|
|
||||||
struct Project;
|
struct Project;
|
||||||
struct QueryDatabase;
|
|
||||||
struct SemanticHighlightSymbolCache;
|
|
||||||
struct WorkingFiles;
|
struct WorkingFiles;
|
||||||
|
struct lsBaseOutMessage;
|
||||||
|
|
||||||
|
namespace ccls::pipeline {
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void LaunchStdin(std::unordered_map<MethodType, Timer>* request_times);
|
||||||
|
void LaunchStdout(std::unordered_map<MethodType, Timer>* request_times);
|
||||||
void Indexer_Main(DiagnosticsEngine* diag_engine,
|
void Indexer_Main(DiagnosticsEngine* diag_engine,
|
||||||
VFS* vfs,
|
VFS* vfs,
|
||||||
Project* project,
|
Project* project,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files);
|
||||||
MultiQueueWaiter* waiter);
|
void MainLoop();
|
||||||
|
|
||||||
void LaunchStdinLoop(std::unordered_map<MethodType, Timer>* request_times);
|
void Index(const std::string& path,
|
||||||
void LaunchStdoutThread(std::unordered_map<MethodType, Timer>* request_times,
|
const std::vector<std::string>& args,
|
||||||
MultiQueueWaiter* waiter);
|
bool is_interactive,
|
||||||
void MainLoop(MultiQueueWaiter* querydb_waiter,
|
lsRequestId id = {});
|
||||||
MultiQueueWaiter* indexer_waiter);
|
|
||||||
|
std::optional<std::string> LoadCachedFileContents(const std::string& path);
|
||||||
|
void WriteStdout(MethodType method, lsBaseOutMessage& response);
|
||||||
|
}
|
||||||
|
10
src/port.cc
10
src/port.cc
@ -1,10 +0,0 @@
|
|||||||
#include "port.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void ccls_unreachable_internal(const char* msg, const char* file, int line) {
|
|
||||||
fprintf(stderr, "unreachable %s:%d %s\n", file, line, msg);
|
|
||||||
CCLS_BUILTIN_UNREACHABLE;
|
|
||||||
abort();
|
|
||||||
}
|
|
34
src/port.h
34
src/port.h
@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef __has_builtin
|
|
||||||
#define __has_builtin(x) 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
|
||||||
#else
|
|
||||||
#define ATTRIBUTE_UNUSED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
#define GUARDED_BY(x) __attribute__((guarded_by(x)))
|
|
||||||
#else
|
|
||||||
#define GUARDED_BY(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO GCC
|
|
||||||
#if __has_builtin(__builtin_unreachable)
|
|
||||||
#define CCLS_BUILTIN_UNREACHABLE __builtin_unreachable()
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
#define CCLS_BUILTIN_UNREACHABLE __assume(false)
|
|
||||||
#else
|
|
||||||
#define CCLS_BUILTIN_UNREACHABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ccls_unreachable_internal(const char* msg, const char* file, int line);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define CCLS_UNREACHABLE(msg) \
|
|
||||||
ccls_unreachable_internal(msg, __FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
#define CCLS_UNREACHABLE(msg)
|
|
||||||
#endif
|
|
@ -1,17 +1,17 @@
|
|||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
|
||||||
#include "cache_manager.h"
|
|
||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
#include "filesystem.hh"
|
#include "filesystem.hh"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "log.hh"
|
#include "log.hh"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
#include "serializers/json.h"
|
#include "serializers/json.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
using namespace ccls;
|
||||||
|
|
||||||
#include <clang/Driver/Options.h>
|
#include <clang/Driver/Options.h>
|
||||||
#include <llvm/ADT/ArrayRef.h>
|
#include <llvm/ADT/ArrayRef.h>
|
||||||
@ -454,17 +454,15 @@ void Project::ForAllFilteredFiles(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::Index(QueueManager* queue,
|
void Project::Index(WorkingFiles* wfiles,
|
||||||
WorkingFiles* wfiles,
|
|
||||||
lsRequestId id) {
|
lsRequestId id) {
|
||||||
ForAllFilteredFiles([&](int i, const Project::Entry& entry) {
|
ForAllFilteredFiles([&](int i, const Project::Entry& entry) {
|
||||||
bool is_interactive = wfiles->GetFileByFilename(entry.filename) != nullptr;
|
bool is_interactive = wfiles->GetFileByFilename(entry.filename) != nullptr;
|
||||||
queue->index_request.PushBack(
|
pipeline::Index(entry.filename, entry.args, is_interactive, id);
|
||||||
Index_Request(entry.filename, entry.args, is_interactive, id));
|
|
||||||
});
|
});
|
||||||
// Dummy request to indicate that project is loaded and
|
// Dummy request to indicate that project is loaded and
|
||||||
// trigger refreshing semantic highlight for all working files.
|
// trigger refreshing semantic highlight for all working files.
|
||||||
queue->index_request.PushBack(Index_Request("", {}, false));
|
pipeline::Index("", {}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_SUITE("Project") {
|
TEST_SUITE("Project") {
|
||||||
|
@ -5,12 +5,10 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class QueueManager;
|
|
||||||
struct WorkingFiles;
|
struct WorkingFiles;
|
||||||
|
|
||||||
struct Project {
|
struct Project {
|
||||||
@ -29,7 +27,7 @@ struct Project {
|
|||||||
|
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::unordered_map<std::string, int> absolute_path_to_entry_index_ GUARDED_BY(mutex_);
|
std::unordered_map<std::string, int> absolute_path_to_entry_index_;
|
||||||
|
|
||||||
// Loads a project for the given |directory|.
|
// Loads a project for the given |directory|.
|
||||||
//
|
//
|
||||||
@ -58,5 +56,5 @@ struct Project {
|
|||||||
void ForAllFilteredFiles(
|
void ForAllFilteredFiles(
|
||||||
std::function<void(int i, const Entry& entry)> action);
|
std::function<void(int i, const Entry& entry)> action);
|
||||||
|
|
||||||
void Index(QueueManager* queue, WorkingFiles* wfiles, lsRequestId id);
|
void Index(WorkingFiles* wfiles, lsRequestId id);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
|
|
||||||
#include "queue_manager.h"
|
#include "pipeline.hh"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
#include "queue_manager.h"
|
|
||||||
|
|
||||||
#include "cache_manager.h"
|
|
||||||
#include "lsp.h"
|
|
||||||
#include "query.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
Index_Request::Index_Request(const std::string& path,
|
|
||||||
const std::vector<std::string>& args,
|
|
||||||
bool is_interactive,
|
|
||||||
lsRequestId id)
|
|
||||||
: path(path), args(args), is_interactive(is_interactive), id(id) {}
|
|
||||||
|
|
||||||
Index_OnIndexed::Index_OnIndexed(IndexUpdate&& update,
|
|
||||||
PerformanceImportFile perf)
|
|
||||||
: update(std::move(update)), perf(perf) {}
|
|
||||||
|
|
||||||
std::unique_ptr<QueueManager> QueueManager::instance_;
|
|
||||||
|
|
||||||
// static
|
|
||||||
void QueueManager::Init(MultiQueueWaiter* querydb_waiter,
|
|
||||||
MultiQueueWaiter* indexer_waiter,
|
|
||||||
MultiQueueWaiter* stdout_waiter) {
|
|
||||||
instance_ = std::unique_ptr<QueueManager>(
|
|
||||||
new QueueManager(querydb_waiter, indexer_waiter, stdout_waiter));
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void QueueManager::WriteStdout(MethodType method, lsBaseOutMessage& response) {
|
|
||||||
std::ostringstream sstream;
|
|
||||||
response.Write(sstream);
|
|
||||||
|
|
||||||
Stdout_Request out;
|
|
||||||
out.content = sstream.str();
|
|
||||||
out.method = method;
|
|
||||||
instance()->for_stdout.PushBack(std::move(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueManager::QueueManager(MultiQueueWaiter* querydb_waiter,
|
|
||||||
MultiQueueWaiter* indexer_waiter,
|
|
||||||
MultiQueueWaiter* stdout_waiter)
|
|
||||||
: for_stdout(stdout_waiter),
|
|
||||||
for_querydb(querydb_waiter),
|
|
||||||
on_indexed(querydb_waiter),
|
|
||||||
index_request(indexer_waiter) {}
|
|
@ -1,84 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "method.h"
|
|
||||||
#include "query.h"
|
|
||||||
#include "threaded_queue.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
struct ICacheManager;
|
|
||||||
struct lsBaseOutMessage;
|
|
||||||
|
|
||||||
struct Stdout_Request {
|
|
||||||
MethodType method;
|
|
||||||
std::string content;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Index_Request {
|
|
||||||
std::string path;
|
|
||||||
// TODO: make |args| a string that is parsed lazily.
|
|
||||||
std::vector<std::string> args;
|
|
||||||
bool is_interactive;
|
|
||||||
lsRequestId id;
|
|
||||||
|
|
||||||
Index_Request(const std::string& path,
|
|
||||||
const std::vector<std::string>& args,
|
|
||||||
bool is_interactive,
|
|
||||||
lsRequestId id = {});
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Index_OnIdMapped {
|
|
||||||
std::shared_ptr<ICacheManager> cache_manager;
|
|
||||||
std::unique_ptr<IndexFile> previous;
|
|
||||||
std::unique_ptr<IndexFile> current;
|
|
||||||
|
|
||||||
PerformanceImportFile perf;
|
|
||||||
bool is_interactive;
|
|
||||||
bool write_to_disk;
|
|
||||||
|
|
||||||
Index_OnIdMapped(const std::shared_ptr<ICacheManager>& cache_manager,
|
|
||||||
std::unique_ptr<IndexFile> previous,
|
|
||||||
std::unique_ptr<IndexFile> current,
|
|
||||||
PerformanceImportFile perf,
|
|
||||||
bool is_interactive,
|
|
||||||
bool write_to_disk)
|
|
||||||
: cache_manager(cache_manager),
|
|
||||||
previous(std::move(previous)),
|
|
||||||
current(std::move(current)),
|
|
||||||
perf(perf),
|
|
||||||
is_interactive(is_interactive),
|
|
||||||
write_to_disk(write_to_disk) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Index_OnIndexed {
|
|
||||||
IndexUpdate update;
|
|
||||||
PerformanceImportFile perf;
|
|
||||||
|
|
||||||
Index_OnIndexed(IndexUpdate&& update, PerformanceImportFile perf);
|
|
||||||
};
|
|
||||||
|
|
||||||
class QueueManager {
|
|
||||||
static std::unique_ptr<QueueManager> instance_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static QueueManager* instance() { return instance_.get(); }
|
|
||||||
static void Init(MultiQueueWaiter* querydb_waiter,
|
|
||||||
MultiQueueWaiter* indexer_waiter,
|
|
||||||
MultiQueueWaiter* stdout_waiter);
|
|
||||||
static void WriteStdout(MethodType method, lsBaseOutMessage& response);
|
|
||||||
|
|
||||||
// Messages received by "stdout" thread.
|
|
||||||
ThreadedQueue<Stdout_Request> for_stdout;
|
|
||||||
|
|
||||||
// Runs on querydb thread.
|
|
||||||
ThreadedQueue<std::unique_ptr<InMessage>> for_querydb;
|
|
||||||
ThreadedQueue<Index_OnIndexed> on_indexed;
|
|
||||||
|
|
||||||
// Runs on indexer threads.
|
|
||||||
ThreadedQueue<Index_Request> index_request;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit QueueManager(MultiQueueWaiter* querydb_waiter,
|
|
||||||
MultiQueueWaiter* indexer_waiter,
|
|
||||||
MultiQueueWaiter* stdout_waiter);
|
|
||||||
};
|
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
#include "maybe.h"
|
#include "maybe.h"
|
||||||
#include "nt_string.h"
|
#include "nt_string.h"
|
||||||
#include "port.h"
|
|
||||||
|
#include <llvm/Support/Compiler.h>
|
||||||
|
|
||||||
#include <macro_map.h>
|
#include <macro_map.h>
|
||||||
|
|
||||||
@ -84,12 +85,12 @@ struct IndexFile;
|
|||||||
#define MAKE_REFLECT_TYPE_PROXY(type_name) \
|
#define MAKE_REFLECT_TYPE_PROXY(type_name) \
|
||||||
MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type_t<type_name>)
|
MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type_t<type_name>)
|
||||||
#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \
|
#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \
|
||||||
ATTRIBUTE_UNUSED inline void Reflect(Reader& visitor, type& value) { \
|
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Reader& visitor, type& value) { \
|
||||||
as_type value0; \
|
as_type value0; \
|
||||||
::Reflect(visitor, value0); \
|
::Reflect(visitor, value0); \
|
||||||
value = static_cast<type>(value0); \
|
value = static_cast<type>(value0); \
|
||||||
} \
|
} \
|
||||||
ATTRIBUTE_UNUSED inline void Reflect(Writer& visitor, type& value) { \
|
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Writer& visitor, type& value) { \
|
||||||
auto value0 = static_cast<as_type>(value); \
|
auto value0 = static_cast<as_type>(value); \
|
||||||
::Reflect(visitor, value0); \
|
::Reflect(visitor, value0); \
|
||||||
}
|
}
|
||||||
|
@ -284,8 +284,6 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
|
|||||||
&all_expected_output);
|
&all_expected_output);
|
||||||
|
|
||||||
// Build flags.
|
// Build flags.
|
||||||
if (!AnyStartsWith(flags, "-x"))
|
|
||||||
flags.push_back("-xc++");
|
|
||||||
flags.push_back("-resource-dir=" + GetDefaultResourceDirectory());
|
flags.push_back("-resource-dir=" + GetDefaultResourceDirectory());
|
||||||
flags.push_back(path);
|
flags.push_back(path);
|
||||||
|
|
||||||
|
@ -94,26 +94,6 @@ struct ThreadedQueue : public BaseThreadQueue {
|
|||||||
Push<&std::deque<T>::push_back>(std::move(t), priority);
|
Push<&std::deque<T>::push_back>(std::move(t), priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a set of elements to the queue.
|
|
||||||
void EnqueueAll(std::vector<T>&& elements, bool priority = false) {
|
|
||||||
if (elements.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
|
|
||||||
total_count_ += elements.size();
|
|
||||||
|
|
||||||
for (T& element : elements) {
|
|
||||||
if (priority)
|
|
||||||
priority_.push_back(std::move(element));
|
|
||||||
else
|
|
||||||
queue_.push_back(std::move(element));
|
|
||||||
}
|
|
||||||
elements.clear();
|
|
||||||
|
|
||||||
waiter_->cv.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return all elements in the queue.
|
// Return all elements in the queue.
|
||||||
std::vector<T> DequeueAll() {
|
std::vector<T> DequeueAll() {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
@ -48,15 +48,6 @@ bool StartsWith(std::string_view s, std::string_view prefix) {
|
|||||||
std::equal(prefix.begin(), prefix.end(), s.begin());
|
std::equal(prefix.begin(), prefix.end(), s.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AnyStartsWith(const std::vector<std::string>& xs,
|
|
||||||
std::string_view prefix) {
|
|
||||||
return std::any_of(xs.begin(), xs.end(), std::bind(StartsWith, _1, prefix));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StartsWithAny(std::string_view s, const std::vector<std::string>& ps) {
|
|
||||||
return std::any_of(ps.begin(), ps.end(), std::bind(StartsWith, s, _1));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EndsWithAny(std::string_view s, const std::vector<std::string>& ss) {
|
bool EndsWithAny(std::string_view s, const std::vector<std::string>& ss) {
|
||||||
return std::any_of(ss.begin(), ss.end(), std::bind(EndsWith, s, _1));
|
return std::any_of(ss.begin(), ss.end(), std::bind(EndsWith, s, _1));
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,6 @@ uint64_t HashUsr(std::string_view s);
|
|||||||
// Returns true if |value| starts/ends with |start| or |ending|.
|
// Returns true if |value| starts/ends with |start| or |ending|.
|
||||||
bool StartsWith(std::string_view value, std::string_view start);
|
bool StartsWith(std::string_view value, std::string_view start);
|
||||||
bool EndsWith(std::string_view value, std::string_view ending);
|
bool EndsWith(std::string_view value, std::string_view ending);
|
||||||
bool AnyStartsWith(const std::vector<std::string>& xs, std::string_view prefix);
|
|
||||||
bool StartsWithAny(std::string_view s, const std::vector<std::string>& ps);
|
|
||||||
bool EndsWithAny(std::string_view s, const std::vector<std::string>& ss);
|
bool EndsWithAny(std::string_view s, const std::vector<std::string>& ss);
|
||||||
bool FindAnyPartial(const std::string& value,
|
bool FindAnyPartial(const std::string& value,
|
||||||
const std::vector<std::string>& values);
|
const std::vector<std::string>& values);
|
||||||
|
Loading…
Reference in New Issue
Block a user