mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-29 02:51:57 +00:00
Use global config.
This commit is contained in:
parent
062b1ad0fd
commit
fdb562bb42
@ -21,7 +21,7 @@ struct RealCacheManager : ICacheManager {
|
|||||||
std::string cache_path = GetCachePath(file.path);
|
std::string cache_path = GetCachePath(file.path);
|
||||||
WriteToFile(cache_path, file.file_contents);
|
WriteToFile(cache_path, file.file_contents);
|
||||||
|
|
||||||
std::string indexed_content = Serialize(g_config.cacheFormat, file);
|
std::string indexed_content = Serialize(g_config->cacheFormat, file);
|
||||||
WriteToFile(AppendSerializationFormat(cache_path), indexed_content);
|
WriteToFile(AppendSerializationFormat(cache_path), indexed_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,34 +38,32 @@ struct RealCacheManager : ICacheManager {
|
|||||||
if (!file_content || !serialized_indexed_content)
|
if (!file_content || !serialized_indexed_content)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return Deserialize(g_config.cacheFormat, path, *serialized_indexed_content,
|
return Deserialize(g_config->cacheFormat, path, *serialized_indexed_content,
|
||||||
*file_content, IndexFile::kMajorVersion);
|
*file_content, IndexFile::kMajorVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetCachePath(const std::string& source_file) {
|
std::string GetCachePath(const std::string& source_file) {
|
||||||
assert(!g_config.cacheDirectory.empty());
|
assert(!g_config->cacheDirectory.empty());
|
||||||
std::string cache_file;
|
std::string cache_file;
|
||||||
size_t len = g_config.projectRoot.size();
|
size_t len = g_config->projectRoot.size();
|
||||||
if (StartsWith(source_file, g_config.projectRoot)) {
|
if (StartsWith(source_file, g_config->projectRoot)) {
|
||||||
cache_file = EscapeFileName(g_config.projectRoot) +
|
cache_file = EscapeFileName(g_config->projectRoot) +
|
||||||
EscapeFileName(source_file.substr(len));
|
EscapeFileName(source_file.substr(len));
|
||||||
} else {
|
} else {
|
||||||
cache_file = '@' + EscapeFileName(g_config.projectRoot) +
|
cache_file = '@' + EscapeFileName(g_config->projectRoot) +
|
||||||
EscapeFileName(source_file);
|
EscapeFileName(source_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_config.cacheDirectory + cache_file;
|
return g_config->cacheDirectory + cache_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AppendSerializationFormat(const std::string& base) {
|
std::string AppendSerializationFormat(const std::string& base) {
|
||||||
switch (g_config.cacheFormat) {
|
switch (g_config->cacheFormat) {
|
||||||
case SerializeFormat::Json:
|
case SerializeFormat::Json:
|
||||||
return base + ".json";
|
return base + ".json";
|
||||||
case SerializeFormat::MessagePack:
|
case SerializeFormat::MessagePack:
|
||||||
return base + ".mpack";
|
return base + ".mpack";
|
||||||
}
|
}
|
||||||
assert(false);
|
|
||||||
return ".json";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ void TryEnsureDocumentParsed(ClangCompleteManager* manager,
|
|||||||
unsaved, Flags());
|
unsaved, Flags());
|
||||||
|
|
||||||
// Build diagnostics.
|
// Build diagnostics.
|
||||||
if (manager->config_->diagnostics.onParse && *tu) {
|
if (g_config->diagnostics.onParse && *tu) {
|
||||||
// If we're emitting diagnostics, do an immediate reparse, otherwise we will
|
// If we're emitting diagnostics, do an immediate reparse, otherwise we will
|
||||||
// emit stale/bad diagnostics.
|
// emit stale/bad diagnostics.
|
||||||
*tu = ClangTranslationUnit::Reparse(std::move(*tu), unsaved);
|
*tu = ClangTranslationUnit::Reparse(std::move(*tu), unsaved);
|
||||||
@ -450,7 +450,7 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
|||||||
completion_manager->completion_request_.Dequeue();
|
completion_manager->completion_request_.Dequeue();
|
||||||
|
|
||||||
// Drop older requests if we're not buffering.
|
// Drop older requests if we're not buffering.
|
||||||
while (completion_manager->config_->completion.dropOldRequests &&
|
while (g_config->completion.dropOldRequests &&
|
||||||
!completion_manager->completion_request_.IsEmpty()) {
|
!completion_manager->completion_request_.IsEmpty()) {
|
||||||
completion_manager->on_dropped_(request->id);
|
completion_manager->on_dropped_(request->id);
|
||||||
request = completion_manager->completion_request_.Dequeue();
|
request = completion_manager->completion_request_.Dequeue();
|
||||||
@ -528,7 +528,7 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
|||||||
clang_getCompletionBriefComment(result.CompletionString));
|
clang_getCompletionBriefComment(result.CompletionString));
|
||||||
|
|
||||||
// label/detail/filterText/insertText/priority
|
// label/detail/filterText/insertText/priority
|
||||||
if (completion_manager->config_->completion.detailedLabel) {
|
if (g_config->completion.detailedLabel) {
|
||||||
ls_completion_item.detail = ToString(
|
ls_completion_item.detail = ToString(
|
||||||
clang_getCompletionParent(result.CompletionString, nullptr));
|
clang_getCompletionParent(result.CompletionString, nullptr));
|
||||||
|
|
||||||
@ -538,10 +538,10 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
|||||||
// label/filterText/insertText
|
// label/filterText/insertText
|
||||||
BuildCompletionItemTexts(
|
BuildCompletionItemTexts(
|
||||||
ls_result, result.CompletionString,
|
ls_result, result.CompletionString,
|
||||||
completion_manager->config_->client.snippetSupport);
|
g_config->client.snippetSupport);
|
||||||
|
|
||||||
for (auto i = first_idx; i < ls_result.size(); ++i) {
|
for (auto i = first_idx; i < ls_result.size(); ++i) {
|
||||||
if (completion_manager->config_->client.snippetSupport &&
|
if (g_config->client.snippetSupport &&
|
||||||
ls_result[i].insertTextFormat ==
|
ls_result[i].insertTextFormat ==
|
||||||
lsInsertTextFormat::Snippet) {
|
lsInsertTextFormat::Snippet) {
|
||||||
ls_result[i].insertText += "$0";
|
ls_result[i].insertText += "$0";
|
||||||
@ -558,8 +558,8 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
|||||||
ls_completion_item.detail, ls_completion_item.insertText,
|
ls_completion_item.detail, ls_completion_item.insertText,
|
||||||
do_insert, ls_completion_item.insertTextFormat,
|
do_insert, ls_completion_item.insertTextFormat,
|
||||||
&ls_completion_item.parameters_,
|
&ls_completion_item.parameters_,
|
||||||
completion_manager->config_->client.snippetSupport);
|
g_config->client.snippetSupport);
|
||||||
if (completion_manager->config_->client.snippetSupport &&
|
if (g_config->client.snippetSupport &&
|
||||||
ls_completion_item.insertTextFormat ==
|
ls_completion_item.insertTextFormat ==
|
||||||
lsInsertTextFormat::Snippet) {
|
lsInsertTextFormat::Snippet) {
|
||||||
ls_completion_item.insertText += "$0";
|
ls_completion_item.insertText += "$0";
|
||||||
@ -658,14 +658,12 @@ ClangCompleteManager::CompletionRequest::CompletionRequest(
|
|||||||
on_complete(on_complete),
|
on_complete(on_complete),
|
||||||
emit_diagnostics(emit_diagnostics) {}
|
emit_diagnostics(emit_diagnostics) {}
|
||||||
|
|
||||||
ClangCompleteManager::ClangCompleteManager(Config* config,
|
ClangCompleteManager::ClangCompleteManager(Project* project,
|
||||||
Project* project,
|
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
OnDiagnostic on_diagnostic,
|
OnDiagnostic on_diagnostic,
|
||||||
OnIndex on_index,
|
OnIndex on_index,
|
||||||
OnDropped on_dropped)
|
OnDropped on_dropped)
|
||||||
: config_(config),
|
: project_(project),
|
||||||
project_(project),
|
|
||||||
working_files_(working_files),
|
working_files_(working_files),
|
||||||
on_diagnostic_(on_diagnostic),
|
on_diagnostic_(on_diagnostic),
|
||||||
on_index_(on_index),
|
on_index_(on_index),
|
||||||
@ -683,8 +681,6 @@ ClangCompleteManager::ClangCompleteManager(Config* config,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangCompleteManager::~ClangCompleteManager() {}
|
|
||||||
|
|
||||||
void ClangCompleteManager::CodeComplete(
|
void ClangCompleteManager::CodeComplete(
|
||||||
const lsRequestId& id,
|
const lsRequestId& id,
|
||||||
const lsTextDocumentPositionParams& completion_location,
|
const lsTextDocumentPositionParams& completion_location,
|
||||||
|
@ -72,13 +72,11 @@ struct ClangCompleteManager {
|
|||||||
bool emit_diagnostics = false;
|
bool emit_diagnostics = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangCompleteManager(Config* config,
|
ClangCompleteManager(Project* project,
|
||||||
Project* project,
|
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
OnDiagnostic on_diagnostic,
|
OnDiagnostic on_diagnostic,
|
||||||
OnIndex on_index,
|
OnIndex on_index,
|
||||||
OnDropped on_dropped);
|
OnDropped on_dropped);
|
||||||
~ClangCompleteManager();
|
|
||||||
|
|
||||||
// Start a code completion at the given location. |on_complete| will run when
|
// Start a code completion at the given location. |on_complete| will run when
|
||||||
// completion results are available. |on_complete| may run on any thread.
|
// completion results are available. |on_complete| may run on any thread.
|
||||||
@ -120,7 +118,6 @@ struct ClangCompleteManager {
|
|||||||
const int kMaxCompletionSessions = 5;
|
const int kMaxCompletionSessions = 5;
|
||||||
|
|
||||||
// Global state.
|
// Global state.
|
||||||
Config* config_;
|
|
||||||
Project* project_;
|
Project* project_;
|
||||||
WorkingFiles* working_files_;
|
WorkingFiles* working_files_;
|
||||||
OnDiagnostic on_diagnostic_;
|
OnDiagnostic on_diagnostic_;
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on
|
// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on
|
||||||
// |Foobar| in DISALLOW_COPY(Foobar)
|
// |Foobar| in DISALLOW_COPY(Foobar)
|
||||||
@ -279,8 +278,6 @@ struct ConstructorCache {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct IndexParam {
|
struct IndexParam {
|
||||||
Config* config = nullptr;
|
|
||||||
|
|
||||||
std::unordered_set<CXFile> seen_cx_files;
|
std::unordered_set<CXFile> seen_cx_files;
|
||||||
std::vector<std::string> seen_files;
|
std::vector<std::string> seen_files;
|
||||||
FileContentsMap file_contents;
|
FileContentsMap file_contents;
|
||||||
@ -300,10 +297,9 @@ struct IndexParam {
|
|||||||
NamespaceHelper ns;
|
NamespaceHelper ns;
|
||||||
ConstructorCache ctors;
|
ConstructorCache ctors;
|
||||||
|
|
||||||
IndexParam(Config* config,
|
IndexParam(ClangTranslationUnit* tu,
|
||||||
ClangTranslationUnit* tu,
|
|
||||||
FileConsumer* file_consumer)
|
FileConsumer* file_consumer)
|
||||||
: config(config), tu(tu), file_consumer(file_consumer) {}
|
: tu(tu), file_consumer(file_consumer) {}
|
||||||
|
|
||||||
#if CINDEX_HAVE_PRETTY
|
#if CINDEX_HAVE_PRETTY
|
||||||
CXPrintingPolicy print_policy = nullptr;
|
CXPrintingPolicy print_policy = nullptr;
|
||||||
@ -585,7 +581,7 @@ void SetVarDetail(IndexVar* var,
|
|||||||
// string. Shorten it to just "lambda".
|
// string. Shorten it to just "lambda".
|
||||||
if (type_name.find("(lambda at") != std::string::npos)
|
if (type_name.find("(lambda at") != std::string::npos)
|
||||||
type_name = "lambda";
|
type_name = "lambda";
|
||||||
if (param->config->index.comments)
|
if (g_config->index.comments)
|
||||||
def.comments = cursor.get_comments();
|
def.comments = cursor.get_comments();
|
||||||
def.storage = GetStorageClass(clang_Cursor_getStorageClass(cursor.cx_cursor));
|
def.storage = GetStorageClass(clang_Cursor_getStorageClass(cursor.cx_cursor));
|
||||||
|
|
||||||
@ -870,10 +866,8 @@ CXIdxClientFile OnIndexIncludedFile(CXClientData client_data,
|
|||||||
ClangCursor::VisitResult DumpVisitor(ClangCursor cursor,
|
ClangCursor::VisitResult DumpVisitor(ClangCursor cursor,
|
||||||
ClangCursor parent,
|
ClangCursor parent,
|
||||||
int* level) {
|
int* level) {
|
||||||
for (int i = 0; i < *level; ++i)
|
fprintf(stderr, "%*s%s %s\n", *level * 2, "",
|
||||||
std::cerr << " ";
|
ToString(cursor.get_kind()).c_str(), cursor.get_spell_name().c_str());
|
||||||
std::cerr << ToString(cursor.get_kind()) << " " << cursor.get_spell_name()
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
*level += 1;
|
*level += 1;
|
||||||
cursor.VisitChildren(&DumpVisitor, level);
|
cursor.VisitChildren(&DumpVisitor, level);
|
||||||
@ -1248,7 +1242,7 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor,
|
|||||||
var_def->def.hover =
|
var_def->def.hover =
|
||||||
"#define " + GetDocumentContentInRange(param->tu->cx_tu, cx_extent);
|
"#define " + GetDocumentContentInRange(param->tu->cx_tu, cx_extent);
|
||||||
var_def->def.kind = lsSymbolKind::Macro;
|
var_def->def.kind = lsSymbolKind::Macro;
|
||||||
if (param->config->index.comments)
|
if (g_config->index.comments)
|
||||||
var_def->def.comments = cursor.get_comments();
|
var_def->def.comments = cursor.get_comments();
|
||||||
var_def->def.spell =
|
var_def->def.spell =
|
||||||
SetUse(db, decl_loc_spelling, parent, Role::Definition);
|
SetUse(db, decl_loc_spelling, parent, Role::Definition);
|
||||||
@ -1615,7 +1609,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
|
|
||||||
IndexFuncId func_id = db->ToFuncId(decl_cursor_resolved.cx_cursor);
|
IndexFuncId func_id = db->ToFuncId(decl_cursor_resolved.cx_cursor);
|
||||||
IndexFunc* func = db->Resolve(func_id);
|
IndexFunc* func = db->Resolve(func_id);
|
||||||
if (param->config->index.comments)
|
if (g_config->index.comments)
|
||||||
func->def.comments = cursor.get_comments();
|
func->def.comments = cursor.get_comments();
|
||||||
func->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
func->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
||||||
func->def.storage =
|
func->def.storage =
|
||||||
@ -1763,7 +1757,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
SetTypeName(type, decl_cursor, decl->semanticContainer,
|
SetTypeName(type, decl_cursor, decl->semanticContainer,
|
||||||
decl->entityInfo->name, param);
|
decl->entityInfo->name, param);
|
||||||
type->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
type->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
||||||
if (param->config->index.comments)
|
if (g_config->index.comments)
|
||||||
type->def.comments = decl_cursor.get_comments();
|
type->def.comments = decl_cursor.get_comments();
|
||||||
|
|
||||||
// For Typedef/CXXTypeAlias spanning a few lines, display the declaration
|
// For Typedef/CXXTypeAlias spanning a few lines, display the declaration
|
||||||
@ -1808,7 +1802,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
SetTypeName(type, cursor, decl->semanticContainer, decl->entityInfo->name,
|
SetTypeName(type, cursor, decl->semanticContainer, decl->entityInfo->name,
|
||||||
param);
|
param);
|
||||||
type->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
type->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
||||||
if (param->config->index.comments)
|
if (g_config->index.comments)
|
||||||
type->def.comments = cursor.get_comments();
|
type->def.comments = cursor.get_comments();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -2099,7 +2093,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
|
|
||||||
bool is_template = ref->referencedEntity->templateKind !=
|
bool is_template = ref->referencedEntity->templateKind !=
|
||||||
CXIdxEntityCXXTemplateKind::CXIdxEntity_NonTemplate;
|
CXIdxEntityCXXTemplateKind::CXIdxEntity_NonTemplate;
|
||||||
if (param->config->index.attributeMakeCallsToCtor && is_template &&
|
if (g_config->index.attributeMakeCallsToCtor && is_template &&
|
||||||
str_begin("make", ref->referencedEntity->name)) {
|
str_begin("make", ref->referencedEntity->name)) {
|
||||||
// Try to find the return type of called function. That type will have
|
// Try to find the return type of called function. That type will have
|
||||||
// the constructor function we add a usage to.
|
// the constructor function we add a usage to.
|
||||||
@ -2154,7 +2148,6 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IndexFile>> Parse(
|
std::vector<std::unique_ptr<IndexFile>> Parse(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
std::string file,
|
std::string file,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
@ -2162,7 +2155,7 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
|
|||||||
PerformanceImportFile* perf,
|
PerformanceImportFile* perf,
|
||||||
ClangIndex* index,
|
ClangIndex* index,
|
||||||
bool dump_ast) {
|
bool dump_ast) {
|
||||||
if (!config->index.enabled)
|
if (!g_config->index.enabled)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
file = NormalizePath(file);
|
file = NormalizePath(file);
|
||||||
@ -2190,12 +2183,11 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
|
|||||||
if (dump_ast)
|
if (dump_ast)
|
||||||
Dump(clang_getTranslationUnitCursor(tu->cx_tu));
|
Dump(clang_getTranslationUnitCursor(tu->cx_tu));
|
||||||
|
|
||||||
return ParseWithTu(config, file_consumer_shared, perf, tu.get(), index, file,
|
return ParseWithTu(file_consumer_shared, perf, tu.get(), index, file,
|
||||||
args, unsaved_files);
|
args, unsaved_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
|
std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
PerformanceImportFile* perf,
|
PerformanceImportFile* perf,
|
||||||
ClangTranslationUnit* tu,
|
ClangTranslationUnit* tu,
|
||||||
@ -2218,7 +2210,7 @@ std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
|
|||||||
callback.indexEntityReference = &OnIndexReference;
|
callback.indexEntityReference = &OnIndexReference;
|
||||||
|
|
||||||
FileConsumer file_consumer(file_consumer_shared, file);
|
FileConsumer file_consumer(file_consumer_shared, file);
|
||||||
IndexParam param(config, tu, &file_consumer);
|
IndexParam param(tu, &file_consumer);
|
||||||
for (const CXUnsavedFile& contents : file_contents) {
|
for (const CXUnsavedFile& contents : file_contents) {
|
||||||
param.file_contents[contents.Filename] = FileContents(
|
param.file_contents[contents.Filename] = FileContents(
|
||||||
contents.Filename, std::string(contents.Contents, contents.Length));
|
contents.Filename, std::string(contents.Contents, contents.Length));
|
||||||
|
@ -109,7 +109,7 @@ std::string FileName(CXFile file) {
|
|||||||
CXString cx_name = clang_getFileName(file);
|
CXString cx_name = clang_getFileName(file);
|
||||||
std::string ret = NormalizePath(ToString(cx_name));
|
std::string ret = NormalizePath(ToString(cx_name));
|
||||||
// Resolve /usr/include/c++/7.3.0 symlink.
|
// Resolve /usr/include/c++/7.3.0 symlink.
|
||||||
if (!StartsWith(ret, g_config.projectRoot))
|
if (!StartsWith(ret, g_config->projectRoot))
|
||||||
ret = fs::canonical(ret);
|
ret = fs::canonical(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -110,8 +110,7 @@ See more on https://github.com/MaskRay/ccls/wiki
|
|||||||
// QUERYDB MAIN ////////////////////////////////////////////////////////////////
|
// QUERYDB MAIN ////////////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool QueryDbMainLoop(Config* config,
|
bool QueryDbMainLoop(QueryDatabase* db,
|
||||||
QueryDatabase* db,
|
|
||||||
MultiQueueWaiter* waiter,
|
MultiQueueWaiter* waiter,
|
||||||
Project* project,
|
Project* project,
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
@ -147,7 +146,7 @@ bool QueryDbMainLoop(Config* config,
|
|||||||
// TODO: consider rate-limiting and checking for IPC messages so we don't
|
// TODO: consider rate-limiting and checking for IPC messages so we don't
|
||||||
// block requests / we can serve partial requests.
|
// block requests / we can serve partial requests.
|
||||||
|
|
||||||
if (QueryDb_ImportMain(config, db, import_manager, status, semantic_cache,
|
if (QueryDb_ImportMain(db, import_manager, status, semantic_cache,
|
||||||
working_files)) {
|
working_files)) {
|
||||||
did_work = true;
|
did_work = true;
|
||||||
}
|
}
|
||||||
@ -156,7 +155,6 @@ bool QueryDbMainLoop(Config* config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RunQueryDbThread(const std::string& bin_name,
|
void RunQueryDbThread(const std::string& bin_name,
|
||||||
Config* config,
|
|
||||||
MultiQueueWaiter* querydb_waiter,
|
MultiQueueWaiter* querydb_waiter,
|
||||||
MultiQueueWaiter* indexer_waiter) {
|
MultiQueueWaiter* indexer_waiter) {
|
||||||
Project project;
|
Project project;
|
||||||
@ -166,14 +164,14 @@ void RunQueryDbThread(const std::string& bin_name,
|
|||||||
DiagnosticsEngine diag_engine;
|
DiagnosticsEngine diag_engine;
|
||||||
|
|
||||||
ClangCompleteManager clang_complete(
|
ClangCompleteManager clang_complete(
|
||||||
config, &project, &working_files,
|
&project, &working_files,
|
||||||
[&](std::string path, std::vector<lsDiagnostic> diagnostics) {
|
[&](std::string path, std::vector<lsDiagnostic> diagnostics) {
|
||||||
diag_engine.Publish(&working_files, path, diagnostics);
|
diag_engine.Publish(&working_files, path, diagnostics);
|
||||||
},
|
},
|
||||||
[&](ClangTranslationUnit* tu, const std::vector<CXUnsavedFile>& unsaved,
|
[&](ClangTranslationUnit* tu, const std::vector<CXUnsavedFile>& unsaved,
|
||||||
const std::string& path, const std::vector<std::string>& args) {
|
const std::string& path, const std::vector<std::string>& args) {
|
||||||
IndexWithTuFromCodeCompletion(config, &file_consumer_shared, tu,
|
IndexWithTuFromCodeCompletion(&file_consumer_shared, tu, unsaved, path,
|
||||||
unsaved, path, args);
|
args);
|
||||||
},
|
},
|
||||||
[](lsRequestId id) {
|
[](lsRequestId id) {
|
||||||
if (!std::holds_alternative<std::monostate>(id)) {
|
if (!std::holds_alternative<std::monostate>(id)) {
|
||||||
@ -187,7 +185,7 @@ void RunQueryDbThread(const std::string& bin_name,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
IncludeComplete include_complete(config, &project);
|
IncludeComplete include_complete(&project);
|
||||||
auto global_code_complete_cache = std::make_unique<CodeCompleteCache>();
|
auto global_code_complete_cache = std::make_unique<CodeCompleteCache>();
|
||||||
auto non_global_code_complete_cache = std::make_unique<CodeCompleteCache>();
|
auto non_global_code_complete_cache = std::make_unique<CodeCompleteCache>();
|
||||||
auto signature_cache = std::make_unique<CodeCompleteCache>();
|
auto signature_cache = std::make_unique<CodeCompleteCache>();
|
||||||
@ -198,7 +196,6 @@ void RunQueryDbThread(const std::string& bin_name,
|
|||||||
|
|
||||||
// Setup shared references.
|
// Setup shared references.
|
||||||
for (MessageHandler* handler : *MessageHandler::message_handlers) {
|
for (MessageHandler* handler : *MessageHandler::message_handlers) {
|
||||||
handler->config = config;
|
|
||||||
handler->db = &db;
|
handler->db = &db;
|
||||||
handler->waiter = indexer_waiter;
|
handler->waiter = indexer_waiter;
|
||||||
handler->project = &project;
|
handler->project = &project;
|
||||||
@ -221,7 +218,7 @@ void RunQueryDbThread(const std::string& bin_name,
|
|||||||
SetCurrentThreadName("querydb");
|
SetCurrentThreadName("querydb");
|
||||||
while (true) {
|
while (true) {
|
||||||
bool did_work = QueryDbMainLoop(
|
bool did_work = QueryDbMainLoop(
|
||||||
config, &db, querydb_waiter, &project, &file_consumer_shared,
|
&db, querydb_waiter, &project, &file_consumer_shared,
|
||||||
&import_manager, &import_pipeline_status, ×tamp_manager,
|
&import_manager, &import_pipeline_status, ×tamp_manager,
|
||||||
&semantic_cache, &working_files, &clang_complete, &include_complete,
|
&semantic_cache, &working_files, &clang_complete, &include_complete,
|
||||||
global_code_complete_cache.get(), non_global_code_complete_cache.get(),
|
global_code_complete_cache.get(), non_global_code_complete_cache.get(),
|
||||||
@ -247,8 +244,7 @@ void RunQueryDbThread(const std::string& bin_name,
|
|||||||
// blocks.
|
// blocks.
|
||||||
//
|
//
|
||||||
// |ipc| is connected to a server.
|
// |ipc| is connected to a server.
|
||||||
void LaunchStdinLoop(Config* config,
|
void LaunchStdinLoop(std::unordered_map<MethodType, Timer>* request_times) {
|
||||||
std::unordered_map<MethodType, Timer>* request_times) {
|
|
||||||
// If flushing cin requires flushing cout there could be deadlocks in some
|
// If flushing cin requires flushing cout there could be deadlocks in some
|
||||||
// clients.
|
// clients.
|
||||||
std::cin.tie(nullptr);
|
std::cin.tie(nullptr);
|
||||||
@ -317,13 +313,12 @@ void LaunchStdoutThread(std::unordered_map<MethodType, Timer>* request_times,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LanguageServerMain(const std::string& bin_name,
|
void LanguageServerMain(const std::string& bin_name,
|
||||||
Config* config,
|
|
||||||
MultiQueueWaiter* querydb_waiter,
|
MultiQueueWaiter* querydb_waiter,
|
||||||
MultiQueueWaiter* indexer_waiter,
|
MultiQueueWaiter* indexer_waiter,
|
||||||
MultiQueueWaiter* stdout_waiter) {
|
MultiQueueWaiter* stdout_waiter) {
|
||||||
std::unordered_map<MethodType, Timer> request_times;
|
std::unordered_map<MethodType, Timer> request_times;
|
||||||
|
|
||||||
LaunchStdinLoop(config, &request_times);
|
LaunchStdinLoop(&request_times);
|
||||||
|
|
||||||
// We run a dedicated thread for writing to stdout because there can be an
|
// We run a dedicated thread for writing to stdout because there can be an
|
||||||
// unknown number of delays when output information.
|
// unknown number of delays when output information.
|
||||||
@ -331,7 +326,7 @@ void LanguageServerMain(const std::string& bin_name,
|
|||||||
|
|
||||||
// Start querydb which takes over this thread. The querydb will launch
|
// Start querydb which takes over this thread. The querydb will launch
|
||||||
// indexer threads as needed.
|
// indexer threads as needed.
|
||||||
RunQueryDbThread(bin_name, config, querydb_waiter, indexer_waiter);
|
RunQueryDbThread(bin_name, querydb_waiter, indexer_waiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@ -410,9 +405,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::cerr << "Running language server" << std::endl;
|
LanguageServerMain(argv[0], &querydb_waiter, &indexer_waiter,
|
||||||
auto config = std::make_unique<Config>();
|
|
||||||
LanguageServerMain(argv[0], config.get(), &querydb_waiter, &indexer_waiter,
|
|
||||||
&stdout_waiter);
|
&stdout_waiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
Config g_config;
|
std::unique_ptr<Config> g_config;
|
||||||
|
14
src/config.h
14
src/config.h
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -197,6 +198,10 @@ struct Config {
|
|||||||
// be logged.
|
// be logged.
|
||||||
bool logSkippedPaths = false;
|
bool logSkippedPaths = false;
|
||||||
|
|
||||||
|
// Allow indexing on textDocument/didChange.
|
||||||
|
// May be too slow for big projects, so it is off by default.
|
||||||
|
bool onDidChange = false;
|
||||||
|
|
||||||
// Number of indexer threads. If 0, 80% of cores are used.
|
// Number of indexer threads. If 0, 80% of cores are used.
|
||||||
int threads = 0;
|
int threads = 0;
|
||||||
|
|
||||||
@ -212,10 +217,6 @@ struct Config {
|
|||||||
bool sort = true;
|
bool sort = true;
|
||||||
} workspaceSymbol;
|
} workspaceSymbol;
|
||||||
|
|
||||||
// Allow indexing on textDocument/didChange.
|
|
||||||
// May be too slow for big projects, so it is off by default.
|
|
||||||
bool enableIndexOnDidChange = false;
|
|
||||||
|
|
||||||
struct Xref {
|
struct Xref {
|
||||||
// If true, |Location[]| response will include lexical container.
|
// If true, |Location[]| response will include lexical container.
|
||||||
bool container = false;
|
bool container = false;
|
||||||
@ -249,6 +250,7 @@ MAKE_REFLECT_STRUCT(Config::Index,
|
|||||||
comments,
|
comments,
|
||||||
enabled,
|
enabled,
|
||||||
logSkippedPaths,
|
logSkippedPaths,
|
||||||
|
onDidChange,
|
||||||
threads,
|
threads,
|
||||||
whitelist);
|
whitelist);
|
||||||
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, maxNum, sort);
|
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, maxNum, sort);
|
||||||
@ -276,9 +278,7 @@ MAKE_REFLECT_STRUCT(Config,
|
|||||||
index,
|
index,
|
||||||
workspaceSymbol,
|
workspaceSymbol,
|
||||||
xref,
|
xref,
|
||||||
|
|
||||||
enableIndexOnDidChange,
|
|
||||||
|
|
||||||
dumpAST);
|
dumpAST);
|
||||||
|
|
||||||
extern Config g_config;
|
extern std::unique_ptr<Config> g_config;
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
void DiagnosticsEngine::Init(Config* config) {
|
void DiagnosticsEngine::Init() {
|
||||||
frequencyMs_ = config->diagnostics.frequencyMs;
|
frequencyMs_ = g_config->diagnostics.frequencyMs;
|
||||||
match_ = std::make_unique<GroupMatch>(config->diagnostics.whitelist,
|
match_ = std::make_unique<GroupMatch>(g_config->diagnostics.whitelist,
|
||||||
config->diagnostics.blacklist);
|
g_config->diagnostics.blacklist);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiagnosticsEngine::Publish(WorkingFiles* working_files,
|
void DiagnosticsEngine::Publish(WorkingFiles* working_files,
|
||||||
|
@ -9,7 +9,7 @@ class DiagnosticsEngine {
|
|||||||
int frequencyMs_;
|
int frequencyMs_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(Config*);
|
void Init();
|
||||||
void Publish(WorkingFiles* working_files,
|
void Publish(WorkingFiles* working_files,
|
||||||
std::string path,
|
std::string path,
|
||||||
std::vector<lsDiagnostic> diagnostics);
|
std::vector<lsDiagnostic> diagnostics);
|
||||||
|
@ -160,7 +160,7 @@ TEST_SUITE("fuzzy_match") {
|
|||||||
CHECK(Ranks("ab", {"ab", "aoo_boo", "acb"}));
|
CHECK(Ranks("ab", {"ab", "aoo_boo", "acb"}));
|
||||||
CHECK(Ranks("CC", {"CamelCase", "camelCase", "camelcase"}));
|
CHECK(Ranks("CC", {"CamelCase", "camelCase", "camelcase"}));
|
||||||
CHECK(Ranks("cC", {"camelCase", "CamelCase", "camelcase"}));
|
CHECK(Ranks("cC", {"camelCase", "CamelCase", "camelcase"}));
|
||||||
CHECK(Ranks("c c", {"camel case", "camelCase", "CamelCase", "camelcase",
|
CHECK(Ranks("c c", {"camelCase", "camel case", "CamelCase", "camelcase",
|
||||||
"camel ace"}));
|
"camel ace"}));
|
||||||
CHECK(Ranks("Da.Te",
|
CHECK(Ranks("Da.Te",
|
||||||
{"Data.Text", "Data.Text.Lazy", "Data.Aeson.Encoding.text"}));
|
{"Data.Text", "Data.Text.Lazy", "Data.Aeson.Encoding.text"}));
|
||||||
|
@ -7,19 +7,18 @@ struct ClangIndexer : IIndexer {
|
|||||||
~ClangIndexer() override = default;
|
~ClangIndexer() override = default;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IndexFile>> Index(
|
std::vector<std::unique_ptr<IndexFile>> Index(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
std::string file,
|
std::string file,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
const std::vector<FileContents>& file_contents,
|
const std::vector<FileContents>& file_contents,
|
||||||
PerformanceImportFile* perf) override {
|
PerformanceImportFile* perf) override {
|
||||||
bool dump_ast = false;
|
bool dump_ast = false;
|
||||||
for (const std::string& pattern : config->dumpAST)
|
for (const std::string& pattern : g_config->dumpAST)
|
||||||
if (file.find(pattern) != std::string::npos) {
|
if (file.find(pattern) != std::string::npos) {
|
||||||
dump_ast = true;
|
dump_ast = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return Parse(config, file_consumer_shared, file, args, file_contents, perf,
|
return Parse(file_consumer_shared, file, args, file_contents, perf,
|
||||||
&index, dump_ast);
|
&index, dump_ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +50,6 @@ struct TestIndexer : IIndexer {
|
|||||||
~TestIndexer() override = default;
|
~TestIndexer() override = default;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IndexFile>> Index(
|
std::vector<std::unique_ptr<IndexFile>> Index(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
std::string file,
|
std::string file,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
// like IndexFile
|
// like IndexFile
|
||||||
// - rename this file to indexer.h
|
// - rename this file to indexer.h
|
||||||
|
|
||||||
struct Config;
|
|
||||||
struct IndexFile;
|
struct IndexFile;
|
||||||
struct FileContents;
|
struct FileContents;
|
||||||
struct FileConsumerSharedState;
|
struct FileConsumerSharedState;
|
||||||
@ -35,7 +34,6 @@ struct IIndexer {
|
|||||||
|
|
||||||
virtual ~IIndexer() = default;
|
virtual ~IIndexer() = default;
|
||||||
virtual std::vector<std::unique_ptr<IndexFile>> Index(
|
virtual std::vector<std::unique_ptr<IndexFile>> Index(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
std::string file,
|
std::string file,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
|
@ -95,15 +95,15 @@ long long GetCurrentTimeInMilliseconds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ActiveThread {
|
struct ActiveThread {
|
||||||
ActiveThread(Config* config, ImportPipelineStatus* status)
|
ActiveThread(ImportPipelineStatus* status)
|
||||||
: config_(config), status_(status) {
|
: status_(status) {
|
||||||
if (config_->progressReportFrequencyMs < 0)
|
if (g_config->progressReportFrequencyMs < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++status_->num_active_threads;
|
++status_->num_active_threads;
|
||||||
}
|
}
|
||||||
~ActiveThread() {
|
~ActiveThread() {
|
||||||
if (config_->progressReportFrequencyMs < 0)
|
if (g_config->progressReportFrequencyMs < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
--status_->num_active_threads;
|
--status_->num_active_threads;
|
||||||
@ -122,7 +122,7 @@ struct ActiveThread {
|
|||||||
out.params.activeThreads = status_->num_active_threads;
|
out.params.activeThreads = status_->num_active_threads;
|
||||||
|
|
||||||
// Ignore this progress update if the last update was too recent.
|
// Ignore this progress update if the last update was too recent.
|
||||||
if (config_->progressReportFrequencyMs != 0) {
|
if (g_config->progressReportFrequencyMs != 0) {
|
||||||
// Make sure we output a status update if queue lengths are zero.
|
// Make sure we output a status update if queue lengths are zero.
|
||||||
bool all_zero =
|
bool all_zero =
|
||||||
out.params.indexRequestCount == 0 && out.params.doIdMapCount == 0 &&
|
out.params.indexRequestCount == 0 && out.params.doIdMapCount == 0 &&
|
||||||
@ -133,13 +133,12 @@ struct ActiveThread {
|
|||||||
GetCurrentTimeInMilliseconds() < status_->next_progress_output)
|
GetCurrentTimeInMilliseconds() < status_->next_progress_output)
|
||||||
return;
|
return;
|
||||||
status_->next_progress_output =
|
status_->next_progress_output =
|
||||||
GetCurrentTimeInMilliseconds() + config_->progressReportFrequencyMs;
|
GetCurrentTimeInMilliseconds() + g_config->progressReportFrequencyMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueManager::WriteStdout(kMethodType_Unknown, out);
|
QueueManager::WriteStdout(kMethodType_Unknown, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
Config* config_;
|
|
||||||
ImportPipelineStatus* status_;
|
ImportPipelineStatus* status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -356,8 +355,7 @@ std::vector<FileContents> PreloadFileContents(
|
|||||||
return file_contents;
|
return file_contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseFile(Config* config,
|
void ParseFile(DiagnosticsEngine* diag_engine,
|
||||||
DiagnosticsEngine* diag_engine,
|
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
TimestampManager* timestamp_manager,
|
TimestampManager* timestamp_manager,
|
||||||
@ -390,11 +388,11 @@ void ParseFile(Config* config,
|
|||||||
|
|
||||||
std::vector<Index_DoIdMap> result;
|
std::vector<Index_DoIdMap> result;
|
||||||
PerformanceImportFile perf;
|
PerformanceImportFile perf;
|
||||||
auto indexes = indexer->Index(config, file_consumer_shared, path_to_index,
|
auto indexes = indexer->Index(file_consumer_shared, path_to_index, entry.args,
|
||||||
entry.args, file_contents, &perf);
|
file_contents, &perf);
|
||||||
|
|
||||||
if (indexes.empty()) {
|
if (indexes.empty()) {
|
||||||
if (config->index.enabled &&
|
if (g_config->index.enabled &&
|
||||||
!std::holds_alternative<std::monostate>(request.id)) {
|
!std::holds_alternative<std::monostate>(request.id)) {
|
||||||
Out_Error out;
|
Out_Error out;
|
||||||
out.id = request.id;
|
out.id = request.id;
|
||||||
@ -428,7 +426,6 @@ void ParseFile(Config* config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IndexMain_DoParse(
|
bool IndexMain_DoParse(
|
||||||
Config* config,
|
|
||||||
DiagnosticsEngine* diag_engine,
|
DiagnosticsEngine* diag_engine,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
@ -444,7 +441,7 @@ bool IndexMain_DoParse(
|
|||||||
Project::Entry entry;
|
Project::Entry entry;
|
||||||
entry.filename = request->path;
|
entry.filename = request->path;
|
||||||
entry.args = request->args;
|
entry.args = request->args;
|
||||||
ParseFile(config, diag_engine, working_files, file_consumer_shared,
|
ParseFile(diag_engine, working_files, file_consumer_shared,
|
||||||
timestamp_manager, modification_timestamp_fetcher, import_manager,
|
timestamp_manager, modification_timestamp_fetcher, import_manager,
|
||||||
indexer, request.value(), entry);
|
indexer, request.value(), entry);
|
||||||
return true;
|
return true;
|
||||||
@ -544,7 +541,6 @@ ImportPipelineStatus::ImportPipelineStatus()
|
|||||||
// real-time indexing.
|
// real-time indexing.
|
||||||
// TODO: add option to disable this.
|
// TODO: add option to disable this.
|
||||||
void IndexWithTuFromCodeCompletion(
|
void IndexWithTuFromCodeCompletion(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
ClangTranslationUnit* tu,
|
ClangTranslationUnit* tu,
|
||||||
const std::vector<CXUnsavedFile>& file_contents,
|
const std::vector<CXUnsavedFile>& file_contents,
|
||||||
@ -554,10 +550,10 @@ void IndexWithTuFromCodeCompletion(
|
|||||||
|
|
||||||
PerformanceImportFile perf;
|
PerformanceImportFile perf;
|
||||||
ClangIndex index;
|
ClangIndex index;
|
||||||
auto indexes = ParseWithTu(config, file_consumer_shared, &perf, tu, &index,
|
auto indexes = ParseWithTu(file_consumer_shared, &perf, tu, &index, path,
|
||||||
path, args, file_contents);
|
args, file_contents);
|
||||||
if (indexes.empty())
|
if (indexes.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<Index_DoIdMap> result;
|
std::vector<Index_DoIdMap> result;
|
||||||
for (std::unique_ptr<IndexFile>& new_index : indexes) {
|
for (std::unique_ptr<IndexFile>& new_index : indexes) {
|
||||||
@ -579,8 +575,7 @@ void IndexWithTuFromCodeCompletion(
|
|||||||
QueueManager::instance()->do_id_map.EnqueueAll(std::move(result));
|
QueueManager::instance()->do_id_map.EnqueueAll(std::move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Indexer_Main(Config* config,
|
void Indexer_Main(DiagnosticsEngine* diag_engine,
|
||||||
DiagnosticsEngine* diag_engine,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
TimestampManager* timestamp_manager,
|
TimestampManager* timestamp_manager,
|
||||||
ImportManager* import_manager,
|
ImportManager* import_manager,
|
||||||
@ -597,7 +592,7 @@ void Indexer_Main(Config* config,
|
|||||||
bool did_work = false;
|
bool did_work = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
ActiveThread active_thread(config, status);
|
ActiveThread active_thread(status);
|
||||||
|
|
||||||
// TODO: process all off IndexMain_DoIndex before calling
|
// TODO: process all off IndexMain_DoIndex before calling
|
||||||
// IndexMain_DoCreateIndexUpdate for better icache behavior. We need to
|
// IndexMain_DoCreateIndexUpdate for better icache behavior. We need to
|
||||||
@ -608,7 +603,7 @@ void Indexer_Main(Config* config,
|
|||||||
// IndexMain_DoCreateIndexUpdate so we don't starve querydb from doing any
|
// IndexMain_DoCreateIndexUpdate so we don't starve querydb from doing any
|
||||||
// work. Running both also lets the user query the partially constructed
|
// work. Running both also lets the user query the partially constructed
|
||||||
// index.
|
// index.
|
||||||
did_work = IndexMain_DoParse(config, diag_engine, working_files,
|
did_work = IndexMain_DoParse(diag_engine, working_files,
|
||||||
file_consumer_shared, timestamp_manager,
|
file_consumer_shared, timestamp_manager,
|
||||||
&modification_timestamp_fetcher,
|
&modification_timestamp_fetcher,
|
||||||
import_manager, indexer.get()) ||
|
import_manager, indexer.get()) ||
|
||||||
@ -723,15 +718,14 @@ void QueryDb_OnIndexed(QueueManager* queue,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool QueryDb_ImportMain(Config* config,
|
bool QueryDb_ImportMain(QueryDatabase* db,
|
||||||
QueryDatabase* db,
|
|
||||||
ImportManager* import_manager,
|
ImportManager* import_manager,
|
||||||
ImportPipelineStatus* status,
|
ImportPipelineStatus* status,
|
||||||
SemanticHighlightSymbolCache* semantic_cache,
|
SemanticHighlightSymbolCache* semantic_cache,
|
||||||
WorkingFiles* working_files) {
|
WorkingFiles* working_files) {
|
||||||
auto* queue = QueueManager::instance();
|
auto* queue = QueueManager::instance();
|
||||||
|
|
||||||
ActiveThread active_thread(config, status);
|
ActiveThread active_thread(status);
|
||||||
|
|
||||||
bool did_work = false;
|
bool did_work = false;
|
||||||
|
|
||||||
@ -760,16 +754,17 @@ bool QueryDb_ImportMain(Config* config,
|
|||||||
TEST_SUITE("ImportPipeline") {
|
TEST_SUITE("ImportPipeline") {
|
||||||
struct Fixture {
|
struct Fixture {
|
||||||
Fixture() {
|
Fixture() {
|
||||||
|
g_config = std::make_unique<Config>();
|
||||||
QueueManager::Init(&querydb_waiter, &indexer_waiter, &stdout_waiter);
|
QueueManager::Init(&querydb_waiter, &indexer_waiter, &stdout_waiter);
|
||||||
|
|
||||||
queue = QueueManager::instance();
|
queue = QueueManager::instance();
|
||||||
cache_manager = ICacheManager::MakeFake({});
|
cache_manager = ICacheManager::MakeFake({});
|
||||||
indexer = IIndexer::MakeTestIndexer({});
|
indexer = IIndexer::MakeTestIndexer({});
|
||||||
diag_engine.Init(&config);
|
diag_engine.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PumpOnce() {
|
bool PumpOnce() {
|
||||||
return IndexMain_DoParse(&config, &diag_engine, &working_files,
|
return IndexMain_DoParse(&diag_engine, &working_files,
|
||||||
&file_consumer_shared, ×tamp_manager,
|
&file_consumer_shared, ×tamp_manager,
|
||||||
&modification_timestamp_fetcher, &import_manager,
|
&modification_timestamp_fetcher, &import_manager,
|
||||||
indexer.get());
|
indexer.get());
|
||||||
@ -788,7 +783,6 @@ TEST_SUITE("ImportPipeline") {
|
|||||||
MultiQueueWaiter stdout_waiter;
|
MultiQueueWaiter stdout_waiter;
|
||||||
|
|
||||||
QueueManager* queue = nullptr;
|
QueueManager* queue = nullptr;
|
||||||
Config config;
|
|
||||||
DiagnosticsEngine diag_engine;
|
DiagnosticsEngine diag_engine;
|
||||||
WorkingFiles working_files;
|
WorkingFiles working_files;
|
||||||
FileConsumerSharedState file_consumer_shared;
|
FileConsumerSharedState file_consumer_shared;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct ClangTranslationUnit;
|
struct ClangTranslationUnit;
|
||||||
struct Config;
|
|
||||||
class DiagnosticsEngine;
|
class DiagnosticsEngine;
|
||||||
struct FileConsumerSharedState;
|
struct FileConsumerSharedState;
|
||||||
struct ImportManager;
|
struct ImportManager;
|
||||||
@ -28,15 +27,13 @@ struct ImportPipelineStatus {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void IndexWithTuFromCodeCompletion(
|
void IndexWithTuFromCodeCompletion(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
ClangTranslationUnit* tu,
|
ClangTranslationUnit* tu,
|
||||||
const std::vector<CXUnsavedFile>& file_contents,
|
const std::vector<CXUnsavedFile>& file_contents,
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
const std::vector<std::string>& args);
|
const std::vector<std::string>& args);
|
||||||
|
|
||||||
void Indexer_Main(Config* config,
|
void Indexer_Main(DiagnosticsEngine* diag_engine,
|
||||||
DiagnosticsEngine* diag_engine,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
TimestampManager* timestamp_manager,
|
TimestampManager* timestamp_manager,
|
||||||
ImportManager* import_manager,
|
ImportManager* import_manager,
|
||||||
@ -45,8 +42,7 @@ void Indexer_Main(Config* config,
|
|||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
MultiQueueWaiter* waiter);
|
MultiQueueWaiter* waiter);
|
||||||
|
|
||||||
bool QueryDb_ImportMain(Config* config,
|
bool QueryDb_ImportMain(QueryDatabase* db,
|
||||||
QueryDatabase* db,
|
|
||||||
ImportManager* import_manager,
|
ImportManager* import_manager,
|
||||||
ImportPipelineStatus* status,
|
ImportPipelineStatus* status,
|
||||||
SemanticHighlightSymbolCache* semantic_cache,
|
SemanticHighlightSymbolCache* semantic_cache,
|
||||||
|
@ -13,14 +13,14 @@ struct CompletionCandidate {
|
|||||||
lsCompletionItem completion_item;
|
lsCompletionItem completion_item;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string ElideLongPath(Config* config, const std::string& path) {
|
std::string ElideLongPath(const std::string& path) {
|
||||||
if (config->completion.includeMaxPathSize <= 0)
|
if (g_config->completion.includeMaxPathSize <= 0)
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
if ((int)path.size() <= config->completion.includeMaxPathSize)
|
if ((int)path.size() <= g_config->completion.includeMaxPathSize)
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
size_t start = path.size() - config->completion.includeMaxPathSize;
|
size_t start = path.size() - g_config->completion.includeMaxPathSize;
|
||||||
return ".." + path.substr(start + 2);
|
return ".." + path.substr(start + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,12 +73,11 @@ bool TrimPath(Project* project,
|
|||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsCompletionItem BuildCompletionItem(Config* config,
|
lsCompletionItem BuildCompletionItem(const std::string& path,
|
||||||
const std::string& path,
|
|
||||||
bool use_angle_brackets,
|
bool use_angle_brackets,
|
||||||
bool is_stl) {
|
bool is_stl) {
|
||||||
lsCompletionItem item;
|
lsCompletionItem item;
|
||||||
item.label = ElideLongPath(config, path);
|
item.label = ElideLongPath(path);
|
||||||
item.detail = path; // the include path, used in de-duplicating
|
item.detail = path; // the include path, used in de-duplicating
|
||||||
item.textEdit = lsTextEdit();
|
item.textEdit = lsTextEdit();
|
||||||
item.textEdit->newText = path;
|
item.textEdit->newText = path;
|
||||||
@ -96,8 +95,8 @@ lsCompletionItem BuildCompletionItem(Config* config,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
IncludeComplete::IncludeComplete(Config* config, Project* project)
|
IncludeComplete::IncludeComplete(Project* project)
|
||||||
: is_scanning(false), config_(config), project_(project) {}
|
: is_scanning(false), project_(project) {}
|
||||||
|
|
||||||
void IncludeComplete::Rescan() {
|
void IncludeComplete::Rescan() {
|
||||||
if (is_scanning)
|
if (is_scanning)
|
||||||
@ -107,17 +106,17 @@ void IncludeComplete::Rescan() {
|
|||||||
absolute_path_to_completion_item.clear();
|
absolute_path_to_completion_item.clear();
|
||||||
inserted_paths.clear();
|
inserted_paths.clear();
|
||||||
|
|
||||||
if (!match_ && (!config_->completion.includeWhitelist.empty() ||
|
if (!match_ && (g_config->completion.includeWhitelist.size() ||
|
||||||
!config_->completion.includeBlacklist.empty()))
|
g_config->completion.includeBlacklist.size()))
|
||||||
match_ = std::make_unique<GroupMatch>(config_->completion.includeWhitelist,
|
match_ = std::make_unique<GroupMatch>(g_config->completion.includeWhitelist,
|
||||||
config_->completion.includeBlacklist);
|
g_config->completion.includeBlacklist);
|
||||||
|
|
||||||
is_scanning = true;
|
is_scanning = true;
|
||||||
StartThread("scan_includes", [this]() {
|
StartThread("scan_includes", [this]() {
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
|
||||||
InsertStlIncludes();
|
InsertStlIncludes();
|
||||||
InsertIncludesFromDirectory(config_->projectRoot,
|
InsertIncludesFromDirectory(g_config->projectRoot,
|
||||||
false /*use_angle_brackets*/);
|
false /*use_angle_brackets*/);
|
||||||
for (const std::string& dir : project_->quote_include_directories)
|
for (const std::string& dir : project_->quote_include_directories)
|
||||||
InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/);
|
InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/);
|
||||||
@ -150,16 +149,16 @@ void IncludeComplete::InsertCompletionItem(const std::string& absolute_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IncludeComplete::AddFile(const std::string& absolute_path) {
|
void IncludeComplete::AddFile(const std::string& absolute_path) {
|
||||||
if (!EndsWithAny(absolute_path, config_->completion.includeSuffixWhitelist))
|
if (!EndsWithAny(absolute_path, g_config->completion.includeSuffixWhitelist))
|
||||||
return;
|
return;
|
||||||
if (match_ && !match_->IsMatch(absolute_path))
|
if (match_ && !match_->IsMatch(absolute_path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string trimmed_path = absolute_path;
|
std::string trimmed_path = absolute_path;
|
||||||
bool use_angle_brackets =
|
bool use_angle_brackets =
|
||||||
TrimPath(project_, config_->projectRoot, &trimmed_path);
|
TrimPath(project_, g_config->projectRoot, &trimmed_path);
|
||||||
lsCompletionItem item = BuildCompletionItem(
|
lsCompletionItem item =
|
||||||
config_, trimmed_path, use_angle_brackets, false /*is_stl*/);
|
BuildCompletionItem(trimmed_path, use_angle_brackets, false /*is_stl*/);
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(completion_items_mutex, std::defer_lock);
|
std::unique_lock<std::mutex> lock(completion_items_mutex, std::defer_lock);
|
||||||
if (is_scanning)
|
if (is_scanning)
|
||||||
@ -180,15 +179,15 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory,
|
|||||||
GetFilesInFolder(
|
GetFilesInFolder(
|
||||||
directory, true /*recursive*/, false /*add_folder_to_path*/,
|
directory, true /*recursive*/, false /*add_folder_to_path*/,
|
||||||
[&](const std::string& path) {
|
[&](const std::string& path) {
|
||||||
if (!EndsWithAny(path, config_->completion.includeSuffixWhitelist))
|
if (!EndsWithAny(path, g_config->completion.includeSuffixWhitelist))
|
||||||
return;
|
return;
|
||||||
if (match_ && !match_->IsMatch(directory + path))
|
if (match_ && !match_->IsMatch(directory + path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CompletionCandidate candidate;
|
CompletionCandidate candidate;
|
||||||
candidate.absolute_path = directory + path;
|
candidate.absolute_path = directory + path;
|
||||||
candidate.completion_item = BuildCompletionItem(
|
candidate.completion_item =
|
||||||
config_, path, use_angle_brackets, false /*is_stl*/);
|
BuildCompletionItem(path, use_angle_brackets, false /*is_stl*/);
|
||||||
results.push_back(candidate);
|
results.push_back(candidate);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -202,7 +201,7 @@ void IncludeComplete::InsertStlIncludes() {
|
|||||||
std::lock_guard<std::mutex> lock(completion_items_mutex);
|
std::lock_guard<std::mutex> lock(completion_items_mutex);
|
||||||
for (const char* stl_header : kStandardLibraryIncludes) {
|
for (const char* stl_header : kStandardLibraryIncludes) {
|
||||||
completion_items.push_back(BuildCompletionItem(
|
completion_items.push_back(BuildCompletionItem(
|
||||||
config_, stl_header, true /*use_angle_brackets*/, true /*is_stl*/));
|
stl_header, true /*use_angle_brackets*/, true /*is_stl*/));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ struct GroupMatch;
|
|||||||
struct Project;
|
struct Project;
|
||||||
|
|
||||||
struct IncludeComplete {
|
struct IncludeComplete {
|
||||||
IncludeComplete(Config* config, Project* project);
|
IncludeComplete(Project* project);
|
||||||
|
|
||||||
// Starts scanning directories. Clears existing cache.
|
// Starts scanning directories. Clears existing cache.
|
||||||
void Rescan();
|
void Rescan();
|
||||||
@ -45,7 +45,6 @@ struct IncludeComplete {
|
|||||||
std::unordered_map<std::string, int> inserted_paths;
|
std::unordered_map<std::string, int> inserted_paths;
|
||||||
|
|
||||||
// Cached references
|
// Cached references
|
||||||
Config* config_;
|
|
||||||
Project* project_;
|
Project* project_;
|
||||||
std::unique_ptr<GroupMatch> match_;
|
std::unique_ptr<GroupMatch> match_;
|
||||||
};
|
};
|
||||||
|
@ -518,7 +518,6 @@ struct NamespaceHelper {
|
|||||||
// |dependencies| are the existing dependencies of |import_file| if this is a
|
// |dependencies| are the existing dependencies of |import_file| if this is a
|
||||||
// reparse.
|
// reparse.
|
||||||
std::vector<std::unique_ptr<IndexFile>> Parse(
|
std::vector<std::unique_ptr<IndexFile>> Parse(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
std::string file,
|
std::string file,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
@ -527,7 +526,6 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
|
|||||||
ClangIndex* index,
|
ClangIndex* index,
|
||||||
bool dump_ast = false);
|
bool dump_ast = false);
|
||||||
std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
|
std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
|
||||||
Config* config,
|
|
||||||
FileConsumerSharedState* file_consumer_shared,
|
FileConsumerSharedState* file_consumer_shared,
|
||||||
PerformanceImportFile* perf,
|
PerformanceImportFile* perf,
|
||||||
ClangTranslationUnit* tu,
|
ClangTranslationUnit* tu,
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <doctest/doctest.h>
|
#include <doctest/doctest.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// VSCode (UTF-16) disagrees with Emacs lsp-mode (UTF-8) on how to represent
|
// VSCode (UTF-16) disagrees with Emacs lsp-mode (UTF-8) on how to represent
|
||||||
// text documents.
|
// text documents.
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
MessageRegistry* MessageRegistry::instance_ = nullptr;
|
MessageRegistry* MessageRegistry::instance_ = nullptr;
|
||||||
|
|
||||||
|
@ -101,9 +101,9 @@ SemanticHighlightSymbolCache::Entry::GetMapForSymbol_(SymbolKind kind) {
|
|||||||
SemanticHighlightSymbolCache::SemanticHighlightSymbolCache()
|
SemanticHighlightSymbolCache::SemanticHighlightSymbolCache()
|
||||||
: cache_(kCacheSize) {}
|
: cache_(kCacheSize) {}
|
||||||
|
|
||||||
void SemanticHighlightSymbolCache::Init(Config* config) {
|
void SemanticHighlightSymbolCache::Init() {
|
||||||
match_ = std::make_unique<GroupMatch>(config->highlight.whitelist,
|
match_ = std::make_unique<GroupMatch>(g_config->highlight.whitelist,
|
||||||
config->highlight.blacklist);
|
g_config->highlight.blacklist);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SemanticHighlightSymbolCache::Entry>
|
std::shared_ptr<SemanticHighlightSymbolCache::Entry>
|
||||||
|
@ -55,7 +55,7 @@ struct SemanticHighlightSymbolCache {
|
|||||||
std::unique_ptr<GroupMatch> match_;
|
std::unique_ptr<GroupMatch> match_;
|
||||||
|
|
||||||
SemanticHighlightSymbolCache();
|
SemanticHighlightSymbolCache();
|
||||||
void Init(Config*);
|
void Init();
|
||||||
std::shared_ptr<Entry> GetCacheForFile(const std::string& path);
|
std::shared_ptr<Entry> GetCacheForFile(const std::string& path);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,7 +103,6 @@ MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting,
|
|||||||
static type type##message_handler_instance_;
|
static type type##message_handler_instance_;
|
||||||
|
|
||||||
struct MessageHandler {
|
struct MessageHandler {
|
||||||
Config* config = nullptr;
|
|
||||||
QueryDatabase* db = nullptr;
|
QueryDatabase* db = nullptr;
|
||||||
MultiQueueWaiter* waiter = nullptr;
|
MultiQueueWaiter* waiter = nullptr;
|
||||||
Project* project = nullptr;
|
Project* project = nullptr;
|
||||||
|
@ -33,15 +33,13 @@ struct Handler_CclsBase : BaseMessageHandler<In_CclsBase> {
|
|||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
if (sym.kind == SymbolKind::Type) {
|
if (sym.kind == SymbolKind::Type) {
|
||||||
if (const auto* def = db->GetType(sym).AnyDef())
|
if (const auto* def = db->GetType(sym).AnyDef())
|
||||||
out.result = GetLsLocationExs(
|
out.result = GetLsLocationExs(db, working_files,
|
||||||
db, working_files, GetDeclarations(db, def->bases),
|
GetDeclarations(db, def->bases));
|
||||||
config->xref.container, config->xref.maxNum);
|
|
||||||
break;
|
break;
|
||||||
} else if (sym.kind == SymbolKind::Func) {
|
} else if (sym.kind == SymbolKind::Func) {
|
||||||
if (const auto* def = db->GetFunc(sym).AnyDef())
|
if (const auto* def = db->GetFunc(sym).AnyDef())
|
||||||
out.result = GetLsLocationExs(
|
out.result = GetLsLocationExs(db, working_files,
|
||||||
db, working_files, GetDeclarations(db, def->bases),
|
GetDeclarations(db, def->bases));
|
||||||
config->xref.container, config->xref.maxNum);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,7 @@ struct Handler_CclsCallers : BaseMessageHandler<In_CclsCallers> {
|
|||||||
uses.push_back(func_ref);
|
uses.push_back(func_ref);
|
||||||
for (Use func_ref : GetUsesForAllDerived(db, func))
|
for (Use func_ref : GetUsesForAllDerived(db, func))
|
||||||
uses.push_back(func_ref);
|
uses.push_back(func_ref);
|
||||||
out.result =
|
out.result = GetLsLocationExs(db, working_files, uses);
|
||||||
GetLsLocationExs(db, working_files, uses, config->xref.container,
|
|
||||||
config->xref.maxNum);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,15 +30,13 @@ struct Handler_CclsDerived : BaseMessageHandler<In_CclsDerived> {
|
|||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
if (sym.kind == SymbolKind::Type) {
|
if (sym.kind == SymbolKind::Type) {
|
||||||
QueryType& type = db->GetType(sym);
|
QueryType& type = db->GetType(sym);
|
||||||
out.result = GetLsLocationExs(
|
out.result = GetLsLocationExs(db, working_files,
|
||||||
db, working_files, GetDeclarations(db, type.derived),
|
GetDeclarations(db, type.derived));
|
||||||
config->xref.container, config->xref.maxNum);
|
|
||||||
break;
|
break;
|
||||||
} else if (sym.kind == SymbolKind::Func) {
|
} else if (sym.kind == SymbolKind::Func) {
|
||||||
QueryFunc& func = db->GetFunc(sym);
|
QueryFunc& func = db->GetFunc(sym);
|
||||||
out.result = GetLsLocationExs(
|
out.result = GetLsLocationExs(db, working_files,
|
||||||
db, working_files, GetDeclarations(db, func.derived),
|
GetDeclarations(db, func.derived));
|
||||||
config->xref.container, config->xref.maxNum);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,7 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler<In_CclsFreshenIndex> {
|
|||||||
|
|
||||||
Timer time;
|
Timer time;
|
||||||
// Send index requests for every file.
|
// Send index requests for every file.
|
||||||
project->Index(config, QueueManager::instance(), working_files,
|
project->Index(QueueManager::instance(), working_files, std::monostate());
|
||||||
std::monostate());
|
|
||||||
time.ResetAndPrint("[perf] Dispatched $ccls/freshenIndex index requests");
|
time.ResetAndPrint("[perf] Dispatched $ccls/freshenIndex index requests");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -132,12 +132,10 @@ struct Handler_CclsRandom : BaseMessageHandler<In_CclsRandom> {
|
|||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
sum += x[i];
|
sum += x[i];
|
||||||
if (sum >= roulette) {
|
if (sum >= roulette) {
|
||||||
Maybe<Use> use = GetDefinitionExtent(db, syms[i]);
|
if (Maybe<Use> use = GetDefinitionExtent(db, syms[i]))
|
||||||
if (!use)
|
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
||||||
continue;
|
g_config->xref.container))
|
||||||
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
out.result.push_back(*ls_loc);
|
||||||
config->xref.container))
|
|
||||||
out.result.push_back(*ls_loc);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,9 +43,8 @@ struct Handler_CclsVars : BaseMessageHandler<In_CclsVars> {
|
|||||||
// fallthrough
|
// fallthrough
|
||||||
case SymbolKind::Type: {
|
case SymbolKind::Type: {
|
||||||
QueryType& type = db->types[id.id];
|
QueryType& type = db->types[id.id];
|
||||||
out.result = GetLsLocationExs(
|
out.result = GetLsLocationExs(db, working_files,
|
||||||
db, working_files, GetDeclarations(db, type.instances),
|
GetDeclarations(db, type.instances));
|
||||||
config->xref.container, config->xref.maxNum);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,6 +428,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
JsonWriter json_writer(&writer);
|
JsonWriter json_writer(&writer);
|
||||||
Reflect(json_writer, request->params.initializationOptions);
|
Reflect(json_writer, request->params.initializationOptions);
|
||||||
LOG_S(INFO) << "Init parameters: " << output.GetString();
|
LOG_S(INFO) << "Init parameters: " << output.GetString();
|
||||||
|
std::unique_ptr<Config> config;
|
||||||
|
|
||||||
if (request->params.rootUri) {
|
if (request->params.rootUri) {
|
||||||
std::string project_path =
|
std::string project_path =
|
||||||
@ -437,9 +438,9 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
|
|
||||||
{
|
{
|
||||||
if (request->params.initializationOptions)
|
if (request->params.initializationOptions)
|
||||||
*config = *request->params.initializationOptions;
|
config = std::make_unique<Config>(*request->params.initializationOptions);
|
||||||
else
|
else
|
||||||
*config = Config();
|
config = std::make_unique<Config>();
|
||||||
rapidjson::Document reader;
|
rapidjson::Document reader;
|
||||||
reader.Parse(g_init_options.c_str());
|
reader.Parse(g_init_options.c_str());
|
||||||
if (!reader.HasParseError()) {
|
if (!reader.HasParseError()) {
|
||||||
@ -508,32 +509,29 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
MakeDirectoryRecursive(config->cacheDirectory + '@' +
|
MakeDirectoryRecursive(config->cacheDirectory + '@' +
|
||||||
EscapeFileName(config->projectRoot));
|
EscapeFileName(config->projectRoot));
|
||||||
|
|
||||||
g_config = *config;
|
g_config = std::move(config);
|
||||||
Timer time;
|
Timer time;
|
||||||
diag_engine->Init(config);
|
diag_engine->Init();
|
||||||
semantic_cache->Init(config);
|
semantic_cache->Init();
|
||||||
|
|
||||||
// Open up / load the project.
|
// Open up / load the project.
|
||||||
project->Load(config, project_path);
|
project->Load(project_path);
|
||||||
time.ResetAndPrint("[perf] Loaded compilation entries (" +
|
time.ResetAndPrint("[perf] Loaded compilation entries (" +
|
||||||
std::to_string(project->entries.size()) + " files)");
|
std::to_string(project->entries.size()) + " files)");
|
||||||
|
|
||||||
// Start indexer threads. Start this after loading the project, as that
|
// Start indexer threads. Start this after loading the project, as that
|
||||||
// may take a long time. Indexer threads will emit status/progress
|
// may take a long time. Indexer threads will emit status/progress
|
||||||
// reports.
|
// reports.
|
||||||
if (config->index.threads == 0) {
|
if (g_config->index.threads == 0) {
|
||||||
// If the user has not specified how many indexers to run, try to
|
// If the user has not specified how many indexers to run, try to
|
||||||
// guess an appropriate value. Default to 80% utilization.
|
// guess an appropriate value. Default to 80% utilization.
|
||||||
const float kDefaultTargetUtilization = 0.8f;
|
g_config->index.threads =
|
||||||
config->index.threads = (int)(std::thread::hardware_concurrency() *
|
std::max(int(std::thread::hardware_concurrency() * 0.8), 1);
|
||||||
kDefaultTargetUtilization);
|
|
||||||
if (config->index.threads <= 0)
|
|
||||||
config->index.threads = 1;
|
|
||||||
}
|
}
|
||||||
LOG_S(INFO) << "Starting " << config->index.threads << " indexers";
|
LOG_S(INFO) << "Starting " << g_config->index.threads << " indexers";
|
||||||
for (int i = 0; i < config->index.threads; ++i) {
|
for (int i = 0; i < g_config->index.threads; ++i) {
|
||||||
StartThread("indexer" + std::to_string(i), [=]() {
|
StartThread("indexer" + std::to_string(i), [=]() {
|
||||||
Indexer_Main(config, diag_engine, file_consumer_shared,
|
Indexer_Main(diag_engine, file_consumer_shared,
|
||||||
timestamp_manager, import_manager,
|
timestamp_manager, import_manager,
|
||||||
import_pipeline_status, project, working_files, waiter);
|
import_pipeline_status, project, working_files, waiter);
|
||||||
});
|
});
|
||||||
@ -544,8 +542,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
include_complete->Rescan();
|
include_complete->Rescan();
|
||||||
|
|
||||||
time.Reset();
|
time.Reset();
|
||||||
project->Index(config, QueueManager::instance(), working_files,
|
project->Index(QueueManager::instance(), working_files, request->id);
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ struct Handler_TextDocumentCodeLens
|
|||||||
case SymbolKind::Var: {
|
case SymbolKind::Var: {
|
||||||
QueryVar& var = db->GetVar(sym);
|
QueryVar& var = db->GetVar(sym);
|
||||||
const QueryVar::Def* def = var.AnyDef();
|
const QueryVar::Def* def = var.AnyDef();
|
||||||
if (!def || (def->is_local() && !config->codeLens.localVariables))
|
if (!def || (def->is_local() && !g_config->codeLens.localVariables))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool force_display = true;
|
bool force_display = true;
|
||||||
|
@ -160,9 +160,8 @@ char* tofixedbase64(T input, char* out) {
|
|||||||
// when given 1000+ completion items.
|
// when given 1000+ completion items.
|
||||||
void FilterAndSortCompletionResponse(
|
void FilterAndSortCompletionResponse(
|
||||||
Out_TextDocumentComplete* complete_response,
|
Out_TextDocumentComplete* complete_response,
|
||||||
const std::string& complete_text,
|
const std::string& complete_text) {
|
||||||
bool enable) {
|
if (!g_config->completion.filterAndSort)
|
||||||
if (!enable)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ScopedPerfTimer timer{"FilterAndSortCompletionResponse"};
|
ScopedPerfTimer timer{"FilterAndSortCompletionResponse"};
|
||||||
@ -327,8 +326,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
|||||||
return k == result.keyword;
|
return k == result.keyword;
|
||||||
})) {
|
})) {
|
||||||
out.result.items = preprocessorKeywordCompletionItems(result.match);
|
out.result.items = preprocessorKeywordCompletionItems(result.match);
|
||||||
FilterAndSortCompletionResponse(&out, result.keyword,
|
FilterAndSortCompletionResponse(&out, result.keyword);
|
||||||
config->completion.filterAndSort);
|
|
||||||
}
|
}
|
||||||
} else if (result.keyword.compare("include") == 0) {
|
} else if (result.keyword.compare("include") == 0) {
|
||||||
{
|
{
|
||||||
@ -342,8 +340,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
|||||||
if (quote.empty() || quote == (item.use_angle_brackets_ ? "<" : "\""))
|
if (quote.empty() || quote == (item.use_angle_brackets_ ? "<" : "\""))
|
||||||
out.result.items.push_back(item);
|
out.result.items.push_back(item);
|
||||||
}
|
}
|
||||||
FilterAndSortCompletionResponse(&out, result.pattern,
|
FilterAndSortCompletionResponse(&out, result.pattern);
|
||||||
config->completion.filterAndSort);
|
|
||||||
DecorateIncludePaths(result.match, &out.result.items);
|
DecorateIncludePaths(result.match, &out.result.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,8 +362,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
|
|||||||
out.result.items = results;
|
out.result.items = results;
|
||||||
|
|
||||||
// Emit completion results.
|
// Emit completion results.
|
||||||
FilterAndSortCompletionResponse(&out, existing_completion,
|
FilterAndSortCompletionResponse(&out, existing_completion);
|
||||||
config->completion.filterAndSort);
|
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
QueueManager::WriteStdout(kMethodType, out);
|
||||||
|
|
||||||
// Cache completion results.
|
// Cache completion results.
|
||||||
|
@ -105,9 +105,7 @@ struct Handler_TextDocumentDefinition
|
|||||||
if (uses.empty() && on_def)
|
if (uses.empty() && on_def)
|
||||||
uses.push_back(*on_def);
|
uses.push_back(*on_def);
|
||||||
}
|
}
|
||||||
AddRange(&out.result,
|
AddRange(&out.result, GetLsLocationExs(db, working_files, uses));
|
||||||
GetLsLocationExs(db, working_files, uses, config->xref.container,
|
|
||||||
config->xref.maxNum));
|
|
||||||
if (!out.result.empty())
|
if (!out.result.empty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -172,7 +170,7 @@ struct Handler_TextDocumentDefinition
|
|||||||
Maybe<Use> use = GetDefinitionSpell(db, db->symbols[best_i]);
|
Maybe<Use> use = GetDefinitionSpell(db, db->symbols[best_i]);
|
||||||
assert(use);
|
assert(use);
|
||||||
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
||||||
config->xref.container))
|
g_config->xref.container))
|
||||||
out.result.push_back(*ls_loc);
|
out.result.push_back(*ls_loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ struct Handler_TextDocumentDidChange
|
|||||||
void Run(In_TextDocumentDidChange* request) override {
|
void Run(In_TextDocumentDidChange* request) override {
|
||||||
std::string path = request->params.textDocument.uri.GetPath();
|
std::string path = request->params.textDocument.uri.GetPath();
|
||||||
working_files->OnChange(request->params);
|
working_files->OnChange(request->params);
|
||||||
if (config->enableIndexOnDidChange) {
|
if (g_config->index.onDidChange) {
|
||||||
std::optional<std::string> content = ReadContent(path);
|
std::optional<std::string> content = ReadContent(path);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
||||||
|
@ -47,7 +47,7 @@ struct Handler_TextDocumentDidSave
|
|||||||
// mutex and check to see if we should skip the current request.
|
// mutex and check to see if we should skip the current request.
|
||||||
// if so, ignore that index response.
|
// if so, ignore that index response.
|
||||||
// TODO: send as priority request
|
// TODO: send as priority request
|
||||||
if (!config->enableIndexOnDidChange) {
|
if (!g_config->index.onDidChange) {
|
||||||
std::optional<std::string> content = ReadContent(path);
|
std::optional<std::string> content = ReadContent(path);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
||||||
|
@ -56,7 +56,7 @@ struct Handler_TextDocumentReferences
|
|||||||
|
|
||||||
Out_TextDocumentReferences out;
|
Out_TextDocumentReferences out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
bool container = config->xref.container;
|
bool container = g_config->xref.container;
|
||||||
|
|
||||||
for (const SymbolRef& sym :
|
for (const SymbolRef& sym :
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
@ -94,8 +94,8 @@ struct Handler_TextDocumentReferences
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int)out.result.size() >= config->xref.maxNum)
|
if ((int)out.result.size() >= g_config->xref.maxNum)
|
||||||
out.result.resize(config->xref.maxNum);
|
out.result.resize(g_config->xref.maxNum);
|
||||||
QueueManager::WriteStdout(kMethodType, out);
|
QueueManager::WriteStdout(kMethodType, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -50,7 +50,7 @@ struct Handler_TextDocumentTypeDefinition
|
|||||||
for (const auto& def : type.def)
|
for (const auto& def : type.def)
|
||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell,
|
if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell,
|
||||||
config->xref.container))
|
g_config->xref.container))
|
||||||
out.result.push_back(*ls_loc);
|
out.result.push_back(*ls_loc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -28,13 +28,12 @@ struct Handler_WorkspaceDidChangeConfiguration
|
|||||||
MethodType GetMethodType() const override { return kMethodType; }
|
MethodType GetMethodType() const override { return kMethodType; }
|
||||||
void Run(In_WorkspaceDidChangeConfiguration* request) override {
|
void Run(In_WorkspaceDidChangeConfiguration* request) override {
|
||||||
Timer time;
|
Timer time;
|
||||||
project->Load(config, config->projectRoot);
|
project->Load(g_config->projectRoot);
|
||||||
time.ResetAndPrint("[perf] Loaded compilation entries (" +
|
time.ResetAndPrint("[perf] Loaded compilation entries (" +
|
||||||
std::to_string(project->entries.size()) + " files)");
|
std::to_string(project->entries.size()) + " files)");
|
||||||
|
|
||||||
time.Reset();
|
time.Reset();
|
||||||
project->Index(config, QueueManager::instance(), working_files,
|
project->Index(QueueManager::instance(), working_files, std::monostate());
|
||||||
std::monostate());
|
|
||||||
time.ResetAndPrint(
|
time.ResetAndPrint(
|
||||||
"[perf] Dispatched workspace/didChangeConfiguration index requests");
|
"[perf] Dispatched workspace/didChangeConfiguration index requests");
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
|
|||||||
// db->detailed_names indices of each lsSymbolInformation in out.result
|
// db->detailed_names indices of each lsSymbolInformation in out.result
|
||||||
std::vector<int> result_indices;
|
std::vector<int> result_indices;
|
||||||
std::vector<lsSymbolInformation> unsorted_results;
|
std::vector<lsSymbolInformation> unsorted_results;
|
||||||
inserted_results.reserve(config->workspaceSymbol.maxNum);
|
inserted_results.reserve(g_config->workspaceSymbol.maxNum);
|
||||||
result_indices.reserve(config->workspaceSymbol.maxNum);
|
result_indices.reserve(g_config->workspaceSymbol.maxNum);
|
||||||
|
|
||||||
// We use detailed_names without parameters for matching.
|
// We use detailed_names without parameters for matching.
|
||||||
|
|
||||||
@ -93,14 +93,14 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
|
|||||||
if (InsertSymbolIntoResult(db, working_files, db->symbols[i],
|
if (InsertSymbolIntoResult(db, working_files, db->symbols[i],
|
||||||
&unsorted_results)) {
|
&unsorted_results)) {
|
||||||
result_indices.push_back(i);
|
result_indices.push_back(i);
|
||||||
if (unsorted_results.size() >= config->workspaceSymbol.maxNum)
|
if (unsorted_results.size() >= g_config->workspaceSymbol.maxNum)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find subsequence matches.
|
// Find subsequence matches.
|
||||||
if (unsorted_results.size() < config->workspaceSymbol.maxNum) {
|
if (unsorted_results.size() < g_config->workspaceSymbol.maxNum) {
|
||||||
std::string query_without_space;
|
std::string query_without_space;
|
||||||
query_without_space.reserve(query.size());
|
query_without_space.reserve(query.size());
|
||||||
for (char c : query)
|
for (char c : query)
|
||||||
@ -118,14 +118,14 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
|
|||||||
if (InsertSymbolIntoResult(db, working_files, db->symbols[i],
|
if (InsertSymbolIntoResult(db, working_files, db->symbols[i],
|
||||||
&unsorted_results)) {
|
&unsorted_results)) {
|
||||||
result_indices.push_back(i);
|
result_indices.push_back(i);
|
||||||
if (unsorted_results.size() >= config->workspaceSymbol.maxNum)
|
if (unsorted_results.size() >= g_config->workspaceSymbol.maxNum)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->workspaceSymbol.sort && query.size() <= FuzzyMatcher::kMaxPat) {
|
if (g_config->workspaceSymbol.sort && query.size() <= FuzzyMatcher::kMaxPat) {
|
||||||
// Sort results with a fuzzy matching algorithm.
|
// Sort results with a fuzzy matching algorithm.
|
||||||
int longest = 0;
|
int longest = 0;
|
||||||
for (int i : result_indices)
|
for (int i : result_indices)
|
||||||
|
@ -21,10 +21,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sstream>
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -61,7 +58,7 @@ struct ProjectConfig {
|
|||||||
// of clang for the same platform are incompatible). Note that libclang always generate it's own pch
|
// of clang for the same platform are incompatible). Note that libclang always generate it's own pch
|
||||||
// internally. For details, see https://github.com/Valloric/ycmd/issues/892 .
|
// internally. For details, see https://github.com/Valloric/ycmd/issues/892 .
|
||||||
std::vector<std::string> kBlacklistMulti = {
|
std::vector<std::string> kBlacklistMulti = {
|
||||||
"-MF", "-MT", "-MQ", "-o", "--serialize-diagnostics", "-Xclang", "-include", "-include-pch"};
|
"-MF", "-MT", "-MQ", "-o", "--serialize-diagnostics", "-Xclang"};
|
||||||
|
|
||||||
// Blacklisted flags which are always removed from the command line.
|
// Blacklisted flags which are always removed from the command line.
|
||||||
std::vector<std::string> kBlacklist = {
|
std::vector<std::string> kBlacklist = {
|
||||||
@ -106,7 +103,6 @@ LanguageId SourceFileLanguage(const std::string& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
||||||
Config* init_opts,
|
|
||||||
ProjectConfig* config,
|
ProjectConfig* config,
|
||||||
const CompileCommandsEntry& entry) {
|
const CompileCommandsEntry& entry) {
|
||||||
Project::Entry result;
|
Project::Entry result;
|
||||||
@ -240,7 +236,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
// Add -resource-dir so clang can correctly resolve system includes like
|
// Add -resource-dir so clang can correctly resolve system includes like
|
||||||
// <cstddef>
|
// <cstddef>
|
||||||
if (!AnyStartsWith(result.args, "-resource-dir"))
|
if (!AnyStartsWith(result.args, "-resource-dir"))
|
||||||
result.args.push_back("-resource-dir=" + init_opts->resourceDirectory);
|
result.args.push_back("-resource-dir=" + g_config->resourceDirectory);
|
||||||
|
|
||||||
// There could be a clang version mismatch between what the project uses and
|
// There could be a clang version mismatch between what the project uses and
|
||||||
// what ccls uses. Make sure we do not emit warnings for mismatched options.
|
// what ccls uses. Make sure we do not emit warnings for mismatched options.
|
||||||
@ -249,7 +245,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
|
|
||||||
// Using -fparse-all-comments enables documentation in the indexer and in
|
// Using -fparse-all-comments enables documentation in the indexer and in
|
||||||
// code completion.
|
// code completion.
|
||||||
if (init_opts->index.comments > 1 &&
|
if (g_config->index.comments > 1 &&
|
||||||
!AnyStartsWith(result.args, "-fparse-all-comments")) {
|
!AnyStartsWith(result.args, "-fparse-all-comments")) {
|
||||||
result.args.push_back("-fparse-all-comments");
|
result.args.push_back("-fparse-all-comments");
|
||||||
}
|
}
|
||||||
@ -269,8 +265,7 @@ std::vector<std::string> ReadCompilerArgumentsFromFile(
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Project::Entry> LoadFromDirectoryListing(Config* init_opts,
|
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
|
||||||
ProjectConfig* config) {
|
|
||||||
std::vector<Project::Entry> result;
|
std::vector<Project::Entry> result;
|
||||||
config->mode = ProjectMode::DotCcls;
|
config->mode = ProjectMode::DotCcls;
|
||||||
LOG_IF_S(WARNING, !FileExists(config->project_dir + "/.ccls") &&
|
LOG_IF_S(WARNING, !FileExists(config->project_dir + "/.ccls") &&
|
||||||
@ -322,24 +317,22 @@ std::vector<Project::Entry> LoadFromDirectoryListing(Config* init_opts,
|
|||||||
if (e.args.empty())
|
if (e.args.empty())
|
||||||
e.args.push_back("%clang"); // Add a Dummy.
|
e.args.push_back("%clang"); // Add a Dummy.
|
||||||
e.args.push_back(e.file);
|
e.args.push_back(e.file);
|
||||||
result.push_back(
|
result.push_back(GetCompilationEntryFromCompileCommandEntry(config, e));
|
||||||
GetCompilationEntryFromCompileCommandEntry(init_opts, config, e));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
||||||
Config* config,
|
|
||||||
ProjectConfig* project,
|
ProjectConfig* project,
|
||||||
const std::string& opt_compilation_db_dir) {
|
const std::string& opt_compilation_db_dir) {
|
||||||
// If there is a .ccls file always load using directory listing.
|
// If there is a .ccls file always load using directory listing.
|
||||||
if (FileExists(project->project_dir + ".ccls"))
|
if (FileExists(project->project_dir + ".ccls"))
|
||||||
return LoadFromDirectoryListing(config, project);
|
return LoadFromDirectoryListing(project);
|
||||||
|
|
||||||
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
||||||
std::string comp_db_dir;
|
fs::path comp_db_dir;
|
||||||
if (config->compilationDatabaseCommand.empty()) {
|
if (g_config->compilationDatabaseCommand.empty()) {
|
||||||
project->mode = ProjectMode::CompileCommandsJson;
|
project->mode = ProjectMode::CompileCommandsJson;
|
||||||
// Try to load compile_commands.json, but fallback to a project listing.
|
// Try to load compile_commands.json, but fallback to a project listing.
|
||||||
comp_db_dir = opt_compilation_db_dir.empty() ? project->project_dir
|
comp_db_dir = opt_compilation_db_dir.empty() ? project->project_dir
|
||||||
@ -356,32 +349,35 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
rapidjson::StringBuffer input;
|
rapidjson::StringBuffer input;
|
||||||
rapidjson::Writer<rapidjson::StringBuffer> writer(input);
|
rapidjson::Writer<rapidjson::StringBuffer> writer(input);
|
||||||
JsonWriter json_writer(&writer);
|
JsonWriter json_writer(&writer);
|
||||||
Reflect(json_writer, *config);
|
Reflect(json_writer, *g_config);
|
||||||
std::string contents = GetExternalCommandOutput(
|
std::string contents = GetExternalCommandOutput(
|
||||||
std::vector<std::string>{config->compilationDatabaseCommand,
|
std::vector<std::string>{g_config->compilationDatabaseCommand,
|
||||||
project->project_dir},
|
project->project_dir},
|
||||||
input.GetString());
|
input.GetString());
|
||||||
std::ofstream(comp_db_dir + "/compile_commands.json") << contents;
|
FILE* fout = fopen((comp_db_dir / "compile_commands.json").c_str(), "wb");
|
||||||
|
fwrite(contents.c_str(), contents.size(), 1, fout);
|
||||||
|
fclose(fout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_S(INFO) << "Trying to load compile_commands.json";
|
fs::path comp_db_path = comp_db_dir / "compile_commands.json";
|
||||||
|
LOG_S(INFO) << "Trying to load " << comp_db_path.string();
|
||||||
CXCompilationDatabase_Error cx_db_load_error;
|
CXCompilationDatabase_Error cx_db_load_error;
|
||||||
CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory(
|
CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory(
|
||||||
comp_db_dir.c_str(), &cx_db_load_error);
|
comp_db_dir.c_str(), &cx_db_load_error);
|
||||||
if (!config->compilationDatabaseCommand.empty()) {
|
if (!g_config->compilationDatabaseCommand.empty()) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// TODO
|
// TODO
|
||||||
#else
|
#else
|
||||||
unlink((comp_db_dir + "/compile_commands.json").c_str());
|
unlink(comp_db_path.c_str());
|
||||||
rmdir(comp_db_dir.c_str());
|
rmdir(comp_db_dir.c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
|
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
|
||||||
LOG_S(INFO) << "Unable to load compile_commands.json located at \""
|
LOG_S(INFO) << "Unable to load " << comp_db_path.string()
|
||||||
<< comp_db_dir << "\"; using directory listing instead.";
|
<< "; using directory listing instead.";
|
||||||
return LoadFromDirectoryListing(config, project);
|
return LoadFromDirectoryListing(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer clang_time;
|
Timer clang_time;
|
||||||
@ -421,7 +417,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
entry.file = entry.ResolveIfRelative(relative_filename);
|
entry.file = entry.ResolveIfRelative(relative_filename);
|
||||||
|
|
||||||
result.push_back(
|
result.push_back(
|
||||||
GetCompilationEntryFromCompileCommandEntry(config, project, entry));
|
GetCompilationEntryFromCompileCommandEntry(project, entry));
|
||||||
our_time.Pause();
|
our_time.Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,13 +448,13 @@ int ComputeGuessScore(std::string_view a, std::string_view b) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Project::Load(Config* config, const std::string& root_directory) {
|
void Project::Load(const std::string& root_directory) {
|
||||||
// Load data.
|
// Load data.
|
||||||
ProjectConfig project;
|
ProjectConfig project;
|
||||||
project.extra_flags = config->extraClangArguments;
|
project.extra_flags = g_config->extraClangArguments;
|
||||||
project.project_dir = root_directory;
|
project.project_dir = root_directory;
|
||||||
entries = LoadCompilationEntriesFromDirectory(
|
entries = LoadCompilationEntriesFromDirectory(
|
||||||
config, &project, config->compilationDatabaseDirectory);
|
&project, g_config->compilationDatabaseDirectory);
|
||||||
|
|
||||||
// Cleanup / postprocess include directories.
|
// Cleanup / postprocess include directories.
|
||||||
quote_include_directories.assign(project.quote_dirs.begin(),
|
quote_include_directories.assign(project.quote_dirs.begin(),
|
||||||
@ -539,28 +535,24 @@ Project::Entry Project::FindCompilationEntryForFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Project::ForAllFilteredFiles(
|
void Project::ForAllFilteredFiles(
|
||||||
Config* config,
|
|
||||||
std::function<void(int i, const Entry& entry)> action) {
|
std::function<void(int i, const Entry& entry)> action) {
|
||||||
GroupMatch matcher(config->index.whitelist, config->index.blacklist);
|
GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist);
|
||||||
for (int i = 0; i < entries.size(); ++i) {
|
for (int i = 0; i < entries.size(); ++i) {
|
||||||
const Project::Entry& entry = entries[i];
|
const Project::Entry& entry = entries[i];
|
||||||
std::string failure_reason;
|
std::string failure_reason;
|
||||||
if (matcher.IsMatch(entry.filename, &failure_reason))
|
if (matcher.IsMatch(entry.filename, &failure_reason))
|
||||||
action(i, entries[i]);
|
action(i, entries[i]);
|
||||||
else {
|
else if (g_config->index.logSkippedPaths) {
|
||||||
if (config->index.logSkippedPaths) {
|
LOG_S(INFO) << "[" << i + 1 << "/" << entries.size() << "]: Failed "
|
||||||
LOG_S(INFO) << "[" << i + 1 << "/" << entries.size() << "]: Failed "
|
<< failure_reason << "; skipping " << entry.filename;
|
||||||
<< failure_reason << "; skipping " << entry.filename;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::Index(Config* config,
|
void Project::Index(QueueManager* queue,
|
||||||
QueueManager* queue,
|
|
||||||
WorkingFiles* wfiles,
|
WorkingFiles* wfiles,
|
||||||
lsRequestId id) {
|
lsRequestId id) {
|
||||||
ForAllFilteredFiles(config, [&](int i, const Project::Entry& entry) {
|
ForAllFilteredFiles([&](int i, const Project::Entry& entry) {
|
||||||
std::optional<std::string> content = ReadContent(entry.filename);
|
std::optional<std::string> content = ReadContent(entry.filename);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
LOG_S(ERROR) << "When loading project, canont read file "
|
LOG_S(ERROR) << "When loading project, canont read file "
|
||||||
@ -578,30 +570,22 @@ TEST_SUITE("Project") {
|
|||||||
void CheckFlags(const std::string& directory, const std::string& file,
|
void CheckFlags(const std::string& directory, const std::string& file,
|
||||||
std::vector<std::string> raw,
|
std::vector<std::string> raw,
|
||||||
std::vector<std::string> expected) {
|
std::vector<std::string> expected) {
|
||||||
Config config;
|
g_config = std::make_unique<Config>();
|
||||||
|
g_config->resourceDirectory = "/w/resource_dir/";
|
||||||
ProjectConfig project;
|
ProjectConfig project;
|
||||||
project.project_dir = "/w/c/s/";
|
project.project_dir = "/w/c/s/";
|
||||||
config.resourceDirectory = "/w/resource_dir/";
|
|
||||||
|
|
||||||
CompileCommandsEntry entry;
|
CompileCommandsEntry entry;
|
||||||
entry.directory = directory;
|
entry.directory = directory;
|
||||||
entry.args = raw;
|
entry.args = raw;
|
||||||
entry.file = file;
|
entry.file = file;
|
||||||
Project::Entry result =
|
Project::Entry result =
|
||||||
GetCompilationEntryFromCompileCommandEntry(&config, &project, entry);
|
GetCompilationEntryFromCompileCommandEntry(&project, entry);
|
||||||
|
|
||||||
if (result.args != expected) {
|
if (result.args != expected) {
|
||||||
std::cout << "Raw: " << StringJoin(raw) << std::endl;
|
fprintf(stderr, "Raw: %s\n", StringJoin(raw).c_str());
|
||||||
std::cout << "Expected: " << StringJoin(expected) << std::endl;
|
fprintf(stderr, "Expected: %s\n", StringJoin(expected).c_str());
|
||||||
std::cout << "Actual: " << StringJoin(result.args) << std::endl;
|
fprintf(stderr, "Actual: %s\n", StringJoin(result.args).c_str());
|
||||||
}
|
|
||||||
for (int i = 0; i < std::min(result.args.size(), expected.size()); ++i) {
|
|
||||||
if (result.args[i] != expected[i]) {
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << "mismatch at " << i << std::endl;
|
|
||||||
std::cout << " expected: " << expected[i] << std::endl;
|
|
||||||
std::cout << " actual: " << result.args[i] << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
REQUIRE(result.args == expected);
|
REQUIRE(result.args == expected);
|
||||||
}
|
}
|
||||||
@ -671,7 +655,7 @@ TEST_SUITE("Project") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Directory extraction") {
|
TEST_CASE("Directory extraction") {
|
||||||
Config init_opts;
|
g_config = std::make_unique<Config>();
|
||||||
ProjectConfig config;
|
ProjectConfig config;
|
||||||
config.project_dir = "/w/c/s/";
|
config.project_dir = "/w/c/s/";
|
||||||
|
|
||||||
@ -701,7 +685,7 @@ TEST_SUITE("Project") {
|
|||||||
"foo.cc"};
|
"foo.cc"};
|
||||||
entry.file = "foo.cc";
|
entry.file = "foo.cc";
|
||||||
Project::Entry result =
|
Project::Entry result =
|
||||||
GetCompilationEntryFromCompileCommandEntry(&init_opts, &config, entry);
|
GetCompilationEntryFromCompileCommandEntry(&config, entry);
|
||||||
|
|
||||||
std::unordered_set<std::string> angle_expected{
|
std::unordered_set<std::string> angle_expected{
|
||||||
"/a_absolute1", "/a_absolute2", "/base/a_relative1",
|
"/a_absolute1", "/a_absolute2", "/base/a_relative1",
|
||||||
|
@ -40,7 +40,7 @@ struct Project {
|
|||||||
// will affect flags in their subtrees (relative paths are relative to the
|
// will affect flags in their subtrees (relative paths are relative to the
|
||||||
// project root, not subdirectories). For compile_commands.json, its entries
|
// project root, not subdirectories). For compile_commands.json, its entries
|
||||||
// are indexed.
|
// are indexed.
|
||||||
void Load(Config* config, const std::string& root_directory);
|
void Load(const std::string& root_directory);
|
||||||
|
|
||||||
// Lookup the CompilationEntry for |filename|. If no entry was found this
|
// Lookup the CompilationEntry for |filename|. If no entry was found this
|
||||||
// will infer one based on existing project structure.
|
// will infer one based on existing project structure.
|
||||||
@ -55,11 +55,7 @@ struct Project {
|
|||||||
|
|
||||||
// Run |action| on every file in the project.
|
// Run |action| on every file in the project.
|
||||||
void ForAllFilteredFiles(
|
void ForAllFilteredFiles(
|
||||||
Config* config,
|
|
||||||
std::function<void(int i, const Entry& entry)> action);
|
std::function<void(int i, const Entry& entry)> action);
|
||||||
|
|
||||||
void Index(Config* config,
|
void Index(QueueManager* queue, WorkingFiles* wfiles, lsRequestId id);
|
||||||
QueueManager* queue,
|
|
||||||
WorkingFiles* wfiles,
|
|
||||||
lsRequestId id);
|
|
||||||
};
|
};
|
||||||
|
@ -251,17 +251,16 @@ std::optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
|||||||
|
|
||||||
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
|
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
const std::vector<Use>& uses,
|
const std::vector<Use>& uses) {
|
||||||
bool container,
|
|
||||||
int limit) {
|
|
||||||
std::vector<lsLocationEx> ret;
|
std::vector<lsLocationEx> ret;
|
||||||
for (Use use : uses)
|
for (Use use : uses)
|
||||||
if (auto loc = GetLsLocationEx(db, working_files, use, container))
|
if (auto loc =
|
||||||
|
GetLsLocationEx(db, working_files, use, g_config->xref.container))
|
||||||
ret.push_back(*loc);
|
ret.push_back(*loc);
|
||||||
std::sort(ret.begin(), ret.end());
|
std::sort(ret.begin(), ret.end());
|
||||||
ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
|
ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
|
||||||
if (ret.size() > limit)
|
if (ret.size() > g_config->xref.maxNum)
|
||||||
ret.resize(limit);
|
ret.resize(g_config->xref.maxNum);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,7 @@ std::optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
|||||||
bool container);
|
bool container);
|
||||||
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
|
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
const std::vector<Use>& refs,
|
const std::vector<Use>& refs);
|
||||||
bool container,
|
|
||||||
int limit);
|
|
||||||
// Returns a symbol. The symbol will have *NOT* have a location assigned.
|
// Returns a symbol. The symbol will have *NOT* have a location assigned.
|
||||||
std::optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
std::optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
|
@ -262,11 +262,11 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
|
|||||||
flags.push_back(path);
|
flags.push_back(path);
|
||||||
|
|
||||||
// Run test.
|
// Run test.
|
||||||
Config config;
|
g_config = std::make_unique<Config>();
|
||||||
FileConsumerSharedState file_consumer_shared;
|
FileConsumerSharedState file_consumer_shared;
|
||||||
PerformanceImportFile perf;
|
PerformanceImportFile perf;
|
||||||
auto dbs = Parse(&config, &file_consumer_shared, path, flags, {}, &perf,
|
auto dbs = Parse(&file_consumer_shared, path, flags, {}, &perf, &index,
|
||||||
&index, false /*dump_ast*/);
|
false /*dump_ast*/);
|
||||||
|
|
||||||
for (const auto& entry : all_expected_output) {
|
for (const auto& entry : all_expected_output) {
|
||||||
const std::string& expected_path = entry.first;
|
const std::string& expected_path = entry.first;
|
||||||
|
Loading…
Reference in New Issue
Block a user