clang-format

DEF CON 26 CTF
This commit is contained in:
Fangrui Song 2018-08-09 10:08:14 -07:00
parent 87f36a4a96
commit 39787d2851
87 changed files with 2058 additions and 2372 deletions

View File

@ -20,7 +20,7 @@ using namespace llvm;
namespace {
std::string StripFileType(const std::string& path) {
std::string StripFileType(const std::string &path) {
SmallString<128> Ret;
sys::path::append(Ret, sys::path::parent_path(path), sys::path::stem(path));
return Ret.str();
@ -41,93 +41,93 @@ unsigned GetCompletionPriority(const CodeCompletionString &CCS,
lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) {
switch (cursor_kind) {
case CXCursor_UnexposedDecl:
return lsCompletionItemKind::Text;
case CXCursor_UnexposedDecl:
return lsCompletionItemKind::Text;
case CXCursor_StructDecl:
case CXCursor_UnionDecl:
return lsCompletionItemKind::Struct;
case CXCursor_ClassDecl:
return lsCompletionItemKind::Class;
case CXCursor_EnumDecl:
return lsCompletionItemKind::Enum;
case CXCursor_FieldDecl:
return lsCompletionItemKind::Field;
case CXCursor_EnumConstantDecl:
return lsCompletionItemKind::EnumMember;
case CXCursor_FunctionDecl:
return lsCompletionItemKind::Function;
case CXCursor_VarDecl:
case CXCursor_ParmDecl:
return lsCompletionItemKind::Variable;
case CXCursor_ObjCInterfaceDecl:
return lsCompletionItemKind::Interface;
case CXCursor_StructDecl:
case CXCursor_UnionDecl:
return lsCompletionItemKind::Struct;
case CXCursor_ClassDecl:
return lsCompletionItemKind::Class;
case CXCursor_EnumDecl:
return lsCompletionItemKind::Enum;
case CXCursor_FieldDecl:
return lsCompletionItemKind::Field;
case CXCursor_EnumConstantDecl:
return lsCompletionItemKind::EnumMember;
case CXCursor_FunctionDecl:
return lsCompletionItemKind::Function;
case CXCursor_VarDecl:
case CXCursor_ParmDecl:
return lsCompletionItemKind::Variable;
case CXCursor_ObjCInterfaceDecl:
return lsCompletionItemKind::Interface;
case CXCursor_ObjCInstanceMethodDecl:
case CXCursor_CXXMethod:
case CXCursor_ObjCClassMethodDecl:
return lsCompletionItemKind::Method;
case CXCursor_ObjCInstanceMethodDecl:
case CXCursor_CXXMethod:
case CXCursor_ObjCClassMethodDecl:
return lsCompletionItemKind::Method;
case CXCursor_FunctionTemplate:
return lsCompletionItemKind::Function;
case CXCursor_FunctionTemplate:
return lsCompletionItemKind::Function;
case CXCursor_Constructor:
case CXCursor_Destructor:
case CXCursor_ConversionFunction:
return lsCompletionItemKind::Constructor;
case CXCursor_Constructor:
case CXCursor_Destructor:
case CXCursor_ConversionFunction:
return lsCompletionItemKind::Constructor;
case CXCursor_ObjCIvarDecl:
return lsCompletionItemKind::Variable;
case CXCursor_ObjCIvarDecl:
return lsCompletionItemKind::Variable;
case CXCursor_ClassTemplate:
case CXCursor_ClassTemplatePartialSpecialization:
case CXCursor_UsingDeclaration:
case CXCursor_TypedefDecl:
case CXCursor_TypeAliasDecl:
case CXCursor_TypeAliasTemplateDecl:
case CXCursor_ObjCCategoryDecl:
case CXCursor_ObjCProtocolDecl:
case CXCursor_ObjCImplementationDecl:
case CXCursor_ObjCCategoryImplDecl:
return lsCompletionItemKind::Class;
case CXCursor_ClassTemplate:
case CXCursor_ClassTemplatePartialSpecialization:
case CXCursor_UsingDeclaration:
case CXCursor_TypedefDecl:
case CXCursor_TypeAliasDecl:
case CXCursor_TypeAliasTemplateDecl:
case CXCursor_ObjCCategoryDecl:
case CXCursor_ObjCProtocolDecl:
case CXCursor_ObjCImplementationDecl:
case CXCursor_ObjCCategoryImplDecl:
return lsCompletionItemKind::Class;
case CXCursor_ObjCPropertyDecl:
return lsCompletionItemKind::Property;
case CXCursor_ObjCPropertyDecl:
return lsCompletionItemKind::Property;
case CXCursor_MacroInstantiation:
case CXCursor_MacroDefinition:
return lsCompletionItemKind::Interface;
case CXCursor_MacroInstantiation:
case CXCursor_MacroDefinition:
return lsCompletionItemKind::Interface;
case CXCursor_Namespace:
case CXCursor_NamespaceAlias:
case CXCursor_NamespaceRef:
return lsCompletionItemKind::Module;
case CXCursor_Namespace:
case CXCursor_NamespaceAlias:
case CXCursor_NamespaceRef:
return lsCompletionItemKind::Module;
case CXCursor_MemberRef:
case CXCursor_TypeRef:
case CXCursor_ObjCSuperClassRef:
case CXCursor_ObjCProtocolRef:
case CXCursor_ObjCClassRef:
return lsCompletionItemKind::Reference;
case CXCursor_MemberRef:
case CXCursor_TypeRef:
case CXCursor_ObjCSuperClassRef:
case CXCursor_ObjCProtocolRef:
case CXCursor_ObjCClassRef:
return lsCompletionItemKind::Reference;
// return lsCompletionItemKind::Unit;
// return lsCompletionItemKind::Value;
// return lsCompletionItemKind::Keyword;
// return lsCompletionItemKind::Snippet;
// return lsCompletionItemKind::Color;
// return lsCompletionItemKind::File;
// return lsCompletionItemKind::Unit;
// return lsCompletionItemKind::Value;
// return lsCompletionItemKind::Keyword;
// return lsCompletionItemKind::Snippet;
// return lsCompletionItemKind::Color;
// return lsCompletionItemKind::File;
case CXCursor_NotImplemented:
case CXCursor_OverloadCandidate:
return lsCompletionItemKind::Text;
case CXCursor_NotImplemented:
case CXCursor_OverloadCandidate:
return lsCompletionItemKind::Text;
case CXCursor_TemplateTypeParameter:
case CXCursor_TemplateTemplateParameter:
return lsCompletionItemKind::TypeParameter;
case CXCursor_TemplateTypeParameter:
case CXCursor_TemplateTemplateParameter:
return lsCompletionItemKind::TypeParameter;
default:
LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind;
return lsCompletionItemKind::Text;
default:
LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind;
return lsCompletionItemKind::Text;
}
}
@ -144,50 +144,50 @@ void BuildCompletionItemTexts(std::vector<lsCompletionItem> &out,
CodeCompletionString::ChunkKind Kind = Chunk.Kind;
std::string text;
switch (Kind) {
case CodeCompletionString::CK_TypedText:
case CodeCompletionString::CK_Text:
case CodeCompletionString::CK_Placeholder:
case CodeCompletionString::CK_Informative:
if (Chunk.Text)
text = Chunk.Text;
for (auto i = out_first; i < out.size(); i++) {
// first TypedText is used for filtering
if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText)
out[i].filterText = text;
if (Kind == CodeCompletionString::CK_Placeholder)
out[i].parameters_.push_back(text);
}
break;
case CodeCompletionString::CK_ResultType:
if (Chunk.Text)
result_type = Chunk.Text;
continue;
case CodeCompletionString::CK_CurrentParameter:
// We have our own parsing logic for active parameter. This doesn't seem
// to be very reliable.
continue;
case CodeCompletionString::CK_Optional: {
// duplicate last element, the recursive call will complete it
out.push_back(out.back());
BuildCompletionItemTexts(out, *Chunk.Optional, include_snippets);
continue;
case CodeCompletionString::CK_TypedText:
case CodeCompletionString::CK_Text:
case CodeCompletionString::CK_Placeholder:
case CodeCompletionString::CK_Informative:
if (Chunk.Text)
text = Chunk.Text;
for (auto i = out_first; i < out.size(); i++) {
// first TypedText is used for filtering
if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText)
out[i].filterText = text;
if (Kind == CodeCompletionString::CK_Placeholder)
out[i].parameters_.push_back(text);
}
// clang-format off
case CodeCompletionString::CK_LeftParen: text = '('; break;
case CodeCompletionString::CK_RightParen: text = ')'; break;
case CodeCompletionString::CK_LeftBracket: text = '['; break;
case CodeCompletionString::CK_RightBracket: text = ']'; break;
case CodeCompletionString::CK_LeftBrace: text = '{'; break;
case CodeCompletionString::CK_RightBrace: text = '}'; break;
case CodeCompletionString::CK_LeftAngle: text = '<'; break;
case CodeCompletionString::CK_RightAngle: text = '>'; break;
case CodeCompletionString::CK_Comma: text = ", "; break;
case CodeCompletionString::CK_Colon: text = ':'; break;
case CodeCompletionString::CK_SemiColon: text = ';'; break;
case CodeCompletionString::CK_Equal: text = '='; break;
case CodeCompletionString::CK_HorizontalSpace: text = ' '; break;
case CodeCompletionString::CK_VerticalSpace: text = ' '; break;
// clang-format on
break;
case CodeCompletionString::CK_ResultType:
if (Chunk.Text)
result_type = Chunk.Text;
continue;
case CodeCompletionString::CK_CurrentParameter:
// We have our own parsing logic for active parameter. This doesn't seem
// to be very reliable.
continue;
case CodeCompletionString::CK_Optional: {
// duplicate last element, the recursive call will complete it
out.push_back(out.back());
BuildCompletionItemTexts(out, *Chunk.Optional, include_snippets);
continue;
}
// clang-format off
case CodeCompletionString::CK_LeftParen: text = '('; break;
case CodeCompletionString::CK_RightParen: text = ')'; break;
case CodeCompletionString::CK_LeftBracket: text = '['; break;
case CodeCompletionString::CK_RightBracket: text = ']'; break;
case CodeCompletionString::CK_LeftBrace: text = '{'; break;
case CodeCompletionString::CK_RightBrace: text = '}'; break;
case CodeCompletionString::CK_LeftAngle: text = '<'; break;
case CodeCompletionString::CK_RightAngle: text = '>'; break;
case CodeCompletionString::CK_Comma: text = ", "; break;
case CodeCompletionString::CK_Colon: text = ':'; break;
case CodeCompletionString::CK_SemiColon: text = ';'; break;
case CodeCompletionString::CK_Equal: text = '='; break;
case CodeCompletionString::CK_HorizontalSpace: text = ' '; break;
case CodeCompletionString::CK_VerticalSpace: text = ' '; break;
// clang-format on
}
if (Kind != CodeCompletionString::CK_Informative)
@ -197,8 +197,9 @@ void BuildCompletionItemTexts(std::vector<lsCompletionItem> &out,
continue;
if (Kind == CodeCompletionString::CK_Placeholder) {
out[i].insertText +=
"${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}";
out[i].insertText += "${" +
std::to_string(out[i].parameters_.size()) + ":" +
text + "}";
out[i].insertTextFormat = lsInsertTextFormat::Snippet;
} else {
out[i].insertText += text;
@ -223,7 +224,7 @@ void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item,
for (unsigned i = 0, num_chunks = CCS.size(); i < num_chunks; ++i) {
const CodeCompletionString::Chunk &Chunk = CCS[i];
CodeCompletionString::ChunkKind Kind = Chunk.Kind;
const char* text = nullptr;
const char *text = nullptr;
switch (Kind) {
case CodeCompletionString::CK_TypedText:
item.label = Chunk.Text;
@ -238,7 +239,8 @@ void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item,
item.detail += Chunk.Text;
// Add parameter declarations as snippets if enabled
if (include_snippets) {
item.insertText += "${" + std::to_string(parameters->size()) + ":" + Chunk.Text + "}";
item.insertText +=
"${" + std::to_string(parameters->size()) + ":" + Chunk.Text + "}";
item.insertTextFormat = lsInsertTextFormat::Snippet;
} else
do_insert = false;
@ -250,8 +252,8 @@ void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item,
case CodeCompletionString::CK_Optional: {
// Do not add text to insert string if we're in angle brackets.
bool should_insert = do_insert && angle_stack == 0;
BuildDetailString(*Chunk.Optional, item, should_insert,
parameters, include_snippets, angle_stack);
BuildDetailString(*Chunk.Optional, item, should_insert, parameters,
include_snippets, angle_stack);
break;
}
case CodeCompletionString::CK_ResultType:
@ -298,10 +300,9 @@ public:
Alloc(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
CCTUInfo(Alloc) {}
void ProcessCodeCompleteResults(Sema &S,
CodeCompletionContext Context,
CodeCompletionResult *Results,
unsigned NumResults) override {
void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
CodeCompletionResult *Results,
unsigned NumResults) override {
ls_items.reserve(NumResults);
for (unsigned i = 0; i != NumResults; i++) {
CodeCompletionString *CCS = Results[i].CreateCodeCompletionString(
@ -312,7 +313,7 @@ public:
lsCompletionItem ls_item;
ls_item.kind = GetCompletionKind(Results[i].CursorKind);
if (const char* brief = CCS->getBriefComment())
if (const char *brief = CCS->getBriefComment())
ls_item.documentation = brief;
// label/detail/filterText/insertText/priority
@ -334,8 +335,7 @@ public:
} else {
bool do_insert = true;
int angle_stack = 0;
BuildDetailString(*CCS, ls_item, do_insert,
&ls_item.parameters_,
BuildDetailString(*CCS, ls_item, do_insert, &ls_item.parameters_,
g_config->client.snippetSupport, angle_stack);
if (g_config->client.snippetSupport &&
ls_item.insertTextFormat == lsInsertTextFormat::Snippet)
@ -353,7 +353,7 @@ public:
CodeCompletionAllocator &getAllocator() override { return *Alloc; }
CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo;}
CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
};
void TryEnsureDocumentParsed(ClangCompleteManager *manager,
@ -374,7 +374,7 @@ void TryEnsureDocumentParsed(ClangCompleteManager *manager,
diagnostic);
}
void CompletionPreloadMain(ClangCompleteManager* completion_manager) {
void CompletionPreloadMain(ClangCompleteManager *completion_manager) {
while (true) {
// Fetching the completion request blocks until we have a request.
auto request = completion_manager->preload_requests_.Dequeue();
@ -390,7 +390,7 @@ void CompletionPreloadMain(ClangCompleteManager* completion_manager) {
// Note: we only preload completion. We emit diagnostics for the
// completion preload though.
CompletionSession::Tu* tu = &session->completion;
CompletionSession::Tu *tu = &session->completion;
// If we've parsed it more recently than the request time, don't bother
// reparsing.
@ -407,7 +407,7 @@ void CompletionPreloadMain(ClangCompleteManager* completion_manager) {
}
}
void CompletionQueryMain(ClangCompleteManager* completion_manager) {
void CompletionQueryMain(ClangCompleteManager *completion_manager) {
while (true) {
// Fetching the completion request blocks until we have a request.
std::unique_ptr<ClangCompleteManager::CompletionRequest> request =
@ -427,11 +427,12 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
true /*create_if_needed*/);
std::lock_guard<std::mutex> lock(session->completion.lock);
TryEnsureDocumentParsed(completion_manager, session, &session->completion.tu, false);
TryEnsureDocumentParsed(completion_manager, session,
&session->completion.tu, false);
// It is possible we failed to create the document despite
// |TryEnsureDocumentParsed|.
if (ClangTranslationUnit* tu = session->completion.tu.get()) {
if (ClangTranslationUnit *tu = session->completion.tu.get()) {
WorkingFiles::Snapshot snapshot =
completion_manager->working_files_->AsSnapshot({StripFileType(path)});
IntrusiveRefCntPtr<FileManager> FileMgr(&tu->Unit->getFileManager());
@ -464,7 +465,8 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
capture, tu->PCHCO, *Diag, LangOpts, *SrcMgr,
*FileMgr, Diagnostics, TemporaryBuffers);
request->on_complete(capture.ls_items, false /*is_cached_result*/);
// completion_manager->on_diagnostic_(session->file.filename, Diags.take());
// completion_manager->on_diagnostic_(session->file.filename,
// Diags.take());
}
}
}
@ -487,7 +489,7 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) {
// It is possible we failed to create the document despite
// |TryEnsureDocumentParsed|.
ClangTranslationUnit* tu = session->diagnostics.tu.get();
ClangTranslationUnit *tu = session->diagnostics.tu.get();
if (!tu)
continue;
@ -509,7 +511,8 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) {
if (!FLoc.isValid()) // why?
continue;
const FileEntry *FE = FLoc.getFileEntry();
if (!FE || FileName(*FE) != path) continue;
if (!FE || FileName(*FE) != path)
continue;
const auto &SM = FLoc.getManager();
SourceRange R;
for (const auto &CR : I->getRanges()) {
@ -553,45 +556,46 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) {
}
}
} // namespace
} // namespace
ClangCompleteManager::ClangCompleteManager(Project* project,
WorkingFiles* working_files,
ClangCompleteManager::ClangCompleteManager(Project *project,
WorkingFiles *working_files,
OnDiagnostic on_diagnostic,
OnDropped on_dropped)
: project_(project),
working_files_(working_files),
on_diagnostic_(on_diagnostic),
on_dropped_(on_dropped),
: project_(project), working_files_(working_files),
on_diagnostic_(on_diagnostic), on_dropped_(on_dropped),
preloaded_sessions_(kMaxPreloadedSessions),
completion_sessions_(kMaxCompletionSessions) {
std::thread([&]() {
set_thread_name("comp-query");
CompletionQueryMain(this);
}).detach();
})
.detach();
std::thread([&]() {
set_thread_name("comp-preload");
CompletionPreloadMain(this);
}).detach();
})
.detach();
std::thread([&]() {
set_thread_name("diag-query");
DiagnosticQueryMain(this);
}).detach();
})
.detach();
}
void ClangCompleteManager::CodeComplete(
const lsRequestId& id,
const lsTextDocumentPositionParams& completion_location,
const OnComplete& on_complete) {
const lsRequestId &id,
const lsTextDocumentPositionParams &completion_location,
const OnComplete &on_complete) {
completion_request_.PushBack(std::make_unique<CompletionRequest>(
id, completion_location.textDocument, completion_location.position,
on_complete));
}
void ClangCompleteManager::DiagnosticsUpdate(
const lsTextDocumentIdentifier& document) {
const lsTextDocumentIdentifier &document) {
bool has = false;
diagnostic_request_.Iterate([&](const DiagnosticRequest& request) {
diagnostic_request_.Iterate([&](const DiagnosticRequest &request) {
if (request.document.uri == document.uri)
has = true;
});
@ -600,7 +604,7 @@ void ClangCompleteManager::DiagnosticsUpdate(
true /*priority*/);
}
void ClangCompleteManager::NotifyView(const std::string& filename) {
void ClangCompleteManager::NotifyView(const std::string &filename) {
//
// On view, we reparse only if the file has not been parsed. The existence of
// a CompletionSession instance implies the file is already parsed or will be
@ -612,7 +616,7 @@ void ClangCompleteManager::NotifyView(const std::string& filename) {
preload_requests_.PushBack(PreloadRequest(filename), true);
}
void ClangCompleteManager::NotifyEdit(const std::string& filename) {
void ClangCompleteManager::NotifyEdit(const std::string &filename) {
//
// We treat an edit like a view, because the completion logic will handle
// moving the CompletionSession instance from preloaded to completion
@ -622,7 +626,7 @@ void ClangCompleteManager::NotifyEdit(const std::string& filename) {
NotifyView(filename);
}
void ClangCompleteManager::NotifySave(const std::string& filename) {
void ClangCompleteManager::NotifySave(const std::string &filename) {
//
// On save, always reparse.
//
@ -631,7 +635,7 @@ void ClangCompleteManager::NotifySave(const std::string& filename) {
preload_requests_.PushBack(PreloadRequest(filename), true);
}
void ClangCompleteManager::NotifyClose(const std::string& filename) {
void ClangCompleteManager::NotifyClose(const std::string &filename) {
//
// On close, we clear any existing CompletionSession instance.
//
@ -652,7 +656,7 @@ void ClangCompleteManager::NotifyClose(const std::string& filename) {
}
bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession(
const std::string& filename) {
const std::string &filename) {
std::lock_guard<std::mutex> lock(sessions_lock_);
// Check for an existing CompletionSession.
@ -668,10 +672,10 @@ bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession(
return true;
}
std::shared_ptr<CompletionSession> ClangCompleteManager::TryGetSession(
const std::string& filename,
bool mark_as_completion,
bool create_if_needed) {
std::shared_ptr<CompletionSession>
ClangCompleteManager::TryGetSession(const std::string &filename,
bool mark_as_completion,
bool create_if_needed) {
std::lock_guard<std::mutex> lock(sessions_lock_);
// Try to find a preloaded session.
@ -701,11 +705,11 @@ std::shared_ptr<CompletionSession> ClangCompleteManager::TryGetSession(
return completion_session;
}
void ClangCompleteManager::FlushSession(const std::string& filename) {
std::lock_guard<std::mutex> lock(sessions_lock_);
void ClangCompleteManager::FlushSession(const std::string &filename) {
std::lock_guard<std::mutex> lock(sessions_lock_);
preloaded_sessions_.TryTake(filename);
completion_sessions_.TryTake(filename);
preloaded_sessions_.TryTake(filename);
completion_sessions_.TryTake(filename);
}
void ClangCompleteManager::FlushAllSessions() {

View File

@ -26,39 +26,34 @@ struct CompletionSession
};
Project::Entry file;
WorkingFiles* working_files;
WorkingFiles *working_files;
Tu completion;
Tu diagnostics;
CompletionSession(const Project::Entry& file, WorkingFiles* wfiles)
CompletionSession(const Project::Entry &file, WorkingFiles *wfiles)
: file(file), working_files(wfiles) {}
};
struct ClangCompleteManager {
using OnDiagnostic =
std::function<void(std::string path,
std::vector<lsDiagnostic> diagnostics)>;
using OnComplete =
std::function<void(const std::vector<lsCompletionItem>& results,
bool is_cached_result)>;
using OnDiagnostic = std::function<void(
std::string path, std::vector<lsDiagnostic> diagnostics)>;
using OnComplete = std::function<void(
const std::vector<lsCompletionItem> &results, bool is_cached_result)>;
using OnDropped = std::function<void(lsRequestId request_id)>;
struct PreloadRequest {
PreloadRequest(const std::string& path)
PreloadRequest(const std::string &path)
: request_time(std::chrono::high_resolution_clock::now()), path(path) {}
std::chrono::time_point<std::chrono::high_resolution_clock> request_time;
std::string path;
};
struct CompletionRequest {
CompletionRequest(const lsRequestId& id,
const lsTextDocumentIdentifier& document,
const lsPosition& position,
const OnComplete& on_complete)
: id(id),
document(document),
position(position),
CompletionRequest(const lsRequestId &id,
const lsTextDocumentIdentifier &document,
const lsPosition &position, const OnComplete &on_complete)
: id(id), document(document), position(position),
on_complete(on_complete) {}
lsRequestId id;
@ -70,42 +65,40 @@ struct ClangCompleteManager {
lsTextDocumentIdentifier document;
};
ClangCompleteManager(Project* project,
WorkingFiles* working_files,
OnDiagnostic on_diagnostic,
OnDropped on_dropped);
ClangCompleteManager(Project *project, WorkingFiles *working_files,
OnDiagnostic on_diagnostic, OnDropped on_dropped);
// Start a code completion at the given location. |on_complete| will run when
// completion results are available. |on_complete| may run on any thread.
void CodeComplete(const lsRequestId& request_id,
const lsTextDocumentPositionParams& completion_location,
const OnComplete& on_complete);
void CodeComplete(const lsRequestId &request_id,
const lsTextDocumentPositionParams &completion_location,
const OnComplete &on_complete);
// Request a diagnostics update.
void DiagnosticsUpdate(const lsTextDocumentIdentifier& document);
void DiagnosticsUpdate(const lsTextDocumentIdentifier &document);
// Notify the completion manager that |filename| has been viewed and we
// should begin preloading completion data.
void NotifyView(const std::string& filename);
void NotifyView(const std::string &filename);
// Notify the completion manager that |filename| has been edited.
void NotifyEdit(const std::string& filename);
void NotifyEdit(const std::string &filename);
// Notify the completion manager that |filename| has been saved. This
// triggers a reparse.
void NotifySave(const std::string& filename);
void NotifySave(const std::string &filename);
// Notify the completion manager that |filename| has been closed. Any existing
// completion session will be dropped.
void NotifyClose(const std::string& filename);
void NotifyClose(const std::string &filename);
// Ensures there is a completion or preloaded session. Returns true if a new
// session was created.
bool EnsureCompletionOrCreatePreloadSession(const std::string& filename);
bool EnsureCompletionOrCreatePreloadSession(const std::string &filename);
// Tries to find an edit session for |filename|. This will move the session
// from view to edit.
std::shared_ptr<CompletionSession> TryGetSession(const std::string& filename,
std::shared_ptr<CompletionSession> TryGetSession(const std::string &filename,
bool mark_as_completion,
bool create_if_needed);
// Flushes all saved sessions with the supplied filename
void FlushSession(const std::string& filename);
void FlushSession(const std::string &filename);
// Flushes all saved sessions
void FlushAllSessions(void);
@ -114,8 +107,8 @@ struct ClangCompleteManager {
const int kMaxCompletionSessions = 5;
// Global state.
Project* project_;
WorkingFiles* working_files_;
Project *project_;
WorkingFiles *working_files_;
OnDiagnostic on_diagnostic_;
OnDropped on_dropped_;

View File

@ -68,7 +68,7 @@ std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
const std::string &filepath, const std::vector<std::string> &args,
const WorkingFiles::Snapshot &snapshot, bool diagnostic) {
std::vector<const char *> Args;
for (auto& arg : args)
for (auto &arg : args)
Args.push_back(arg.c_str());
Args.push_back("-fallow-editor-placeholders");
if (!diagnostic)
@ -103,9 +103,8 @@ std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
ret->PCHCO->getRawReader().getFormat(), &ErrUnit));
};
if (!CRC.RunSafely(parse)) {
LOG_S(ERROR)
<< "clang crashed for " << filepath << "\n"
<< StringJoin(args, " ") + " -fsyntax-only";
LOG_S(ERROR) << "clang crashed for " << filepath << "\n"
<< StringJoin(args, " ") + " -fsyntax-only";
return {};
}
if (!Unit && !ErrUnit)

View File

@ -7,9 +7,9 @@
#include <llvm/Support/CrashRecoveryContext.h>
#include <memory>
#include <stdlib.h>
#include <string>
#include <vector>
#include <stdlib.h>
std::vector<clang::ASTUnit::RemappedFile>
GetRemapped(const WorkingFiles::Snapshot &snapshot);
@ -19,12 +19,12 @@ Range FromCharSourceRange(const clang::SourceManager &SM,
clang::CharSourceRange R,
llvm::sys::fs::UniqueID *UniqueID = nullptr);
Range FromCharRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts,
clang::SourceRange R,
Range FromCharRange(const clang::SourceManager &SM,
const clang::LangOptions &LangOpts, clang::SourceRange R,
llvm::sys::fs::UniqueID *UniqueID = nullptr);
Range FromTokenRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts,
clang::SourceRange R,
Range FromTokenRange(const clang::SourceManager &SM,
const clang::LangOptions &LangOpts, clang::SourceRange R,
llvm::sys::fs::UniqueID *UniqueID = nullptr);
struct ClangTranslationUnit {

View File

@ -10,7 +10,7 @@
using namespace clang;
using namespace llvm;
std::string FileName(const FileEntry& file) {
std::string FileName(const FileEntry &file) {
StringRef Name = file.tryGetRealPathName();
if (Name.empty())
Name = file.getName();
@ -25,7 +25,7 @@ std::string FileName(const FileEntry& file) {
}
// clang::BuiltinType::getName without PrintingPolicy
const char* ClangBuiltinTypeName(int kind) {
const char *ClangBuiltinTypeName(int kind) {
switch (BuiltinType::Kind(kind)) {
case BuiltinType::Void:
return "void";

View File

@ -5,6 +5,6 @@
#include <string>
// Returns the absolute path to |file|.
std::string FileName(const clang::FileEntry& file);
std::string FileName(const clang::FileEntry &file);
const char* ClangBuiltinTypeName(int);
const char *ClangBuiltinTypeName(int);

View File

@ -1,4 +1,4 @@
#include "config.h"
Config* g_config;
Config *g_config;
thread_local int g_thread_id;

View File

@ -218,49 +218,23 @@ struct Config {
MAKE_REFLECT_STRUCT(Config::Clang, extraArgs, resourceDir);
MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport);
MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables);
MAKE_REFLECT_STRUCT(Config::Completion,
caseSensitivity,
dropOldRequests,
detailedLabel,
filterAndSort,
includeBlacklist,
includeMaxPathSize,
includeSuffixWhitelist,
MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, dropOldRequests,
detailedLabel, filterAndSort, includeBlacklist,
includeMaxPathSize, includeSuffixWhitelist,
includeWhitelist);
MAKE_REFLECT_STRUCT(Config::Diagnostics,
blacklist,
frequencyMs,
onParse,
onType,
whitelist)
MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onParse,
onType, whitelist)
MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist)
MAKE_REFLECT_STRUCT(Config::Index,
attributeMakeCallsToCtor,
blacklist,
comments,
enabled,
onDidChange,
reparseForDependency,
threads,
whitelist);
MAKE_REFLECT_STRUCT(Config::Index, attributeMakeCallsToCtor, blacklist,
comments, enabled, onDidChange, reparseForDependency,
threads, whitelist);
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort);
MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum);
MAKE_REFLECT_STRUCT(Config,
compilationDatabaseCommand,
compilationDatabaseDirectory,
cacheDirectory,
cacheFormat,
MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand,
compilationDatabaseDirectory, cacheDirectory, cacheFormat,
clang,
client,
codeLens,
completion,
diagnostics,
highlight,
index,
largeFileSize,
workspaceSymbol,
xref);
clang, client, codeLens, completion, diagnostics, highlight,
index, largeFileSize, workspaceSymbol, xref);
extern Config* g_config;
extern Config *g_config;
thread_local extern int g_thread_id;

View File

@ -8,9 +8,9 @@
namespace {
std::optional<std::string> GetFileContents(
const std::string& path,
std::unordered_map<std::string, FileContents>* file_contents) {
std::optional<std::string>
GetFileContents(const std::string &path,
std::unordered_map<std::string, FileContents> *file_contents) {
auto it = file_contents->find(path);
if (it == file_contents->end()) {
std::optional<std::string> content = ReadContent(path);
@ -21,9 +21,9 @@ std::optional<std::string> GetFileContents(
return it->second.content;
}
} // namespace
} // namespace
FileContents::FileContents(const std::string& path, const std::string& content)
FileContents::FileContents(const std::string &path, const std::string &content)
: path(path), content(content) {
line_offsets_.push_back(0);
for (size_t i = 0; i < content.size(); i++) {
@ -43,13 +43,13 @@ std::optional<int> FileContents::ToOffset(Position p) const {
std::optional<std::string> FileContents::ContentsInRange(Range range) const {
std::optional<int> start_offset = ToOffset(range.start),
end_offset = ToOffset(range.end);
end_offset = ToOffset(range.end);
if (start_offset && end_offset && *start_offset < *end_offset)
return content.substr(*start_offset, *end_offset - *start_offset);
return std::nullopt;
}
VFS::State VFS::Get(const std::string& file) {
VFS::State VFS::Get(const std::string &file) {
std::lock_guard<std::mutex> lock(mutex);
auto it = state.find(file);
if (it != state.end())
@ -57,9 +57,9 @@ VFS::State VFS::Get(const std::string& file) {
return {0, 0, 0};
}
bool VFS::Mark(const std::string& file, int owner, int stage) {
bool VFS::Mark(const std::string &file, int owner, int stage) {
std::lock_guard<std::mutex> lock(mutex);
State& st = state[file];
State &st = state[file];
if (st.stage < stage) {
st.owner = owner;
st.stage = stage;
@ -68,9 +68,9 @@ bool VFS::Mark(const std::string& file, int owner, int stage) {
return false;
}
bool VFS::Stamp(const std::string& file, int64_t ts) {
bool VFS::Stamp(const std::string &file, int64_t ts) {
std::lock_guard<std::mutex> lock(mutex);
State& st = state[file];
State &st = state[file];
if (st.timestamp < ts) {
st.timestamp = ts;
return true;
@ -78,23 +78,23 @@ bool VFS::Stamp(const std::string& file, int64_t ts) {
return false;
}
void VFS::ResetLocked(const std::string& file) {
State& st = state[file];
void VFS::ResetLocked(const std::string &file) {
State &st = state[file];
if (st.owner == 0 || st.owner == g_thread_id)
st.stage = 0;
}
void VFS::Reset(const std::string& file) {
void VFS::Reset(const std::string &file) {
std::lock_guard<std::mutex> lock(mutex);
ResetLocked(file);
}
FileConsumer::FileConsumer(VFS* vfs, const std::string& parse_file)
FileConsumer::FileConsumer(VFS *vfs, const std::string &parse_file)
: vfs_(vfs), parse_file_(parse_file), thread_id_(g_thread_id) {}
IndexFile* FileConsumer::TryConsumeFile(
const clang::FileEntry& File,
std::unordered_map<std::string, FileContents>* file_contents_map) {
IndexFile *FileConsumer::TryConsumeFile(
const clang::FileEntry &File,
std::unordered_map<std::string, FileContents> *file_contents_map) {
auto UniqueID = File.getUniqueID();
auto it = local_.find(UniqueID);
if (it != local_.end())
@ -115,13 +115,14 @@ IndexFile* FileConsumer::TryConsumeFile(
return nullptr;
// Build IndexFile instance.
local_[UniqueID] = std::make_unique<IndexFile>(UniqueID, file_name, *contents);
local_[UniqueID] =
std::make_unique<IndexFile>(UniqueID, file_name, *contents);
return local_[UniqueID].get();
}
std::vector<std::unique_ptr<IndexFile>> FileConsumer::TakeLocalState() {
std::vector<std::unique_ptr<IndexFile>> result;
for (auto& entry : local_) {
for (auto &entry : local_) {
if (entry.second)
result.push_back(std::move(entry.second));
}

View File

@ -14,7 +14,7 @@ struct IndexFile;
struct FileContents {
FileContents() = default;
FileContents(const std::string& path, const std::string& content);
FileContents(const std::string &path, const std::string &content);
std::optional<int> ToOffset(Position p) const;
std::optional<std::string> ContentsInRange(Range range) const;
@ -34,23 +34,22 @@ struct VFS {
mutable std::unordered_map<std::string, State> state;
mutable std::mutex mutex;
State Get(const std::string& file);
bool Mark(const std::string& file, int owner, int stage);
bool Stamp(const std::string& file, int64_t ts);
void ResetLocked(const std::string& file);
void Reset(const std::string& file);
State Get(const std::string &file);
bool Mark(const std::string &file, int owner, int stage);
bool Stamp(const std::string &file, int64_t ts);
void ResetLocked(const std::string &file);
void Reset(const std::string &file);
};
namespace std {
template <>
struct hash<llvm::sys::fs::UniqueID> {
template <> struct hash<llvm::sys::fs::UniqueID> {
std::size_t operator()(llvm::sys::fs::UniqueID ID) const {
size_t ret = ID.getDevice();
hash_combine(ret, ID.getFile());
return ret;
}
};
}
} // namespace std
// FileConsumer is used by the indexer. When it encouters a file, it tries to
// take ownership over it. If the indexer has ownership over a file, it will
@ -60,7 +59,7 @@ struct hash<llvm::sys::fs::UniqueID> {
// The indexer does this because header files do not have their own translation
// units but we still want to index them.
struct FileConsumer {
FileConsumer(VFS* vfs, const std::string& parse_file);
FileConsumer(VFS *vfs, const std::string &parse_file);
// Returns IndexFile for the file or nullptr. |is_first_ownership| is set
// to true iff the function just took ownership over the file. Otherwise it
@ -68,15 +67,17 @@ struct FileConsumer {
//
// note: file_contents is passed as a parameter instead of as a member
// variable since it is large and we do not want to copy it.
IndexFile* TryConsumeFile(const clang::FileEntry& file,
std::unordered_map<std::string, FileContents>* file_contents);
IndexFile *
TryConsumeFile(const clang::FileEntry &file,
std::unordered_map<std::string, FileContents> *file_contents);
// Returns and passes ownership of all local state.
std::vector<std::unique_ptr<IndexFile>> TakeLocalState();
private:
std::unordered_map<llvm::sys::fs::UniqueID, std::unique_ptr<IndexFile>> local_;
VFS* vfs_;
private:
std::unordered_map<llvm::sys::fs::UniqueID, std::unique_ptr<IndexFile>>
local_;
VFS *vfs_;
std::string parse_file_;
int thread_id_;
};

View File

@ -6,10 +6,8 @@ using namespace llvm;
#include <set>
#include <vector>
void GetFilesInFolder(std::string folder,
bool recursive,
bool dir_prefix,
const std::function<void(const std::string&)>& handler) {
void GetFilesInFolder(std::string folder, bool recursive, bool dir_prefix,
const std::function<void(const std::string &)> &handler) {
EnsureEndsInSlash(folder);
sys::fs::file_status Status;
if (sys::fs::status(folder, Status, true))
@ -20,7 +18,7 @@ void GetFilesInFolder(std::string folder,
std::set<sys::fs::UniqueID> seen{Status.getUniqueID()};
while (curr.size() || succ.size()) {
if (curr.empty()) {
for (auto& it : succ)
for (auto &it : succ)
if (!seen.count(it.second.getUniqueID()))
curr.push_back(std::move(it.first));
succ.clear();

View File

@ -1,8 +1,8 @@
#include "fuzzy_match.h"
#include <algorithm>
#include <ctype.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
enum CharClass { Other, Lower, Upper };
@ -17,7 +17,7 @@ CharClass GetCharClass(int c) {
return Other;
}
void CalculateRoles(std::string_view s, int roles[], int* class_set) {
void CalculateRoles(std::string_view s, int roles[], int *class_set) {
if (s.empty()) {
*class_set = 0;
return;
@ -41,7 +41,7 @@ void CalculateRoles(std::string_view s, int roles[], int* class_set) {
}
roles[s.size() - 1] = fn();
}
} // namespace
} // namespace
int FuzzyMatcher::MissScore(int j, bool last) {
int s = -3;

View File

@ -5,7 +5,7 @@
#include <string_view>
class FuzzyMatcher {
public:
public:
constexpr static int kMaxPat = 100;
constexpr static int kMaxText = 200;
// Negative but far from INT_MIN so that intermediate results are hard to
@ -15,7 +15,7 @@ class FuzzyMatcher {
FuzzyMatcher(std::string_view pattern, int case_sensitivity);
int Match(std::string_view text);
private:
private:
int case_sensitivity;
std::string pat;
std::string_view text;

View File

@ -19,7 +19,7 @@ struct CompletionCandidate {
lsCompletionItem completion_item;
};
std::string ElideLongPath(const std::string& path) {
std::string ElideLongPath(const std::string &path) {
if (g_config->completion.includeMaxPathSize <= 0)
return path;
@ -30,8 +30,8 @@ std::string ElideLongPath(const std::string& path) {
return ".." + path.substr(start + 2);
}
size_t TrimCommonPathPrefix(const std::string& result,
const std::string& trimmer) {
size_t TrimCommonPathPrefix(const std::string &result,
const std::string &trimmer) {
#ifdef _WIN32
std::string s = result, t = trimmer;
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
@ -46,16 +46,15 @@ size_t TrimCommonPathPrefix(const std::string& result,
}
// Returns true iff angle brackets should be used.
bool TrimPath(Project* project,
const std::string& project_root,
std::string* insert_path) {
bool TrimPath(Project *project, const std::string &project_root,
std::string *insert_path) {
size_t start = TrimCommonPathPrefix(*insert_path, project_root);
bool angle = false;
for (auto& include_dir : project->quote_include_directories)
for (auto &include_dir : project->quote_include_directories)
start = std::max(start, TrimCommonPathPrefix(*insert_path, include_dir));
for (auto& include_dir : project->angle_include_directories) {
for (auto &include_dir : project->angle_include_directories) {
auto len = TrimCommonPathPrefix(*insert_path, include_dir);
if (len > start) {
start = len;
@ -67,12 +66,11 @@ bool TrimPath(Project* project,
return angle;
}
lsCompletionItem BuildCompletionItem(const std::string& path,
bool use_angle_brackets,
bool is_stl) {
lsCompletionItem BuildCompletionItem(const std::string &path,
bool use_angle_brackets, bool is_stl) {
lsCompletionItem item;
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->newText = path;
item.insertTextFormat = lsInsertTextFormat::PlainText;
@ -87,9 +85,9 @@ lsCompletionItem BuildCompletionItem(const std::string& path,
return item;
}
} // namespace
} // namespace
IncludeComplete::IncludeComplete(Project* project)
IncludeComplete::IncludeComplete(Project *project)
: is_scanning(false), project_(project) {}
void IncludeComplete::Rescan() {
@ -102,8 +100,9 @@ void IncludeComplete::Rescan() {
if (!match_ && (g_config->completion.includeWhitelist.size() ||
g_config->completion.includeBlacklist.size()))
match_ = std::make_unique<GroupMatch>(g_config->completion.includeWhitelist,
g_config->completion.includeBlacklist);
match_ =
std::make_unique<GroupMatch>(g_config->completion.includeWhitelist,
g_config->completion.includeBlacklist);
is_scanning = true;
std::thread([this]() {
@ -111,17 +110,18 @@ void IncludeComplete::Rescan() {
Timer timer("include", "scan include paths");
TimeRegion region(timer);
for (const std::string& dir : project_->quote_include_directories)
for (const std::string &dir : project_->quote_include_directories)
InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/);
for (const std::string& dir : project_->angle_include_directories)
for (const std::string &dir : project_->angle_include_directories)
InsertIncludesFromDirectory(dir, true /*use_angle_brackets*/);
is_scanning = false;
}).detach();
})
.detach();
}
void IncludeComplete::InsertCompletionItem(const std::string& absolute_path,
lsCompletionItem&& item) {
void IncludeComplete::InsertCompletionItem(const std::string &absolute_path,
lsCompletionItem &&item) {
if (inserted_paths.insert({item.detail, inserted_paths.size()}).second) {
completion_items.push_back(item);
// insert if not found or with shorter include path
@ -132,7 +132,7 @@ void IncludeComplete::InsertCompletionItem(const std::string& absolute_path,
completion_items.size() - 1;
}
} else {
lsCompletionItem& inserted_item =
lsCompletionItem &inserted_item =
completion_items[inserted_paths[item.detail]];
// Update |use_angle_brackets_|, prefer quotes.
if (!item.use_angle_brackets_)
@ -140,7 +140,7 @@ 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, g_config->completion.includeSuffixWhitelist))
return;
if (match_ && !match_->IsMatch(absolute_path))
@ -184,13 +184,14 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory,
});
std::lock_guard<std::mutex> lock(completion_items_mutex);
for (CompletionCandidate& result : results)
for (CompletionCandidate &result : results)
InsertCompletionItem(result.absolute_path,
std::move(result.completion_item));
}
std::optional<lsCompletionItem> IncludeComplete::FindCompletionItemForAbsolutePath(
const std::string& absolute_path) {
std::optional<lsCompletionItem>
IncludeComplete::FindCompletionItemForAbsolutePath(
const std::string &absolute_path) {
std::lock_guard<std::mutex> lock(completion_items_mutex);
auto it = absolute_path_to_completion_item.find(absolute_path);

View File

@ -10,26 +10,26 @@ struct GroupMatch;
struct Project;
struct IncludeComplete {
IncludeComplete(Project* project);
IncludeComplete(Project *project);
// Starts scanning directories. Clears existing cache.
void Rescan();
// Ensures the one-off file is inside |completion_items|.
void AddFile(const std::string& absolute_path);
void AddFile(const std::string &absolute_path);
// Scans the given directory and inserts all includes from this. This is a
// blocking function and should be run off the querydb thread.
void InsertIncludesFromDirectory(std::string directory,
bool use_angle_brackets);
std::optional<lsCompletionItem> FindCompletionItemForAbsolutePath(
const std::string& absolute_path);
std::optional<lsCompletionItem>
FindCompletionItemForAbsolutePath(const std::string &absolute_path);
// Insert item to |completion_items|.
// Update |absolute_path_to_completion_item| and |inserted_paths|.
void InsertCompletionItem(const std::string& absolute_path,
lsCompletionItem&& item);
void InsertCompletionItem(const std::string &absolute_path,
lsCompletionItem &&item);
// Guards |completion_items| when |is_scanning| is true.
std::mutex completion_items_mutex;
@ -44,6 +44,6 @@ struct IncludeComplete {
std::unordered_map<std::string, int> inserted_paths;
// Cached references
Project* project_;
Project *project_;
std::unique_ptr<GroupMatch> match_;
};

View File

@ -21,9 +21,9 @@ using ccls::Intern;
using namespace clang;
using llvm::Timer;
#include <algorithm>
#include <inttypes.h>
#include <limits.h>
#include <algorithm>
#include <map>
#include <unordered_set>
@ -40,14 +40,14 @@ struct IndexParam {
std::string short_name;
std::string qualified;
};
std::unordered_map<const Decl*, DeclInfo> Decl2Info;
std::unordered_map<const Decl *, DeclInfo> Decl2Info;
ASTUnit& Unit;
ASTContext* Ctx;
ASTUnit &Unit;
ASTContext *Ctx;
FileConsumer* file_consumer = nullptr;
FileConsumer *file_consumer = nullptr;
IndexParam(ASTUnit& Unit, FileConsumer* file_consumer)
IndexParam(ASTUnit &Unit, FileConsumer *file_consumer)
: Unit(Unit), file_consumer(file_consumer) {}
IndexFile *ConsumeFile(const FileEntry &File) {
@ -63,7 +63,7 @@ struct IndexParam {
// Set modification time.
std::optional<int64_t> write_time = LastWriteTime(file_name);
LOG_IF_S(ERROR, !write_time)
<< "failed to fetch write time for " << file_name;
<< "failed to fetch write time for " << file_name;
if (write_time)
file2write_time[file_name] = *write_time;
}
@ -81,12 +81,13 @@ StringRef GetSourceInRange(const SourceManager &SM, const LangOptions &LangOpts,
StringRef Buf = SM.getBufferData(BInfo.first, &invalid);
if (invalid)
return "";
return Buf.substr(BInfo.second, EInfo.second + Lexer::MeasureTokenLength(
ELoc, SM, LangOpts) -
BInfo.second);
return Buf.substr(BInfo.second,
EInfo.second +
Lexer::MeasureTokenLength(ELoc, SM, LangOpts) -
BInfo.second);
}
SymbolKind GetSymbolKind(const Decl* D) {
SymbolKind GetSymbolKind(const Decl *D) {
switch (D->getKind()) {
case Decl::TranslationUnit:
return SymbolKind::File;
@ -136,46 +137,46 @@ SymbolKind GetSymbolKind(const Decl* D) {
LanguageId GetDeclLanguage(const Decl *D) {
switch (D->getKind()) {
default:
return LanguageId::C;
case Decl::ImplicitParam:
case Decl::ObjCAtDefsField:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCCompatibleAlias:
case Decl::ObjCImplementation:
case Decl::ObjCInterface:
case Decl::ObjCIvar:
case Decl::ObjCMethod:
case Decl::ObjCProperty:
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
case Decl::ObjCTypeParam:
return LanguageId::ObjC;
case Decl::CXXConstructor:
case Decl::CXXConversion:
case Decl::CXXDestructor:
case Decl::CXXMethod:
case Decl::CXXRecord:
case Decl::ClassTemplate:
case Decl::ClassTemplatePartialSpecialization:
case Decl::ClassTemplateSpecialization:
case Decl::Friend:
case Decl::FriendTemplate:
case Decl::FunctionTemplate:
case Decl::LinkageSpec:
case Decl::Namespace:
case Decl::NamespaceAlias:
case Decl::NonTypeTemplateParm:
case Decl::StaticAssert:
case Decl::TemplateTemplateParm:
case Decl::TemplateTypeParm:
case Decl::UnresolvedUsingTypename:
case Decl::UnresolvedUsingValue:
case Decl::Using:
case Decl::UsingDirective:
case Decl::UsingShadow:
return LanguageId::Cpp;
default:
return LanguageId::C;
case Decl::ImplicitParam:
case Decl::ObjCAtDefsField:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCCompatibleAlias:
case Decl::ObjCImplementation:
case Decl::ObjCInterface:
case Decl::ObjCIvar:
case Decl::ObjCMethod:
case Decl::ObjCProperty:
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
case Decl::ObjCTypeParam:
return LanguageId::ObjC;
case Decl::CXXConstructor:
case Decl::CXXConversion:
case Decl::CXXDestructor:
case Decl::CXXMethod:
case Decl::CXXRecord:
case Decl::ClassTemplate:
case Decl::ClassTemplatePartialSpecialization:
case Decl::ClassTemplateSpecialization:
case Decl::Friend:
case Decl::FriendTemplate:
case Decl::FunctionTemplate:
case Decl::LinkageSpec:
case Decl::Namespace:
case Decl::NamespaceAlias:
case Decl::NonTypeTemplateParm:
case Decl::StaticAssert:
case Decl::TemplateTemplateParm:
case Decl::TemplateTypeParm:
case Decl::UnresolvedUsingTypename:
case Decl::UnresolvedUsingValue:
case Decl::Using:
case Decl::UsingDirective:
case Decl::UsingShadow:
return LanguageId::Cpp;
}
}
@ -187,7 +188,7 @@ QualType GetBaseType(QualType T, bool deduce_auto) {
BaseType = PTy->getPointeeType();
else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
BaseType = BPy->getPointeeType();
else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
else if (const ArrayType *ATy = dyn_cast<ArrayType>(BaseType))
BaseType = ATy->getElementType();
else if (const VectorType *VTy = BaseType->getAs<VectorType>())
BaseType = VTy->getElementType();
@ -200,8 +201,7 @@ QualType GetBaseType(QualType T, bool deduce_auto) {
BaseType = ATy->getDeducedType();
else
break;
}
else
} else
break;
}
return BaseType;
@ -210,7 +210,7 @@ QualType GetBaseType(QualType T, bool deduce_auto) {
const Decl *GetTypeDecl(QualType T, bool *specialization = nullptr) {
Decl *D = nullptr;
T = GetBaseType(T.getUnqualifiedType(), true);
const Type* TP = T.getTypePtrOrNull();
const Type *TP = T.getTypePtrOrNull();
if (!TP)
return nullptr;
@ -254,7 +254,7 @@ try_again:
D = cast<InjectedClassNameType>(TP)->getDecl();
break;
// FIXME: Template type parameters!
// FIXME: Template type parameters!
case Type::Elaborated:
TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
@ -266,19 +266,19 @@ try_again:
return D;
}
const Decl* GetSpecialized(const Decl* D) {
const Decl *GetSpecialized(const Decl *D) {
if (!D)
return D;
Decl *Template = nullptr;
if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
if (const ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
if (const ClassTemplatePartialSpecializationDecl *PartialSpec =
dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
Template = PartialSpec->getSpecializedTemplate();
else if (const ClassTemplateSpecializationDecl *ClassSpec
= dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
else if (const ClassTemplateSpecializationDecl *ClassSpec =
dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *> Result
= ClassSpec->getSpecializedTemplateOrPartial();
ClassTemplatePartialSpecializationDecl *>
Result = ClassSpec->getSpecializedTemplateOrPartial();
if (Result.is<ClassTemplateDecl *>())
Template = Result.get<ClassTemplateDecl *>();
else
@ -293,8 +293,8 @@ const Decl* GetSpecialized(const Decl* D) {
} else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (Var->isStaticDataMember())
Template = Var->getInstantiatedFromStaticDataMember();
} else if (const RedeclarableTemplateDecl *Tmpl
= dyn_cast<RedeclarableTemplateDecl>(D))
} else if (const RedeclarableTemplateDecl *Tmpl =
dyn_cast<RedeclarableTemplateDecl>(D))
Template = Tmpl->getInstantiatedFromMemberTemplate();
else
return nullptr;
@ -302,7 +302,7 @@ const Decl* GetSpecialized(const Decl* D) {
}
bool ValidateRecord(const RecordDecl *RD) {
for (const auto *I : RD->fields()){
for (const auto *I : RD->fields()) {
QualType FQT = I->getType();
if (FQT->isIncompleteType() || FQT->isDependentType())
return false;
@ -317,12 +317,13 @@ bool ValidateRecord(const RecordDecl *RD) {
class IndexDataConsumer : public index::IndexDataConsumer {
public:
ASTContext *Ctx;
IndexParam& param;
IndexParam &param;
std::string GetComment(const Decl* D) {
std::string GetComment(const Decl *D) {
SourceManager &SM = Ctx->getSourceManager();
const RawComment *RC = Ctx->getRawCommentForAnyRedecl(D);
if (!RC) return "";
if (!RC)
return "";
StringRef Raw = RC->getRawText(Ctx->getSourceManager());
SourceRange R = RC->getSourceRange();
std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(R.getBegin());
@ -422,7 +423,7 @@ public:
return PP;
}
static void SimplifyAnonymous(std::string& name) {
static void SimplifyAnonymous(std::string &name) {
for (std::string::size_type i = 0;;) {
if ((i = name.find("(anonymous ", i)) == std::string::npos)
break;
@ -476,7 +477,7 @@ public:
void SetVarName(const Decl *D, std::string_view short_name,
std::string_view qualified, IndexVar::Def &def) {
QualType T;
const Expr* init = nullptr;
const Expr *init = nullptr;
bool binding = false;
if (auto *VD = dyn_cast<VarDecl>(D)) {
T = VD->getType();
@ -496,7 +497,7 @@ public:
PrintingPolicy PP = GetDefaultPolicy();
T.print(OS, PP);
if (Str.size() &&
(Str.back() != ' ' && Str.back() != '*' && Str.back() != '&'))
(Str.back() != ' ' && Str.back() != '*' && Str.back() != '&'))
Str += ' ';
def.qual_name_offset = Str.size();
def.short_name_offset = Str.size() + qualified.size() - short_name.size();
@ -508,7 +509,7 @@ public:
}
if (init) {
SourceManager &SM = Ctx->getSourceManager();
const LangOptions& Lang = Ctx->getLangOpts();
const LangOptions &Lang = Ctx->getLangOpts();
SourceRange R = SM.getExpansionRange(init->getSourceRange())
#if LLVM_VERSION_MAJOR >= 7
.getAsRange()
@ -533,7 +534,8 @@ public:
void AddMacroUse(IndexFile *db, SourceManager &SM, Usr usr, SymbolKind kind,
SourceLocation Spell) const {
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Spell));
if (!FE) return;
if (!FE)
return;
auto UID = FE->getUniqueID();
auto [it, inserted] = db->uid2lid_and_path.try_emplace(UID);
if (inserted) {
@ -565,10 +567,8 @@ public:
}
public:
IndexDataConsumer(IndexParam& param) : param(param) {}
void initialize(ASTContext &Ctx) override {
this->Ctx = param.Ctx = &Ctx;
}
IndexDataConsumer(IndexParam &param) : param(param) {}
void initialize(ASTContext &Ctx) override { this->Ctx = param.Ctx = &Ctx; }
bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
ArrayRef<index::SymbolRelation> Relations,
#if LLVM_VERSION_MAJOR >= 7
@ -615,7 +615,7 @@ public:
if (!db)
return true;
const Decl* OrigD = ASTNode.OrigD;
const Decl *OrigD = ASTNode.OrigD;
const DeclContext *SemDC = OrigD->getDeclContext();
const DeclContext *LexDC = ASTNode.ContainerDC;
Role role = static_cast<Role>(Roles);
@ -629,7 +629,7 @@ public:
IndexType *type = nullptr;
IndexVar *var = nullptr;
SymbolKind kind = GetSymbolKind(D);
IndexParam::DeclInfo* info;
IndexParam::DeclInfo *info;
Usr usr = GetUsr(D, &info);
auto do_def_decl = [&](auto *entity) {
@ -687,7 +687,7 @@ public:
if (type->def.detailed_name[0] == '\0')
SetName(OrigD, info->short_name, info->qualified, type->def);
if (is_def || is_decl) {
const Decl* DC = cast<Decl>(SemDC);
const Decl *DC = cast<Decl>(SemDC);
if (GetSymbolKind(DC) == SymbolKind::Type)
db->ToType(GetUsr(DC)).def.types.push_back(usr);
}
@ -717,7 +717,7 @@ public:
db->ToType(usr1).instances.push_back(usr);
} else {
for (const Decl *D1 = GetTypeDecl(T); D1; D1 = GetSpecialized(D1)) {
IndexParam::DeclInfo* info1;
IndexParam::DeclInfo *info1;
Usr usr1 = GetUsr(D1, &info1);
auto it = db->usr2type.find(usr1);
if (it != db->usr2type.end()) {
@ -725,10 +725,11 @@ public:
it->second.instances.push_back(usr);
break;
}
// e.g. TemplateTypeParmDecl is not handled by handleDeclOccurence.
// e.g. TemplateTypeParmDecl is not handled by
// handleDeclOccurence.
SourceRange R1 = D1->getSourceRange();
if (SM.getFileID(R1.getBegin()) == LocFID) {
IndexType& type1 = db->ToType(usr1);
IndexType &type1 = db->ToType(usr1);
SourceLocation L1 = D1->getLocation();
type1.def.spell = GetUse(db, FromTokenRange(SM, Lang, {L1, L1}),
SemDC, Role::Definition);
@ -932,7 +933,7 @@ public:
if (auto *ND = dyn_cast<NamedDecl>(D)) {
SmallVector<const NamedDecl *, 8> OverDecls;
Ctx->getOverriddenMethods(ND, OverDecls);
for (const auto* ND1 : OverDecls) {
for (const auto *ND1 : OverDecls) {
Usr usr1 = GetUsr(ND1);
func->def.bases.push_back(usr1);
db->ToFunc(usr1).derived.push_back(usr);
@ -985,10 +986,10 @@ public:
};
class IndexPPCallbacks : public PPCallbacks {
SourceManager& SM;
IndexParam& param;
SourceManager &SM;
IndexParam &param;
std::pair<StringRef, Usr> GetMacro(const Token& Tok) const {
std::pair<StringRef, Usr> GetMacro(const Token &Tok) const {
StringRef Name = Tok.getIdentifierInfo()->getName();
SmallString<256> USR("@macro@");
USR += Name;
@ -1025,13 +1026,13 @@ public:
}
void MacroDefined(const Token &Tok, const MacroDirective *MD) override {
llvm::sys::fs::UniqueID UniqueID;
const LangOptions& Lang = param.Ctx->getLangOpts();
const LangOptions &Lang = param.Ctx->getLangOpts();
SourceLocation L = MD->getLocation();
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(L));
if (!FE)
return;
if (IndexFile *db = param.ConsumeFile(*FE)) {
auto[Name, usr] = GetMacro(Tok);
auto [Name, usr] = GetMacro(Tok);
IndexVar &var = db->ToVar(usr);
auto range = FromTokenRange(SM, Lang, {L, L}, &UniqueID);
var.def.kind = lsSymbolKind::Macro;
@ -1053,15 +1054,15 @@ public:
}
}
}
void MacroExpands(const Token &Tok, const MacroDefinition &MD,
SourceRange R, const MacroArgs *Args) override {
void MacroExpands(const Token &Tok, const MacroDefinition &MD, SourceRange R,
const MacroArgs *Args) override {
llvm::sys::fs::UniqueID UniqueID;
SourceLocation L = SM.getSpellingLoc(R.getBegin());
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(L));
if (!FE)
return;
if (IndexFile *db = param.ConsumeFile(*FE)) {
auto[Name, usr] = GetMacro(Tok);
auto [Name, usr] = GetMacro(Tok);
IndexVar &var = db->ToVar(usr);
var.uses.push_back(
{{FromTokenRange(SM, param.Ctx->getLangOpts(), {L, L}, &UniqueID), 0,
@ -1085,17 +1086,19 @@ public:
};
class IndexFrontendAction : public ASTFrontendAction {
IndexParam& param;
IndexParam &param;
public:
IndexFrontendAction(IndexParam& param) : param(param) {}
IndexFrontendAction(IndexParam &param) : param(param) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override {
Preprocessor &PP = CI.getPreprocessor();
PP.addPPCallbacks(std::make_unique<IndexPPCallbacks>(PP.getSourceManager(), param));
PP.addPPCallbacks(
std::make_unique<IndexPPCallbacks>(PP.getSourceManager(), param));
return std::make_unique<ASTConsumer>();
}
};
}
} // namespace
const int IndexFile::kMajorVersion = 17;
const int IndexFile::kMinorVersion = 1;
@ -1104,21 +1107,21 @@ IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path,
const std::string &contents)
: UniqueID(UniqueID), path(path), file_contents(contents) {}
IndexFunc& IndexFile::ToFunc(Usr usr) {
IndexFunc &IndexFile::ToFunc(Usr usr) {
auto [it, inserted] = usr2func.try_emplace(usr);
if (inserted)
it->second.usr = usr;
return it->second;
}
IndexType& IndexFile::ToType(Usr usr) {
IndexType &IndexFile::ToType(Usr usr) {
auto [it, inserted] = usr2type.try_emplace(usr);
if (inserted)
it->second.usr = usr;
return it->second;
}
IndexVar& IndexFile::ToVar(Usr usr) {
IndexVar &IndexFile::ToVar(Usr usr) {
auto [it, inserted] = usr2var.try_emplace(usr);
if (inserted)
it->second.usr = usr;
@ -1129,8 +1132,7 @@ std::string IndexFile::ToString() {
return ccls::Serialize(SerializeFormat::Json, *this);
}
template <typename T>
void Uniquify(std::vector<T>& a) {
template <typename T> void Uniquify(std::vector<T> &a) {
std::unordered_set<T> seen;
size_t n = 0;
for (size_t i = 0; i < a.size(); i++)
@ -1140,21 +1142,19 @@ void Uniquify(std::vector<T>& a) {
}
namespace ccls::idx {
std::vector<std::unique_ptr<IndexFile>> Index(
VFS* vfs,
const std::string& opt_wdir,
const std::string& file,
const std::vector<std::string>& args,
const std::vector<FileContents>& file_contents) {
std::vector<std::unique_ptr<IndexFile>>
Index(VFS *vfs, const std::string &opt_wdir, const std::string &file,
const std::vector<std::string> &args,
const std::vector<FileContents> &file_contents) {
if (!g_config->index.enabled)
return {};
std::vector<const char *> Args;
for (auto& arg: args)
for (auto &arg : args)
Args.push_back(arg.c_str());
auto PCHCO = std::make_shared<PCHContainerOperations>();
IntrusiveRefCntPtr<DiagnosticsEngine>
Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
CompilerInstance::createDiagnostics(new DiagnosticOptions));
std::shared_ptr<CompilerInvocation> CI =
createInvocationFromCommandLine(Args, Diags);
if (!CI)
@ -1212,34 +1212,34 @@ std::vector<std::unique_ptr<IndexFile>> Index(
return {};
}
const SourceManager& SM = Unit->getSourceManager();
const FileEntry* FE = SM.getFileEntryForID(SM.getMainFileID());
IndexFile* main_file = param.ConsumeFile(*FE);
const SourceManager &SM = Unit->getSourceManager();
const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID());
IndexFile *main_file = param.ConsumeFile(*FE);
std::unordered_map<std::string, int> inc_to_line;
if (main_file)
for (auto& inc : main_file->includes)
for (auto &inc : main_file->includes)
inc_to_line[inc.resolved_path] = inc.line;
auto result = param.file_consumer->TakeLocalState();
for (std::unique_ptr<IndexFile>& entry : result) {
for (std::unique_ptr<IndexFile> &entry : result) {
entry->import_file = file;
entry->args = args;
for (auto &[_, it] : entry->uid2lid_and_path)
entry->lid2path.emplace_back(it.first, std::move(it.second));
entry->uid2lid_and_path.clear();
for (auto& it : entry->usr2func) {
for (auto &it : entry->usr2func) {
// e.g. declaration + out-of-line definition
Uniquify(it.second.derived);
Uniquify(it.second.uses);
}
for (auto& it : entry->usr2type) {
for (auto &it : entry->usr2type) {
Uniquify(it.second.derived);
Uniquify(it.second.uses);
// e.g. declaration + out-of-line definition
Uniquify(it.second.def.bases);
Uniquify(it.second.def.funcs);
}
for (auto& it : entry->usr2var)
for (auto &it : entry->usr2var)
Uniquify(it.second.uses);
if (main_file) {
@ -1270,7 +1270,7 @@ std::vector<std::unique_ptr<IndexFile>> Index(
return result;
}
}
} // namespace ccls::idx
// |SymbolRef| is serialized this way.
// |Use| also uses this though it has an extra field |file|,
@ -1306,10 +1306,10 @@ void Reflect(Writer &vis, Reference &v) {
}
}
void Reflect(Reader& vis, Use& v) {
void Reflect(Reader &vis, Use &v) {
if (vis.Format() == SerializeFormat::Json) {
std::string t = vis.GetString();
char* s = const_cast<char*>(t.c_str());
char *s = const_cast<char *>(t.c_str());
v.range = Range::FromString(s);
s = strchr(s, '|');
v.usr = strtoull(s + 1, &s, 10);
@ -1318,11 +1318,11 @@ void Reflect(Reader& vis, Use& v) {
if (*s == '|')
v.file_id = static_cast<int>(strtol(s + 1, &s, 10));
} else {
Reflect(vis, static_cast<Reference&>(v));
Reflect(vis, static_cast<Reference &>(v));
Reflect(vis, v.file_id);
}
}
void Reflect(Writer& vis, Use& v) {
void Reflect(Writer &vis, Use &v) {
if (vis.Format() == SerializeFormat::Json) {
char buf[99];
if (v.file_id == -1)
@ -1335,7 +1335,7 @@ void Reflect(Writer& vis, Use& v) {
std::string s(buf);
Reflect(vis, s);
} else {
Reflect(vis, static_cast<Reference&>(v));
Reflect(vis, static_cast<Reference &>(v));
Reflect(vis, v.file_id);
}
}

View File

@ -14,9 +14,9 @@
#include <clang/Basic/Specifiers.h>
#include <llvm/ADT/StringMap.h>
#include <stdint.h>
#include <algorithm>
#include <optional>
#include <stdint.h>
#include <string_view>
#include <unordered_map>
#include <vector>
@ -27,10 +27,10 @@ struct SymbolIdx {
Usr usr;
SymbolKind kind;
bool operator==(const SymbolIdx& o) const {
bool operator==(const SymbolIdx &o) const {
return usr == o.usr && kind == o.kind;
}
bool operator<(const SymbolIdx& o) const {
bool operator<(const SymbolIdx &o) const {
return usr != o.usr ? usr < o.usr : kind < o.kind;
}
};
@ -47,8 +47,8 @@ struct Reference {
std::tuple<Range, Usr, SymbolKind, Role> ToTuple() const {
return std::make_tuple(range, usr, kind, role);
}
bool operator==(const Reference& o) const { return ToTuple() == o.ToTuple(); }
bool operator<(const Reference& o) const { return ToTuple() < o.ToTuple(); }
bool operator==(const Reference &o) const { return ToTuple() == o.ToTuple(); }
bool operator<(const Reference &o) const { return ToTuple() < o.ToTuple(); }
};
// |id,kind| refer to the referenced entity.
@ -60,22 +60,21 @@ MAKE_HASHABLE(SymbolRef, t.range, t.usr, t.kind, t.role);
struct Use : Reference {
// |file| is used in Query* but not in Index*
int file_id = -1;
bool operator==(const Use& o) const {
bool operator==(const Use &o) const {
// lexical container info is ignored.
return range == o.range && file_id == o.file_id;
}
};
MAKE_HASHABLE(Use, t.range, t.file_id)
void Reflect(Reader& visitor, Reference& value);
void Reflect(Writer& visitor, Reference& value);
void Reflect(Reader& visitor, Use& value);
void Reflect(Writer& visitor, Use& value);
void Reflect(Reader &visitor, Reference &value);
void Reflect(Writer &visitor, Reference &value);
void Reflect(Reader &visitor, Use &value);
void Reflect(Writer &visitor, Use &value);
template <typename D>
struct NameMixin {
template <typename D> struct NameMixin {
std::string_view Name(bool qualified) const {
auto self = static_cast<const D*>(this);
auto self = static_cast<const D *>(this);
return qualified
? std::string_view(self->detailed_name + self->qual_name_offset,
self->short_name_offset -
@ -88,9 +87,9 @@ struct NameMixin {
struct FuncDef : NameMixin<FuncDef> {
// General metadata.
const char* detailed_name = "";
const char* hover = "";
const char* comments = "";
const char *detailed_name = "";
const char *hover = "";
const char *comments = "";
Maybe<Use> spell;
Maybe<Use> extent;
@ -112,20 +111,9 @@ struct FuncDef : NameMixin<FuncDef> {
std::vector<Usr> GetBases() const { return bases; }
};
MAKE_REFLECT_STRUCT(FuncDef,
detailed_name,
qual_name_offset,
short_name_offset,
short_name_size,
kind,
storage,
hover,
comments,
spell,
extent,
bases,
vars,
callees);
MAKE_REFLECT_STRUCT(FuncDef, detailed_name, qual_name_offset, short_name_offset,
short_name_size, kind, storage, hover, comments, spell,
extent, bases, vars, callees);
struct IndexFunc : NameMixin<IndexFunc> {
using Def = FuncDef;
@ -137,9 +125,9 @@ struct IndexFunc : NameMixin<IndexFunc> {
};
struct TypeDef : NameMixin<TypeDef> {
const char* detailed_name = "";
const char* hover = "";
const char* comments = "";
const char *detailed_name = "";
const char *hover = "";
const char *comments = "";
Maybe<Use> spell;
Maybe<Use> extent;
@ -163,21 +151,9 @@ struct TypeDef : NameMixin<TypeDef> {
std::vector<Usr> GetBases() const { return bases; }
};
MAKE_REFLECT_STRUCT(TypeDef,
detailed_name,
qual_name_offset,
short_name_offset,
short_name_size,
kind,
hover,
comments,
spell,
extent,
alias_of,
bases,
types,
funcs,
vars);
MAKE_REFLECT_STRUCT(TypeDef, detailed_name, qual_name_offset, short_name_offset,
short_name_size, kind, hover, comments, spell, extent,
alias_of, bases, types, funcs, vars);
struct IndexType {
using Def = TypeDef;
@ -191,9 +167,9 @@ struct IndexType {
struct VarDef : NameMixin<VarDef> {
// General metadata.
const char* detailed_name = "";
const char* hover = "";
const char* comments = "";
const char *detailed_name = "";
const char *hover = "";
const char *comments = "";
Maybe<Use> spell;
Maybe<Use> extent;
@ -217,17 +193,8 @@ struct VarDef : NameMixin<VarDef> {
std::vector<Usr> GetBases() const { return {}; }
};
MAKE_REFLECT_STRUCT(VarDef,
detailed_name,
qual_name_offset,
short_name_offset,
short_name_size,
hover,
comments,
spell,
extent,
type,
kind,
MAKE_REFLECT_STRUCT(VarDef, detailed_name, qual_name_offset, short_name_offset,
short_name_size, hover, comments, spell, extent, type, kind,
storage);
struct IndexVar {
@ -289,9 +256,9 @@ struct IndexFile {
IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path,
const std::string &contents);
IndexFunc& ToFunc(Usr usr);
IndexType& ToType(Usr usr);
IndexVar& ToVar(Usr usr);
IndexFunc &ToFunc(Usr usr);
IndexType &ToType(Usr usr);
IndexVar &ToVar(Usr usr);
std::string ToString();
};
@ -299,6 +266,6 @@ struct IndexFile {
namespace ccls::idx {
std::vector<std::unique_ptr<IndexFile>>
Index(VFS *vfs, const std::string &opt_wdir, const std::string &file,
const std::vector<std::string> &args,
const std::vector<FileContents> &file_contents);
const std::vector<std::string> &args,
const std::vector<FileContents> &file_contents);
}

View File

@ -14,7 +14,7 @@ LanguageId SourceFileLanguage(std::string_view path) {
return LanguageId::Unknown;
}
const char* LanguageIdentifier(LanguageId lang) {
const char *LanguageIdentifier(LanguageId lang) {
switch (lang) {
case LanguageId::C:
return "c";

View File

@ -11,4 +11,4 @@ enum class LanguageId { Unknown = 0, C = 1, Cpp = 2, ObjC = 3, ObjCpp = 4 };
MAKE_REFLECT_TYPE_PROXY(LanguageId);
LanguageId SourceFileLanguage(std::string_view path);
const char* LanguageIdentifier(LanguageId lang);
const char *LanguageIdentifier(LanguageId lang);

View File

@ -3,18 +3,18 @@
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/Threading.h>
#include <iomanip>
#include <mutex>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <iomanip>
#include <mutex>
namespace ccls::log {
static std::mutex mtx;
FILE* file;
FILE *file;
Verbosity verbosity;
Message::Message(Verbosity verbosity, const char* file, int line)
Message::Message(Verbosity verbosity, const char *file, int line)
: verbosity_(verbosity) {
using namespace llvm;
time_t tim = time(NULL);
@ -32,7 +32,7 @@ Message::Message(Verbosity verbosity, const char* file, int line)
stream_ << std::left << std::setw(13) << Name.c_str();
}
{
const char* p = strrchr(file, '/');
const char *p = strrchr(file, '/');
if (p)
file = p + 1;
stream_ << std::right << std::setw(15) << file << ':' << std::left
@ -52,11 +52,12 @@ Message::Message(Verbosity verbosity, const char* file, int line)
}
Message::~Message() {
if (!file) return;
if (!file)
return;
std::lock_guard<std::mutex> lock(mtx);
stream_ << '\n';
fputs(stream_.str().c_str(), file);
if (verbosity_ == Verbosity_FATAL)
abort();
}
}
} // namespace ccls::log

View File

@ -8,31 +8,29 @@
// Cache that evicts old entries which have not been used recently. Implemented
// using array/linear search so this works well for small array sizes.
template <typename TKey, typename TValue>
struct LruCache {
template <typename TKey, typename TValue> struct LruCache {
explicit LruCache(int max_entries);
// Fetches an entry for |key|. If it does not exist, |allocator| will be
// invoked to create one.
template <typename TAllocator>
std::shared_ptr<TValue> Get(const TKey& key, TAllocator allocator);
std::shared_ptr<TValue> Get(const TKey &key, TAllocator allocator);
// Fetches the entry for |filename| and updates it's usage so it is less
// likely to be evicted.
std::shared_ptr<TValue> TryGet(const TKey& key);
std::shared_ptr<TValue> TryGet(const TKey &key);
// TryGetEntry, except the entry is removed from the cache.
std::shared_ptr<TValue> TryTake(const TKey& key);
std::shared_ptr<TValue> TryTake(const TKey &key);
// Inserts an entry. Evicts the oldest unused entry if there is no space.
void Insert(const TKey& key, const std::shared_ptr<TValue>& value);
void Insert(const TKey &key, const std::shared_ptr<TValue> &value);
// Call |func| on existing entries. If |func| returns false iteration
// temrinates early.
template <typename TFunc>
void IterateValues(TFunc func);
template <typename TFunc> void IterateValues(TFunc func);
// Empties the cache
void Clear(void);
private:
private:
// There is a global score counter, when we access an element we increase
// its score to the current global value, so it has the highest overall
// score. This means that the oldest/least recently accessed value has the
@ -43,7 +41,7 @@ struct LruCache {
uint32_t score = 0;
TKey key;
std::shared_ptr<TValue> value;
bool operator<(const Entry& other) const { return score < other.score; }
bool operator<(const Entry &other) const { return score < other.score; }
};
void IncrementScore();
@ -60,7 +58,7 @@ LruCache<TKey, TValue>::LruCache(int max_entries) : max_entries_(max_entries) {
template <typename TKey, typename TValue>
template <typename TAllocator>
std::shared_ptr<TValue> LruCache<TKey, TValue>::Get(const TKey& key,
std::shared_ptr<TValue> LruCache<TKey, TValue>::Get(const TKey &key,
TAllocator allocator) {
std::shared_ptr<TValue> result = TryGet(key);
if (!result)
@ -69,9 +67,9 @@ std::shared_ptr<TValue> LruCache<TKey, TValue>::Get(const TKey& key,
}
template <typename TKey, typename TValue>
std::shared_ptr<TValue> LruCache<TKey, TValue>::TryGet(const TKey& key) {
std::shared_ptr<TValue> LruCache<TKey, TValue>::TryGet(const TKey &key) {
// Assign new score.
for (Entry& entry : entries_) {
for (Entry &entry : entries_) {
if (entry.key == key) {
entry.score = next_score_;
IncrementScore();
@ -83,7 +81,7 @@ std::shared_ptr<TValue> LruCache<TKey, TValue>::TryGet(const TKey& key) {
}
template <typename TKey, typename TValue>
std::shared_ptr<TValue> LruCache<TKey, TValue>::TryTake(const TKey& key) {
std::shared_ptr<TValue> LruCache<TKey, TValue>::TryTake(const TKey &key) {
for (size_t i = 0; i < entries_.size(); ++i) {
if (entries_[i].key == key) {
std::shared_ptr<TValue> copy = entries_[i].value;
@ -96,8 +94,8 @@ std::shared_ptr<TValue> LruCache<TKey, TValue>::TryTake(const TKey& key) {
}
template <typename TKey, typename TValue>
void LruCache<TKey, TValue>::Insert(const TKey& key,
const std::shared_ptr<TValue>& value) {
void LruCache<TKey, TValue>::Insert(const TKey &key,
const std::shared_ptr<TValue> &value) {
if ((int)entries_.size() >= max_entries_)
entries_.erase(std::min_element(entries_.begin(), entries_.end()));
@ -112,7 +110,7 @@ void LruCache<TKey, TValue>::Insert(const TKey& key,
template <typename TKey, typename TValue>
template <typename TFunc>
void LruCache<TKey, TValue>::IterateValues(TFunc func) {
for (Entry& entry : entries_) {
for (Entry &entry : entries_) {
if (!func(entry.value))
break;
}
@ -123,13 +121,13 @@ void LruCache<TKey, TValue>::IncrementScore() {
// Overflow.
if (++next_score_ == 0) {
std::sort(entries_.begin(), entries_.end());
for (Entry& entry : entries_)
for (Entry &entry : entries_)
entry.score = next_score_++;
}
}
template <typename TKey, typename TValue>
void LruCache<TKey, TValue>::Clear(void) {
entries_.clear();
next_score_ = 0;
entries_.clear();
next_score_ = 0;
}

View File

@ -7,7 +7,7 @@
#include <stdio.h>
MessageRegistry* MessageRegistry::instance_ = nullptr;
MessageRegistry *MessageRegistry::instance_ = nullptr;
lsTextDocumentIdentifier
lsVersionedTextDocumentIdentifier::AsTextDocumentIdentifier() const {
@ -17,8 +17,8 @@ lsVersionedTextDocumentIdentifier::AsTextDocumentIdentifier() const {
}
// Reads a JsonRpc message. |read| returns the next input character.
std::optional<std::string> ReadJsonRpcContentFrom(
std::function<std::optional<char>()> read) {
std::optional<std::string>
ReadJsonRpcContentFrom(std::function<std::optional<char>()> read) {
// Read the content length. It is terminated by the "\r\n" sequence.
int exit_seq = 0;
std::string stringified_content_length;
@ -37,7 +37,7 @@ std::optional<std::string> ReadJsonRpcContentFrom(
stringified_content_length += c;
}
const char* kContentLengthStart = "Content-Length: ";
const char *kContentLengthStart = "Content-Length: ";
assert(StartsWith(stringified_content_length, kContentLengthStart));
int content_length =
atoi(stringified_content_length.c_str() + strlen(kContentLengthStart));
@ -78,8 +78,8 @@ std::optional<char> ReadCharFromStdinBlocking() {
return std::nullopt;
}
std::optional<std::string> MessageRegistry::ReadMessageFromStdin(
std::unique_ptr<InMessage>* message) {
std::optional<std::string>
MessageRegistry::ReadMessageFromStdin(std::unique_ptr<InMessage> *message) {
std::optional<std::string> content =
ReadJsonRpcContentFrom(&ReadCharFromStdinBlocking);
if (!content) {
@ -95,9 +95,8 @@ std::optional<std::string> MessageRegistry::ReadMessageFromStdin(
return Parse(json_reader, message);
}
std::optional<std::string> MessageRegistry::Parse(
Reader& visitor,
std::unique_ptr<InMessage>* message) {
std::optional<std::string>
MessageRegistry::Parse(Reader &visitor, std::unique_ptr<InMessage> *message) {
if (!visitor.HasMember("jsonrpc") ||
std::string(visitor["jsonrpc"]->GetString()) != "2.0") {
LOG_S(FATAL) << "Bad or missing jsonrpc version";
@ -111,20 +110,20 @@ std::optional<std::string> MessageRegistry::Parse(
return std::string("Unable to find registered handler for method '") +
method + "'";
Allocator& allocator = allocators[method];
Allocator &allocator = allocators[method];
try {
allocator(visitor, message);
return std::nullopt;
} catch (std::invalid_argument& e) {
} catch (std::invalid_argument &e) {
// *message is partially deserialized but some field (e.g. |id|) are likely
// available.
return std::string("Fail to parse '") + method + "' " +
static_cast<JsonReader&>(visitor).GetPath() + ", expected " +
static_cast<JsonReader &>(visitor).GetPath() + ", expected " +
e.what();
}
}
MessageRegistry* MessageRegistry::instance() {
MessageRegistry *MessageRegistry::instance() {
if (!instance_)
instance_ = new MessageRegistry();
@ -133,7 +132,7 @@ MessageRegistry* MessageRegistry::instance() {
lsBaseOutMessage::~lsBaseOutMessage() = default;
void lsBaseOutMessage::Write(std::ostream& out) {
void lsBaseOutMessage::Write(std::ostream &out) {
rapidjson::StringBuffer output;
rapidjson::Writer<rapidjson::StringBuffer> writer(output);
JsonWriter json_writer{&writer};
@ -144,8 +143,8 @@ void lsBaseOutMessage::Write(std::ostream& out) {
out.flush();
}
void lsResponseError::Write(Writer& visitor) {
auto& value = *this;
void lsResponseError::Write(Writer &visitor) {
auto &value = *this;
int code2 = static_cast<int>(this->code);
visitor.StartObject();
@ -154,22 +153,22 @@ void lsResponseError::Write(Writer& visitor) {
visitor.EndObject();
}
lsDocumentUri lsDocumentUri::FromPath(const std::string& path) {
lsDocumentUri lsDocumentUri::FromPath(const std::string &path) {
lsDocumentUri result;
result.SetPath(path);
return result;
}
bool lsDocumentUri::operator==(const lsDocumentUri& other) const {
bool lsDocumentUri::operator==(const lsDocumentUri &other) const {
return raw_uri == other.raw_uri;
}
void lsDocumentUri::SetPath(const std::string& path) {
void lsDocumentUri::SetPath(const std::string &path) {
// file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests
raw_uri = path;
size_t index = raw_uri.find(":");
if (index == 1) { // widows drive letters must always be 1 char
if (index == 1) { // widows drive letters must always be 1 char
raw_uri.replace(raw_uri.begin() + index, raw_uri.begin() + index + 1,
"%3A");
}
@ -231,11 +230,11 @@ std::string lsPosition::ToString() const {
return std::to_string(line) + ":" + std::to_string(character);
}
bool lsTextEdit::operator==(const lsTextEdit& that) {
bool lsTextEdit::operator==(const lsTextEdit &that) {
return range == that.range && newText == that.newText;
}
void Reflect(Writer& visitor, lsMarkedString& value) {
void Reflect(Writer &visitor, lsMarkedString &value) {
// If there is a language, emit a `{language:string, value:string}` object. If
// not, emit a string.
if (value.language) {

View File

@ -8,52 +8,50 @@
#include <iosfwd>
#include <unordered_map>
#define REGISTER_IN_MESSAGE(type) \
#define REGISTER_IN_MESSAGE(type) \
static MessageRegistryRegister<type> type##message_handler_instance_;
struct MessageRegistry {
static MessageRegistry* instance_;
static MessageRegistry* instance();
static MessageRegistry *instance_;
static MessageRegistry *instance();
using Allocator =
std::function<void(Reader& visitor, std::unique_ptr<InMessage>*)>;
std::function<void(Reader &visitor, std::unique_ptr<InMessage> *)>;
std::unordered_map<std::string, Allocator> allocators;
std::optional<std::string> ReadMessageFromStdin(
std::unique_ptr<InMessage>* message);
std::optional<std::string> Parse(Reader& visitor,
std::unique_ptr<InMessage>* message);
std::optional<std::string>
ReadMessageFromStdin(std::unique_ptr<InMessage> *message);
std::optional<std::string> Parse(Reader &visitor,
std::unique_ptr<InMessage> *message);
};
template <typename T>
struct MessageRegistryRegister {
template <typename T> struct MessageRegistryRegister {
MessageRegistryRegister() {
T dummy;
std::string method_name = dummy.GetMethodType();
MessageRegistry::instance()->allocators[method_name] =
[](Reader& visitor, std::unique_ptr<InMessage>* message) {
[](Reader &visitor, std::unique_ptr<InMessage> *message) {
*message = std::make_unique<T>();
// Reflect may throw and *message will be partially deserialized.
Reflect(visitor, static_cast<T&>(**message));
Reflect(visitor, static_cast<T &>(**message));
};
}
};
struct lsBaseOutMessage {
virtual ~lsBaseOutMessage();
virtual void ReflectWriter(Writer&) = 0;
virtual void ReflectWriter(Writer &) = 0;
// Send the message to the language client by writing it to stdout.
void Write(std::ostream& out);
void Write(std::ostream &out);
};
template <typename TDerived>
struct lsOutMessage : lsBaseOutMessage {
template <typename TDerived> struct lsOutMessage : lsBaseOutMessage {
// All derived types need to reflect on the |jsonrpc| member.
std::string jsonrpc = "2.0";
void ReflectWriter(Writer& writer) override {
Reflect(writer, static_cast<TDerived&>(*this));
void ReflectWriter(Writer &writer) override {
Reflect(writer, static_cast<TDerived &>(*this));
}
};
@ -75,7 +73,7 @@ struct lsResponseError {
// Short description.
std::string message;
void Write(Writer& visitor);
void Write(Writer &visitor);
};
/////////////////////////////////////////////////////////////////////////////
@ -87,28 +85,28 @@ struct lsResponseError {
/////////////////////////////////////////////////////////////////////////////
struct lsDocumentUri {
static lsDocumentUri FromPath(const std::string& path);
static lsDocumentUri FromPath(const std::string &path);
bool operator==(const lsDocumentUri& other) const;
bool operator==(const lsDocumentUri &other) const;
void SetPath(const std::string& path);
void SetPath(const std::string &path);
std::string GetPath() const;
std::string raw_uri;
};
template <typename TVisitor>
void Reflect(TVisitor& visitor, lsDocumentUri& value) {
void Reflect(TVisitor &visitor, lsDocumentUri &value) {
Reflect(visitor, value.raw_uri);
}
struct lsPosition {
int line = 0;
int character = 0;
bool operator==(const lsPosition& o) const {
bool operator==(const lsPosition &o) const {
return line == o.line && character == o.character;
}
bool operator<(const lsPosition& o) const {
bool operator<(const lsPosition &o) const {
return line != o.line ? line < o.line : character < o.character;
}
std::string ToString() const;
@ -118,10 +116,10 @@ MAKE_REFLECT_STRUCT(lsPosition, line, character);
struct lsRange {
lsPosition start;
lsPosition end;
bool operator==(const lsRange& o) const {
bool operator==(const lsRange &o) const {
return start == o.start && end == o.end;
}
bool operator<(const lsRange& o) const {
bool operator<(const lsRange &o) const {
return !(start == o.start) ? start < o.start : end < o.end;
}
};
@ -130,10 +128,10 @@ MAKE_REFLECT_STRUCT(lsRange, start, end);
struct lsLocation {
lsDocumentUri uri;
lsRange range;
bool operator==(const lsLocation& o) const {
bool operator==(const lsLocation &o) const {
return uri == o.uri && range == o.range;
}
bool operator<(const lsLocation& o) const {
bool operator<(const lsLocation &o) const {
return !(uri.raw_uri == o.uri.raw_uri) ? uri.raw_uri < o.uri.raw_uri
: range < o.range;
}
@ -192,8 +190,7 @@ struct lsLocationEx : lsLocation {
};
MAKE_REFLECT_STRUCT(lsLocationEx, uri, range, containerName, parentKind, role);
template <typename T>
struct lsCommand {
template <typename T> struct lsCommand {
// Title of the command (ie, 'save')
std::string title;
// Actual command identifier.
@ -204,7 +201,7 @@ struct lsCommand {
T arguments;
};
template <typename TVisitor, typename T>
void Reflect(TVisitor& visitor, lsCommand<T>& value) {
void Reflect(TVisitor &visitor, lsCommand<T> &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(title);
REFLECT_MEMBER(command);
@ -212,8 +209,7 @@ void Reflect(TVisitor& visitor, lsCommand<T>& value) {
REFLECT_MEMBER_END();
}
template <typename TData, typename TCommandArguments>
struct lsCodeLens {
template <typename TData, typename TCommandArguments> struct lsCodeLens {
// The range in which this code lens is valid. Should only span a single line.
lsRange range;
// The command this code lens represents.
@ -223,7 +219,7 @@ struct lsCodeLens {
TData data;
};
template <typename TVisitor, typename TData, typename TCommandArguments>
void Reflect(TVisitor& visitor, lsCodeLens<TData, TCommandArguments>& value) {
void Reflect(TVisitor &visitor, lsCodeLens<TData, TCommandArguments> &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(range);
REFLECT_MEMBER(command);
@ -263,7 +259,7 @@ struct lsTextEdit {
// empty string.
std::string newText;
bool operator==(const lsTextEdit& that);
bool operator==(const lsTextEdit &that);
};
MAKE_REFLECT_STRUCT(lsTextEdit, range, newText);
@ -321,7 +317,7 @@ struct lsMarkedString {
std::optional<std::string> language;
std::string value;
};
void Reflect(Writer& visitor, lsMarkedString& value);
void Reflect(Writer &visitor, lsMarkedString &value);
struct lsTextDocumentContentChangeEvent {
// The range of the document that changed.
@ -337,8 +333,7 @@ struct lsTextDocumentDidChangeParams {
lsVersionedTextDocumentIdentifier textDocument;
std::vector<lsTextDocumentContentChangeEvent> contentChanges;
};
MAKE_REFLECT_STRUCT(lsTextDocumentDidChangeParams,
textDocument,
MAKE_REFLECT_STRUCT(lsTextDocumentDidChangeParams, textDocument,
contentChanges);
// Show a message to the user.
@ -360,7 +355,7 @@ struct Out_ShowLogMessage : public lsOutMessage<Out_ShowLogMessage> {
};
template <typename TVisitor>
void Reflect(TVisitor& visitor, Out_ShowLogMessage& value) {
void Reflect(TVisitor &visitor, Out_ShowLogMessage &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(jsonrpc);
std::string method = value.method();

View File

@ -106,9 +106,9 @@ struct lsCompletionItem {
// nor with themselves.
// std::vector<TextEdit> additionalTextEdits;
// An std::optional command that is executed *after* inserting this completion.
// *Note* that additional modifications to the current document should be
// described with the additionalTextEdits-property. Command command;
// An std::optional command that is executed *after* inserting this
// completion. *Note* that additional modifications to the current document
// should be described with the additionalTextEdits-property. Command command;
// An data entry field that is preserved on a completion item between
// a completion and a completion resolve request.
@ -117,7 +117,7 @@ struct lsCompletionItem {
// Use this helper to figure out what content the completion item will insert
// into the document, as it could live in either |textEdit|, |insertText|, or
// |label|.
const std::string& InsertedContent() const {
const std::string &InsertedContent() const {
if (textEdit)
return textEdit->newText;
if (!insertText.empty())
@ -125,13 +125,6 @@ struct lsCompletionItem {
return label;
}
};
MAKE_REFLECT_STRUCT(lsCompletionItem,
label,
kind,
detail,
documentation,
sortText,
insertText,
filterText,
insertTextFormat,
MAKE_REFLECT_STRUCT(lsCompletionItem, label, kind, detail, documentation,
sortText, insertText, filterText, insertTextFormat,
textEdit);

View File

@ -88,7 +88,7 @@ struct Out_TextDocumentPublishDiagnostics
Params params;
};
template <typename TVisitor>
void Reflect(TVisitor& visitor, Out_TextDocumentPublishDiagnostics& value) {
void Reflect(TVisitor &visitor, Out_TextDocumentPublishDiagnostics &value) {
std::string method = "textDocument/publishDiagnostics";
REFLECT_MEMBER_START();
REFLECT_MEMBER(jsonrpc);
@ -96,6 +96,5 @@ void Reflect(TVisitor& visitor, Out_TextDocumentPublishDiagnostics& value) {
REFLECT_MEMBER(params);
REFLECT_MEMBER_END();
}
MAKE_REFLECT_STRUCT(Out_TextDocumentPublishDiagnostics::Params,
uri,
MAKE_REFLECT_STRUCT(Out_TextDocumentPublishDiagnostics::Params, uri,
diagnostics);

View File

@ -28,21 +28,21 @@ std::string g_init_options;
namespace {
opt<bool> opt_help("h", desc("Alias for -help"));
opt<int> opt_verbose("v", desc("verbosity"), init(0));
opt<std::string> opt_test_index("test-index", ValueOptional, init("!"), desc("run index tests"));
opt<std::string> opt_test_index("test-index", ValueOptional, init("!"),
desc("run index tests"));
opt<std::string> opt_init("init", desc("extra initialization options"));
opt<std::string> opt_log_file("log-file", desc("log"), value_desc("filename"));
opt<std::string> opt_log_file_append("log-file-append", desc("log"), value_desc("filename"));
opt<std::string> opt_log_file_append("log-file-append", desc("log"),
value_desc("filename"));
list<std::string> opt_extra(Positional, ZeroOrMore, desc("extra"));
void CloseLog() {
fclose(ccls::log::file);
}
void CloseLog() { fclose(ccls::log::file); }
} // namespace
} // namespace
int main(int argc, char** argv) {
int main(int argc, char **argv) {
TraceMe();
sys::PrintStackTraceOnErrorSignal(argv[0]);
@ -98,9 +98,9 @@ int main(int argc, char** argv) {
try {
Config config;
Reflect(json_reader, config);
} catch (std::invalid_argument& e) {
} catch (std::invalid_argument &e) {
fprintf(stderr, "Failed to parse --init %s, expected %s\n",
static_cast<JsonReader&>(json_reader).GetPath().c_str(),
static_cast<JsonReader &>(json_reader).GetPath().c_str(),
e.what());
return 1;
}
@ -108,11 +108,13 @@ int main(int argc, char** argv) {
sys::ChangeStdinToBinary();
sys::ChangeStdoutToBinary();
// The thread that reads from stdin and dispatchs commands to the main thread.
// The thread that reads from stdin and dispatchs commands to the main
// thread.
pipeline::LaunchStdin();
// The thread that writes responses from the main thread to stdout.
pipeline::LaunchStdout();
// Main thread which also spawns indexer threads upon the "initialize" request.
// Main thread which also spawns indexer threads upon the "initialize"
// request.
pipeline::MainLoop();
}

View File

@ -5,7 +5,7 @@
using namespace ccls;
// static
std::optional<Matcher> Matcher::Create(const std::string& search) {
std::optional<Matcher> Matcher::Create(const std::string &search) {
/*
std::string real_search;
real_search.reserve(search.size() * 3 + 2);
@ -19,51 +19,51 @@ std::optional<Matcher> Matcher::Create(const std::string& search) {
try {
Matcher m;
m.regex_string = search;
m.regex = std::regex(
search, std::regex_constants::ECMAScript | std::regex_constants::icase |
std::regex_constants::optimize
// std::regex_constants::nosubs
m.regex = std::regex(search, std::regex_constants::ECMAScript |
std::regex_constants::icase |
std::regex_constants::optimize
// std::regex_constants::nosubs
);
return m;
} catch (const std::exception& e) {
} catch (const std::exception &e) {
Out_ShowLogMessage out;
out.display_type = Out_ShowLogMessage::DisplayType::Show;
out.params.type = lsMessageType::Error;
out.params.message = "ccls: Parsing EMCAScript regex \"" + search +
"\" failed; " + e.what();
out.params.message =
"ccls: Parsing EMCAScript regex \"" + search + "\" failed; " + e.what();
pipeline::WriteStdout(kMethodType_Unknown, out);
return std::nullopt;
}
}
bool Matcher::IsMatch(const std::string& value) const {
bool Matcher::IsMatch(const std::string &value) const {
// std::smatch match;
// return std::regex_match(value, match, regex);
return std::regex_search(value, regex, std::regex_constants::match_any);
}
GroupMatch::GroupMatch(const std::vector<std::string>& whitelist,
const std::vector<std::string>& blacklist) {
for (const std::string& entry : whitelist) {
GroupMatch::GroupMatch(const std::vector<std::string> &whitelist,
const std::vector<std::string> &blacklist) {
for (const std::string &entry : whitelist) {
std::optional<Matcher> m = Matcher::Create(entry);
if (m)
this->whitelist.push_back(*m);
}
for (const std::string& entry : blacklist) {
for (const std::string &entry : blacklist) {
std::optional<Matcher> m = Matcher::Create(entry);
if (m)
this->blacklist.push_back(*m);
}
}
bool GroupMatch::IsMatch(const std::string& value,
std::string* match_failure_reason) const {
for (const Matcher& m : whitelist) {
bool GroupMatch::IsMatch(const std::string &value,
std::string *match_failure_reason) const {
for (const Matcher &m : whitelist) {
if (m.IsMatch(value))
return true;
}
for (const Matcher& m : blacklist) {
for (const Matcher &m : blacklist) {
if (m.IsMatch(value)) {
if (match_failure_reason)
*match_failure_reason = "blacklist \"" + m.regex_string + "\"";

View File

@ -7,9 +7,9 @@
#include <vector>
struct Matcher {
static std::optional<Matcher> Create(const std::string& search);
static std::optional<Matcher> Create(const std::string &search);
bool IsMatch(const std::string& value) const;
bool IsMatch(const std::string &value) const;
std::string regex_string;
std::regex regex;
@ -17,11 +17,11 @@ struct Matcher {
// Check multiple |Matcher| instances at the same time.
struct GroupMatch {
GroupMatch(const std::vector<std::string>& whitelist,
const std::vector<std::string>& blacklist);
GroupMatch(const std::vector<std::string> &whitelist,
const std::vector<std::string> &blacklist);
bool IsMatch(const std::string& value,
std::string* match_failure_reason = nullptr) const;
bool IsMatch(const std::string &value,
std::string *match_failure_reason = nullptr) const;
std::vector<Matcher> whitelist;
std::vector<Matcher> blacklist;

View File

@ -4,29 +4,28 @@
#include <utility>
// Like std::optional, but the stored data is responsible for containing the empty
// state. T should define a function `bool T::Valid()`.
template <typename T>
class Maybe {
// Like std::optional, but the stored data is responsible for containing the
// empty state. T should define a function `bool T::Valid()`.
template <typename T> class Maybe {
T storage;
public:
public:
constexpr Maybe() = default;
Maybe(const Maybe&) = default;
Maybe(const Maybe &) = default;
Maybe(std::nullopt_t) {}
Maybe(const T& x) : storage(x) {}
Maybe(T&& x) : storage(std::forward<T>(x)) {}
Maybe(const T &x) : storage(x) {}
Maybe(T &&x) : storage(std::forward<T>(x)) {}
Maybe& operator=(const Maybe&) = default;
Maybe& operator=(const T& x) {
Maybe &operator=(const Maybe &) = default;
Maybe &operator=(const T &x) {
storage = x;
return *this;
}
const T* operator->() const { return &storage; }
T* operator->() { return &storage; }
const T& operator*() const { return storage; }
T& operator*() { return storage; }
const T *operator->() const { return &storage; }
T *operator->() { return &storage; }
const T &operator*() const { return storage; }
T &operator*() { return storage; }
bool Valid() const { return storage.Valid(); }
explicit operator bool() const { return Valid(); }
@ -36,9 +35,9 @@ class Maybe {
return std::nullopt;
}
void operator=(std::optional<T>&& o) { storage = o ? *o : T(); }
void operator=(std::optional<T> &&o) { storage = o ? *o : T(); }
// Does not test if has_value()
bool operator==(const Maybe& o) const { return storage == o.storage; }
bool operator!=(const Maybe& o) const { return !(*this == o); }
bool operator==(const Maybe &o) const { return storage == o.storage; }
bool operator!=(const Maybe &o) const { return !(*this == o); }
};

View File

@ -337,15 +337,16 @@ void EmitSemanticHighlighting(DB *db,
out.params.uri = lsDocumentUri::FromPath(wfile->filename);
// Transform lsRange into pair<int, int> (offset pairs)
if (!g_config->highlight.lsRanges) {
std::vector<std::pair<lsRange, Out_CclsPublishSemanticHighlighting::Symbol *>>
scratch;
std::vector<
std::pair<lsRange, Out_CclsPublishSemanticHighlighting::Symbol *>>
scratch;
for (auto &entry : grouped_symbols) {
for (auto &range : entry.second.lsRanges)
scratch.emplace_back(range, &entry.second);
entry.second.lsRanges.clear();
}
std::sort(scratch.begin(), scratch.end(),
[](auto &l, auto &r) { return l.first.start < r.first.start; });
[](auto &l, auto &r) { return l.first.start < r.first.start; });
const auto &buf = wfile->buffer_content;
int l = 0, c = 0, i = 0, p = 0;
auto mov = [&](int line, int col) {
@ -357,11 +358,13 @@ void EmitSemanticHighlighting(DB *db,
if (uint8_t(buf[i]) < 128 || 192 <= uint8_t(buf[i]))
p++;
}
if (l < line) return true;
if (l < line)
return true;
for (; c < col && i < buf.size() && buf[i] != '\n'; c++)
if (p++, uint8_t(buf[i++]) >= 128)
// Skip 0b10xxxxxx
while (i < buf.size() && uint8_t(buf[i]) >= 128 && uint8_t(buf[i]) < 192)
while (i < buf.size() && uint8_t(buf[i]) >= 128 &&
uint8_t(buf[i]) < 192)
i++;
return c < col;
};

View File

@ -6,8 +6,8 @@
#include "method.h"
#include "query.h"
#include <optional>
#include <memory>
#include <optional>
#include <unordered_map>
#include <vector>
@ -28,7 +28,7 @@ struct WorkingFiles;
// relatively stable ids. Only supports xxx files at a time.
struct SemanticHighlightSymbolCache {
struct Entry {
SemanticHighlightSymbolCache* all_caches_ = nullptr;
SemanticHighlightSymbolCache *all_caches_ = nullptr;
// The path this cache belongs to.
std::string path;
@ -38,13 +38,13 @@ struct SemanticHighlightSymbolCache {
TNameToId detailed_func_name_to_stable_id;
TNameToId detailed_var_name_to_stable_id;
Entry(SemanticHighlightSymbolCache* all_caches, const std::string& path);
Entry(SemanticHighlightSymbolCache *all_caches, const std::string &path);
std::optional<int> TryGetStableId(SymbolKind kind,
const std::string& detailed_name);
int GetStableId(SymbolKind kind, const std::string& detailed_name);
const std::string &detailed_name);
int GetStableId(SymbolKind kind, const std::string &detailed_name);
TNameToId* GetMapForSymbol_(SymbolKind kind);
TNameToId *GetMapForSymbol_(SymbolKind kind);
};
constexpr static int kCacheSize = 10;
@ -54,7 +54,7 @@ struct SemanticHighlightSymbolCache {
SemanticHighlightSymbolCache();
void Init();
std::shared_ptr<Entry> GetCacheForFile(const std::string& path);
std::shared_ptr<Entry> GetCacheForFile(const std::string &path);
};
struct Out_CclsPublishSemanticHighlighting
@ -79,9 +79,7 @@ struct Out_CclsPublishSemanticHighlighting
MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting::Symbol, stableId,
parentKind, kind, storage, ranges, lsRanges);
MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting::Params, uri, symbols);
MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting,
jsonrpc,
method,
MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting, jsonrpc, method,
params);
// Usage:
@ -94,54 +92,49 @@ MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting,
// Then there will be a global FooHandler instance in
// |MessageHandler::message_handlers|.
#define REGISTER_MESSAGE_HANDLER(type) \
#define REGISTER_MESSAGE_HANDLER(type) \
static type type##message_handler_instance_;
struct MessageHandler {
DB* db = nullptr;
MultiQueueWaiter* waiter = nullptr;
Project* project = nullptr;
DiagnosticsPublisher* diag_pub = nullptr;
VFS* vfs = nullptr;
ImportManager* import_manager = nullptr;
SemanticHighlightSymbolCache* semantic_cache = nullptr;
WorkingFiles* working_files = nullptr;
ClangCompleteManager* clang_complete = nullptr;
IncludeComplete* include_complete = nullptr;
CodeCompleteCache* global_code_complete_cache = nullptr;
CodeCompleteCache* non_global_code_complete_cache = nullptr;
CodeCompleteCache* signature_cache = nullptr;
DB *db = nullptr;
MultiQueueWaiter *waiter = nullptr;
Project *project = nullptr;
DiagnosticsPublisher *diag_pub = nullptr;
VFS *vfs = nullptr;
ImportManager *import_manager = nullptr;
SemanticHighlightSymbolCache *semantic_cache = nullptr;
WorkingFiles *working_files = nullptr;
ClangCompleteManager *clang_complete = nullptr;
IncludeComplete *include_complete = nullptr;
CodeCompleteCache *global_code_complete_cache = nullptr;
CodeCompleteCache *non_global_code_complete_cache = nullptr;
CodeCompleteCache *signature_cache = nullptr;
virtual MethodType GetMethodType() const = 0;
virtual void Run(std::unique_ptr<InMessage> message) = 0;
static std::vector<MessageHandler*>* message_handlers;
static std::vector<MessageHandler *> *message_handlers;
protected:
protected:
MessageHandler();
};
template <typename TMessage>
struct BaseMessageHandler : MessageHandler {
virtual void Run(TMessage* message) = 0;
template <typename TMessage> struct BaseMessageHandler : MessageHandler {
virtual void Run(TMessage *message) = 0;
// MessageHandler:
void Run(std::unique_ptr<InMessage> message) override {
Run(static_cast<TMessage*>(message.get()));
Run(static_cast<TMessage *>(message.get()));
}
};
bool FindFileOrFail(DB* db,
Project* project,
std::optional<lsRequestId> id,
const std::string& absolute_path,
QueryFile** out_query_file,
int* out_file_id = nullptr);
bool FindFileOrFail(DB *db, Project *project, std::optional<lsRequestId> id,
const std::string &absolute_path,
QueryFile **out_query_file, int *out_file_id = nullptr);
void EmitSkippedRanges(WorkingFile *working_file,
const std::vector<Range> &skipped_ranges);
void EmitSemanticHighlighting(DB* db,
SemanticHighlightSymbolCache* semantic_cache,
WorkingFile* working_file,
QueryFile* file);
void EmitSemanticHighlighting(DB *db,
SemanticHighlightSymbolCache *semantic_cache,
WorkingFile *working_file, QueryFile *file);

View File

@ -18,14 +18,14 @@ REGISTER_IN_MESSAGE(In_CclsBase);
struct Handler_CclsBase : BaseMessageHandler<In_CclsBase> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_CclsBase* request) override {
QueryFile* file;
void Run(In_CclsBase *request) override {
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file)) {
return;
}
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_LocationList out;
@ -33,12 +33,12 @@ struct Handler_CclsBase : BaseMessageHandler<In_CclsBase> {
for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Type) {
if (const auto* def = db->GetType(sym).AnyDef())
if (const auto *def = db->GetType(sym).AnyDef())
out.result = GetLsLocationExs(db, working_files,
GetTypeDeclarations(db, def->bases));
break;
} 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(db, working_files,
GetFuncDeclarations(db, def->bases));
break;
@ -48,4 +48,4 @@ struct Handler_CclsBase : BaseMessageHandler<In_CclsBase> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_CclsBase);
} // namespace
} // namespace

View File

@ -44,16 +44,9 @@ struct In_CclsCallHierarchy : public RequestInMessage {
int levels = 1;
};
Params params;
};
MAKE_REFLECT_STRUCT(In_CclsCallHierarchy::Params,
textDocument,
position,
id,
callee,
callType,
qualified,
levels);
MAKE_REFLECT_STRUCT(In_CclsCallHierarchy::Params, textDocument, position, id,
callee, callType, qualified, levels);
MAKE_REFLECT_STRUCT(In_CclsCallHierarchy, id, params);
REGISTER_IN_MESSAGE(In_CclsCallHierarchy);
@ -72,26 +65,15 @@ struct Out_CclsCallHierarchy : public lsOutMessage<Out_CclsCallHierarchy> {
lsRequestId id;
std::optional<Entry> result;
};
MAKE_REFLECT_STRUCT(Out_CclsCallHierarchy::Entry,
id,
name,
location,
callType,
numChildren,
children);
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsCallHierarchy,
jsonrpc,
id,
MAKE_REFLECT_STRUCT(Out_CclsCallHierarchy::Entry, id, name, location, callType,
numChildren, children);
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsCallHierarchy, jsonrpc, id,
result);
bool Expand(MessageHandler* m,
Out_CclsCallHierarchy::Entry* entry,
bool callee,
CallType call_type,
bool qualified,
int levels) {
const QueryFunc& func = m->db->Func(entry->usr);
const QueryFunc::Def* def = func.AnyDef();
bool Expand(MessageHandler *m, Out_CclsCallHierarchy::Entry *entry, bool callee,
CallType call_type, bool qualified, int levels) {
const QueryFunc &func = m->db->Func(entry->usr);
const QueryFunc::Def *def = func.AnyDef();
entry->numChildren = 0;
if (!def)
return false;
@ -108,13 +90,12 @@ bool Expand(MessageHandler* m,
entry->children.push_back(std::move(entry1));
}
};
auto handle_uses = [&](const QueryFunc& func, CallType call_type) {
auto handle_uses = [&](const QueryFunc &func, CallType call_type) {
if (callee) {
if (const auto* def = func.AnyDef())
if (const auto *def = func.AnyDef())
for (SymbolRef ref : def->callees)
if (ref.kind == SymbolKind::Func)
handle(Use{{ref.range, ref.usr, ref.kind, ref.role},
def->file_id},
handle(Use{{ref.range, ref.usr, ref.kind, ref.role}, def->file_id},
call_type);
} else {
for (Use use : func.uses)
@ -125,7 +106,7 @@ bool Expand(MessageHandler* m,
std::unordered_set<Usr> seen;
seen.insert(func.usr);
std::vector<const QueryFunc*> stack;
std::vector<const QueryFunc *> stack;
entry->name = def->Name(qualified);
handle_uses(func, CallType::Direct);
@ -133,10 +114,10 @@ bool Expand(MessageHandler* m,
if (call_type & CallType::Base) {
stack.push_back(&func);
while (stack.size()) {
const QueryFunc& func1 = *stack.back();
const QueryFunc &func1 = *stack.back();
stack.pop_back();
if (auto* def1 = func1.AnyDef()) {
EachDefinedFunc(m->db, def1->bases, [&](QueryFunc& func2) {
if (auto *def1 = func1.AnyDef()) {
EachDefinedFunc(m->db, def1->bases, [&](QueryFunc &func2) {
if (!seen.count(func2.usr)) {
seen.insert(func2.usr);
stack.push_back(&func2);
@ -151,9 +132,9 @@ bool Expand(MessageHandler* m,
if (call_type & CallType::Derived) {
stack.push_back(&func);
while (stack.size()) {
const QueryFunc& func1 = *stack.back();
const QueryFunc &func1 = *stack.back();
stack.pop_back();
EachDefinedFunc(m->db, func1.derived, [&](QueryFunc& func2) {
EachDefinedFunc(m->db, func1.derived, [&](QueryFunc &func2) {
if (!seen.count(func2.usr)) {
seen.insert(func2.usr);
stack.push_back(&func2);
@ -165,16 +146,13 @@ bool Expand(MessageHandler* m,
return true;
}
struct Handler_CclsCallHierarchy
: BaseMessageHandler<In_CclsCallHierarchy> {
struct Handler_CclsCallHierarchy : BaseMessageHandler<In_CclsCallHierarchy> {
MethodType GetMethodType() const override { return kMethodType; }
std::optional<Out_CclsCallHierarchy::Entry> BuildInitial(Usr root_usr,
bool callee,
CallType call_type,
bool qualified,
int levels) {
const auto* def = db->Func(root_usr).AnyDef();
std::optional<Out_CclsCallHierarchy::Entry>
BuildInitial(Usr root_usr, bool callee, CallType call_type, bool qualified,
int levels) {
const auto *def = db->Func(root_usr).AnyDef();
if (!def)
return {};
@ -191,8 +169,8 @@ struct Handler_CclsCallHierarchy
return entry;
}
void Run(In_CclsCallHierarchy* request) override {
auto& params = request->params;
void Run(In_CclsCallHierarchy *request) override {
auto &params = request->params;
Out_CclsCallHierarchy out;
out.id = request->id;
@ -211,11 +189,11 @@ struct Handler_CclsCallHierarchy
params.levels);
out.result = std::move(entry);
} else {
QueryFile* file;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, params.position)) {
@ -232,4 +210,4 @@ struct Handler_CclsCallHierarchy
};
REGISTER_MESSAGE_HANDLER(Handler_CclsCallHierarchy);
} // namespace
} // namespace

View File

@ -15,14 +15,14 @@ REGISTER_IN_MESSAGE(In_CclsCallers);
struct Handler_CclsCallers : BaseMessageHandler<In_CclsCallers> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_CclsCallers* request) override {
QueryFile* file;
void Run(In_CclsCallers *request) override {
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file)) {
return;
}
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_LocationList out;
@ -30,7 +30,7 @@ struct Handler_CclsCallers : BaseMessageHandler<In_CclsCallers> {
for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym);
QueryFunc &func = db->GetFunc(sym);
std::vector<Use> uses = func.uses;
for (Use func_ref : GetUsesForAllBases(db, func))
uses.push_back(func_ref);
@ -44,4 +44,4 @@ struct Handler_CclsCallers : BaseMessageHandler<In_CclsCallers> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_CclsCallers);
} // namespace
} // namespace

View File

@ -3,14 +3,8 @@
#include "query_utils.h"
using namespace ccls;
MAKE_REFLECT_STRUCT(QueryFile::Def,
path,
args,
language,
outline,
all_symbols,
skipped_ranges,
dependencies);
MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, outline, all_symbols,
skipped_ranges, dependencies);
namespace {
MethodType kMethodType = "$ccls/fileInfo";
@ -35,8 +29,8 @@ MAKE_REFLECT_STRUCT(Out_CclsFileInfo, jsonrpc, id, result);
struct Handler_CclsFileInfo : BaseMessageHandler<In_CclsFileInfo> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_CclsFileInfo* request) override {
QueryFile* file;
void Run(In_CclsFileInfo *request) override {
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file)) {
return;
@ -54,4 +48,4 @@ struct Handler_CclsFileInfo : BaseMessageHandler<In_CclsFileInfo> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_CclsFileInfo);
} // namespace
} // namespace

View File

@ -1,8 +1,8 @@
#include "match.h"
#include "message_handler.h"
#include "pipeline.hh"
#include "platform.h"
#include "project.h"
#include "pipeline.hh"
#include "working_files.h"
using namespace ccls;
@ -21,38 +21,36 @@ struct In_CclsFreshenIndex : public NotificationInMessage {
};
Params params;
};
MAKE_REFLECT_STRUCT(In_CclsFreshenIndex::Params,
dependencies,
whitelist,
MAKE_REFLECT_STRUCT(In_CclsFreshenIndex::Params, dependencies, whitelist,
blacklist);
MAKE_REFLECT_STRUCT(In_CclsFreshenIndex, params);
REGISTER_IN_MESSAGE(In_CclsFreshenIndex);
struct Handler_CclsFreshenIndex : BaseMessageHandler<In_CclsFreshenIndex> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_CclsFreshenIndex* request) override {
void Run(In_CclsFreshenIndex *request) override {
GroupMatch matcher(request->params.whitelist, request->params.blacklist);
std::queue<const QueryFile*> q;
std::queue<const QueryFile *> q;
// |need_index| stores every filename ever enqueued.
std::unordered_set<std::string> need_index;
// Reverse dependency graph.
std::unordered_map<std::string, std::vector<std::string>> graph;
// filename -> QueryFile mapping for files haven't enqueued.
std::unordered_map<std::string, const QueryFile*> path_to_file;
std::unordered_map<std::string, const QueryFile *> path_to_file;
for (const auto& file : db->files)
for (const auto &file : db->files)
if (file.def) {
if (matcher.IsMatch(file.def->path))
q.push(&file);
else
path_to_file[file.def->path] = &file;
for (const std::string& dependency : file.def->dependencies)
for (const std::string &dependency : file.def->dependencies)
graph[dependency].push_back(file.def->path);
}
while (!q.empty()) {
const QueryFile* file = q.front();
const QueryFile *file = q.front();
q.pop();
need_index.insert(file->def->path);
@ -61,13 +59,13 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler<In_CclsFreshenIndex> {
continue;
{
std::lock_guard<std::mutex> lock(vfs->mutex);
VFS::State& st = vfs->state[file->def->path];
VFS::State &st = vfs->state[file->def->path];
if (st.timestamp < write_time)
st.stage = 0;
}
if (request->params.dependencies)
for (const std::string& path : graph[file->def->path]) {
for (const std::string &path : graph[file->def->path]) {
auto it = path_to_file.find(path);
if (it != path_to_file.end()) {
q.push(it->second);
@ -81,4 +79,4 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler<In_CclsFreshenIndex> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_CclsFreshenIndex);
} // namespace
} // namespace

View File

@ -51,32 +51,18 @@ struct Out_CclsInheritanceHierarchy
lsRequestId id;
std::optional<Entry> result;
};
MAKE_REFLECT_STRUCT(Out_CclsInheritanceHierarchy::Entry,
id,
kind,
name,
location,
numChildren,
children);
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsInheritanceHierarchy,
jsonrpc,
id,
result);
MAKE_REFLECT_STRUCT(Out_CclsInheritanceHierarchy::Entry, id, kind, name,
location, numChildren, children);
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsInheritanceHierarchy, jsonrpc,
id, result);
bool Expand(MessageHandler* m,
Out_CclsInheritanceHierarchy::Entry* entry,
bool derived,
bool qualified,
int levels);
bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry,
bool derived, bool qualified, int levels);
template <typename Q>
bool ExpandHelper(MessageHandler* m,
Out_CclsInheritanceHierarchy::Entry* entry,
bool derived,
bool qualified,
int levels,
Q& entity) {
const auto* def = entity.AnyDef();
bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry,
bool derived, bool qualified, int levels, Q &entity) {
const auto *def = entity.AnyDef();
if (def) {
entry->name = def->Name(qualified);
if (def->spell) {
@ -122,11 +108,8 @@ bool ExpandHelper(MessageHandler* m,
return true;
}
bool Expand(MessageHandler* m,
Out_CclsInheritanceHierarchy::Entry* entry,
bool derived,
bool qualified,
int levels) {
bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry,
bool derived, bool qualified, int levels) {
if (entry->kind == SymbolKind::Func)
return ExpandHelper(m, entry, derived, qualified, levels,
m->db->Func(entry->usr));
@ -149,8 +132,8 @@ struct Handler_CclsInheritanceHierarchy
return entry;
}
void Run(In_CclsInheritanceHierarchy* request) override {
auto& params = request->params;
void Run(In_CclsInheritanceHierarchy *request) override {
auto &params = request->params;
Out_CclsInheritanceHierarchy out;
out.id = request->id;
@ -169,12 +152,11 @@ struct Handler_CclsInheritanceHierarchy
Expand(this, &entry, params.derived, params.qualified, params.levels))
out.result = std::move(entry);
} else {
QueryFile* file;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;
WorkingFile* wfile =
working_files->GetFileByFilename(file->def->path);
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, params.position))
if (sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) {
@ -208,4 +190,4 @@ struct Handler_CclsInheritanceHierarchy
};
REGISTER_MESSAGE_HANDLER(Handler_CclsInheritanceHierarchy);
} // namespace
} // namespace

View File

@ -30,17 +30,12 @@ struct In_CclsMemberHierarchy : public RequestInMessage {
Params params;
};
MAKE_REFLECT_STRUCT(In_CclsMemberHierarchy::Params,
textDocument,
position,
id,
qualified,
levels);
MAKE_REFLECT_STRUCT(In_CclsMemberHierarchy::Params, textDocument, position, id,
qualified, levels);
MAKE_REFLECT_STRUCT(In_CclsMemberHierarchy, id, params);
REGISTER_IN_MESSAGE(In_CclsMemberHierarchy);
struct Out_CclsMemberHierarchy
: public lsOutMessage<Out_CclsMemberHierarchy> {
struct Out_CclsMemberHierarchy : public lsOutMessage<Out_CclsMemberHierarchy> {
struct Entry {
Usr usr;
std::string id;
@ -56,31 +51,18 @@ struct Out_CclsMemberHierarchy
lsRequestId id;
std::optional<Entry> result;
};
MAKE_REFLECT_STRUCT(Out_CclsMemberHierarchy::Entry,
id,
name,
fieldName,
location,
numChildren,
children);
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsMemberHierarchy,
jsonrpc,
id,
MAKE_REFLECT_STRUCT(Out_CclsMemberHierarchy::Entry, id, name, fieldName,
location, numChildren, children);
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsMemberHierarchy, jsonrpc, id,
result);
bool Expand(MessageHandler* m,
Out_CclsMemberHierarchy::Entry* entry,
bool qualified,
int levels);
bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry,
bool qualified, int levels);
// Add a field to |entry| which is a Func/Type.
void DoField(MessageHandler* m,
Out_CclsMemberHierarchy::Entry* entry,
const QueryVar& var,
int64_t offset,
bool qualified,
int levels) {
const QueryVar::Def* def1 = var.AnyDef();
void DoField(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry,
const QueryVar &var, int64_t offset, bool qualified, int levels) {
const QueryVar::Def *def1 = var.AnyDef();
if (!def1)
return;
Out_CclsMemberHierarchy::Entry entry1;
@ -120,37 +102,35 @@ void DoField(MessageHandler* m,
}
// Expand a type node by adding members recursively to it.
bool Expand(MessageHandler* m,
Out_CclsMemberHierarchy::Entry* entry,
bool qualified,
int levels) {
bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry,
bool qualified, int levels) {
if (0 < entry->usr && entry->usr <= BuiltinType::LastKind) {
entry->name = ClangBuiltinTypeName(int(entry->usr));
return true;
}
const QueryType& type = m->db->Type(entry->usr);
const QueryType::Def* def = type.AnyDef();
const QueryType &type = m->db->Type(entry->usr);
const QueryType::Def *def = type.AnyDef();
// builtin types have no declaration and empty |qualified|.
if (!def)
return false;
entry->name = def->Name(qualified);
std::unordered_set<Usr> seen;
if (levels > 0) {
std::vector<const QueryType*> stack;
std::vector<const QueryType *> stack;
seen.insert(type.usr);
stack.push_back(&type);
while (stack.size()) {
const auto* def = stack.back()->AnyDef();
const auto *def = stack.back()->AnyDef();
stack.pop_back();
if (def) {
EachDefinedType(m->db, def->bases, [&](QueryType& type1) {
EachDefinedType(m->db, def->bases, [&](QueryType &type1) {
if (!seen.count(type1.usr)) {
seen.insert(type1.usr);
stack.push_back(&type1);
}
});
if (def->alias_of) {
const QueryType::Def* def1 = m->db->Type(def->alias_of).AnyDef();
const QueryType::Def *def1 = m->db->Type(def->alias_of).AnyDef();
Out_CclsMemberHierarchy::Entry entry1;
entry1.id = std::to_string(def->alias_of);
entry1.usr = def->alias_of;
@ -176,7 +156,7 @@ bool Expand(MessageHandler* m,
}
} else {
for (auto it : def->vars) {
QueryVar& var = m->db->Var(it.first);
QueryVar &var = m->db->Var(it.first);
if (!var.def.empty())
DoField(m, entry, var, it.second, qualified, levels - 1);
}
@ -193,15 +173,13 @@ struct Handler_CclsMemberHierarchy
: BaseMessageHandler<In_CclsMemberHierarchy> {
MethodType GetMethodType() const override { return kMethodType; }
std::optional<Out_CclsMemberHierarchy::Entry> BuildInitial(SymbolKind kind,
Usr root_usr,
bool qualified,
int levels) {
std::optional<Out_CclsMemberHierarchy::Entry>
BuildInitial(SymbolKind kind, Usr root_usr, bool qualified, int levels) {
switch (kind) {
default:
return {};
case SymbolKind::Func: {
const auto* def = db->Func(root_usr).AnyDef();
const auto *def = db->Func(root_usr).AnyDef();
if (!def)
return {};
@ -210,16 +188,16 @@ struct Handler_CclsMemberHierarchy
entry.name = def->Name(qualified);
if (def->spell) {
if (std::optional<lsLocation> loc =
GetLsLocation(db, working_files, *def->spell))
GetLsLocation(db, working_files, *def->spell))
entry.location = *loc;
}
EachDefinedVar(db, def->vars, [&](QueryVar& var) {
DoField(this, &entry, var, -1, qualified, levels - 1);
});
EachDefinedVar(db, def->vars, [&](QueryVar &var) {
DoField(this, &entry, var, -1, qualified, levels - 1);
});
return entry;
}
case SymbolKind::Type: {
const auto* def = db->Type(root_usr).AnyDef();
const auto *def = db->Type(root_usr).AnyDef();
if (!def)
return {};
@ -228,7 +206,7 @@ struct Handler_CclsMemberHierarchy
entry.usr = root_usr;
if (def->spell) {
if (std::optional<lsLocation> loc =
GetLsLocation(db, working_files, *def->spell))
GetLsLocation(db, working_files, *def->spell))
entry.location = *loc;
}
Expand(this, &entry, qualified, levels);
@ -237,8 +215,8 @@ struct Handler_CclsMemberHierarchy
}
}
void Run(In_CclsMemberHierarchy* request) override {
auto& params = request->params;
void Run(In_CclsMemberHierarchy *request) override {
auto &params = request->params;
Out_CclsMemberHierarchy out;
out.id = request->id;
@ -256,29 +234,28 @@ struct Handler_CclsMemberHierarchy
Expand(this, &entry, params.qualified, params.levels))
out.result = std::move(entry);
} else {
QueryFile* file;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;
WorkingFile* wfile =
working_files->GetFileByFilename(file->def->path);
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
for (SymbolRef sym :
FindSymbolsAtLocation(wfile, file, params.position)) {
switch (sym.kind) {
case SymbolKind::Func:
case SymbolKind::Type:
out.result = BuildInitial(sym.kind, sym.usr, params.qualified,
params.levels);
break;
case SymbolKind::Var: {
const QueryVar::Def* def = db->GetVar(sym).AnyDef();
if (def && def->type)
out.result = BuildInitial(SymbolKind::Type, def->type,
params.qualified, params.levels);
break;
}
default:
continue;
case SymbolKind::Func:
case SymbolKind::Type:
out.result =
BuildInitial(sym.kind, sym.usr, params.qualified, params.levels);
break;
case SymbolKind::Var: {
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
if (def && def->type)
out.result = BuildInitial(SymbolKind::Type, def->type,
params.qualified, params.levels);
break;
}
default:
continue;
}
break;
}
@ -289,4 +266,4 @@ struct Handler_CclsMemberHierarchy
};
REGISTER_MESSAGE_HANDLER(Handler_CclsMemberHierarchy);
} // namespace
} // namespace

View File

@ -1,6 +1,6 @@
#include "message_handler.h"
#include "query_utils.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
namespace {
@ -15,24 +15,21 @@ struct In_CclsVars : public RequestInMessage {
unsigned kind = ~0u;
} params;
};
MAKE_REFLECT_STRUCT(In_CclsVars::Params,
textDocument,
position,
kind);
MAKE_REFLECT_STRUCT(In_CclsVars::Params, textDocument, position, kind);
MAKE_REFLECT_STRUCT(In_CclsVars, id, params);
REGISTER_IN_MESSAGE(In_CclsVars);
struct Handler_CclsVars : BaseMessageHandler<In_CclsVars> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_CclsVars* request) override {
auto& params = request->params;
QueryFile* file;
void Run(In_CclsVars *request) override {
auto &params = request->params;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_LocationList out;
@ -41,24 +38,24 @@ struct Handler_CclsVars : BaseMessageHandler<In_CclsVars> {
FindSymbolsAtLocation(working_file, file, params.position)) {
Usr usr = sym.usr;
switch (sym.kind) {
default:
break;
case SymbolKind::Var: {
const QueryVar::Def* def = db->GetVar(sym).AnyDef();
if (!def || !def->type)
continue;
usr = def->type;
[[fallthrough]];
}
case SymbolKind::Type:
out.result = GetLsLocationExs(
db, working_files,
GetVarDeclarations(db, db->Type(usr).instances, params.kind));
break;
default:
break;
case SymbolKind::Var: {
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
if (!def || !def->type)
continue;
usr = def->type;
[[fallthrough]];
}
case SymbolKind::Type:
out.result = GetLsLocationExs(
db, working_files,
GetVarDeclarations(db, db->Type(usr).instances, params.kind));
break;
}
}
pipeline::WriteStdout(kMethodType, out);
}
};
REGISTER_MESSAGE_HANDLER(Handler_CclsVars);
} // namespace
} // namespace

View File

@ -10,9 +10,7 @@ REGISTER_IN_MESSAGE(In_Exit);
struct Handler_Exit : MessageHandler {
MethodType GetMethodType() const override { return kMethodType_Exit; }
void Run(std::unique_ptr<InMessage> request) override {
exit(0);
}
void Run(std::unique_ptr<InMessage> request) override { exit(0); }
};
REGISTER_MESSAGE_HANDLER(Handler_Exit);
} // namespace
} // namespace

View File

@ -55,8 +55,7 @@ struct lsDocumentOnTypeFormattingOptions {
// More trigger characters.
std::vector<std::string> moreTriggerCharacter;
};
MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions,
firstTriggerCharacter,
MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter,
moreTriggerCharacter);
// Document link options
@ -119,12 +118,8 @@ struct lsTextDocumentSyncOptions {
// Save notifications are sent to the server.
std::optional<lsSaveOptions> save;
};
MAKE_REFLECT_STRUCT(lsTextDocumentSyncOptions,
openClose,
change,
willSave,
willSaveWaitUntil,
save);
MAKE_REFLECT_STRUCT(lsTextDocumentSyncOptions, openClose, change, willSave,
willSaveWaitUntil, save);
struct lsServerCapabilities {
// Defines how text documents are synced. Is either a detailed structure
@ -161,7 +156,8 @@ struct lsServerCapabilities {
// The server provides document range formatting.
bool documentRangeFormattingProvider = false;
// The server provides document formatting on typing.
std::optional<lsDocumentOnTypeFormattingOptions> documentOnTypeFormattingProvider;
std::optional<lsDocumentOnTypeFormattingOptions>
documentOnTypeFormattingProvider;
// The server provides rename support.
bool renameProvider = true;
// The server provides document link support.
@ -169,25 +165,15 @@ struct lsServerCapabilities {
// The server provides execute command support.
lsExecuteCommandOptions executeCommandProvider;
};
MAKE_REFLECT_STRUCT(lsServerCapabilities,
textDocumentSync,
hoverProvider,
completionProvider,
signatureHelpProvider,
definitionProvider,
typeDefinitionProvider,
referencesProvider,
documentHighlightProvider,
documentSymbolProvider,
workspaceSymbolProvider,
codeActionProvider,
codeLensProvider,
documentFormattingProvider,
documentRangeFormattingProvider,
documentOnTypeFormattingProvider,
renameProvider,
documentLinkProvider,
executeCommandProvider);
MAKE_REFLECT_STRUCT(lsServerCapabilities, textDocumentSync, hoverProvider,
completionProvider, signatureHelpProvider,
definitionProvider, typeDefinitionProvider,
referencesProvider, documentHighlightProvider,
documentSymbolProvider, workspaceSymbolProvider,
codeActionProvider, codeLensProvider,
documentFormattingProvider, documentRangeFormattingProvider,
documentOnTypeFormattingProvider, renameProvider,
documentLinkProvider, executeCommandProvider);
// Workspace specific client capabilities.
struct lsWorkspaceClientCapabilites {
@ -226,12 +212,8 @@ MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsWorkspaceEdit,
documentChanges);
MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsGenericDynamicReg,
dynamicRegistration);
MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites,
applyEdit,
workspaceEdit,
didChangeConfiguration,
didChangeWatchedFiles,
symbol,
MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites, applyEdit, workspaceEdit,
didChangeConfiguration, didChangeWatchedFiles, symbol,
executeCommand);
// Text document specific client capabilities.
@ -287,13 +269,9 @@ struct lsTextDocumentClientCapabilities {
};
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsSynchronization,
dynamicRegistration,
willSave,
willSaveWaitUntil,
didSave);
dynamicRegistration, willSave, willSaveWaitUntil, didSave);
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsCompletion,
dynamicRegistration,
completionItem);
dynamicRegistration, completionItem);
MAKE_REFLECT_STRUCT(
lsTextDocumentClientCapabilities::lsCompletion::lsCompletionItem,
snippetSupport);
@ -301,12 +279,9 @@ MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsGenericDynamicReg,
dynamicRegistration);
MAKE_REFLECT_STRUCT(
lsTextDocumentClientCapabilities::CodeLensRegistrationOptions,
dynamicRegistration,
resolveProvider);
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities,
synchronization,
completion,
rename);
dynamicRegistration, resolveProvider);
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, synchronization,
completion, rename);
struct lsClientCapabilities {
// Workspace specific client capabilities.
@ -343,16 +318,16 @@ struct lsInitializeParams {
enum class lsTrace {
// NOTE: serialized as a string, one of 'off' | 'messages' | 'verbose';
Off, // off
Messages, // messages
Verbose // verbose
Off, // off
Messages, // messages
Verbose // verbose
};
// The initial trace setting. If omitted trace is disabled ('off').
lsTrace trace = lsTrace::Off;
};
void Reflect(Reader& reader, lsInitializeParams::lsTrace& value) {
void Reflect(Reader &reader, lsInitializeParams::lsTrace &value) {
if (!reader.IsString()) {
value = lsInitializeParams::lsTrace::Off;
return;
@ -366,7 +341,7 @@ void Reflect(Reader& reader, lsInitializeParams::lsTrace& value) {
value = lsInitializeParams::lsTrace::Verbose;
}
#if 0 // unused
#if 0 // unused
void Reflect(Writer& writer, lsInitializeParams::lsTrace& value) {
switch (value) {
case lsInitializeParams::lsTrace::Off:
@ -382,13 +357,8 @@ void Reflect(Writer& writer, lsInitializeParams::lsTrace& value) {
}
#endif
MAKE_REFLECT_STRUCT(lsInitializeParams,
processId,
rootPath,
rootUri,
initializationOptions,
capabilities,
trace);
MAKE_REFLECT_STRUCT(lsInitializeParams, processId, rootPath, rootUri,
initializationOptions, capabilities, trace);
struct lsInitializeError {
// Indicates whether the client should retry to send the
@ -419,8 +389,8 @@ MAKE_REFLECT_STRUCT(Out_InitializeResponse, jsonrpc, id, result);
struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_InitializeRequest* request) override {
auto& params = request->params;
void Run(In_InitializeRequest *request) override {
auto &params = request->params;
if (!params.rootUri)
return;
std::string project_path = NormalizePath(params.rootUri->GetPath());
@ -438,7 +408,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
JsonReader json_reader{&reader};
try {
Reflect(json_reader, *g_config);
} catch (std::invalid_argument&) {
} catch (std::invalid_argument &) {
// This will not trigger because parse error is handled in
// MessageRegistry::Parse in lsp.cc
}
@ -460,7 +430,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
}
// Client capabilities
const auto& capabilities = params.capabilities;
const auto &capabilities = params.capabilities;
g_config->client.snippetSupport =
capabilities.textDocument.completion.completionItem.snippetSupport;
@ -508,7 +478,8 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
std::string name = "indexer" + std::to_string(i);
set_thread_name(name.c_str());
pipeline::Indexer_Main(diag_pub, vfs, project, working_files);
}).detach();
})
.detach();
}
// Start scanning include directories before dispatching project
@ -520,4 +491,4 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_Initialize);
} // namespace
} // namespace

View File

@ -19,11 +19,11 @@ MAKE_REFLECT_STRUCT(Out_Shutdown, jsonrpc, id, result);
struct Handler_Shutdown : BaseMessageHandler<In_Shutdown> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_Shutdown* request) override {
void Run(In_Shutdown *request) override {
Out_Shutdown out;
out.id = request->id;
pipeline::WriteStdout(kMethodType, out);
}
};
REGISTER_MESSAGE_HANDLER(Handler_Shutdown);
} // namespace
} // namespace

View File

@ -33,10 +33,8 @@ struct In_TextDocumentCodeAction : public RequestInMessage {
};
MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction::lsCodeActionContext,
diagnostics);
MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction::lsCodeActionParams,
textDocument,
range,
context);
MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction::lsCodeActionParams, textDocument,
range, context);
MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction, id, params);
REGISTER_IN_MESSAGE(In_TextDocumentCodeAction);
@ -51,7 +49,7 @@ struct Handler_TextDocumentCodeAction
: BaseMessageHandler<In_TextDocumentCodeAction> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentCodeAction* request) override {
void Run(In_TextDocumentCodeAction *request) override {
const auto &params = request->params;
WorkingFile *wfile =
working_files->GetFileByFilename(params.textDocument.uri.GetPath());
@ -74,4 +72,4 @@ struct Handler_TextDocumentCodeAction
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentCodeAction);
}
} // namespace

View File

@ -1,8 +1,8 @@
#include "clang_complete.h"
#include "lsp_code_action.h"
#include "message_handler.h"
#include "query_utils.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
namespace {
@ -30,10 +30,10 @@ struct Out_TextDocumentCodeLens
MAKE_REFLECT_STRUCT(Out_TextDocumentCodeLens, jsonrpc, id, result);
struct CommonCodeLensParams {
std::vector<TCodeLens>* result;
DB* db;
WorkingFiles* working_files;
WorkingFile* working_file;
std::vector<TCodeLens> *result;
DB *db;
WorkingFiles *working_files;
WorkingFile *working_file;
};
Use OffsetStartColumn(Use use, int16_t offset) {
@ -41,12 +41,9 @@ Use OffsetStartColumn(Use use, int16_t offset) {
return use;
}
void AddCodeLens(const char* singular,
const char* plural,
CommonCodeLensParams* common,
Use use,
const std::vector<Use>& uses,
bool force_display) {
void AddCodeLens(const char *singular, const char *plural,
CommonCodeLensParams *common, Use use,
const std::vector<Use> &uses, bool force_display) {
TCodeLens code_lens;
std::optional<lsRange> range = GetLsRange(common->working_file, use.range);
if (!range)
@ -83,7 +80,7 @@ void AddCodeLens(const char* singular,
struct Handler_TextDocumentCodeLens
: BaseMessageHandler<In_TextDocumentCodeLens> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentCodeLens* request) override {
void Run(In_TextDocumentCodeLens *request) override {
Out_TextDocumentCodeLens out;
out.id = request->id;
@ -92,7 +89,7 @@ struct Handler_TextDocumentCodeLens
clang_complete->NotifyView(path);
QueryFile* file;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file)) {
return;
@ -110,119 +107,118 @@ struct Handler_TextDocumentCodeLens
Use use{{sym.range, sym.usr, sym.kind, sym.role}, file->id};
switch (sym.kind) {
case SymbolKind::Type: {
QueryType& type = db->GetType(sym);
const QueryType::Def* def = type.AnyDef();
if (!def || def->kind == lsSymbolKind::Namespace)
continue;
AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0),
type.uses, true /*force_display*/);
AddCodeLens("derived", "derived", &common, OffsetStartColumn(use, 1),
GetTypeDeclarations(db, type.derived),
false /*force_display*/);
AddCodeLens("var", "vars", &common, OffsetStartColumn(use, 2),
GetVarDeclarations(db, type.instances, true),
false /*force_display*/);
break;
}
case SymbolKind::Func: {
QueryFunc& func = db->GetFunc(sym);
const QueryFunc::Def* def = func.AnyDef();
if (!def)
continue;
case SymbolKind::Type: {
QueryType &type = db->GetType(sym);
const QueryType::Def *def = type.AnyDef();
if (!def || def->kind == lsSymbolKind::Namespace)
continue;
AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0),
type.uses, true /*force_display*/);
AddCodeLens("derived", "derived", &common, OffsetStartColumn(use, 1),
GetTypeDeclarations(db, type.derived),
false /*force_display*/);
AddCodeLens("var", "vars", &common, OffsetStartColumn(use, 2),
GetVarDeclarations(db, type.instances, true),
false /*force_display*/);
break;
}
case SymbolKind::Func: {
QueryFunc &func = db->GetFunc(sym);
const QueryFunc::Def *def = func.AnyDef();
if (!def)
continue;
int16_t offset = 0;
int16_t offset = 0;
// For functions, the outline will report a location that is using the
// extent since that is better for outline. This tries to convert the
// extent location to the spelling location.
auto try_ensure_spelling = [&](Use use) {
Maybe<Use> def = GetDefinitionSpell(db, use);
if (!def || def->range.start.line != use.range.start.line) {
return use;
}
return *def;
};
std::vector<Use> base_callers = GetUsesForAllBases(db, func);
std::vector<Use> derived_callers = GetUsesForAllDerived(db, func);
if (base_callers.empty() && derived_callers.empty()) {
Use loc = try_ensure_spelling(use);
AddCodeLens("call", "calls", &common,
OffsetStartColumn(loc, offset++), func.uses,
true /*force_display*/);
} else {
Use loc = try_ensure_spelling(use);
AddCodeLens("direct call", "direct calls", &common,
OffsetStartColumn(loc, offset++), func.uses,
false /*force_display*/);
if (!base_callers.empty())
AddCodeLens("base call", "base calls", &common,
OffsetStartColumn(loc, offset++), base_callers,
false /*force_display*/);
if (!derived_callers.empty())
AddCodeLens("derived call", "derived calls", &common,
OffsetStartColumn(loc, offset++), derived_callers,
false /*force_display*/);
// For functions, the outline will report a location that is using the
// extent since that is better for outline. This tries to convert the
// extent location to the spelling location.
auto try_ensure_spelling = [&](Use use) {
Maybe<Use> def = GetDefinitionSpell(db, use);
if (!def || def->range.start.line != use.range.start.line) {
return use;
}
return *def;
};
AddCodeLens("derived", "derived", &common,
OffsetStartColumn(use, offset++),
GetFuncDeclarations(db, func.derived),
std::vector<Use> base_callers = GetUsesForAllBases(db, func);
std::vector<Use> derived_callers = GetUsesForAllDerived(db, func);
if (base_callers.empty() && derived_callers.empty()) {
Use loc = try_ensure_spelling(use);
AddCodeLens("call", "calls", &common,
OffsetStartColumn(loc, offset++), func.uses,
true /*force_display*/);
} else {
Use loc = try_ensure_spelling(use);
AddCodeLens("direct call", "direct calls", &common,
OffsetStartColumn(loc, offset++), func.uses,
false /*force_display*/);
if (!base_callers.empty())
AddCodeLens("base call", "base calls", &common,
OffsetStartColumn(loc, offset++), base_callers,
false /*force_display*/);
if (!derived_callers.empty())
AddCodeLens("derived call", "derived calls", &common,
OffsetStartColumn(loc, offset++), derived_callers,
false /*force_display*/);
}
// "Base"
if (def->bases.size() == 1) {
Maybe<Use> base_loc = GetDefinitionSpell(
db, SymbolIdx{def->bases[0], SymbolKind::Func});
if (base_loc) {
std::optional<lsLocation> ls_base =
GetLsLocation(db, working_files, *base_loc);
if (ls_base) {
std::optional<lsRange> range =
GetLsRange(common.working_file, sym.range);
if (range) {
TCodeLens code_lens;
code_lens.range = *range;
code_lens.range.start.character += offset++;
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
code_lens.command->title = "Base";
code_lens.command->command = "ccls.goto";
code_lens.command->arguments.uri = ls_base->uri;
code_lens.command->arguments.position = ls_base->range.start;
out.result.push_back(code_lens);
}
AddCodeLens(
"derived", "derived", &common, OffsetStartColumn(use, offset++),
GetFuncDeclarations(db, func.derived), false /*force_display*/);
// "Base"
if (def->bases.size() == 1) {
Maybe<Use> base_loc = GetDefinitionSpell(
db, SymbolIdx{def->bases[0], SymbolKind::Func});
if (base_loc) {
std::optional<lsLocation> ls_base =
GetLsLocation(db, working_files, *base_loc);
if (ls_base) {
std::optional<lsRange> range =
GetLsRange(common.working_file, sym.range);
if (range) {
TCodeLens code_lens;
code_lens.range = *range;
code_lens.range.start.character += offset++;
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
code_lens.command->title = "Base";
code_lens.command->command = "ccls.goto";
code_lens.command->arguments.uri = ls_base->uri;
code_lens.command->arguments.position = ls_base->range.start;
out.result.push_back(code_lens);
}
}
} else {
AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1),
GetTypeDeclarations(db, def->bases),
false /*force_display*/);
}
break;
} else {
AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1),
GetTypeDeclarations(db, def->bases),
false /*force_display*/);
}
case SymbolKind::Var: {
QueryVar& var = db->GetVar(sym);
const QueryVar::Def* def = var.AnyDef();
if (!def || (def->is_local() && !g_config->codeLens.localVariables))
continue;
bool force_display = true;
// Do not show 0 refs on macro with no uses, as it is most likely
// a header guard.
if (def->kind == lsSymbolKind::Macro)
force_display = false;
break;
}
case SymbolKind::Var: {
QueryVar &var = db->GetVar(sym);
const QueryVar::Def *def = var.AnyDef();
if (!def || (def->is_local() && !g_config->codeLens.localVariables))
continue;
AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0),
var.uses, force_display);
break;
}
case SymbolKind::File:
case SymbolKind::Invalid: {
assert(false && "unexpected");
break;
}
bool force_display = true;
// Do not show 0 refs on macro with no uses, as it is most likely
// a header guard.
if (def->kind == lsSymbolKind::Macro)
force_display = false;
AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0), var.uses,
force_display);
break;
}
case SymbolKind::File:
case SymbolKind::Invalid: {
assert(false && "unexpected");
break;
}
};
}
@ -230,4 +226,4 @@ struct Handler_TextDocumentCodeLens
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentCodeLens);
} // namespace
} // namespace

View File

@ -70,8 +70,8 @@ struct Out_TextDocumentComplete
};
MAKE_REFLECT_STRUCT(Out_TextDocumentComplete, jsonrpc, id, result);
void DecorateIncludePaths(const std::smatch& match,
std::vector<lsCompletionItem>* items) {
void DecorateIncludePaths(const std::smatch &match,
std::vector<lsCompletionItem> *items) {
std::string spaces_after_include = " ";
if (match[3].compare("include") == 0 && match[5].length())
spaces_after_include = match[4].str();
@ -80,7 +80,7 @@ void DecorateIncludePaths(const std::smatch& match,
match[1].str() + '#' + match[2].str() + "include" + spaces_after_include;
std::string suffix = match[7].str();
for (lsCompletionItem& item : *items) {
for (lsCompletionItem &item : *items) {
char quote0, quote1;
if (match[5].compare("<") == 0 ||
(match[5].length() == 0 && item.use_angle_brackets_))
@ -103,17 +103,16 @@ struct ParseIncludeLineResult {
std::smatch match;
};
ParseIncludeLineResult ParseIncludeLine(const std::string& line) {
static const std::regex pattern(
"(\\s*)" // [1]: spaces before '#'
"#" //
"(\\s*)" // [2]: spaces after '#'
"([^\\s\"<]*)" // [3]: "include"
"(\\s*)" // [4]: spaces before quote
"([\"<])?" // [5]: the first quote char
"([^\\s\">]*)" // [6]: path of file
"[\">]?" //
"(.*)"); // [7]: suffix after quote char
ParseIncludeLineResult ParseIncludeLine(const std::string &line) {
static const std::regex pattern("(\\s*)" // [1]: spaces before '#'
"#" //
"(\\s*)" // [2]: spaces after '#'
"([^\\s\"<]*)" // [3]: "include"
"(\\s*)" // [4]: spaces before quote
"([\"<])?" // [5]: the first quote char
"([^\\s\">]*)" // [6]: path of file
"[\">]?" //
"(.*)"); // [7]: suffix after quote char
std::smatch match;
bool ok = std::regex_match(line, match, pattern);
return {ok, match[3], match[5], match[6], match};
@ -123,10 +122,10 @@ static const std::vector<std::string> preprocessorKeywords = {
"define", "undef", "include", "if", "ifdef", "ifndef",
"else", "elif", "endif", "line", "error", "pragma"};
std::vector<lsCompletionItem> PreprocessorKeywordCompletionItems(
const std::smatch& match) {
std::vector<lsCompletionItem>
PreprocessorKeywordCompletionItems(const std::smatch &match) {
std::vector<lsCompletionItem> items;
for (auto& keyword : preprocessorKeywords) {
for (auto &keyword : preprocessorKeywords) {
lsCompletionItem item;
item.label = keyword;
item.priority_ = (keyword == "include" ? 2 : 1);
@ -140,12 +139,10 @@ std::vector<lsCompletionItem> PreprocessorKeywordCompletionItems(
return items;
}
template <typename T>
char* tofixedbase64(T input, char* out) {
const char* digits =
"./0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
template <typename T> char *tofixedbase64(T input, char *out) {
const char *digits = "./0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int len = (sizeof(T) * 8 - 1) / 6 + 1;
for (int i = len - 1; i >= 0; i--) {
out[i] = digits[input % 64];
@ -159,16 +156,15 @@ char* tofixedbase64(T input, char* out) {
// significantly snappier completion experience as vscode is easily overloaded
// when given 1000+ completion items.
void FilterAndSortCompletionResponse(
Out_TextDocumentComplete* complete_response,
const std::string& complete_text,
bool has_open_paren) {
Out_TextDocumentComplete *complete_response,
const std::string &complete_text, bool has_open_paren) {
if (!g_config->completion.filterAndSort)
return;
static Timer timer("FilterAndSortCompletionResponse", "");
TimeRegion region(timer);
auto& items = complete_response->result.items;
auto &items = complete_response->result.items;
auto finalize = [&]() {
const size_t kMaxResultSize = 100u;
@ -178,7 +174,7 @@ void FilterAndSortCompletionResponse(
}
if (has_open_paren)
for (auto& item: items)
for (auto &item : items)
item.insertText = item.label;
// Set sortText. Note that this happens after resizing - we could do it
@ -195,7 +191,7 @@ void FilterAndSortCompletionResponse(
}
// Make sure all items have |filterText| set, code that follow needs it.
for (auto& item : items) {
for (auto &item : items) {
if (!item.filterText)
item.filterText = item.label;
}
@ -203,19 +199,19 @@ void FilterAndSortCompletionResponse(
// Fuzzy match and remove awful candidates.
bool sensitive = g_config->completion.caseSensitivity;
FuzzyMatcher fuzzy(complete_text, sensitive);
for (auto& item : items) {
for (auto &item : items) {
item.score_ =
ReverseSubseqMatch(complete_text, *item.filterText, sensitive) >= 0
? fuzzy.Match(*item.filterText)
: FuzzyMatcher::kMinScore;
}
items.erase(std::remove_if(items.begin(), items.end(),
[](const lsCompletionItem& item) {
[](const lsCompletionItem &item) {
return item.score_ <= FuzzyMatcher::kMinScore;
}),
items.end());
std::sort(items.begin(), items.end(),
[](const lsCompletionItem& lhs, const lsCompletionItem& rhs) {
[](const lsCompletionItem &lhs, const lsCompletionItem &rhs) {
if (lhs.score_ != rhs.score_)
return lhs.score_ > rhs.score_;
if (lhs.priority_ != rhs.priority_)
@ -231,16 +227,17 @@ void FilterAndSortCompletionResponse(
// Returns true if position is an points to a '(' character in |lines|. Skips
// whitespace.
bool IsOpenParenOrAngle(const std::vector<std::string>& lines,
const lsPosition& position) {
bool IsOpenParenOrAngle(const std::vector<std::string> &lines,
const lsPosition &position) {
auto [c, l] = position;
while (l < lines.size()) {
const auto& line = lines[l];
const auto &line = lines[l];
if (c >= line.size())
return false;
if (line[c] == '(' || line[c] == '<')
return true;
if (!isspace(line[c])) break;
if (!isspace(line[c]))
break;
if (++c >= line.size()) {
c = 0;
l++;
@ -254,8 +251,8 @@ struct Handler_TextDocumentCompletion : MessageHandler {
void Run(std::unique_ptr<InMessage> message) override {
auto request = std::shared_ptr<In_TextDocumentComplete>(
static_cast<In_TextDocumentComplete*>(message.release()));
auto& params = request->params;
static_cast<In_TextDocumentComplete *>(message.release()));
auto &params = request->params;
auto write_empty_result = [request]() {
Out_TextDocumentComplete out;
@ -264,7 +261,7 @@ struct Handler_TextDocumentCompletion : MessageHandler {
};
std::string path = params.textDocument.uri.GetPath();
WorkingFile* file = working_files->GetFileByFilename(path);
WorkingFile *file = working_files->GetFileByFilename(path);
if (!file) {
write_empty_result();
return;
@ -350,15 +347,16 @@ struct Handler_TextDocumentCompletion : MessageHandler {
if (include_complete->is_scanning)
lock.lock();
std::string quote = result.match[5];
for (auto& item : include_complete->completion_items)
if (quote.empty() || quote == (item.use_angle_brackets_ ? "<" : "\""))
out.result.items.push_back(item);
for (auto &item : include_complete->completion_items)
if (quote.empty() ||
quote == (item.use_angle_brackets_ ? "<" : "\""))
out.result.items.push_back(item);
}
FilterAndSortCompletionResponse(&out, result.pattern, has_open_paren);
DecorateIncludePaths(result.match, &out.result.items);
}
for (lsCompletionItem& item : out.result.items) {
for (lsCompletionItem &item : out.result.items) {
item.textEdit->range.start.line = params.position.line;
item.textEdit->range.start.character = 0;
item.textEdit->range.end.line = params.position.line;
@ -369,14 +367,15 @@ struct Handler_TextDocumentCompletion : MessageHandler {
} else {
ClangCompleteManager::OnComplete callback = std::bind(
[this, request, params, is_global_completion, existing_completion,
has_open_paren](const std::vector<lsCompletionItem>& results,
has_open_paren](const std::vector<lsCompletionItem> &results,
bool is_cached_result) {
Out_TextDocumentComplete out;
out.id = request->id;
out.result.items = results;
// Emit completion results.
FilterAndSortCompletionResponse(&out, existing_completion, has_open_paren);
FilterAndSortCompletionResponse(&out, existing_completion,
has_open_paren);
pipeline::WriteStdout(kMethodType, out);
// Cache completion results.
@ -435,4 +434,4 @@ struct Handler_TextDocumentCompletion : MessageHandler {
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentCompletion);
} // namespace
} // namespace

View File

@ -3,9 +3,9 @@
#include "query_utils.h"
using namespace ccls;
#include <cstdlib>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
namespace {
MethodType kMethodType = "textDocument/definition";
@ -24,35 +24,35 @@ struct Out_TextDocumentDefinition
};
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
std::vector<Use> GetNonDefDeclarationTargets(DB* db, SymbolRef sym) {
std::vector<Use> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
switch (sym.kind) {
case SymbolKind::Var: {
std::vector<Use> ret = GetNonDefDeclarations(db, sym);
// If there is no declaration, jump the its type.
if (ret.empty()) {
for (auto& def : db->GetVar(sym).def)
if (def.type) {
if (Maybe<Use> use = GetDefinitionSpell(
db, SymbolIdx{def.type, SymbolKind::Type})) {
ret.push_back(*use);
break;
}
case SymbolKind::Var: {
std::vector<Use> ret = GetNonDefDeclarations(db, sym);
// If there is no declaration, jump the its type.
if (ret.empty()) {
for (auto &def : db->GetVar(sym).def)
if (def.type) {
if (Maybe<Use> use = GetDefinitionSpell(
db, SymbolIdx{def.type, SymbolKind::Type})) {
ret.push_back(*use);
break;
}
}
return ret;
}
}
default:
return GetNonDefDeclarations(db, sym);
return ret;
}
default:
return GetNonDefDeclarations(db, sym);
}
}
struct Handler_TextDocumentDefinition
: BaseMessageHandler<In_TextDocumentDefinition> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDefinition* request) override {
auto& params = request->params;
void Run(In_TextDocumentDefinition *request) override {
auto &params = request->params;
int file_id;
QueryFile* file;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file, &file_id))
return;
@ -62,9 +62,8 @@ struct Handler_TextDocumentDefinition
Maybe<Use> on_def;
bool has_symbol = false;
WorkingFile* wfile =
working_files->GetFileByFilename(file->def->path);
lsPosition& ls_pos = params.position;
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
lsPosition &ls_pos = params.position;
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) {
// Found symbol. Return definition.
@ -75,7 +74,7 @@ struct Handler_TextDocumentDefinition
// - start at spelling but end at extent for better mouse tooltip
// - goto declaration while in definition of recursive type
std::vector<Use> uses;
EachEntityDef(db, sym, [&](const auto& def) {
EachEntityDef(db, sym, [&](const auto &def) {
if (def.spell && def.extent) {
Use spell = *def.spell;
// If on a definition, clear |uses| to find declarations below.
@ -109,7 +108,7 @@ struct Handler_TextDocumentDefinition
// No symbols - check for includes.
if (out.result.empty()) {
for (const IndexInclude& include : file->def->includes) {
for (const IndexInclude &include : file->def->includes) {
if (include.line == ls_pos.line) {
lsLocationEx result;
result.uri = lsDocumentUri::FromPath(include.resolved_path);
@ -121,7 +120,7 @@ struct Handler_TextDocumentDefinition
// Find the best match of the identifier at point.
if (!has_symbol) {
lsPosition position = request->params.position;
const std::string& buffer = wfile->buffer_content;
const std::string &buffer = wfile->buffer_content;
std::string_view query = LexIdentifierAroundPos(position, buffer);
std::string_view short_query = query;
{
@ -161,11 +160,11 @@ struct Handler_TextDocumentDefinition
}
}
};
for (auto& func : db->funcs)
for (auto &func : db->funcs)
fn({func.usr, SymbolKind::Func});
for (auto& type : db->types)
for (auto &type : db->types)
fn({type.usr, SymbolKind::Type});
for (auto& var : db->vars)
for (auto &var : db->vars)
if (var.def.size() && !var.def[0].is_local())
fn({var.usr, SymbolKind::Var});
@ -183,4 +182,4 @@ struct Handler_TextDocumentDefinition
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDefinition);
} // namespace
} // namespace

View File

@ -1,8 +1,8 @@
#include "clang_complete.h"
#include "message_handler.h"
#include "pipeline.hh"
#include "project.h"
#include "working_files.h"
#include "pipeline.hh"
using namespace ccls;
namespace {
@ -20,7 +20,7 @@ struct Handler_TextDocumentDidChange
: BaseMessageHandler<In_TextDocumentDidChange> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDidChange* request) override {
void Run(In_TextDocumentDidChange *request) override {
std::string path = request->params.textDocument.uri.GetPath();
working_files->OnChange(request->params);
if (g_config->index.onDidChange) {
@ -33,4 +33,4 @@ struct Handler_TextDocumentDidChange
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidChange);
} // namespace
} // namespace

View File

@ -22,7 +22,7 @@ struct Handler_TextDocumentDidClose
: BaseMessageHandler<In_TextDocumentDidClose> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDidClose* request) override {
void Run(In_TextDocumentDidClose *request) override {
std::string path = request->params.textDocument.uri.GetPath();
// Clear any diagnostics for the file.
@ -36,4 +36,4 @@ struct Handler_TextDocumentDidClose
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidClose);
} // namespace
} // namespace

View File

@ -1,8 +1,8 @@
#include "clang_complete.h"
#include "include_complete.h"
#include "message_handler.h"
#include "project.h"
#include "pipeline.hh"
#include "project.h"
#include "working_files.h"
using namespace ccls;
@ -12,7 +12,7 @@ MethodType kMethodType = "textDocument/didOpen";
// Open, view, change, close file
struct In_TextDocumentDidOpen : public NotificationInMessage {
MethodType GetMethodType() const override { return kMethodType; }
struct Params {
lsTextDocumentItem textDocument;
@ -31,18 +31,18 @@ struct Handler_TextDocumentDidOpen
: BaseMessageHandler<In_TextDocumentDidOpen> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDidOpen* request) override {
void Run(In_TextDocumentDidOpen *request) override {
// NOTE: This function blocks code lens. If it starts taking a long time
// we will need to find a way to unblock the code lens request.
const auto& params = request->params;
const auto &params = request->params;
std::string path = params.textDocument.uri.GetPath();
WorkingFile* working_file = working_files->OnOpen(params.textDocument);
WorkingFile *working_file = working_files->OnOpen(params.textDocument);
if (std::optional<std::string> cached_file_contents =
pipeline::LoadCachedFileContents(path))
working_file->SetIndexContent(*cached_file_contents);
QueryFile* file = nullptr;
QueryFile *file = nullptr;
FindFileOrFail(db, project, std::nullopt, path, &file);
if (file && file->def) {
EmitSkippedRanges(working_file, file->def->skipped_ranges);
@ -68,4 +68,4 @@ struct Handler_TextDocumentDidOpen
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen);
} // namespace
} // namespace

View File

@ -1,7 +1,7 @@
#include "clang_complete.h"
#include "message_handler.h"
#include "project.h"
#include "pipeline.hh"
#include "project.h"
using namespace ccls;
namespace {
@ -28,8 +28,8 @@ struct Handler_TextDocumentDidSave
: BaseMessageHandler<In_TextDocumentDidSave> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDidSave* request) override {
const auto& params = request->params;
void Run(In_TextDocumentDidSave *request) override {
const auto &params = request->params;
std::string path = params.textDocument.uri.GetPath();
// Send out an index request, and copy the current buffer state so we
@ -55,4 +55,4 @@ struct Handler_TextDocumentDidSave
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave);
} // namespace
} // namespace

View File

@ -24,16 +24,16 @@ MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentHighlight, jsonrpc, id, result);
struct Handler_TextDocumentDocumentHighlight
: BaseMessageHandler<In_TextDocumentDocumentHighlight> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDocumentHighlight* request) override {
void Run(In_TextDocumentDocumentHighlight *request) override {
int file_id;
QueryFile* file;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file,
&file_id)) {
return;
}
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_TextDocumentDocumentHighlight out;
@ -66,4 +66,4 @@ struct Handler_TextDocumentDocumentHighlight
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentHighlight);
} // namespace
} // namespace

View File

@ -38,10 +38,10 @@ MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentSymbol, jsonrpc, id, result);
struct Handler_TextDocumentDocumentSymbol
: BaseMessageHandler<In_TextDocumentDocumentSymbol> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDocumentSymbol* request) override {
auto& params = request->params;
void Run(In_TextDocumentDocumentSymbol *request) override {
auto &params = request->params;
QueryFile* file;
QueryFile *file;
int file_id;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file, &file_id))
@ -67,8 +67,8 @@ struct Handler_TextDocumentDocumentSymbol
if (std::optional<lsSymbolInformation> info =
GetSymbolInfo(db, working_files, sym, false)) {
if (sym.kind == SymbolKind::Var) {
QueryVar& var = db->GetVar(sym);
auto* def = var.AnyDef();
QueryVar &var = db->GetVar(sym);
auto *def = var.AnyDef();
if (!def || !def->spell || def->is_local())
continue;
}
@ -84,4 +84,4 @@ struct Handler_TextDocumentDocumentSymbol
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentSymbol);
} // namespace
} // namespace

View File

@ -7,10 +7,10 @@ namespace {
MethodType kMethodType = "textDocument/hover";
// Find the comments for |sym|, if any.
std::optional<lsMarkedString> GetComments(DB* db, SymbolRef sym) {
std::optional<lsMarkedString> GetComments(DB *db, SymbolRef sym) {
std::optional<lsMarkedString> ret;
WithEntity(db, sym, [&](const auto& entity) {
if (const auto* def = entity.AnyDef())
WithEntity(db, sym, [&](const auto &entity) {
if (const auto *def = entity.AnyDef())
if (def->comments[0]) {
lsMarkedString m;
m.value = def->comments;
@ -21,12 +21,11 @@ std::optional<lsMarkedString> GetComments(DB* db, SymbolRef sym) {
}
// Returns the hover or detailed name for `sym`, if any.
std::optional<lsMarkedString> GetHoverOrName(DB* db,
LanguageId lang,
std::optional<lsMarkedString> GetHoverOrName(DB *db, LanguageId lang,
SymbolRef sym) {
std::optional<lsMarkedString> ret;
WithEntity(db, sym, [&](const auto& entity) {
if (const auto* def = entity.AnyDef()) {
WithEntity(db, sym, [&](const auto &entity) {
if (const auto *def = entity.AnyDef()) {
lsMarkedString m;
m.language = LanguageIdentifier(lang);
if (def->hover[0]) {
@ -58,21 +57,19 @@ struct Out_TextDocumentHover : public lsOutMessage<Out_TextDocumentHover> {
std::optional<Result> result;
};
MAKE_REFLECT_STRUCT(Out_TextDocumentHover::Result, contents, range);
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_TextDocumentHover,
jsonrpc,
id,
MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_TextDocumentHover, jsonrpc, id,
result);
struct Handler_TextDocumentHover : BaseMessageHandler<In_TextDocumentHover> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentHover* request) override {
auto& params = request->params;
QueryFile* file;
void Run(In_TextDocumentHover *request) override {
auto &params = request->params;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_TextDocumentHover out;
@ -104,4 +101,4 @@ struct Handler_TextDocumentHover : BaseMessageHandler<In_TextDocumentHover> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentHover);
} // namespace
} // namespace

View File

@ -1,6 +1,6 @@
#include "message_handler.h"
#include "query_utils.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
namespace {
@ -16,14 +16,14 @@ REGISTER_IN_MESSAGE(In_TextDocumentImplementation);
struct Handler_TextDocumentImplementation
: BaseMessageHandler<In_TextDocumentImplementation> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentImplementation* request) override {
QueryFile* file;
void Run(In_TextDocumentImplementation *request) override {
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file)) {
return;
}
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_LocationList out;
@ -31,12 +31,12 @@ struct Handler_TextDocumentImplementation
for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Type) {
QueryType& type = db->GetType(sym);
QueryType &type = db->GetType(sym);
out.result = GetLsLocationExs(db, working_files,
GetTypeDeclarations(db, type.derived));
break;
} else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym);
QueryFunc &func = db->GetFunc(sym);
out.result = GetLsLocationExs(db, working_files,
GetFuncDeclarations(db, func.derived));
break;
@ -46,4 +46,4 @@ struct Handler_TextDocumentImplementation
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentImplementation);
} // namespace
} // namespace

View File

@ -27,14 +27,9 @@ struct In_TextDocumentReferences : public RequestInMessage {
Params params;
};
MAKE_REFLECT_STRUCT(In_TextDocumentReferences::lsReferenceContext,
base,
excludeRole,
includeDeclaration,
role);
MAKE_REFLECT_STRUCT(In_TextDocumentReferences::Params,
textDocument,
position,
MAKE_REFLECT_STRUCT(In_TextDocumentReferences::lsReferenceContext, base,
excludeRole, includeDeclaration, role);
MAKE_REFLECT_STRUCT(In_TextDocumentReferences::Params, textDocument, position,
context);
MAKE_REFLECT_STRUCT(In_TextDocumentReferences, id, params);
REGISTER_IN_MESSAGE(In_TextDocumentReferences);
@ -50,15 +45,14 @@ struct Handler_TextDocumentReferences
: BaseMessageHandler<In_TextDocumentReferences> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentReferences* request) override {
auto& params = request->params;
QueryFile* file;
void Run(In_TextDocumentReferences *request) override {
auto &params = request->params;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;
WorkingFile* wfile =
working_files->GetFileByFilename(file->def->path);
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
Out_TextDocumentReferences out;
out.id = request->id;
@ -86,9 +80,9 @@ struct Handler_TextDocumentReferences
out.result.push_back(*ls_loc);
}
};
WithEntity(db, sym, [&](const auto& entity) {
WithEntity(db, sym, [&](const auto &entity) {
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
for (auto& def : entity.def)
for (auto &def : entity.def)
if (def.spell) {
parent_kind = GetSymbolKind(db, sym);
if (params.context.base)
@ -102,7 +96,7 @@ struct Handler_TextDocumentReferences
for (Use use : entity.uses)
fn(use, parent_kind);
if (params.context.includeDeclaration) {
for (auto& def : entity.def)
for (auto &def : entity.def)
if (def.spell)
fn(*def.spell, parent_kind);
for (Use use : entity.declarations)
@ -120,21 +114,20 @@ struct Handler_TextDocumentReferences
std::string path;
if (params.position.line == 0)
path = file->def->path;
for (const IndexInclude& include : file->def->includes)
for (const IndexInclude &include : file->def->includes)
if (include.line == params.position.line) {
path = include.resolved_path;
break;
}
if (path.size())
for (QueryFile& file1 : db->files)
for (QueryFile &file1 : db->files)
if (file1.def)
for (const IndexInclude& include : file1.def->includes)
for (const IndexInclude &include : file1.def->includes)
if (include.resolved_path == path) {
// Another file |file1| has the same include line.
lsLocationEx result;
result.uri = lsDocumentUri::FromPath(file1.def->path);
result.range.start.line = result.range.end.line =
include.line;
result.range.start.line = result.range.end.line = include.line;
out.result.push_back(std::move(result));
break;
}
@ -146,4 +139,4 @@ struct Handler_TextDocumentReferences
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentReferences);
} // namespace
} // namespace

View File

@ -1,19 +1,18 @@
#include "message_handler.h"
#include "query_utils.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
namespace {
MethodType kMethodType = "textDocument/rename";
lsWorkspaceEdit BuildWorkspaceEdit(DB* db,
WorkingFiles* working_files,
SymbolRef sym,
const std::string& new_text) {
lsWorkspaceEdit BuildWorkspaceEdit(DB *db, WorkingFiles *working_files,
SymbolRef sym, const std::string &new_text) {
std::unordered_map<int, lsTextDocumentEdit> path_to_edit;
EachOccurrence(db, sym, true, [&](Use use) {
std::optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
std::optional<lsLocation> ls_location =
GetLsLocation(db, working_files, use);
if (!ls_location)
return;
@ -21,14 +20,14 @@ lsWorkspaceEdit BuildWorkspaceEdit(DB* db,
if (path_to_edit.find(file_id) == path_to_edit.end()) {
path_to_edit[file_id] = lsTextDocumentEdit();
QueryFile& file = db->files[file_id];
QueryFile &file = db->files[file_id];
if (!file.def)
return;
const std::string& path = file.def->path;
const std::string &path = file.def->path;
path_to_edit[file_id].textDocument.uri = lsDocumentUri::FromPath(path);
WorkingFile* working_file = working_files->GetFileByFilename(path);
WorkingFile *working_file = working_files->GetFileByFilename(path);
if (working_file)
path_to_edit[file_id].textDocument.version = working_file->version;
}
@ -38,13 +37,13 @@ lsWorkspaceEdit BuildWorkspaceEdit(DB* db,
edit.newText = new_text;
// vscode complains if we submit overlapping text edits.
auto& edits = path_to_edit[file_id].edits;
auto &edits = path_to_edit[file_id].edits;
if (std::find(edits.begin(), edits.end(), edit) == edits.end())
edits.push_back(edit);
});
lsWorkspaceEdit edit;
for (const auto& changes : path_to_edit)
for (const auto &changes : path_to_edit)
edit.documentChanges.push_back(changes.second);
return edit;
}
@ -65,9 +64,7 @@ struct In_TextDocumentRename : public RequestInMessage {
};
Params params;
};
MAKE_REFLECT_STRUCT(In_TextDocumentRename::Params,
textDocument,
position,
MAKE_REFLECT_STRUCT(In_TextDocumentRename::Params, textDocument, position,
newName);
MAKE_REFLECT_STRUCT(In_TextDocumentRename, id, params);
REGISTER_IN_MESSAGE(In_TextDocumentRename);
@ -80,16 +77,16 @@ MAKE_REFLECT_STRUCT(Out_TextDocumentRename, jsonrpc, id, result);
struct Handler_TextDocumentRename : BaseMessageHandler<In_TextDocumentRename> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentRename* request) override {
void Run(In_TextDocumentRename *request) override {
int file_id;
QueryFile* file;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file,
&file_id)) {
return;
}
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_TextDocumentRename out;
@ -107,4 +104,4 @@ struct Handler_TextDocumentRename : BaseMessageHandler<In_TextDocumentRename> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRename);
} // namespace
} // namespace

View File

@ -70,9 +70,7 @@ struct lsSignatureHelp {
// active signature does have any.
std::optional<int> activeParameter;
};
MAKE_REFLECT_STRUCT(lsSignatureHelp,
signatures,
activeSignature,
MAKE_REFLECT_STRUCT(lsSignatureHelp, signatures, activeSignature,
activeParameter);
struct Out_TextDocumentSignatureHelp
@ -86,9 +84,9 @@ struct Handler_TextDocumentSignatureHelp : MessageHandler {
MethodType GetMethodType() const override { return kMethodType; }
void Run(std::unique_ptr<InMessage> message) override {
auto request = static_cast<In_TextDocumentSignatureHelp*>(message.get());
lsTextDocumentPositionParams& params = request->params;
WorkingFile* file =
auto request = static_cast<In_TextDocumentSignatureHelp *>(message.get());
lsTextDocumentPositionParams &params = request->params;
WorkingFile *file =
working_files->GetFileByFilename(params.textDocument.uri.GetPath());
std::string search;
int active_param = 0;
@ -102,21 +100,21 @@ struct Handler_TextDocumentSignatureHelp : MessageHandler {
return;
ClangCompleteManager::OnComplete callback = std::bind(
[this](InMessage* message, std::string search, int active_param,
const std::vector<lsCompletionItem>& results,
[this](InMessage *message, std::string search, int active_param,
const std::vector<lsCompletionItem> &results,
bool is_cached_result) {
auto msg = static_cast<In_TextDocumentSignatureHelp*>(message);
auto msg = static_cast<In_TextDocumentSignatureHelp *>(message);
Out_TextDocumentSignatureHelp out;
out.id = msg->id;
for (auto& result : results) {
for (auto &result : results) {
if (result.label != search)
continue;
lsSignatureInformation signature;
signature.label = result.detail;
for (auto& parameter : result.parameters_) {
for (auto &parameter : result.parameters_) {
lsParameterInformation ls_param;
ls_param.label = parameter;
signature.parameters.push_back(ls_param);
@ -168,4 +166,4 @@ struct Handler_TextDocumentSignatureHelp : MessageHandler {
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentSignatureHelp);
} // namespace
} // namespace

View File

@ -23,14 +23,14 @@ MAKE_REFLECT_STRUCT(Out_TextDocumentTypeDefinition, jsonrpc, id, result);
struct Handler_TextDocumentTypeDefinition
: BaseMessageHandler<In_TextDocumentTypeDefinition> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentTypeDefinition* request) override {
QueryFile* file;
void Run(In_TextDocumentTypeDefinition *request) override {
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file,
nullptr)) {
return;
}
WorkingFile* working_file =
WorkingFile *working_file =
working_files->GetFileByFilename(file->def->path);
Out_TextDocumentTypeDefinition out;
@ -39,25 +39,25 @@ struct Handler_TextDocumentTypeDefinition
FindSymbolsAtLocation(working_file, file, request->params.position)) {
Usr usr = sym.usr;
switch (sym.kind) {
case SymbolKind::Var: {
const QueryVar::Def* def = db->GetVar(sym).AnyDef();
if (!def || !def->type)
continue;
usr = def->type;
[[fallthrough]];
}
case SymbolKind::Type: {
QueryType& type = db->Type(usr);
for (const auto& def : type.def)
if (def.spell) {
if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell,
g_config->xref.container))
out.result.push_back(*ls_loc);
}
break;
}
default:
break;
case SymbolKind::Var: {
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
if (!def || !def->type)
continue;
usr = def->type;
[[fallthrough]];
}
case SymbolKind::Type: {
QueryType &type = db->Type(usr);
for (const auto &def : type.def)
if (def.spell) {
if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell,
g_config->xref.container))
out.result.push_back(*ls_loc);
}
break;
}
default:
break;
}
}
@ -66,4 +66,4 @@ struct Handler_TextDocumentTypeDefinition
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentTypeDefinition);
} // namespace
} // namespace

View File

@ -1,7 +1,7 @@
#include "clang_complete.h"
#include "message_handler.h"
#include "project.h"
#include "pipeline.hh"
#include "project.h"
#include "working_files.h"
using namespace ccls;
@ -23,7 +23,7 @@ REGISTER_IN_MESSAGE(In_WorkspaceDidChangeConfiguration);
struct Handler_WorkspaceDidChangeConfiguration
: BaseMessageHandler<In_WorkspaceDidChangeConfiguration> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_WorkspaceDidChangeConfiguration* request) override {
void Run(In_WorkspaceDidChangeConfiguration *request) override {
project->Load(g_config->projectRoot);
project->Index(working_files, lsRequestId());
@ -31,4 +31,4 @@ struct Handler_WorkspaceDidChangeConfiguration
}
};
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceDidChangeConfiguration);
} // namespace
} // namespace

View File

@ -1,7 +1,7 @@
#include "clang_complete.h"
#include "message_handler.h"
#include "project.h"
#include "pipeline.hh"
#include "project.h"
#include "working_files.h"
using namespace ccls;
@ -36,8 +36,8 @@ REGISTER_IN_MESSAGE(In_WorkspaceDidChangeWatchedFiles);
struct Handler_WorkspaceDidChangeWatchedFiles
: BaseMessageHandler<In_WorkspaceDidChangeWatchedFiles> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_WorkspaceDidChangeWatchedFiles* request) override {
for (lsFileEvent& event : request->params.changes) {
void Run(In_WorkspaceDidChangeWatchedFiles *request) override {
for (lsFileEvent &event : request->params.changes) {
std::string path = event.uri.GetPath();
Project::Entry entry;
{
@ -50,19 +50,19 @@ struct Handler_WorkspaceDidChangeWatchedFiles
bool is_interactive =
working_files->GetFileByFilename(entry.filename) != nullptr;
switch (event.type) {
case lsFileChangeType::Created:
case lsFileChangeType::Changed: {
pipeline::Index(path, entry.args, is_interactive);
if (is_interactive)
clang_complete->NotifySave(path);
break;
}
case lsFileChangeType::Deleted:
pipeline::Index(path, entry.args, is_interactive);
break;
case lsFileChangeType::Created:
case lsFileChangeType::Changed: {
pipeline::Index(path, entry.args, is_interactive);
if (is_interactive)
clang_complete->NotifySave(path);
break;
}
case lsFileChangeType::Deleted:
pipeline::Index(path, entry.args, is_interactive);
break;
}
}
}
};
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceDidChangeWatchedFiles);
} // namespace
} // namespace

View File

@ -1,7 +1,7 @@
#include "lsp_code_action.h"
#include "message_handler.h"
#include "query_utils.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
namespace {
@ -24,8 +24,8 @@ MAKE_REFLECT_STRUCT(Out_WorkspaceExecuteCommand, jsonrpc, id, result);
struct Handler_WorkspaceExecuteCommand
: BaseMessageHandler<In_WorkspaceExecuteCommand> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_WorkspaceExecuteCommand* request) override {
const auto& params = request->params;
void Run(In_WorkspaceExecuteCommand *request) override {
const auto &params = request->params;
Out_WorkspaceExecuteCommand out;
out.id = request->id;
if (params.command == "ccls._applyFixIt") {
@ -40,4 +40,4 @@ struct Handler_WorkspaceExecuteCommand
};
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceExecuteCommand);
} // namespace
} // namespace

View File

@ -4,21 +4,18 @@
#include "query_utils.h"
using namespace ccls;
#include <ctype.h>
#include <limits.h>
#include <algorithm>
#include <ctype.h>
#include <functional>
#include <limits.h>
namespace {
MethodType kMethodType = "workspace/symbol";
// Lookup |symbol| in |db| and insert the value into |result|.
bool AddSymbol(
DB* db,
WorkingFiles* working_files,
SymbolIdx sym,
bool use_detailed,
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>>* result) {
DB *db, WorkingFiles *working_files, SymbolIdx sym, bool use_detailed,
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> *result) {
std::optional<lsSymbolInformation> info =
GetSymbolInfo(db, working_files, sym, true);
if (!info)
@ -63,7 +60,7 @@ MAKE_REFLECT_STRUCT(Out_WorkspaceSymbol, jsonrpc, id, result);
struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_WorkspaceSymbol* request) override {
void Run(In_WorkspaceSymbol *request) override {
Out_WorkspaceSymbol out;
out.id = request->id;
@ -83,40 +80,41 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
auto Add = [&](SymbolIdx sym) {
std::string_view detailed_name = db->GetSymbolName(sym, true);
int pos =
ReverseSubseqMatch(query_without_space, detailed_name, sensitive);
ReverseSubseqMatch(query_without_space, detailed_name, sensitive);
return pos >= 0 &&
AddSymbol(db, working_files, sym,
detailed_name.find(':', pos) != std::string::npos,
&cands) &&
cands.size() >= g_config->workspaceSymbol.maxNum;
};
for (auto& func : db->funcs)
for (auto &func : db->funcs)
if (Add({func.usr, SymbolKind::Func}))
goto done_add;
for (auto& type : db->types)
for (auto &type : db->types)
if (Add({type.usr, SymbolKind::Type}))
goto done_add;
for (auto& var : db->vars)
for (auto &var : db->vars)
if (var.def.size() && !var.def[0].is_local() &&
Add({var.usr, SymbolKind::Var}))
goto done_add;
done_add:
done_add:
if (g_config->workspaceSymbol.sort && query.size() <= FuzzyMatcher::kMaxPat) {
if (g_config->workspaceSymbol.sort &&
query.size() <= FuzzyMatcher::kMaxPat) {
// Sort results with a fuzzy matching algorithm.
int longest = 0;
for (auto& cand : cands)
for (auto &cand : cands)
longest = std::max(
longest, int(db->GetSymbolName(std::get<2>(cand), true).size()));
FuzzyMatcher fuzzy(query, g_config->workspaceSymbol.caseSensitivity);
for (auto& cand : cands)
for (auto &cand : cands)
std::get<1>(cand) = fuzzy.Match(
db->GetSymbolName(std::get<2>(cand), std::get<1>(cand)));
std::sort(cands.begin(), cands.end(), [](const auto& l, const auto& r) {
std::sort(cands.begin(), cands.end(), [](const auto &l, const auto &r) {
return std::get<1>(l) > std::get<1>(r);
});
out.result.reserve(cands.size());
for (auto& cand: cands) {
for (auto &cand : cands) {
// Discard awful candidates.
if (std::get<1>(cand) <= FuzzyMatcher::kMinScore)
break;
@ -124,7 +122,7 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
}
} else {
out.result.reserve(cands.size());
for (auto& cand : cands)
for (auto &cand : cands)
out.result.push_back(std::get<0>(cand));
}
@ -132,4 +130,4 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
}
};
REGISTER_MESSAGE_HANDLER(Handler_WorkspaceSymbol);
} // namespace
} // namespace

View File

@ -4,12 +4,11 @@ MethodType kMethodType_Unknown = "$unknown";
MethodType kMethodType_Exit = "exit";
MethodType kMethodType_TextDocumentPublishDiagnostics =
"textDocument/publishDiagnostics";
MethodType kMethodType_CclsPublishSkippedRanges =
"$ccls/publishSkippedRanges";
MethodType kMethodType_CclsPublishSkippedRanges = "$ccls/publishSkippedRanges";
MethodType kMethodType_CclsPublishSemanticHighlighting =
"$ccls/publishSemanticHighlighting";
void Reflect(Reader& visitor, lsRequestId& value) {
void Reflect(Reader &visitor, lsRequestId &value) {
if (visitor.IsInt64()) {
value.type = lsRequestId::kInt;
value.value = int(visitor.GetInt64());
@ -25,7 +24,7 @@ void Reflect(Reader& visitor, lsRequestId& value) {
}
}
void Reflect(Writer& visitor, lsRequestId& value) {
void Reflect(Writer &visitor, lsRequestId &value) {
switch (value.type) {
case lsRequestId::kNone:
visitor.Null();

View File

@ -5,7 +5,7 @@
#include <string>
using MethodType = const char*;
using MethodType = const char *;
extern MethodType kMethodType_Unknown;
extern MethodType kMethodType_Exit;
extern MethodType kMethodType_TextDocumentPublishDiagnostics;
@ -22,8 +22,8 @@ struct lsRequestId {
bool Valid() const { return type != kNone; }
};
void Reflect(Reader& visitor, lsRequestId& value);
void Reflect(Writer& visitor, lsRequestId& value);
void Reflect(Reader &visitor, lsRequestId &value);
void Reflect(Writer &visitor, lsRequestId &value);
struct InMessage {
virtual ~InMessage() = default;
@ -35,14 +35,10 @@ struct InMessage {
struct RequestInMessage : public InMessage {
// number or string, actually no null
lsRequestId id;
lsRequestId GetRequestId() const override {
return id;
}
lsRequestId GetRequestId() const override { return id; }
};
// NotificationInMessage does not have |id|.
struct NotificationInMessage : public InMessage {
lsRequestId GetRequestId() const override {
return lsRequestId();
}
lsRequestId GetRequestId() const override { return lsRequestId(); }
};

View File

@ -6,10 +6,10 @@
#include "log.hh"
#include "lsp.h"
#include "message_handler.h"
#include "pipeline.hh"
#include "platform.h"
#include "project.h"
#include "query_utils.h"
#include "pipeline.hh"
#include <llvm/ADT/Twine.h>
#include <llvm/Support/Threading.h>
@ -28,12 +28,12 @@ void DiagnosticsPublisher::Init() {
g_config->diagnostics.blacklist);
}
void DiagnosticsPublisher::Publish(WorkingFiles* working_files,
void DiagnosticsPublisher::Publish(WorkingFiles *working_files,
std::string path,
std::vector<lsDiagnostic> diagnostics) {
bool good = true;
// Cache diagnostics so we can show fixits.
working_files->DoActionOnFile(path, [&](WorkingFile* working_file) {
working_files->DoActionOnFile(path, [&](WorkingFile *working_file) {
if (working_file) {
good = working_file->diagnostics_.empty();
working_file->diagnostics_ = diagnostics;
@ -52,7 +52,8 @@ void DiagnosticsPublisher::Publish(WorkingFiles* working_files,
Out_TextDocumentPublishDiagnostics out;
out.params.uri = lsDocumentUri::FromPath(path);
out.params.diagnostics = diagnostics;
ccls::pipeline::WriteStdout(kMethodType_TextDocumentPublishDiagnostics, out);
ccls::pipeline::WriteStdout(kMethodType_TextDocumentPublishDiagnostics,
out);
}
}
@ -71,13 +72,13 @@ struct Stdout_Request {
std::string content;
};
MultiQueueWaiter* main_waiter;
MultiQueueWaiter* indexer_waiter;
MultiQueueWaiter* stdout_waiter;
ThreadedQueue<std::unique_ptr<InMessage>>* on_request;
ThreadedQueue<Index_Request>* index_request;
ThreadedQueue<IndexUpdate>* on_indexed;
ThreadedQueue<Stdout_Request>* for_stdout;
MultiQueueWaiter *main_waiter;
MultiQueueWaiter *indexer_waiter;
MultiQueueWaiter *stdout_waiter;
ThreadedQueue<std::unique_ptr<InMessage>> *on_request;
ThreadedQueue<Index_Request> *index_request;
ThreadedQueue<IndexUpdate> *on_indexed;
ThreadedQueue<Stdout_Request> *for_stdout;
bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path,
const std::vector<std::string> &args,
@ -92,23 +93,24 @@ bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path,
}
if (prev->args != args) {
LOG_S(INFO) << "args changed for " << path << (from ? " (via " + *from + ")" : std::string());
LOG_S(INFO) << "args changed for " << path
<< (from ? " (via " + *from + ")" : std::string());
return true;
}
return false;
};
std::string AppendSerializationFormat(const std::string& base) {
std::string AppendSerializationFormat(const std::string &base) {
switch (g_config->cacheFormat) {
case SerializeFormat::Binary:
return base + ".blob";
case SerializeFormat::Json:
return base + ".json";
case SerializeFormat::Binary:
return base + ".blob";
case SerializeFormat::Json:
return base + ".json";
}
}
std::string GetCachePath(const std::string& source_file) {
std::string GetCachePath(const std::string &source_file) {
std::string cache_file;
size_t len = g_config->projectRoot.size();
if (StartsWith(source_file, g_config->projectRoot)) {
@ -122,8 +124,7 @@ std::string GetCachePath(const std::string& source_file) {
return g_config->cacheDirectory + cache_file;
}
std::unique_ptr<IndexFile> RawCacheLoad(
const std::string& path) {
std::unique_ptr<IndexFile> RawCacheLoad(const std::string &path) {
std::string cache_path = GetCachePath(path);
std::optional<std::string> file_content = ReadContent(cache_path);
std::optional<std::string> serialized_indexed_content =
@ -136,14 +137,12 @@ std::unique_ptr<IndexFile> RawCacheLoad(
IndexFile::kMajorVersion);
}
bool Indexer_Parse(DiagnosticsPublisher* diag_pub,
WorkingFiles* working_files,
Project* project,
VFS* vfs) {
bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files,
Project *project, VFS *vfs) {
std::optional<Index_Request> opt_request = index_request->TryPopFront();
if (!opt_request)
return false;
auto& request = *opt_request;
auto &request = *opt_request;
// Dummy one to trigger refresh semantic highlight.
if (request.path.empty()) {
@ -183,7 +182,7 @@ bool Indexer_Parse(DiagnosticsPublisher* diag_pub,
reparse = 2;
int reparseForDep = g_config->index.reparseForDependency;
if (reparseForDep > 1 || (reparseForDep == 1 && !Project::loaded))
for (const auto& dep : prev->dependencies) {
for (const auto &dep : prev->dependencies) {
if (auto write_time1 = LastWriteTime(dep.first().str())) {
if (dep.second < *write_time1) {
reparse = 2;
@ -210,7 +209,7 @@ bool Indexer_Parse(DiagnosticsPublisher* diag_pub,
}
std::lock_guard<std::mutex> lock(vfs->mutex);
VFS::State& state = vfs->state[path_to_index];
VFS::State &state = vfs->state[path_to_index];
if (state.owner == g_thread_id)
state.stage = 0;
return true;
@ -218,7 +217,8 @@ bool Indexer_Parse(DiagnosticsPublisher* diag_pub,
LOG_S(INFO) << "parse " << path_to_index;
auto indexes = idx::Index(vfs, entry.directory, path_to_index, entry.args, {});
auto indexes =
idx::Index(vfs, entry.directory, path_to_index, entry.args, {});
if (indexes.empty()) {
if (g_config->index.enabled && request.id.Valid()) {
@ -232,7 +232,7 @@ bool Indexer_Parse(DiagnosticsPublisher* diag_pub,
return true;
}
for (std::unique_ptr<IndexFile>& curr : indexes) {
for (std::unique_ptr<IndexFile> &curr : indexes) {
// Only emit diagnostics for non-interactive sessions, which makes it easier
// to identify indexing problems. For interactive sessions, diagnostics are
// handled by code completion.
@ -260,7 +260,7 @@ bool Indexer_Parse(DiagnosticsPublisher* diag_pub,
vfs->Reset(path);
if (entry.id >= 0) {
std::lock_guard<std::mutex> lock(project->mutex_);
for (auto& dep : curr->dependencies)
for (auto &dep : curr->dependencies)
project->absolute_path_to_entry_index_[dep.first()] = entry.id;
}
@ -274,7 +274,7 @@ bool Indexer_Parse(DiagnosticsPublisher* diag_pub,
return true;
}
} // namespace
} // namespace
void Init() {
main_waiter = new MultiQueueWaiter;
@ -288,28 +288,25 @@ void Init() {
for_stdout = new ThreadedQueue<Stdout_Request>(stdout_waiter);
}
void Indexer_Main(DiagnosticsPublisher* diag_pub,
VFS* vfs,
Project* project,
WorkingFiles* working_files) {
void Indexer_Main(DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project,
WorkingFiles *working_files) {
while (true)
if (!Indexer_Parse(diag_pub, working_files, project, vfs))
indexer_waiter->Wait(index_request);
}
void Main_OnIndexed(DB* db,
SemanticHighlightSymbolCache* semantic_cache,
WorkingFiles* working_files,
IndexUpdate* update) {
void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache,
WorkingFiles *working_files, IndexUpdate *update) {
if (update->refresh) {
Project::loaded = true;
LOG_S(INFO) << "loaded project. Refresh semantic highlight for all working file.";
LOG_S(INFO)
<< "loaded project. Refresh semantic highlight for all working file.";
std::lock_guard<std::mutex> lock(working_files->files_mutex);
for (auto& f : working_files->files) {
for (auto &f : working_files->files) {
std::string filename = LowerPathIfInsensitive(f->filename);
if (db->name2file_id.find(filename) == db->name2file_id.end())
continue;
QueryFile* file = &db->files[db->name2file_id[filename]];
QueryFile *file = &db->files[db->name2file_id[filename]];
EmitSemanticHighlighting(db, semantic_cache, f.get(), file);
}
return;
@ -322,9 +319,9 @@ void Main_OnIndexed(DB* db,
// Update indexed content, skipped ranges, and semantic highlighting.
if (update->files_def_update) {
auto& def_u = *update->files_def_update;
auto &def_u = *update->files_def_update;
LOG_S(INFO) << "apply index for " << def_u.first.path;
if (WorkingFile* working_file =
if (WorkingFile *working_file =
working_files->GetFileByFilename(def_u.first.path)) {
working_file->SetIndexContent(def_u.second);
EmitSkippedRanges(working_file, def_u.first.skipped_ranges);
@ -369,7 +366,8 @@ void LaunchStdin() {
if (method_type == kMethodType_Exit)
break;
}
}).detach();
})
.detach();
}
void LaunchStdout() {
@ -383,7 +381,7 @@ void LaunchStdout() {
continue;
}
for (auto& message : messages) {
for (auto &message : messages) {
#ifdef _WIN32
fwrite(message.content.c_str(), message.content.size(), 1, stdout);
fflush(stdout);
@ -392,7 +390,8 @@ void LaunchStdout() {
#endif
}
}
}).detach();
})
.detach();
}
void MainLoop() {
@ -412,9 +411,8 @@ void MainLoop() {
Out_Error out;
out.id = id;
out.error.code = lsErrorCodes::InternalError;
out.error.message =
"Dropping completion request; a newer request "
"has come in that will be serviced instead.";
out.error.message = "Dropping completion request; a newer request "
"has come in that will be serviced instead.";
pipeline::WriteStdout(kMethodType_Unknown, out);
}
});
@ -426,7 +424,7 @@ void MainLoop() {
DB db;
// Setup shared references.
for (MessageHandler* handler : *MessageHandler::message_handlers) {
for (MessageHandler *handler : *MessageHandler::message_handlers) {
handler->db = &db;
handler->waiter = indexer_waiter;
handler->project = &project;
@ -445,9 +443,9 @@ void MainLoop() {
while (true) {
std::vector<std::unique_ptr<InMessage>> messages = on_request->DequeueAll();
bool did_work = messages.size();
for (auto& message : messages) {
for (auto &message : messages) {
// TODO: Consider using std::unordered_map to lookup the handler
for (MessageHandler* handler : *MessageHandler::message_handlers) {
for (MessageHandler *handler : *MessageHandler::message_handlers) {
if (handler->GetMethodType() == message->GetMethodType()) {
handler->Run(std::move(message));
break;
@ -473,18 +471,16 @@ void MainLoop() {
}
}
void Index(const std::string& path,
const std::vector<std::string>& args,
bool interactive,
lsRequestId id) {
void Index(const std::string &path, const std::vector<std::string> &args,
bool interactive, lsRequestId id) {
index_request->PushBack({path, args, interactive, id}, interactive);
}
std::optional<std::string> LoadCachedFileContents(const std::string& path) {
std::optional<std::string> LoadCachedFileContents(const std::string &path) {
return ReadContent(GetCachePath(path));
}
void WriteStdout(MethodType method, lsBaseOutMessage& response) {
void WriteStdout(MethodType method, lsBaseOutMessage &response) {
std::ostringstream sstream;
response.Write(sstream);
@ -494,4 +490,4 @@ void WriteStdout(MethodType method, lsBaseOutMessage& response) {
for_stdout->PushBack(std::move(out));
}
}
} // namespace ccls::pipeline

View File

@ -4,7 +4,7 @@
#include <string_view>
#include <vector>
std::string NormalizePath(const std::string& path);
std::string NormalizePath(const std::string &path);
// Free any unused memory and return it to the system.
void FreeUnusedMemory();
@ -12,5 +12,5 @@ void FreeUnusedMemory();
// Stop self and wait for SIGCONT.
void TraceMe();
std::string GetExternalCommandOutput(const std::vector<std::string>& command,
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
std::string_view input);

View File

@ -14,10 +14,10 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h> // required for stat.h
#include <sys/types.h> // required for stat.h
#include <sys/wait.h>
#include <unistd.h>
#ifdef __GLIBC__
#include <malloc.h>
#endif
@ -89,9 +89,9 @@ std::optional<std::string> RealPathNotExpandSymlink(std::string path) {
return resolved;
}
} // namespace
} // namespace
std::string NormalizePath(const std::string& path) {
std::string NormalizePath(const std::string &path) {
std::optional<std::string> resolved = RealPathNotExpandSymlink(path);
return resolved ? *resolved : path;
}
@ -106,12 +106,12 @@ void TraceMe() {
// If the environment variable is defined, wait for a debugger.
// In gdb, you need to invoke `signal SIGCONT` if you want ccls to continue
// after detaching.
const char* traceme = getenv("CCLS_TRACEME");
const char *traceme = getenv("CCLS_TRACEME");
if (traceme)
raise(traceme[0] == 's' ? SIGSTOP : SIGTSTP);
}
std::string GetExternalCommandOutput(const std::vector<std::string>& command,
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
std::string_view input) {
int pin[2], pout[2];
if (pipe(pin) < 0) {
@ -132,9 +132,9 @@ std::string GetExternalCommandOutput(const std::vector<std::string>& command,
close(pin[1]);
close(pout[0]);
close(pout[1]);
auto argv = new char*[command.size() + 1];
auto argv = new char *[command.size() + 1];
for (size_t i = 0; i < command.size(); i++)
argv[i] = const_cast<char*>(command[i].c_str());
argv[i] = const_cast<char *>(command[i].c_str());
argv[command.size()] = nullptr;
execvp(argv[0], argv);
_Exit(127);

View File

@ -15,10 +15,10 @@
#include <cassert>
#include <string>
std::string NormalizePath(const std::string& path) {
std::string NormalizePath(const std::string &path) {
DWORD retval = 0;
TCHAR buffer[MAX_PATH] = TEXT("");
TCHAR** lpp_part = {NULL};
TCHAR **lpp_part = {NULL};
retval = GetFullPathName(path.c_str(), MAX_PATH, buffer, lpp_part);
// fail, return original
@ -36,7 +36,7 @@ void FreeUnusedMemory() {}
// TODO Wait for debugger to attach
void TraceMe() {}
std::string GetExternalCommandOutput(const std::vector<std::string>& command,
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
std::string_view input) {
return "";
}

View File

@ -6,8 +6,8 @@
#include <stdio.h>
#include <stdlib.h>
Position Position::FromString(const std::string& encoded) {
char* p = const_cast<char*>(encoded.c_str());
Position Position::FromString(const std::string &encoded) {
char *p = const_cast<char *>(encoded.c_str());
int16_t line = int16_t(strtol(p, &p, 10)) - 1;
assert(*p == ':');
p++;
@ -21,9 +21,9 @@ std::string Position::ToString() {
return buf;
}
Range Range::FromString(const std::string& encoded) {
Range Range::FromString(const std::string &encoded) {
Position start, end;
char* p = const_cast<char*>(encoded.c_str());
char *p = const_cast<char *>(encoded.c_str());
start.line = int16_t(strtol(p, &p, 10)) - 1;
assert(*p == ':');
p++;
@ -57,7 +57,7 @@ std::string Range::ToString() {
}
// Position
void Reflect(Reader& visitor, Position& value) {
void Reflect(Reader &visitor, Position &value) {
if (visitor.Format() == SerializeFormat::Json) {
value = Position::FromString(visitor.GetString());
} else {
@ -65,7 +65,7 @@ void Reflect(Reader& visitor, Position& value) {
Reflect(visitor, value.column);
}
}
void Reflect(Writer& visitor, Position& value) {
void Reflect(Writer &visitor, Position &value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string output = value.ToString();
visitor.String(output.c_str(), output.size());
@ -76,7 +76,7 @@ void Reflect(Writer& visitor, Position& value) {
}
// Range
void Reflect(Reader& visitor, Range& value) {
void Reflect(Reader &visitor, Range &value) {
if (visitor.Format() == SerializeFormat::Json) {
value = Range::FromString(visitor.GetString());
} else {
@ -86,7 +86,7 @@ void Reflect(Reader& visitor, Range& value) {
Reflect(visitor, value.end.column);
}
}
void Reflect(Writer& visitor, Range& value) {
void Reflect(Writer &visitor, Range &value) {
if (visitor.Format() == SerializeFormat::Json) {
std::string output = value.ToString();
visitor.String(output.c_str(), output.size());

View File

@ -10,17 +10,17 @@ struct Position {
int16_t line = -1;
int16_t column = -1;
static Position FromString(const std::string& encoded);
static Position FromString(const std::string &encoded);
bool Valid() const { return line >= 0; }
std::string ToString();
// Compare two Positions and check if they are equal. Ignores the value of
// |interesting|.
bool operator==(const Position& o) const {
bool operator==(const Position &o) const {
return line == o.line && column == o.column;
}
bool operator<(const Position& o) const {
bool operator<(const Position &o) const {
if (line != o.line)
return line < o.line;
return column < o.column;
@ -32,7 +32,7 @@ struct Range {
Position start;
Position end;
static Range FromString(const std::string& encoded);
static Range FromString(const std::string &encoded);
bool Valid() const { return start.Valid(); }
bool Contains(int line, int column) const;
@ -40,17 +40,16 @@ struct Range {
std::string ToString();
bool operator==(const Range& o) const {
bool operator==(const Range &o) const {
return start == o.start && end == o.end;
}
bool operator<(const Range& o) const {
bool operator<(const Range &o) const {
return !(start == o.start) ? start < o.start : end < o.end;
}
};
namespace std {
template <>
struct hash<Range> {
template <> struct hash<Range> {
std::size_t operator()(Range x) const {
union U {
Range range = {};
@ -61,12 +60,12 @@ struct hash<Range> {
return hash<uint64_t>()(u.u64);
}
};
}
} // namespace std
// Reflection
class Reader;
class Writer;
void Reflect(Reader& visitor, Position& value);
void Reflect(Writer& visitor, Position& value);
void Reflect(Reader& visitor, Range& value);
void Reflect(Writer& visitor, Range& value);
void Reflect(Reader &visitor, Position &value);
void Reflect(Writer &visitor, Position &value);
void Reflect(Reader &visitor, Range &value);
void Reflect(Writer &visitor, Range &value);

View File

@ -5,8 +5,8 @@
#include "language.h"
#include "log.hh"
#include "match.h"
#include "platform.h"
#include "pipeline.hh"
#include "platform.h"
#include "serializers/json.h"
#include "utils.h"
#include "working_files.h"
@ -67,9 +67,9 @@ enum OptionClass {
Separate,
};
Project::Entry GetCompilationEntryFromCompileCommandEntry(
ProjectConfig* config,
const CompileCommandsEntry& entry) {
Project::Entry
GetCompilationEntryFromCompileCommandEntry(ProjectConfig *config,
const CompileCommandsEntry &entry) {
Project::Entry result;
result.filename = entry.file;
const std::string base_name = sys::path::filename(entry.file);
@ -77,7 +77,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
// Expand %c %cpp %clang
std::vector<std::string> args;
const LanguageId lang = SourceFileLanguage(entry.file);
for (const std::string& arg : entry.args) {
for (const std::string &arg : entry.args) {
if (arg.compare(0, 3, "%c ") == 0) {
if (lang == LanguageId::C)
args.push_back(arg.substr(3));
@ -106,21 +106,21 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
auto TargetAndMode =
driver::ToolChain::getTargetAndModeFromProgramName(args[0]);
if (!TargetAndMode.TargetPrefix.empty()) {
const char* arr[] = {"-target", TargetAndMode.TargetPrefix.c_str()};
const char *arr[] = {"-target", TargetAndMode.TargetPrefix.c_str()};
args.insert(args.begin() + 1, std::begin(arr), std::end(arr));
Driver.setTargetAndMode(TargetAndMode);
}
Driver.setCheckInputsExist(false);
std::vector<const char*> cargs;
for (auto& arg : args)
std::vector<const char *> cargs;
for (auto &arg : args)
cargs.push_back(arg.c_str());
cargs.push_back("-fsyntax-only");
std::unique_ptr<driver::Compilation> C(Driver.BuildCompilation(cargs));
const driver::JobList& Jobs = C->getJobs();
const driver::JobList &Jobs = C->getJobs();
if (Jobs.size() != 1)
return result;
const driver::ArgStringList& CCArgs = Jobs.begin()->getArguments();
const driver::ArgStringList &CCArgs = Jobs.begin()->getArguments();
auto CI = std::make_unique<CompilerInvocation>();
CompilerInvocation::CreateFromArgs(*CI, CCArgs.data(),
@ -132,16 +132,16 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
for (auto &E : HeaderOpts.UserEntries) {
std::string path = entry.ResolveIfRelative(E.Path);
switch (E.Group) {
default:
config->angle_dirs.insert(path);
break;
case frontend::Quoted:
config->quote_dirs.insert(path);
break;
case frontend::Angled:
config->angle_dirs.insert(path);
config->quote_dirs.insert(path);
break;
default:
config->angle_dirs.insert(path);
break;
case frontend::Quoted:
config->quote_dirs.insert(path);
break;
case frontend::Angled:
config->angle_dirs.insert(path);
config->quote_dirs.insert(path);
break;
}
}
@ -155,7 +155,8 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
continue;
}
// if (!sys::fs::exists(HeaderOpts.ResourceDir) && HeaderOpts.UseBuiltinIncludes)
// if (!sys::fs::exists(HeaderOpts.ResourceDir) &&
// HeaderOpts.UseBuiltinIncludes)
args.push_back("-resource-dir=" + g_config->clang.resourceDir);
if (CI->getFileSystemOpts().WorkingDir.empty())
args.push_back("-working-directory=" + entry.directory);
@ -169,17 +170,18 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
return result;
}
std::vector<std::string> ReadCompilerArgumentsFromFile(
const std::string& path) {
std::vector<std::string>
ReadCompilerArgumentsFromFile(const std::string &path) {
auto MBOrErr = MemoryBuffer::getFile(path);
if (!MBOrErr) return {};
if (!MBOrErr)
return {};
std::vector<std::string> args;
for (line_iterator I(*MBOrErr.get(), true, '#'), E; I != E; ++I)
args.push_back(*I);
return args;
}
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig *config) {
std::vector<Project::Entry> result;
config->mode = ProjectMode::DotCcls;
SmallString<256> Path;
@ -194,7 +196,7 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
GetFilesInFolder(config->project_dir, true /*recursive*/,
true /*add_folder_to_path*/,
[&folder_args, &files](const std::string& path) {
[&folder_args, &files](const std::string &path) {
if (SourceFileLanguage(path) != LanguageId::Unknown) {
files.push_back(path);
} else if (sys::path::filename(path) == ".ccls") {
@ -204,12 +206,13 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
}
});
const std::string& project_dir = config->project_dir;
const auto& project_dir_args = folder_args[project_dir];
const std::string &project_dir = config->project_dir;
const auto &project_dir_args = folder_args[project_dir];
LOG_IF_S(INFO, !project_dir_args.empty())
<< "Using .ccls arguments " << StringJoin(project_dir_args);
auto GetCompilerArgumentForFile = [&project_dir, &folder_args](std::string cur) {
auto GetCompilerArgumentForFile = [&project_dir,
&folder_args](std::string cur) {
while (!(cur = sys::path::parent_path(cur)).empty()) {
auto it = folder_args.find(cur);
if (it != folder_args.end())
@ -223,13 +226,13 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
return folder_args[project_dir];
};
for (const std::string& file : files) {
for (const std::string &file : files) {
CompileCommandsEntry e;
e.directory = config->project_dir;
e.file = file;
e.args = GetCompilerArgumentForFile(file);
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);
result.push_back(GetCompilationEntryFromCompileCommandEntry(config, e));
}
@ -237,9 +240,9 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
return result;
}
std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
ProjectConfig* project,
const std::string& opt_compilation_db_dir) {
std::vector<Project::Entry>
LoadCompilationEntriesFromDirectory(ProjectConfig *project,
const std::string &opt_compilation_db_dir) {
// If there is a .ccls file always load using directory listing.
SmallString<256> Path;
sys::path::append(Path, project->project_dir, ".ccls");
@ -273,7 +276,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
std::vector<std::string>{g_config->compilationDatabaseCommand,
project->project_dir},
input.GetString());
FILE* fout = fopen(Path.c_str(), "wb");
FILE *fout = fopen(Path.c_str(), "wb");
fwrite(contents.c_str(), contents.size(), 1, fout);
fclose(fout);
#endif
@ -284,7 +287,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
tooling::CompilationDatabase::loadFromDirectory(comp_db_dir, err_msg);
if (!g_config->compilationDatabaseCommand.empty()) {
#ifdef _WIN32
// TODO
// TODO
#else
unlink(Path.c_str());
rmdir(comp_db_dir.c_str());
@ -326,11 +329,11 @@ int ComputeGuessScore(std::string_view a, std::string_view b) {
return score;
}
} // namespace
} // namespace
bool Project::loaded = false;
void Project::Load(const std::string& root_directory) {
void Project::Load(const std::string &root_directory) {
Project::loaded = false;
// Load data.
ProjectConfig project;
@ -344,11 +347,11 @@ void Project::Load(const std::string& root_directory) {
project.quote_dirs.end());
angle_include_directories.assign(project.angle_dirs.begin(),
project.angle_dirs.end());
for (std::string& path : quote_include_directories) {
for (std::string &path : quote_include_directories) {
EnsureEndsInSlash(path);
LOG_S(INFO) << "quote_include_dir: " << path;
}
for (std::string& path : angle_include_directories) {
for (std::string &path : angle_include_directories) {
EnsureEndsInSlash(path);
LOG_S(INFO) << "angle_include_dir: " << path;
}
@ -362,9 +365,8 @@ void Project::Load(const std::string& root_directory) {
}
}
void Project::SetFlagsForFile(
const std::vector<std::string>& flags,
const std::string& path) {
void Project::SetFlagsForFile(const std::vector<std::string> &flags,
const std::string &path) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = absolute_path_to_entry_index_.find(path);
if (it != absolute_path_to_entry_index_.end()) {
@ -380,8 +382,8 @@ void Project::SetFlagsForFile(
}
}
Project::Entry Project::FindCompilationEntryForFile(
const std::string& filename) {
Project::Entry
Project::FindCompilationEntryForFile(const std::string &filename) {
{
std::lock_guard<std::mutex> lock(mutex_);
auto it = absolute_path_to_entry_index_.find(filename);
@ -391,9 +393,9 @@ Project::Entry Project::FindCompilationEntryForFile(
// We couldn't find the file. Try to infer it.
// TODO: Cache inferred file in a separate array (using a lock or similar)
Entry* best_entry = nullptr;
Entry *best_entry = nullptr;
int best_score = std::numeric_limits<int>::min();
for (Entry& entry : entries) {
for (Entry &entry : entries) {
int score = ComputeGuessScore(filename, entry.filename);
if (score > best_score) {
best_score = score;
@ -412,8 +414,9 @@ Project::Entry Project::FindCompilationEntryForFile(
// |best_entry| probably has its own path in the arguments. We need to remap
// that path to the new filename.
std::string best_entry_base_name = sys::path::filename(best_entry->filename);
for (std::string& arg : result.args) {
std::string best_entry_base_name =
sys::path::filename(best_entry->filename);
for (std::string &arg : result.args) {
try {
if (arg == best_entry->filename ||
sys::path::filename(arg) == best_entry_base_name)
@ -427,10 +430,10 @@ Project::Entry Project::FindCompilationEntryForFile(
}
void Project::ForAllFilteredFiles(
std::function<void(int i, const Entry& entry)> action) {
std::function<void(int i, const Entry &entry)> action) {
GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist);
for (int i = 0; i < entries.size(); ++i) {
const Project::Entry& entry = entries[i];
const Project::Entry &entry = entries[i];
std::string failure_reason;
if (matcher.IsMatch(entry.filename, &failure_reason))
action(i, entries[i]);
@ -441,9 +444,8 @@ void Project::ForAllFilteredFiles(
}
}
void Project::Index(WorkingFiles* wfiles,
lsRequestId id) {
ForAllFilteredFiles([&](int i, const Project::Entry& entry) {
void Project::Index(WorkingFiles *wfiles, lsRequestId id) {
ForAllFilteredFiles([&](int i, const Project::Entry &entry) {
bool is_interactive = wfiles->GetFileByFilename(entry.filename) != nullptr;
pipeline::Index(entry.filename, entry.args, is_interactive, id);
});

View File

@ -40,24 +40,23 @@ struct Project {
// will affect flags in their subtrees (relative paths are relative to the
// project root, not subdirectories). For compile_commands.json, its entries
// are indexed.
void Load(const std::string& root_directory);
void Load(const std::string &root_directory);
// Lookup the CompilationEntry for |filename|. If no entry was found this
// will infer one based on existing project structure.
Entry FindCompilationEntryForFile(const std::string& filename);
Entry FindCompilationEntryForFile(const std::string &filename);
// If the client has overridden the flags, or specified them for a file
// that is not in the compilation_database.json make sure those changes
// are permanent.
void SetFlagsForFile(
const std::vector<std::string>& flags,
const std::string& path);
void SetFlagsForFile(const std::vector<std::string> &flags,
const std::string &path);
// Run |action| on every file in the project.
void ForAllFilteredFiles(
std::function<void(int i, const Entry& entry)> action);
void
ForAllFilteredFiles(std::function<void(int i, const Entry &entry)> action);
void Index(WorkingFiles* wfiles, lsRequestId id);
void Index(WorkingFiles *wfiles, lsRequestId id);
static bool loaded;
};

View File

@ -19,7 +19,7 @@ void AssignFileId(const Lid2file_id &, int file_id, SymbolRef &ref) {
ref.usr = file_id;
}
void AssignFileId(const Lid2file_id& lid2file_id, int file_id, Use& use) {
void AssignFileId(const Lid2file_id &lid2file_id, int file_id, Use &use) {
if (use.kind == SymbolKind::File)
use.usr = file_id;
if (use.file_id == -1)
@ -44,35 +44,35 @@ void AssignFileId(const Lid2file_id &lid2file_id, int file_id,
AssignFileId(lid2file_id, file_id, x);
}
void AddRange(std::vector<Use>& into, const std::vector<Use>& from) {
void AddRange(std::vector<Use> &into, const std::vector<Use> &from) {
into.reserve(into.size() + from.size());
for (Use use : from)
into.push_back(use);
}
void AddRange(std::vector<Usr>& into, const std::vector<Usr>& from) {
void AddRange(std::vector<Usr> &into, const std::vector<Usr> &from) {
into.insert(into.end(), from.begin(), from.end());
}
template <typename T>
void RemoveRange(std::vector<T>& from, const std::vector<T>& to_remove) {
void RemoveRange(std::vector<T> &from, const std::vector<T> &to_remove) {
if (to_remove.size()) {
std::unordered_set<T> to_remove_set(to_remove.begin(), to_remove.end());
from.erase(
std::remove_if(from.begin(), from.end(),
[&](const T& t) { return to_remove_set.count(t) > 0; }),
from.end());
std::remove_if(from.begin(), from.end(),
[&](const T &t) { return to_remove_set.count(t) > 0; }),
from.end());
}
}
QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile &indexed) {
QueryFile::Def def;
def.path = std::move(indexed.path);
def.args = std::move(indexed.args);
def.includes = std::move(indexed.includes);
def.skipped_ranges = std::move(indexed.skipped_ranges);
def.dependencies.reserve(indexed.dependencies.size());
for (auto& dep : indexed.dependencies)
for (auto &dep : indexed.dependencies)
def.dependencies.push_back(dep.first());
def.language = indexed.language;
@ -83,8 +83,8 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
def.outline.push_back(SymbolRef{{use.range, usr, kind, use.role}});
};
for (auto& it : indexed.usr2type) {
const IndexType& type = it.second;
for (auto &it : indexed.usr2type) {
const IndexType &type = it.second;
if (type.def.spell)
add_all_symbols(*type.def.spell, type.usr, SymbolKind::Type);
if (type.def.extent)
@ -100,8 +100,8 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
if (use.file_id == -1)
add_all_symbols(use, type.usr, SymbolKind::Type);
}
for (auto& it: indexed.usr2func) {
const IndexFunc& func = it.second;
for (auto &it : indexed.usr2func) {
const IndexFunc &func = it.second;
if (func.def.spell)
add_all_symbols(*func.def.spell, func.usr, SymbolKind::Func);
if (func.def.extent)
@ -124,8 +124,8 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
add_all_symbols(use, func.usr, SymbolKind::Func);
}
}
for (auto& it : indexed.usr2var) {
const IndexVar& var = it.second;
for (auto &it : indexed.usr2var) {
const IndexVar &var = it.second;
if (var.def.spell)
add_all_symbols(*var.def.spell, var.usr, SymbolKind::Var);
if (var.def.extent)
@ -140,11 +140,11 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
}
std::sort(def.outline.begin(), def.outline.end(),
[](const SymbolRef& a, const SymbolRef& b) {
[](const SymbolRef &a, const SymbolRef &b) {
return a.range.start < b.range.start;
});
std::sort(def.all_symbols.begin(), def.all_symbols.end(),
[](const SymbolRef& a, const SymbolRef& b) {
[](const SymbolRef &a, const SymbolRef &b) {
return a.range.start < b.range.start;
});
@ -153,8 +153,8 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
// Returns true if an element with the same file is found.
template <typename Q>
bool TryReplaceDef(llvm::SmallVectorImpl<Q>& def_list, Q&& def) {
for (auto& def1 : def_list)
bool TryReplaceDef(llvm::SmallVectorImpl<Q> &def_list, Q &&def) {
for (auto &def1 : def_list)
if (def1.file_id == def.file_id) {
def1 = std::move(def);
return true;
@ -162,10 +162,9 @@ bool TryReplaceDef(llvm::SmallVectorImpl<Q>& def_list, Q&& def) {
return false;
}
} // namespace
} // namespace
IndexUpdate IndexUpdate::CreateDelta(IndexFile* previous,
IndexFile* current) {
IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
IndexUpdate r;
static IndexFile empty(llvm::sys::fs::UniqueID(0, 0), current->path,
"<empty>");
@ -177,16 +176,16 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile* previous,
r.files_def_update = BuildFileDefUpdate(std::move(*current));
r.funcs_hint = int(current->usr2func.size() - previous->usr2func.size());
for (auto& it : previous->usr2func) {
auto& func = it.second;
for (auto &it : previous->usr2func) {
auto &func = it.second;
if (func.def.detailed_name[0])
r.funcs_removed.push_back(func.usr);
r.funcs_declarations[func.usr].first = std::move(func.declarations);
r.funcs_uses[func.usr].first = std::move(func.uses);
r.funcs_derived[func.usr].first = std::move(func.derived);
}
for (auto& it : current->usr2func) {
auto& func = it.second;
for (auto &it : current->usr2func) {
auto &func = it.second;
if (func.def.detailed_name[0])
r.funcs_def_update.emplace_back(it.first, func.def);
r.funcs_declarations[func.usr].second = std::move(func.declarations);
@ -195,8 +194,8 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile* previous,
}
r.types_hint = int(current->usr2type.size() - previous->usr2type.size());
for (auto& it : previous->usr2type) {
auto& type = it.second;
for (auto &it : previous->usr2type) {
auto &type = it.second;
if (type.def.detailed_name[0])
r.types_removed.push_back(type.usr);
r.types_declarations[type.usr].first = std::move(type.declarations);
@ -204,8 +203,8 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile* previous,
r.types_derived[type.usr].first = std::move(type.derived);
r.types_instances[type.usr].first = std::move(type.instances);
};
for (auto& it : current->usr2type) {
auto& type = it.second;
for (auto &it : current->usr2type) {
auto &type = it.second;
if (type.def.detailed_name[0])
r.types_def_update.emplace_back(it.first, type.def);
r.types_declarations[type.usr].second = std::move(type.declarations);
@ -215,15 +214,15 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile* previous,
};
r.vars_hint = int(current->usr2var.size() - previous->usr2var.size());
for (auto& it : previous->usr2var) {
auto& var = it.second;
for (auto &it : previous->usr2var) {
auto &var = it.second;
if (var.def.detailed_name[0])
r.vars_removed.push_back(var.usr);
r.vars_declarations[var.usr].first = std::move(var.declarations);
r.vars_uses[var.usr].first = std::move(var.uses);
}
for (auto& it : current->usr2var) {
auto& var = it.second;
for (auto &it : current->usr2var) {
auto &var = it.second;
if (var.def.detailed_name[0])
r.vars_def_update.emplace_back(it.first, var.def);
r.vars_declarations[var.usr].second = std::move(var.declarations);
@ -233,51 +232,53 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile* previous,
return r;
}
void DB::RemoveUsrs(SymbolKind kind,
int file_id,
const std::vector<Usr>& to_remove) {
void DB::RemoveUsrs(SymbolKind kind, int file_id,
const std::vector<Usr> &to_remove) {
switch (kind) {
case SymbolKind::Func: {
for (Usr usr : to_remove) {
// FIXME
if (!HasFunc(usr)) continue;
QueryFunc& func = Func(usr);
auto it = llvm::find_if(func.def, [=](const QueryFunc::Def& def) {
return def.file_id == file_id;
});
if (it != func.def.end())
func.def.erase(it);
}
break;
case SymbolKind::Func: {
for (Usr usr : to_remove) {
// FIXME
if (!HasFunc(usr))
continue;
QueryFunc &func = Func(usr);
auto it = llvm::find_if(func.def, [=](const QueryFunc::Def &def) {
return def.file_id == file_id;
});
if (it != func.def.end())
func.def.erase(it);
}
case SymbolKind::Type: {
for (Usr usr : to_remove) {
// FIXME
if (!HasType(usr)) continue;
QueryType& type = Type(usr);
auto it = llvm::find_if(type.def, [=](const QueryType::Def& def) {
return def.file_id == file_id;
});
if (it != type.def.end())
type.def.erase(it);
}
break;
break;
}
case SymbolKind::Type: {
for (Usr usr : to_remove) {
// FIXME
if (!HasType(usr))
continue;
QueryType &type = Type(usr);
auto it = llvm::find_if(type.def, [=](const QueryType::Def &def) {
return def.file_id == file_id;
});
if (it != type.def.end())
type.def.erase(it);
}
case SymbolKind::Var: {
for (Usr usr : to_remove) {
// FIXME
if (!HasVar(usr)) continue;
QueryVar& var = Var(usr);
auto it = llvm::find_if(var.def, [=](const QueryVar::Def& def) {
return def.file_id == file_id;
});
if (it != var.def.end())
var.def.erase(it);
}
break;
break;
}
case SymbolKind::Var: {
for (Usr usr : to_remove) {
// FIXME
if (!HasVar(usr))
continue;
QueryVar &var = Var(usr);
auto it = llvm::find_if(var.def, [=](const QueryVar::Def &def) {
return def.file_id == file_id;
});
if (it != var.def.end())
var.def.erase(it);
}
default:
break;
break;
}
default:
break;
}
}
@ -295,9 +296,9 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
}
std::unordered_map<int, int> prev_lid2file_id, lid2file_id;
for (auto & [ lid, path ] : u->prev_lid2path)
for (auto &[lid, path] : u->prev_lid2path)
prev_lid2file_id[lid] = GetFileId(path);
for (auto & [ lid, path ] : u->lid2path)
for (auto &[lid, path] : u->lid2path)
lid2file_id[lid] = GetFileId(path);
auto UpdateUses = [&](Usr usr, SymbolKind kind,
@ -347,7 +348,7 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
Update(lid2file_id, u->file_id, std::move(u->funcs_def_update));
REMOVE_ADD(func, declarations);
REMOVE_ADD(func, derived);
for (auto & [ usr, p ] : u->funcs_uses)
for (auto &[usr, p] : u->funcs_uses)
UpdateUses(usr, SymbolKind::Func, func_usr, funcs, p);
if ((t = types.size() + u->types_hint) > types.capacity()) {
@ -360,7 +361,7 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
REMOVE_ADD(type, declarations);
REMOVE_ADD(type, derived);
REMOVE_ADD(type, instances);
for (auto & [ usr, p ] : u->types_uses)
for (auto &[usr, p] : u->types_uses)
UpdateUses(usr, SymbolKind::Type, type_usr, types, p);
if ((t = vars.size() + u->vars_hint) > vars.capacity()) {
@ -371,13 +372,13 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
RemoveUsrs(SymbolKind::Var, u->file_id, u->vars_removed);
Update(lid2file_id, u->file_id, std::move(u->vars_def_update));
REMOVE_ADD(var, declarations);
for (auto & [ usr, p ] : u->vars_uses)
for (auto &[usr, p] : u->vars_uses)
UpdateUses(usr, SymbolKind::Var, var_usr, vars, p);
#undef REMOVE_ADD
}
int DB::GetFileId(const std::string& path) {
int DB::GetFileId(const std::string &path) {
auto it = name2file_id.try_emplace(LowerPathIfInsensitive(path));
if (it.second) {
int id = files.size();
@ -386,7 +387,7 @@ int DB::GetFileId(const std::string& path) {
return it.first->second;
}
int DB::Update(QueryFile::DefUpdate&& u) {
int DB::Update(QueryFile::DefUpdate &&u) {
int file_id = GetFileId(u.first.path);
files[file_id].def = u.first;
return file_id;
@ -395,7 +396,7 @@ int DB::Update(QueryFile::DefUpdate&& u) {
void DB::Update(const Lid2file_id &lid2file_id, int file_id,
std::vector<std::pair<Usr, QueryFunc::Def>> &&us) {
for (auto &u : us) {
auto& def = u.second;
auto &def = u.second;
assert(def.detailed_name[0]);
u.second.file_id = file_id;
AssignFileId(lid2file_id, file_id, def.spell);
@ -404,7 +405,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
auto R = func_usr.try_emplace({u.first}, func_usr.size());
if (R.second)
funcs.emplace_back();
QueryFunc& existing = funcs[R.first->second];
QueryFunc &existing = funcs[R.first->second];
existing.usr = u.first;
if (!TryReplaceDef(existing.def, std::move(def)))
existing.def.push_back(std::move(def));
@ -414,7 +415,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
void DB::Update(const Lid2file_id &lid2file_id, int file_id,
std::vector<std::pair<Usr, QueryType::Def>> &&us) {
for (auto &u : us) {
auto& def = u.second;
auto &def = u.second;
assert(def.detailed_name[0]);
u.second.file_id = file_id;
AssignFileId(lid2file_id, file_id, def.spell);
@ -422,7 +423,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
auto R = type_usr.try_emplace({u.first}, type_usr.size());
if (R.second)
types.emplace_back();
QueryType& existing = types[R.first->second];
QueryType &existing = types[R.first->second];
existing.usr = u.first;
if (!TryReplaceDef(existing.def, std::move(def)))
existing.def.push_back(std::move(def));
@ -432,7 +433,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
void DB::Update(const Lid2file_id &lid2file_id, int file_id,
std::vector<std::pair<Usr, QueryVar::Def>> &&us) {
for (auto &u : us) {
auto& def = u.second;
auto &def = u.second;
assert(def.detailed_name[0]);
u.second.file_id = file_id;
AssignFileId(lid2file_id, file_id, def.spell);
@ -440,7 +441,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
auto R = var_usr.try_emplace({u.first}, var_usr.size());
if (R.second)
vars.emplace_back();
QueryVar& existing = vars[R.first->second];
QueryVar &existing = vars[R.first->second];
existing.usr = u.first;
if (!TryReplaceDef(existing.def, std::move(def)))
existing.def.push_back(std::move(def));
@ -450,24 +451,24 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
std::string_view DB::GetSymbolName(SymbolIdx sym, bool qualified) {
Usr usr = sym.usr;
switch (sym.kind) {
default:
break;
case SymbolKind::File:
if (files[usr].def)
return files[usr].def->path;
break;
case SymbolKind::Func:
if (const auto* def = Func(usr).AnyDef())
return def->Name(qualified);
break;
case SymbolKind::Type:
if (const auto* def = Type(usr).AnyDef())
return def->Name(qualified);
break;
case SymbolKind::Var:
if (const auto* def = Var(usr).AnyDef())
return def->Name(qualified);
break;
default:
break;
case SymbolKind::File:
if (files[usr].def)
return files[usr].def->path;
break;
case SymbolKind::Func:
if (const auto *def = Func(usr).AnyDef())
return def->Name(qualified);
break;
case SymbolKind::Type:
if (const auto *def = Type(usr).AnyDef())
return def->Name(qualified);
break;
case SymbolKind::Var:
if (const auto *def = Var(usr).AnyDef())
return def->Name(qualified);
break;
}
return "";
}

View File

@ -31,19 +31,20 @@ struct QueryFile {
std::unordered_map<SymbolRef, int> symbol2refcnt;
};
template <typename Q, typename QDef>
struct QueryEntity {
template <typename Q, typename QDef> struct QueryEntity {
using Def = QDef;
Def* AnyDef() {
Def* ret = nullptr;
for (auto& i : static_cast<Q*>(this)->def) {
Def *AnyDef() {
Def *ret = nullptr;
for (auto &i : static_cast<Q *>(this)->def) {
ret = &i;
if (i.spell)
break;
}
return ret;
}
const Def* AnyDef() const { return const_cast<QueryEntity*>(this)->AnyDef(); }
const Def *AnyDef() const {
return const_cast<QueryEntity *>(this)->AnyDef();
}
};
using UseUpdate =
@ -78,8 +79,7 @@ struct QueryVar : QueryEntity<QueryVar, VarDef> {
struct IndexUpdate {
// Creates a new IndexUpdate based on the delta from previous to current. If
// no delta computation should be done just pass null for previous.
static IndexUpdate CreateDelta(IndexFile* previous,
IndexFile* current);
static IndexUpdate CreateDelta(IndexFile *previous, IndexFile *current);
int file_id;
@ -121,8 +121,7 @@ struct IndexUpdate {
struct WrappedUsr {
Usr usr;
};
template <>
struct llvm::DenseMapInfo<WrappedUsr> {
template <> struct llvm::DenseMapInfo<WrappedUsr> {
static inline WrappedUsr getEmptyKey() { return {0}; }
static inline WrappedUsr getTombstoneKey() { return {~0ULL}; }
static unsigned getHashValue(WrappedUsr w) { return w.usr; }
@ -141,11 +140,12 @@ struct DB {
std::vector<QueryType> types;
std::vector<QueryVar> vars;
void RemoveUsrs(SymbolKind kind, int file_id, const std::vector<Usr>& to_remove);
void RemoveUsrs(SymbolKind kind, int file_id,
const std::vector<Usr> &to_remove);
// Insert the contents of |update| into |db|.
void ApplyIndexUpdate(IndexUpdate* update);
int GetFileId(const std::string& path);
int Update(QueryFile::DefUpdate&& u);
void ApplyIndexUpdate(IndexUpdate *update);
int GetFileId(const std::string &path);
int Update(QueryFile::DefUpdate &&u);
void Update(const Lid2file_id &, int file_id,
std::vector<std::pair<Usr, QueryType::Def>> &&us);
void Update(const Lid2file_id &, int file_id,
@ -158,12 +158,12 @@ struct DB {
bool HasType(Usr usr) const { return type_usr.count({usr}); }
bool HasVar(Usr usr) const { return var_usr.count({usr}); }
QueryFunc& Func(Usr usr) { return funcs[func_usr[{usr}]]; }
QueryType& Type(Usr usr) { return types[type_usr[{usr}]]; }
QueryVar& Var(Usr usr) { return vars[var_usr[{usr}]]; }
QueryFunc &Func(Usr usr) { return funcs[func_usr[{usr}]]; }
QueryType &Type(Usr usr) { return types[type_usr[{usr}]]; }
QueryVar &Var(Usr usr) { return vars[var_usr[{usr}]]; }
QueryFile& GetFile(SymbolIdx ref) { return files[ref.usr]; }
QueryFunc& GetFunc(SymbolIdx ref) { return Func(ref.usr); }
QueryType& GetType(SymbolIdx ref) { return Type(ref.usr); }
QueryVar& GetVar(SymbolIdx ref) { return Var(ref.usr); }
QueryFile &GetFile(SymbolIdx ref) { return files[ref.usr]; }
QueryFunc &GetFunc(SymbolIdx ref) { return Func(ref.usr); }
QueryType &GetType(SymbolIdx ref) { return Type(ref.usr); }
QueryVar &GetVar(SymbolIdx ref) { return Var(ref.usr); }
};

View File

@ -8,22 +8,22 @@
namespace {
// Computes roughly how long |range| is.
int ComputeRangeSize(const Range& range) {
int ComputeRangeSize(const Range &range) {
if (range.start.line != range.end.line)
return INT_MAX;
return range.end.column - range.start.column;
}
template <typename Q>
std::vector<Use> GetDeclarations(llvm::DenseMap<WrappedUsr, int>& entity_usr,
std::vector<Q>& entities,
const std::vector<Usr>& usrs) {
std::vector<Use> GetDeclarations(llvm::DenseMap<WrappedUsr, int> &entity_usr,
std::vector<Q> &entities,
const std::vector<Usr> &usrs) {
std::vector<Use> ret;
ret.reserve(usrs.size());
for (Usr usr : usrs) {
Q& entity = entities[entity_usr[{usr}]];
Q &entity = entities[entity_usr[{usr}]];
bool has_def = false;
for (auto& def : entity.def)
for (auto &def : entity.def)
if (def.spell) {
ret.push_back(*def.spell);
has_def = true;
@ -35,39 +35,38 @@ std::vector<Use> GetDeclarations(llvm::DenseMap<WrappedUsr, int>& entity_usr,
return ret;
}
} // namespace
} // namespace
Maybe<Use> GetDefinitionSpell(DB* db, SymbolIdx sym) {
Maybe<Use> GetDefinitionSpell(DB *db, SymbolIdx sym) {
Maybe<Use> ret;
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.spell); });
EachEntityDef(db, sym, [&](const auto &def) { return !(ret = def.spell); });
return ret;
}
Maybe<Use> GetDefinitionExtent(DB* db, SymbolIdx sym) {
Maybe<Use> GetDefinitionExtent(DB *db, SymbolIdx sym) {
// Used to jump to file.
if (sym.kind == SymbolKind::File)
return Use{{Range{{0, 0}, {0, 0}}, sym.usr, sym.kind, Role::None},
int(sym.usr)};
Maybe<Use> ret;
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.extent); });
EachEntityDef(db, sym, [&](const auto &def) { return !(ret = def.extent); });
return ret;
}
std::vector<Use> GetFuncDeclarations(DB* db, const std::vector<Usr>& usrs) {
std::vector<Use> GetFuncDeclarations(DB *db, const std::vector<Usr> &usrs) {
return GetDeclarations(db->func_usr, db->funcs, usrs);
}
std::vector<Use> GetTypeDeclarations(DB* db, const std::vector<Usr>& usrs) {
std::vector<Use> GetTypeDeclarations(DB *db, const std::vector<Usr> &usrs) {
return GetDeclarations(db->type_usr, db->types, usrs);
}
std::vector<Use> GetVarDeclarations(DB* db,
const std::vector<Usr>& usrs,
std::vector<Use> GetVarDeclarations(DB *db, const std::vector<Usr> &usrs,
unsigned kind) {
std::vector<Use> ret;
ret.reserve(usrs.size());
for (Usr usr : usrs) {
QueryVar& var = db->Var(usr);
QueryVar &var = db->Var(usr);
bool has_def = false;
for (auto& def : var.def)
for (auto &def : var.def)
if (def.spell) {
has_def = true;
// See messages/ccls_vars.cc
@ -90,29 +89,29 @@ std::vector<Use> GetVarDeclarations(DB* db,
return ret;
}
std::vector<Use> GetNonDefDeclarations(DB* db, SymbolIdx sym) {
std::vector<Use> GetNonDefDeclarations(DB *db, SymbolIdx sym) {
switch (sym.kind) {
case SymbolKind::Func:
return db->GetFunc(sym).declarations;
case SymbolKind::Type:
return db->GetType(sym).declarations;
case SymbolKind::Var:
return db->GetVar(sym).declarations;
default:
return {};
case SymbolKind::Func:
return db->GetFunc(sym).declarations;
case SymbolKind::Type:
return db->GetType(sym).declarations;
case SymbolKind::Var:
return db->GetVar(sym).declarations;
default:
return {};
}
}
std::vector<Use> GetUsesForAllBases(DB* db, QueryFunc& root) {
std::vector<Use> GetUsesForAllBases(DB *db, QueryFunc &root) {
std::vector<Use> ret;
std::vector<QueryFunc*> stack{&root};
std::vector<QueryFunc *> stack{&root};
std::unordered_set<Usr> seen;
seen.insert(root.usr);
while (!stack.empty()) {
QueryFunc& func = *stack.back();
QueryFunc &func = *stack.back();
stack.pop_back();
if (auto* def = func.AnyDef()) {
EachDefinedFunc(db, def->bases, [&](QueryFunc& func1) {
if (auto *def = func.AnyDef()) {
EachDefinedFunc(db, def->bases, [&](QueryFunc &func1) {
if (!seen.count(func1.usr)) {
seen.insert(func1.usr);
stack.push_back(&func1);
@ -125,15 +124,15 @@ std::vector<Use> GetUsesForAllBases(DB* db, QueryFunc& root) {
return ret;
}
std::vector<Use> GetUsesForAllDerived(DB* db, QueryFunc& root) {
std::vector<Use> GetUsesForAllDerived(DB *db, QueryFunc &root) {
std::vector<Use> ret;
std::vector<QueryFunc*> stack{&root};
std::vector<QueryFunc *> stack{&root};
std::unordered_set<Usr> seen;
seen.insert(root.usr);
while (!stack.empty()) {
QueryFunc& func = *stack.back();
QueryFunc &func = *stack.back();
stack.pop_back();
EachDefinedFunc(db, func.derived, [&](QueryFunc& func1) {
EachDefinedFunc(db, func.derived, [&](QueryFunc &func1) {
if (!seen.count(func1.usr)) {
seen.insert(func1.usr);
stack.push_back(&func1);
@ -145,8 +144,8 @@ std::vector<Use> GetUsesForAllDerived(DB* db, QueryFunc& root) {
return ret;
}
std::optional<lsPosition> GetLsPosition(WorkingFile* working_file,
const Position& position) {
std::optional<lsPosition> GetLsPosition(WorkingFile *working_file,
const Position &position) {
if (!working_file)
return lsPosition{position.line, position.column};
@ -157,8 +156,8 @@ std::optional<lsPosition> GetLsPosition(WorkingFile* working_file,
return std::nullopt;
}
std::optional<lsRange> GetLsRange(WorkingFile* working_file,
const Range& location) {
std::optional<lsRange> GetLsRange(WorkingFile *working_file,
const Range &location) {
if (!working_file) {
return lsRange{lsPosition{location.start.line, location.start.column},
lsPosition{location.end.line, location.end.column}};
@ -187,8 +186,8 @@ std::optional<lsRange> GetLsRange(WorkingFile* working_file,
lsPosition{*end, end_column}};
}
lsDocumentUri GetLsDocumentUri(DB* db, int file_id, std::string* path) {
QueryFile& file = db->files[file_id];
lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path) {
QueryFile &file = db->files[file_id];
if (file.def) {
*path = file.def->path;
return lsDocumentUri::FromPath(*path);
@ -198,8 +197,8 @@ lsDocumentUri GetLsDocumentUri(DB* db, int file_id, std::string* path) {
}
}
lsDocumentUri GetLsDocumentUri(DB* db, int file_id) {
QueryFile& file = db->files[file_id];
lsDocumentUri GetLsDocumentUri(DB *db, int file_id) {
QueryFile &file = db->files[file_id];
if (file.def) {
return lsDocumentUri::FromPath(file.def->path);
} else {
@ -207,8 +206,7 @@ lsDocumentUri GetLsDocumentUri(DB* db, int file_id) {
}
}
std::optional<lsLocation> GetLsLocation(DB* db,
WorkingFiles* working_files,
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *working_files,
Use use) {
std::string path;
lsDocumentUri uri = GetLsDocumentUri(db, use.file_id, &path);
@ -219,10 +217,8 @@ std::optional<lsLocation> GetLsLocation(DB* db,
return lsLocation{uri, *range};
}
std::optional<lsLocationEx> GetLsLocationEx(DB* db,
WorkingFiles* working_files,
Use use,
bool container) {
std::optional<lsLocationEx> GetLsLocationEx(DB *db, WorkingFiles *working_files,
Use use, bool container) {
std::optional<lsLocation> ls_loc = GetLsLocation(db, working_files, use);
if (!ls_loc)
return std::nullopt;
@ -230,7 +226,7 @@ std::optional<lsLocationEx> GetLsLocationEx(DB* db,
ret.lsLocation::operator=(*ls_loc);
if (container) {
ret.role = uint16_t(use.role);
EachEntityDef(db, use, [&](const auto& def) {
EachEntityDef(db, use, [&](const auto &def) {
ret.containerName = std::string_view(def.detailed_name);
return false;
});
@ -238,9 +234,8 @@ std::optional<lsLocationEx> GetLsLocationEx(DB* db,
return ret;
}
std::vector<lsLocationEx> GetLsLocationExs(DB* db,
WorkingFiles* working_files,
const std::vector<Use>& uses) {
std::vector<lsLocationEx> GetLsLocationExs(DB *db, WorkingFiles *working_files,
const std::vector<Use> &uses) {
std::vector<lsLocationEx> ret;
for (Use use : uses)
if (auto loc =
@ -253,14 +248,14 @@ std::vector<lsLocationEx> GetLsLocationExs(DB* db,
return ret;
}
lsSymbolKind GetSymbolKind(DB* db, SymbolIdx sym) {
lsSymbolKind GetSymbolKind(DB *db, SymbolIdx sym) {
lsSymbolKind ret;
if (sym.kind == SymbolKind::File)
ret = lsSymbolKind::File;
else {
ret = lsSymbolKind::Unknown;
WithEntity(db, sym, [&](const auto& entity) {
for (auto& def : entity.def) {
WithEntity(db, sym, [&](const auto &entity) {
for (auto &def : entity.def) {
ret = def.kind;
break;
}
@ -270,44 +265,44 @@ lsSymbolKind GetSymbolKind(DB* db, SymbolIdx sym) {
}
// Returns a symbol. The symbol will have *NOT* have a location assigned.
std::optional<lsSymbolInformation> GetSymbolInfo(DB* db,
WorkingFiles* working_files,
std::optional<lsSymbolInformation> GetSymbolInfo(DB *db,
WorkingFiles *working_files,
SymbolIdx sym,
bool detailed_name) {
switch (sym.kind) {
case SymbolKind::Invalid:
case SymbolKind::Invalid:
break;
case SymbolKind::File: {
QueryFile &file = db->GetFile(sym);
if (!file.def)
break;
case SymbolKind::File: {
QueryFile& file = db->GetFile(sym);
if (!file.def)
break;
lsSymbolInformation info;
info.name = file.def->path;
info.kind = lsSymbolKind::File;
return info;
}
default: {
lsSymbolInformation info;
EachEntityDef(db, sym, [&](const auto& def) {
if (detailed_name)
info.name = def.detailed_name;
else
info.name = def.Name(true);
info.kind = def.kind;
info.containerName = def.detailed_name;
return false;
});
return info;
}
lsSymbolInformation info;
info.name = file.def->path;
info.kind = lsSymbolKind::File;
return info;
}
default: {
lsSymbolInformation info;
EachEntityDef(db, sym, [&](const auto &def) {
if (detailed_name)
info.name = def.detailed_name;
else
info.name = def.Name(true);
info.kind = def.kind;
info.containerName = def.detailed_name;
return false;
});
return info;
}
}
return std::nullopt;
}
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
QueryFile* file,
lsPosition& ls_pos) {
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile *working_file,
QueryFile *file,
lsPosition &ls_pos) {
std::vector<SymbolRef> symbols;
if (working_file) {
if (auto line = working_file->GetIndexPosFromBufferPos(
@ -322,7 +317,7 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
for (SymbolRef sym : file->def->all_symbols)
if (sym.range.Contains(ls_pos.line, ls_pos.character))
symbols.push_back(sym);
for (auto[sym, refcnt] : file->symbol2refcnt)
for (auto [sym, refcnt] : file->symbol2refcnt)
if (refcnt > 0 && sym.range.Contains(ls_pos.line, ls_pos.character))
symbols.push_back(sym);
@ -337,22 +332,23 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
//
// Then order functions before other types, which makes goto definition work
// better on constructors.
std::sort(symbols.begin(), symbols.end(),
[](const SymbolRef& a, const SymbolRef& b) {
int t = ComputeRangeSize(a.range) - ComputeRangeSize(b.range);
if (t)
return t < 0;
// MacroExpansion
if ((t = (a.role & Role::Dynamic) - (b.role & Role::Dynamic)))
return t > 0;
if ((t = (a.role & Role::Definition) - (b.role & Role::Definition)))
return t > 0;
// operator> orders Var/Func before Type.
t = static_cast<int>(a.kind) - static_cast<int>(b.kind);
if (t)
return t > 0;
return a.usr < b.usr;
});
std::sort(
symbols.begin(), symbols.end(),
[](const SymbolRef &a, const SymbolRef &b) {
int t = ComputeRangeSize(a.range) - ComputeRangeSize(b.range);
if (t)
return t < 0;
// MacroExpansion
if ((t = (a.role & Role::Dynamic) - (b.role & Role::Dynamic)))
return t > 0;
if ((t = (a.role & Role::Definition) - (b.role & Role::Definition)))
return t > 0;
// operator> orders Var/Func before Type.
t = static_cast<int>(a.kind) - static_cast<int>(b.kind);
if (t)
return t > 0;
return a.usr < b.usr;
});
return symbols;
}

View File

@ -5,81 +5,75 @@
#include <optional>
Maybe<Use> GetDefinitionSpell(DB* db, SymbolIdx sym);
Maybe<Use> GetDefinitionExtent(DB* db, SymbolIdx sym);
Maybe<Use> GetDefinitionSpell(DB *db, SymbolIdx sym);
Maybe<Use> GetDefinitionExtent(DB *db, SymbolIdx sym);
// Get defining declaration (if exists) or an arbitrary declaration (otherwise)
// for each id.
std::vector<Use> GetFuncDeclarations(DB*, const std::vector<Usr>&);
std::vector<Use> GetTypeDeclarations(DB*, const std::vector<Usr>&);
std::vector<Use> GetVarDeclarations(DB*, const std::vector<Usr>&, unsigned);
std::vector<Use> GetFuncDeclarations(DB *, const std::vector<Usr> &);
std::vector<Use> GetTypeDeclarations(DB *, const std::vector<Usr> &);
std::vector<Use> GetVarDeclarations(DB *, const std::vector<Usr> &, unsigned);
// Get non-defining declarations.
std::vector<Use> GetNonDefDeclarations(DB* db, SymbolIdx sym);
std::vector<Use> GetNonDefDeclarations(DB *db, SymbolIdx sym);
std::vector<Use> GetUsesForAllBases(DB* db, QueryFunc& root);
std::vector<Use> GetUsesForAllDerived(DB* db, QueryFunc& root);
std::optional<lsPosition> GetLsPosition(WorkingFile* working_file,
const Position& position);
std::optional<lsRange> GetLsRange(WorkingFile* working_file,
const Range& location);
lsDocumentUri GetLsDocumentUri(DB* db, int file_id, std::string* path);
lsDocumentUri GetLsDocumentUri(DB* db, int file_id);
std::vector<Use> GetUsesForAllBases(DB *db, QueryFunc &root);
std::vector<Use> GetUsesForAllDerived(DB *db, QueryFunc &root);
std::optional<lsPosition> GetLsPosition(WorkingFile *working_file,
const Position &position);
std::optional<lsRange> GetLsRange(WorkingFile *working_file,
const Range &location);
lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path);
lsDocumentUri GetLsDocumentUri(DB *db, int file_id);
std::optional<lsLocation> GetLsLocation(DB* db,
WorkingFiles* working_files,
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *working_files,
Use use);
std::optional<lsLocationEx> GetLsLocationEx(DB* db,
WorkingFiles* working_files,
Use use,
bool container);
std::vector<lsLocationEx> GetLsLocationExs(DB* db,
WorkingFiles* working_files,
const std::vector<Use>& refs);
std::optional<lsLocationEx> GetLsLocationEx(DB *db, WorkingFiles *working_files,
Use use, bool container);
std::vector<lsLocationEx> GetLsLocationExs(DB *db, WorkingFiles *working_files,
const std::vector<Use> &refs);
// Returns a symbol. The symbol will have *NOT* have a location assigned.
std::optional<lsSymbolInformation> GetSymbolInfo(DB* db,
WorkingFiles* working_files,
std::optional<lsSymbolInformation> GetSymbolInfo(DB *db,
WorkingFiles *working_files,
SymbolIdx sym,
bool detailed_name);
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
QueryFile* file,
lsPosition& ls_pos);
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile *working_file,
QueryFile *file,
lsPosition &ls_pos);
template <typename Fn>
void WithEntity(DB* db, SymbolIdx sym, Fn&& fn) {
template <typename Fn> void WithEntity(DB *db, SymbolIdx sym, Fn &&fn) {
switch (sym.kind) {
case SymbolKind::Invalid:
case SymbolKind::File:
break;
case SymbolKind::Func:
fn(db->GetFunc(sym));
break;
case SymbolKind::Type:
fn(db->GetType(sym));
break;
case SymbolKind::Var:
fn(db->GetVar(sym));
break;
case SymbolKind::Invalid:
case SymbolKind::File:
break;
case SymbolKind::Func:
fn(db->GetFunc(sym));
break;
case SymbolKind::Type:
fn(db->GetType(sym));
break;
case SymbolKind::Var:
fn(db->GetVar(sym));
break;
}
}
template <typename Fn>
void EachEntityDef(DB* db, SymbolIdx sym, Fn&& fn) {
WithEntity(db, sym, [&](const auto& entity) {
for (auto& def : entity.def)
template <typename Fn> void EachEntityDef(DB *db, SymbolIdx sym, Fn &&fn) {
WithEntity(db, sym, [&](const auto &entity) {
for (auto &def : entity.def)
if (!fn(def))
break;
});
}
template <typename Fn>
void EachOccurrence(DB* db, SymbolIdx sym, bool include_decl, Fn&& fn) {
WithEntity(db, sym, [&](const auto& entity) {
void EachOccurrence(DB *db, SymbolIdx sym, bool include_decl, Fn &&fn) {
WithEntity(db, sym, [&](const auto &entity) {
for (Use use : entity.uses)
fn(use);
if (include_decl) {
for (auto& def : entity.def)
for (auto &def : entity.def)
if (def.spell)
fn(*def.spell);
for (Use use : entity.declarations)
@ -88,31 +82,30 @@ void EachOccurrence(DB* db, SymbolIdx sym, bool include_decl, Fn&& fn) {
});
}
lsSymbolKind GetSymbolKind(DB* db, SymbolIdx sym);
lsSymbolKind GetSymbolKind(DB *db, SymbolIdx sym);
template <typename Fn>
void EachDefinedFunc(DB* db, const std::vector<Usr>& usrs, Fn&& fn) {
void EachDefinedFunc(DB *db, const std::vector<Usr> &usrs, Fn &&fn) {
for (Usr usr : usrs) {
auto& obj = db->Func(usr);
if (!obj.def.empty())
fn(obj);
}
}
template <typename Fn>
void EachDefinedType(DB* db, const std::vector<Usr>& usrs, Fn&& fn) {
for (Usr usr : usrs) {
auto& obj = db->Type(usr);
auto &obj = db->Func(usr);
if (!obj.def.empty())
fn(obj);
}
}
template <typename Fn>
void EachDefinedVar(DB* db, const std::vector<Usr>& usrs, Fn&& fn) {
void EachDefinedType(DB *db, const std::vector<Usr> &usrs, Fn &&fn) {
for (Usr usr : usrs) {
auto& obj = db->Var(usr);
auto &obj = db->Type(usr);
if (!obj.def.empty())
fn(obj);
}
}
template <typename Fn>
void EachDefinedVar(DB *db, const std::vector<Usr> &usrs, Fn &&fn) {
for (Usr usr : usrs) {
auto &obj = db->Var(usr);
if (!obj.def.empty())
fn(obj);
}

View File

@ -18,143 +18,115 @@ bool gTestOutputMode = false;
//// Elementary types
void Reflect(Reader& visitor, uint8_t& value) {
value = visitor.GetUInt8();
}
void Reflect(Writer& visitor, uint8_t& value) {
visitor.UInt8(value);
}
void Reflect(Reader &visitor, uint8_t &value) { value = visitor.GetUInt8(); }
void Reflect(Writer &visitor, uint8_t &value) { visitor.UInt8(value); }
void Reflect(Reader& visitor, short& value) {
void Reflect(Reader &visitor, short &value) {
if (!visitor.IsInt())
throw std::invalid_argument("short");
value = (short)visitor.GetInt();
}
void Reflect(Writer& visitor, short& value) {
visitor.Int(value);
}
void Reflect(Writer &visitor, short &value) { visitor.Int(value); }
void Reflect(Reader& visitor, unsigned short& value) {
void Reflect(Reader &visitor, unsigned short &value) {
if (!visitor.IsInt())
throw std::invalid_argument("unsigned short");
value = (unsigned short)visitor.GetInt();
}
void Reflect(Writer& visitor, unsigned short& value) {
visitor.Int(value);
}
void Reflect(Writer &visitor, unsigned short &value) { visitor.Int(value); }
void Reflect(Reader& visitor, int& value) {
void Reflect(Reader &visitor, int &value) {
if (!visitor.IsInt())
throw std::invalid_argument("int");
value = visitor.GetInt();
}
void Reflect(Writer& visitor, int& value) {
visitor.Int(value);
}
void Reflect(Writer &visitor, int &value) { visitor.Int(value); }
void Reflect(Reader& visitor, unsigned& value) {
void Reflect(Reader &visitor, unsigned &value) {
if (!visitor.IsUInt64())
throw std::invalid_argument("unsigned");
value = visitor.GetUInt32();
}
void Reflect(Writer& visitor, unsigned& value) {
visitor.UInt32(value);
}
void Reflect(Writer &visitor, unsigned &value) { visitor.UInt32(value); }
void Reflect(Reader& visitor, long& value) {
void Reflect(Reader &visitor, long &value) {
if (!visitor.IsInt64())
throw std::invalid_argument("long");
value = long(visitor.GetInt64());
}
void Reflect(Writer& visitor, long& value) {
visitor.Int64(value);
}
void Reflect(Writer &visitor, long &value) { visitor.Int64(value); }
void Reflect(Reader& visitor, unsigned long& value) {
void Reflect(Reader &visitor, unsigned long &value) {
if (!visitor.IsUInt64())
throw std::invalid_argument("unsigned long");
value = (unsigned long)visitor.GetUInt64();
}
void Reflect(Writer& visitor, unsigned long& value) {
visitor.UInt64(value);
}
void Reflect(Writer &visitor, unsigned long &value) { visitor.UInt64(value); }
void Reflect(Reader& visitor, long long& value) {
void Reflect(Reader &visitor, long long &value) {
if (!visitor.IsInt64())
throw std::invalid_argument("long long");
value = visitor.GetInt64();
}
void Reflect(Writer& visitor, long long& value) {
visitor.Int64(value);
}
void Reflect(Writer &visitor, long long &value) { visitor.Int64(value); }
void Reflect(Reader& visitor, unsigned long long& value) {
void Reflect(Reader &visitor, unsigned long long &value) {
if (!visitor.IsUInt64())
throw std::invalid_argument("unsigned long long");
value = visitor.GetUInt64();
}
void Reflect(Writer& visitor, unsigned long long& value) {
void Reflect(Writer &visitor, unsigned long long &value) {
visitor.UInt64(value);
}
void Reflect(Reader& visitor, double& value) {
void Reflect(Reader &visitor, double &value) {
if (!visitor.IsDouble())
throw std::invalid_argument("double");
value = visitor.GetDouble();
}
void Reflect(Writer& visitor, double& value) {
visitor.Double(value);
}
void Reflect(Writer &visitor, double &value) { visitor.Double(value); }
void Reflect(Reader& visitor, bool& value) {
void Reflect(Reader &visitor, bool &value) {
if (!visitor.IsBool())
throw std::invalid_argument("bool");
value = visitor.GetBool();
}
void Reflect(Writer& visitor, bool& value) {
visitor.Bool(value);
}
void Reflect(Writer &visitor, bool &value) { visitor.Bool(value); }
void Reflect(Reader& visitor, std::string& value) {
void Reflect(Reader &visitor, std::string &value) {
if (!visitor.IsString())
throw std::invalid_argument("std::string");
value = visitor.GetString();
}
void Reflect(Writer& visitor, std::string& value) {
void Reflect(Writer &visitor, std::string &value) {
visitor.String(value.c_str(), (rapidjson::SizeType)value.size());
}
void Reflect(Reader&, std::string_view&) {
assert(0);
}
void Reflect(Writer& visitor, std::string_view& data) {
void Reflect(Reader &, std::string_view &) { assert(0); }
void Reflect(Writer &visitor, std::string_view &data) {
if (data.empty())
visitor.String("");
else
visitor.String(&data[0], (rapidjson::SizeType)data.size());
}
void Reflect(Reader& vis, const char*& v) {
const char* str = vis.GetString();
void Reflect(Reader &vis, const char *&v) {
const char *str = vis.GetString();
v = ccls::Intern(str);
}
void Reflect(Writer& vis, const char*& v) {
vis.String(v);
}
void Reflect(Writer &vis, const char *&v) { vis.String(v); }
void Reflect(Reader& visitor, JsonNull& value) {
void Reflect(Reader &visitor, JsonNull &value) {
assert(visitor.Format() == SerializeFormat::Json);
visitor.GetNull();
}
void Reflect(Writer& visitor, JsonNull& value) {
visitor.Null();
}
void Reflect(Writer &visitor, JsonNull &value) { visitor.Null(); }
// std::unordered_map
template <typename V>
void Reflect(Reader& visitor, std::unordered_map<Usr, V>& map) {
visitor.IterArray([&](Reader& entry) {
void Reflect(Reader &visitor, std::unordered_map<Usr, V> &map) {
visitor.IterArray([&](Reader &entry) {
V val;
Reflect(entry, val);
auto usr = val.usr;
@ -162,20 +134,20 @@ void Reflect(Reader& visitor, std::unordered_map<Usr, V>& map) {
});
}
template <typename V>
void Reflect(Writer& visitor, std::unordered_map<Usr, V>& map) {
void Reflect(Writer &visitor, std::unordered_map<Usr, V> &map) {
std::vector<std::pair<uint64_t, V>> xs(map.begin(), map.end());
std::sort(xs.begin(), xs.end(),
[](const auto& a, const auto& b) { return a.first < b.first; });
[](const auto &a, const auto &b) { return a.first < b.first; });
visitor.StartArray(xs.size());
for (auto& it : xs)
for (auto &it : xs)
Reflect(visitor, it.second);
visitor.EndArray();
}
// Used by IndexFile::dependencies. Timestamps are emitted for Binary.
void Reflect(Reader& visitor, StringMap<int64_t>& map) {
visitor.IterArray([&](Reader& entry) {
std::string name;
void Reflect(Reader &visitor, StringMap<int64_t> &map) {
visitor.IterArray([&](Reader &entry) {
std::string name;
Reflect(entry, name);
if (visitor.Format() == SerializeFormat::Binary)
Reflect(entry, map[name]);
@ -183,9 +155,9 @@ void Reflect(Reader& visitor, StringMap<int64_t>& map) {
map[name] = 0;
});
}
void Reflect(Writer& visitor, StringMap<int64_t>& map) {
void Reflect(Writer &visitor, StringMap<int64_t> &map) {
visitor.StartArray(map.size());
for (auto& it : map) {
for (auto &it : map) {
std::string key = it.first();
Reflect(visitor, key);
if (visitor.Format() == SerializeFormat::Binary)
@ -195,13 +167,13 @@ void Reflect(Writer& visitor, StringMap<int64_t>& map) {
}
// TODO: Move this to indexer.cc
void Reflect(Reader& visitor, IndexInclude& value) {
void Reflect(Reader &visitor, IndexInclude &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(line);
REFLECT_MEMBER(resolved_path);
REFLECT_MEMBER_END();
}
void Reflect(Writer& visitor, IndexInclude& value) {
void Reflect(Writer &visitor, IndexInclude &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER(line);
if (gTestOutputMode) {
@ -216,13 +188,13 @@ void Reflect(Writer& visitor, IndexInclude& value) {
}
template <typename Def>
void ReflectHoverAndComments(Reader& visitor, Def& def) {
void ReflectHoverAndComments(Reader &visitor, Def &def) {
ReflectMember(visitor, "hover", def.hover);
ReflectMember(visitor, "comments", def.comments);
}
template <typename Def>
void ReflectHoverAndComments(Writer& visitor, Def& def) {
void ReflectHoverAndComments(Writer &visitor, Def &def) {
// Don't emit empty hover and comments in JSON test mode.
if (!gTestOutputMode || def.hover[0])
ReflectMember(visitor, "hover", def.hover);
@ -230,12 +202,12 @@ void ReflectHoverAndComments(Writer& visitor, Def& def) {
ReflectMember(visitor, "comments", def.comments);
}
template <typename Def>
void ReflectShortName(Reader& visitor, Def& def) {
template <typename Def> void ReflectShortName(Reader &visitor, Def &def) {
if (gTestOutputMode) {
std::string short_name;
ReflectMember(visitor, "short_name", short_name);
def.short_name_offset = std::string_view(def.detailed_name).find(short_name);
def.short_name_offset =
std::string_view(def.detailed_name).find(short_name);
assert(def.short_name_offset != std::string::npos);
def.short_name_size = short_name.size();
} else {
@ -244,8 +216,7 @@ void ReflectShortName(Reader& visitor, Def& def) {
}
}
template <typename Def>
void ReflectShortName(Writer& visitor, Def& def) {
template <typename Def> void ReflectShortName(Writer &visitor, Def &def) {
if (gTestOutputMode) {
std::string_view short_name(def.detailed_name + def.short_name_offset,
def.short_name_size);
@ -256,8 +227,7 @@ void ReflectShortName(Writer& visitor, Def& def) {
}
}
template <typename TVisitor>
void Reflect(TVisitor& visitor, IndexType& value) {
template <typename TVisitor> void Reflect(TVisitor &visitor, IndexType &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER2("usr", value.usr);
REFLECT_MEMBER2("detailed_name", value.def.detailed_name);
@ -279,8 +249,7 @@ void Reflect(TVisitor& visitor, IndexType& value) {
REFLECT_MEMBER_END();
}
template <typename TVisitor>
void Reflect(TVisitor& visitor, IndexFunc& value) {
template <typename TVisitor> void Reflect(TVisitor &visitor, IndexFunc &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER2("usr", value.usr);
REFLECT_MEMBER2("detailed_name", value.def.detailed_name);
@ -300,8 +269,7 @@ void Reflect(TVisitor& visitor, IndexFunc& value) {
REFLECT_MEMBER_END();
}
template <typename TVisitor>
void Reflect(TVisitor& visitor, IndexVar& value) {
template <typename TVisitor> void Reflect(TVisitor &visitor, IndexVar &value) {
REFLECT_MEMBER_START();
REFLECT_MEMBER2("usr", value.usr);
REFLECT_MEMBER2("detailed_name", value.def.detailed_name);
@ -319,12 +287,11 @@ void Reflect(TVisitor& visitor, IndexVar& value) {
}
// IndexFile
bool ReflectMemberStart(Writer& visitor, IndexFile& value) {
bool ReflectMemberStart(Writer &visitor, IndexFile &value) {
visitor.StartObject();
return true;
}
template <typename TVisitor>
void Reflect(TVisitor& visitor, IndexFile& value) {
template <typename TVisitor> void Reflect(TVisitor &visitor, IndexFile &value) {
REFLECT_MEMBER_START();
if (!gTestOutputMode) {
REFLECT_MEMBER(last_write_time);
@ -342,19 +309,19 @@ void Reflect(TVisitor& visitor, IndexFile& value) {
REFLECT_MEMBER_END();
}
void Reflect(Reader& visitor, SerializeFormat& value) {
void Reflect(Reader &visitor, SerializeFormat &value) {
std::string fmt = visitor.GetString();
value = fmt[0] == 'b' ? SerializeFormat::Binary : SerializeFormat::Json;
}
void Reflect(Writer& visitor, SerializeFormat& value) {
void Reflect(Writer &visitor, SerializeFormat &value) {
switch (value) {
case SerializeFormat::Binary:
visitor.String("binary");
break;
case SerializeFormat::Json:
visitor.String("json");
break;
case SerializeFormat::Binary:
visitor.String("binary");
break;
case SerializeFormat::Json:
visitor.String("json");
break;
}
}
@ -363,8 +330,9 @@ static BumpPtrAllocator Alloc;
static DenseSet<StringRef> Strings;
static std::mutex AllocMutex;
const char* Intern(const std::string& str) {
if (str.empty()) return "";
const char *Intern(const std::string &str) {
if (str.empty())
return "";
StringRef Str(str.data(), str.size() + 1);
std::lock_guard lock(AllocMutex);
auto R = Strings.insert(Str);
@ -373,100 +341,98 @@ const char* Intern(const std::string& str) {
return R.first->data();
}
std::string Serialize(SerializeFormat format, IndexFile& file) {
std::string Serialize(SerializeFormat format, IndexFile &file) {
switch (format) {
case SerializeFormat::Binary: {
BinaryWriter writer;
int major = IndexFile::kMajorVersion;
int minor = IndexFile::kMinorVersion;
Reflect(writer, major);
Reflect(writer, minor);
Reflect(writer, file);
return writer.Take();
}
case SerializeFormat::Json: {
rapidjson::StringBuffer output;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(output);
writer.SetFormatOptions(
rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
writer.SetIndent(' ', 2);
JsonWriter json_writer(&writer);
if (!gTestOutputMode) {
std::string version = std::to_string(IndexFile::kMajorVersion);
for (char c : version)
output.Put(c);
output.Put('\n');
}
Reflect(json_writer, file);
return output.GetString();
case SerializeFormat::Binary: {
BinaryWriter writer;
int major = IndexFile::kMajorVersion;
int minor = IndexFile::kMinorVersion;
Reflect(writer, major);
Reflect(writer, minor);
Reflect(writer, file);
return writer.Take();
}
case SerializeFormat::Json: {
rapidjson::StringBuffer output;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(output);
writer.SetFormatOptions(
rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
writer.SetIndent(' ', 2);
JsonWriter json_writer(&writer);
if (!gTestOutputMode) {
std::string version = std::to_string(IndexFile::kMajorVersion);
for (char c : version)
output.Put(c);
output.Put('\n');
}
Reflect(json_writer, file);
return output.GetString();
}
}
return "";
}
std::unique_ptr<IndexFile> Deserialize(
SerializeFormat format,
const std::string& path,
const std::string& serialized_index_content,
const std::string& file_content,
std::optional<int> expected_version) {
std::unique_ptr<IndexFile>
Deserialize(SerializeFormat format, const std::string &path,
const std::string &serialized_index_content,
const std::string &file_content,
std::optional<int> expected_version) {
if (serialized_index_content.empty())
return nullptr;
std::unique_ptr<IndexFile> file;
switch (format) {
case SerializeFormat::Binary: {
try {
int major, minor;
if (serialized_index_content.size() < 8)
throw std::invalid_argument("Invalid");
BinaryReader reader(serialized_index_content);
Reflect(reader, major);
Reflect(reader, minor);
if (major != IndexFile::kMajorVersion ||
minor != IndexFile::kMinorVersion)
throw std::invalid_argument("Invalid version");
file = std::make_unique<IndexFile>(sys::fs::UniqueID(0, 0), path,
file_content);
Reflect(reader, *file);
} catch (std::invalid_argument& e) {
LOG_S(INFO) << "failed to deserialize '" << path
<< "': " << e.what();
return nullptr;
}
break;
}
case SerializeFormat::Json: {
rapidjson::Document reader;
if (gTestOutputMode || !expected_version) {
reader.Parse(serialized_index_content.c_str());
} else {
const char* p = strchr(serialized_index_content.c_str(), '\n');
if (!p)
return nullptr;
if (atoi(serialized_index_content.c_str()) != *expected_version)
return nullptr;
reader.Parse(p + 1);
}
if (reader.HasParseError())
return nullptr;
case SerializeFormat::Binary: {
try {
int major, minor;
if (serialized_index_content.size() < 8)
throw std::invalid_argument("Invalid");
BinaryReader reader(serialized_index_content);
Reflect(reader, major);
Reflect(reader, minor);
if (major != IndexFile::kMajorVersion ||
minor != IndexFile::kMinorVersion)
throw std::invalid_argument("Invalid version");
file = std::make_unique<IndexFile>(sys::fs::UniqueID(0, 0), path,
file_content);
JsonReader json_reader{&reader};
try {
Reflect(json_reader, *file);
} catch (std::invalid_argument& e) {
LOG_S(INFO) << "'" << path << "': failed to deserialize "
<< json_reader.GetPath() << "." << e.what();
return nullptr;
}
break;
Reflect(reader, *file);
} catch (std::invalid_argument &e) {
LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what();
return nullptr;
}
break;
}
case SerializeFormat::Json: {
rapidjson::Document reader;
if (gTestOutputMode || !expected_version) {
reader.Parse(serialized_index_content.c_str());
} else {
const char *p = strchr(serialized_index_content.c_str(), '\n');
if (!p)
return nullptr;
if (atoi(serialized_index_content.c_str()) != *expected_version)
return nullptr;
reader.Parse(p + 1);
}
if (reader.HasParseError())
return nullptr;
file = std::make_unique<IndexFile>(sys::fs::UniqueID(0, 0), path,
file_content);
JsonReader json_reader{&reader};
try {
Reflect(json_reader, *file);
} catch (std::invalid_argument &e) {
LOG_S(INFO) << "'" << path << "': failed to deserialize "
<< json_reader.GetPath() << "." << e.what();
return nullptr;
}
break;
}
}
// Restore non-serialized state.
file->path = path;
return file;
}
}
} // namespace ccls

View File

@ -21,7 +21,7 @@ struct JsonNull {};
struct mandatory_optional_tag {};
class Reader {
public:
public:
virtual ~Reader() {}
virtual SerializeFormat Format() const = 0;
@ -41,17 +41,17 @@ class Reader {
virtual int64_t GetInt64() = 0;
virtual uint64_t GetUInt64() = 0;
virtual double GetDouble() = 0;
virtual const char* GetString() = 0;
virtual const char *GetString() = 0;
virtual bool HasMember(const char* x) = 0;
virtual std::unique_ptr<Reader> operator[](const char* x) = 0;
virtual bool HasMember(const char *x) = 0;
virtual std::unique_ptr<Reader> operator[](const char *x) = 0;
virtual void IterArray(std::function<void(Reader&)> fn) = 0;
virtual void Member(const char* name, std::function<void()> fn) = 0;
virtual void IterArray(std::function<void(Reader &)> fn) = 0;
virtual void Member(const char *name, std::function<void()> fn) = 0;
};
class Writer {
public:
public:
virtual ~Writer() {}
virtual SerializeFormat Format() const = 0;
@ -63,13 +63,13 @@ class Writer {
virtual void UInt32(uint32_t x) = 0;
virtual void UInt64(uint64_t x) = 0;
virtual void Double(double x) = 0;
virtual void String(const char* x) = 0;
virtual void String(const char* x, size_t len) = 0;
virtual void String(const char *x) = 0;
virtual void String(const char *x, size_t len) = 0;
virtual void StartArray(size_t) = 0;
virtual void EndArray() = 0;
virtual void StartObject() = 0;
virtual void EndObject() = 0;
virtual void Key(const char* name) = 0;
virtual void Key(const char *name) = 0;
};
struct IndexFile;
@ -77,48 +77,45 @@ struct IndexFile;
#define REFLECT_MEMBER_START() ReflectMemberStart(visitor)
#define REFLECT_MEMBER_END() ReflectMemberEnd(visitor);
#define REFLECT_MEMBER(name) ReflectMember(visitor, #name, value.name)
#define REFLECT_MEMBER_MANDATORY_OPTIONAL(name) \
#define REFLECT_MEMBER_MANDATORY_OPTIONAL(name) \
ReflectMember(visitor, #name, value.name, mandatory_optional_tag{})
#define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value)
#define MAKE_REFLECT_TYPE_PROXY(type_name) \
#define MAKE_REFLECT_TYPE_PROXY(type_name) \
MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type_t<type_name>)
#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Reader& visitor, type& value) { \
as_type value0; \
::Reflect(visitor, value0); \
value = static_cast<type>(value0); \
} \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Writer& visitor, type& value) { \
auto value0 = static_cast<as_type>(value); \
::Reflect(visitor, value0); \
#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Reader &visitor, type &value) { \
as_type value0; \
::Reflect(visitor, value0); \
value = static_cast<type>(value0); \
} \
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Writer &visitor, type &value) { \
auto value0 = static_cast<as_type>(value); \
::Reflect(visitor, value0); \
}
#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name);
#define _MAPPABLE_REFLECT_MEMBER_MANDATORY_OPTIONAL(name) \
#define _MAPPABLE_REFLECT_MEMBER_MANDATORY_OPTIONAL(name) \
REFLECT_MEMBER_MANDATORY_OPTIONAL(name);
#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \
template <typename TVisitor> \
void Reflect(TVisitor& visitor, type& value) { \
REFLECT_MEMBER_START(); \
REFLECT_MEMBER_END(); \
#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \
template <typename TVisitor> void Reflect(TVisitor &visitor, type &value) { \
REFLECT_MEMBER_START(); \
REFLECT_MEMBER_END(); \
}
#define MAKE_REFLECT_STRUCT(type, ...) \
template <typename TVisitor> \
void Reflect(TVisitor& visitor, type& value) { \
REFLECT_MEMBER_START(); \
MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \
REFLECT_MEMBER_END(); \
#define MAKE_REFLECT_STRUCT(type, ...) \
template <typename TVisitor> void Reflect(TVisitor &visitor, type &value) { \
REFLECT_MEMBER_START(); \
MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \
REFLECT_MEMBER_END(); \
}
#define MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(type, ...) \
template <typename TVisitor> \
void Reflect(TVisitor& visitor, type& value) { \
REFLECT_MEMBER_START(); \
MACRO_MAP(_MAPPABLE_REFLECT_MEMBER_MANDATORY_OPTIONAL, __VA_ARGS__) \
REFLECT_MEMBER_END(); \
#define MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(type, ...) \
template <typename TVisitor> void Reflect(TVisitor &visitor, type &value) { \
REFLECT_MEMBER_START(); \
MACRO_MAP(_MAPPABLE_REFLECT_MEMBER_MANDATORY_OPTIONAL, __VA_ARGS__) \
REFLECT_MEMBER_END(); \
}
// clang-format off
@ -131,71 +128,70 @@ struct IndexFile;
// Reflects the struct so it is serialized as an array instead of an object.
// This currently only supports writers.
#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \
inline void Reflect(Writer& visitor, type& value) { \
visitor.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \
MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \
visitor.EndArray(); \
#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \
inline void Reflect(Writer &visitor, type &value) { \
visitor.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \
MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \
visitor.EndArray(); \
}
//// Elementary types
void Reflect(Reader& visitor, uint8_t& value);
void Reflect(Writer& visitor, uint8_t& value);
void Reflect(Reader &visitor, uint8_t &value);
void Reflect(Writer &visitor, uint8_t &value);
void Reflect(Reader& visitor, short& value);
void Reflect(Writer& visitor, short& value);
void Reflect(Reader &visitor, short &value);
void Reflect(Writer &visitor, short &value);
void Reflect(Reader& visitor, unsigned short& value);
void Reflect(Writer& visitor, unsigned short& value);
void Reflect(Reader &visitor, unsigned short &value);
void Reflect(Writer &visitor, unsigned short &value);
void Reflect(Reader& visitor, int& value);
void Reflect(Writer& visitor, int& value);
void Reflect(Reader &visitor, int &value);
void Reflect(Writer &visitor, int &value);
void Reflect(Reader& visitor, unsigned& value);
void Reflect(Writer& visitor, unsigned& value);
void Reflect(Reader &visitor, unsigned &value);
void Reflect(Writer &visitor, unsigned &value);
void Reflect(Reader& visitor, long& value);
void Reflect(Writer& visitor, long& value);
void Reflect(Reader &visitor, long &value);
void Reflect(Writer &visitor, long &value);
void Reflect(Reader& visitor, unsigned long& value);
void Reflect(Writer& visitor, unsigned long& value);
void Reflect(Reader &visitor, unsigned long &value);
void Reflect(Writer &visitor, unsigned long &value);
void Reflect(Reader& visitor, long long& value);
void Reflect(Writer& visitor, long long& value);
void Reflect(Reader &visitor, long long &value);
void Reflect(Writer &visitor, long long &value);
void Reflect(Reader& visitor, unsigned long long& value);
void Reflect(Writer& visitor, unsigned long long& value);
void Reflect(Reader &visitor, unsigned long long &value);
void Reflect(Writer &visitor, unsigned long long &value);
void Reflect(Reader& visitor, double& value);
void Reflect(Writer& visitor, double& value);
void Reflect(Reader &visitor, double &value);
void Reflect(Writer &visitor, double &value);
void Reflect(Reader& visitor, bool& value);
void Reflect(Writer& visitor, bool& value);
void Reflect(Reader &visitor, bool &value);
void Reflect(Writer &visitor, bool &value);
void Reflect(Reader& visitor, std::string& value);
void Reflect(Writer& visitor, std::string& value);
void Reflect(Reader &visitor, std::string &value);
void Reflect(Writer &visitor, std::string &value);
void Reflect(Reader& visitor, std::string_view& view);
void Reflect(Writer& visitor, std::string_view& view);
void Reflect(Reader &visitor, std::string_view &view);
void Reflect(Writer &visitor, std::string_view &view);
void Reflect(Reader& vis, const char*& v);
void Reflect(Writer& vis, const char*& v);
void Reflect(Reader &vis, const char *&v);
void Reflect(Writer &vis, const char *&v);
void Reflect(Reader& visitor, JsonNull& value);
void Reflect(Writer& visitor, JsonNull& value);
void Reflect(Reader &visitor, JsonNull &value);
void Reflect(Writer &visitor, JsonNull &value);
void Reflect(Reader& visitor, SerializeFormat& value);
void Reflect(Writer& visitor, SerializeFormat& value);
void Reflect(Reader &visitor, SerializeFormat &value);
void Reflect(Writer &visitor, SerializeFormat &value);
//// Type constructors
// ReflectMember std::optional<T> is used to represent TypeScript optional properties
// (in `key: value` context).
// Reflect std::optional<T> is used for a different purpose, whether an object is
// nullable (possibly in `value` context).
template <typename T>
void Reflect(Reader& visitor, std::optional<T>& value) {
// ReflectMember std::optional<T> is used to represent TypeScript optional
// properties (in `key: value` context). Reflect std::optional<T> is used for a
// different purpose, whether an object is nullable (possibly in `value`
// context).
template <typename T> void Reflect(Reader &visitor, std::optional<T> &value) {
if (visitor.IsNull()) {
visitor.GetNull();
return;
@ -204,8 +200,7 @@ void Reflect(Reader& visitor, std::optional<T>& value) {
Reflect(visitor, real_value);
value = std::move(real_value);
}
template <typename T>
void Reflect(Writer& visitor, std::optional<T>& value) {
template <typename T> void Reflect(Writer &visitor, std::optional<T> &value) {
if (value) {
if (visitor.Format() != SerializeFormat::Json)
visitor.UInt8(1);
@ -215,8 +210,7 @@ void Reflect(Writer& visitor, std::optional<T>& value) {
}
// The same as std::optional
template <typename T>
void Reflect(Reader& visitor, Maybe<T>& value) {
template <typename T> void Reflect(Reader &visitor, Maybe<T> &value) {
if (visitor.IsNull()) {
visitor.GetNull();
return;
@ -225,8 +219,7 @@ void Reflect(Reader& visitor, Maybe<T>& value) {
Reflect(visitor, real_value);
value = std::move(real_value);
}
template <typename T>
void Reflect(Writer& visitor, Maybe<T>& value) {
template <typename T> void Reflect(Writer &visitor, Maybe<T> &value) {
if (value) {
if (visitor.Format() != SerializeFormat::Json)
visitor.UInt8(1);
@ -236,7 +229,7 @@ void Reflect(Writer& visitor, Maybe<T>& value) {
}
template <typename T>
void ReflectMember(Writer& visitor, const char* name, std::optional<T>& value) {
void ReflectMember(Writer &visitor, const char *name, std::optional<T> &value) {
// For TypeScript std::optional property key?: value in the spec,
// We omit both key and value if value is std::nullopt (null) for JsonWriter
// to reduce output. But keep it for other serialization formats.
@ -248,7 +241,7 @@ void ReflectMember(Writer& visitor, const char* name, std::optional<T>& value) {
// The same as std::optional
template <typename T>
void ReflectMember(Writer& visitor, const char* name, Maybe<T>& value) {
void ReflectMember(Writer &visitor, const char *name, Maybe<T> &value) {
if (value.Valid() || visitor.Format() != SerializeFormat::Json) {
visitor.Key(name);
Reflect(visitor, value);
@ -256,21 +249,19 @@ void ReflectMember(Writer& visitor, const char* name, Maybe<T>& value) {
}
template <typename T>
void ReflectMember(Writer& visitor,
const char* name,
T& value,
void ReflectMember(Writer &visitor, const char *name, T &value,
mandatory_optional_tag) {
visitor.Key(name);
Reflect(visitor, value);
}
template <typename L, typename R>
void Reflect(Reader& vis, std::pair<L, R>& v) {
void Reflect(Reader &vis, std::pair<L, R> &v) {
vis.Member("L", [&]() { Reflect(vis, v.first); });
vis.Member("R", [&]() { Reflect(vis, v.second); });
}
template <typename L, typename R>
void Reflect(Writer& vis, std::pair<L, R>& v) {
void Reflect(Writer &vis, std::pair<L, R> &v) {
vis.StartObject();
ReflectMember(vis, "L", v.first);
ReflectMember(vis, "R", v.second);
@ -278,43 +269,35 @@ void Reflect(Writer& vis, std::pair<L, R>& v) {
}
// std::vector
template <typename T>
void Reflect(Reader& visitor, std::vector<T>& values) {
visitor.IterArray([&](Reader& entry) {
template <typename T> void Reflect(Reader &visitor, std::vector<T> &values) {
visitor.IterArray([&](Reader &entry) {
T entry_value;
Reflect(entry, entry_value);
values.push_back(std::move(entry_value));
});
}
template <typename T>
void Reflect(Writer& visitor, std::vector<T>& values) {
template <typename T> void Reflect(Writer &visitor, std::vector<T> &values) {
visitor.StartArray(values.size());
for (auto& value : values)
for (auto &value : values)
Reflect(visitor, value);
visitor.EndArray();
}
// ReflectMember
inline bool ReflectMemberStart(Reader& vis) {
return false;
}
inline bool ReflectMemberStart(Writer& vis) {
inline bool ReflectMemberStart(Reader &vis) { return false; }
inline bool ReflectMemberStart(Writer &vis) {
vis.StartObject();
return true;
}
inline void ReflectMemberEnd(Reader& vis) {}
inline void ReflectMemberEnd(Writer& vis) {
vis.EndObject();
}
inline void ReflectMemberEnd(Reader &vis) {}
inline void ReflectMemberEnd(Writer &vis) { vis.EndObject(); }
template <typename T>
void ReflectMember(Reader& vis, const char* name, T& v) {
template <typename T> void ReflectMember(Reader &vis, const char *name, T &v) {
vis.Member(name, [&]() { Reflect(vis, v); });
}
template <typename T>
void ReflectMember(Writer& vis, const char* name, T& v) {
template <typename T> void ReflectMember(Writer &vis, const char *name, T &v) {
vis.Key(name);
Reflect(vis, v);
}
@ -322,12 +305,11 @@ void ReflectMember(Writer& vis, const char* name, T& v) {
// API
namespace ccls {
const char* Intern(const std::string& str);
std::string Serialize(SerializeFormat format, IndexFile& file);
std::unique_ptr<IndexFile> Deserialize(
SerializeFormat format,
const std::string& path,
const std::string& serialized_index_content,
const std::string& file_content,
std::optional<int> expected_version);
}
const char *Intern(const std::string &str);
std::string Serialize(SerializeFormat format, IndexFile &file);
std::unique_ptr<IndexFile>
Deserialize(SerializeFormat format, const std::string &path,
const std::string &serialized_index_content,
const std::string &file_content,
std::optional<int> expected_version);
} // namespace ccls

View File

@ -5,17 +5,16 @@
#include <assert.h>
class BinaryReader : public Reader {
const char* p_;
const char *p_;
template <typename T>
T Get() {
auto ret = *reinterpret_cast<const T*>(p_);
template <typename T> T Get() {
auto ret = *reinterpret_cast<const T *>(p_);
p_ += sizeof(T);
return ret;
}
uint64_t VarUInt() {
auto x = *reinterpret_cast<const uint8_t*>(p_++);
auto x = *reinterpret_cast<const uint8_t *>(p_++);
if (x < 253)
return x;
if (x == 253)
@ -29,11 +28,9 @@ class BinaryReader : public Reader {
return int64_t(x >> 1 ^ -(x & 1));
}
public:
public:
BinaryReader(std::string_view buf) : p_(buf.data()) {}
SerializeFormat Format() const override {
return SerializeFormat::Binary;
}
SerializeFormat Format() const override { return SerializeFormat::Binary; }
bool IsBool() override { return true; }
// Abuse how the function is called in serializer.h
@ -52,35 +49,32 @@ class BinaryReader : public Reader {
uint32_t GetUInt32() override { return VarUInt(); }
uint64_t GetUInt64() override { return VarUInt(); }
double GetDouble() override { return Get<double>(); }
const char* GetString() override {
const char* ret = p_;
const char *GetString() override {
const char *ret = p_;
while (*p_)
p_++;
p_++;
return ret;
}
bool HasMember(const char* x) override { return true; }
std::unique_ptr<Reader> operator[](const char* x) override { return {}; }
bool HasMember(const char *x) override { return true; }
std::unique_ptr<Reader> operator[](const char *x) override { return {}; }
void IterArray(std::function<void(Reader&)> fn) override {
void IterArray(std::function<void(Reader &)> fn) override {
for (auto n = VarUInt(); n; n--)
fn(*this);
}
void Member(const char*, std::function<void()> fn) override {
fn();
}
void Member(const char *, std::function<void()> fn) override { fn(); }
};
class BinaryWriter : public Writer {
std::string buf_;
template <typename T>
void Pack(T x) {
template <typename T> void Pack(T x) {
auto i = buf_.size();
buf_.resize(i + sizeof(x));
*reinterpret_cast<T*>(buf_.data() + i) = x;
*reinterpret_cast<T *>(buf_.data() + i) = x;
}
void VarUInt(uint64_t n) {
@ -97,14 +91,10 @@ class BinaryWriter : public Writer {
Pack<uint64_t>(n);
}
}
void VarInt(int64_t n) {
VarUInt(uint64_t(n) << 1 ^ n >> 63);
}
void VarInt(int64_t n) { VarUInt(uint64_t(n) << 1 ^ n >> 63); }
public:
SerializeFormat Format() const override {
return SerializeFormat::Binary;
}
public:
SerializeFormat Format() const override { return SerializeFormat::Binary; }
std::string Take() { return std::move(buf_); }
void Null() override { Pack(uint8_t(0)); }
@ -115,8 +105,8 @@ class BinaryWriter : public Writer {
void UInt32(uint32_t x) override { VarUInt(x); }
void UInt64(uint64_t x) override { VarUInt(x); }
void Double(double x) override { Pack(x); }
void String(const char* x) override { String(x, strlen(x)); }
void String(const char* x, size_t len) override {
void String(const char *x) override { String(x, strlen(x)); }
void String(const char *x, size_t len) override {
auto i = buf_.size();
buf_.resize(i + len + 1);
memcpy(buf_.data() + i, x, len);
@ -125,5 +115,5 @@ class BinaryWriter : public Writer {
void EndArray() override {}
void StartObject() override {}
void EndObject() override {}
void Key(const char* name) override {}
void Key(const char *name) override {}
};

View File

@ -6,11 +6,11 @@
#include <rapidjson/prettywriter.h>
class JsonReader : public Reader {
rapidjson::GenericValue<rapidjson::UTF8<>>* m_;
std::vector<const char*> path_;
rapidjson::GenericValue<rapidjson::UTF8<>> *m_;
std::vector<const char *> path_;
public:
JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>>* m) : m_(m) {}
public:
JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>> *m) : m_(m) {}
SerializeFormat Format() const override { return SerializeFormat::Json; }
bool IsBool() override { return m_->IsBool(); }
@ -29,20 +29,20 @@ class JsonReader : public Reader {
uint32_t GetUInt32() override { return uint32_t(m_->GetUint64()); }
uint64_t GetUInt64() override { return m_->GetUint64(); }
double GetDouble() override { return m_->GetDouble(); }
const char* GetString() override { return m_->GetString(); }
const char *GetString() override { return m_->GetString(); }
bool HasMember(const char* x) override { return m_->HasMember(x); }
std::unique_ptr<Reader> operator[](const char* x) override {
auto& sub = (*m_)[x];
bool HasMember(const char *x) override { return m_->HasMember(x); }
std::unique_ptr<Reader> operator[](const char *x) override {
auto &sub = (*m_)[x];
return std::unique_ptr<JsonReader>(new JsonReader(&sub));
}
void IterArray(std::function<void(Reader&)> fn) override {
void IterArray(std::function<void(Reader &)> fn) override {
if (!m_->IsArray())
throw std::invalid_argument("array");
// Use "0" to indicate any element for now.
path_.push_back("0");
for (auto& entry : m_->GetArray()) {
for (auto &entry : m_->GetArray()) {
auto saved = m_;
m_ = &entry;
fn(*this);
@ -51,7 +51,7 @@ class JsonReader : public Reader {
path_.pop_back();
}
void Member(const char* name, std::function<void()> fn) override {
void Member(const char *name, std::function<void()> fn) override {
path_.push_back(name);
auto it = m_->FindMember(name);
if (it != m_->MemberEnd()) {
@ -65,7 +65,7 @@ class JsonReader : public Reader {
std::string GetPath() const {
std::string ret;
for (auto& t : path_) {
for (auto &t : path_) {
ret += '/';
ret += t;
}
@ -75,10 +75,10 @@ class JsonReader : public Reader {
};
class JsonWriter : public Writer {
rapidjson::Writer<rapidjson::StringBuffer>* m_;
rapidjson::Writer<rapidjson::StringBuffer> *m_;
public:
JsonWriter(rapidjson::Writer<rapidjson::StringBuffer>* m) : m_(m) {}
public:
JsonWriter(rapidjson::Writer<rapidjson::StringBuffer> *m) : m_(m) {}
SerializeFormat Format() const override { return SerializeFormat::Json; }
void Null() override { m_->Null(); }
@ -89,11 +89,11 @@ class JsonWriter : public Writer {
void UInt32(uint32_t x) override { m_->Uint64(x); }
void UInt64(uint64_t x) override { m_->Uint64(x); }
void Double(double x) override { m_->Double(x); }
void String(const char* x) override { m_->String(x); }
void String(const char* x, size_t len) override { m_->String(x, len); }
void String(const char *x) override { m_->String(x); }
void String(const char *x, size_t len) override { m_->String(x, len); }
void StartArray(size_t) override { m_->StartArray(); }
void EndArray() override { m_->EndArray(); }
void StartObject() override { m_->StartObject(); }
void EndObject() override { m_->EndObject(); }
void Key(const char* name) override { m_->Key(name); }
void Key(const char *name) override { m_->Key(name); }
};

View File

@ -13,9 +13,9 @@
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
// The 'diff' utility is available and we can use dprintf(3).
#if _POSIX_C_SOURCE >= 200809L
@ -25,7 +25,7 @@
extern bool gTestOutputMode;
std::string ToString(const rapidjson::Document& document) {
std::string ToString(const rapidjson::Document &document) {
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
writer.SetFormatOptions(
@ -45,18 +45,18 @@ struct TextReplacer {
std::vector<Replacement> replacements;
std::string Apply(const std::string& content) {
std::string Apply(const std::string &content) {
std::string result = content;
for (const Replacement& replacement : replacements) {
for (const Replacement &replacement : replacements) {
while (true) {
size_t idx = result.find(replacement.from);
if (idx == std::string::npos)
break;
result.replace(result.begin() + idx,
result.begin() + idx + replacement.from.size(),
replacement.to);
result.begin() + idx + replacement.from.size(),
replacement.to);
}
}
@ -65,11 +65,10 @@ struct TextReplacer {
};
void ParseTestExpectation(
const std::string& filename,
const std::vector<std::string>& lines_with_endings,
TextReplacer* replacer,
std::vector<std::string>* flags,
std::unordered_map<std::string, std::string>* output_sections) {
const std::string &filename,
const std::vector<std::string> &lines_with_endings, TextReplacer *replacer,
std::vector<std::string> *flags,
std::unordered_map<std::string, std::string> *output_sections) {
// Scan for EXTRA_FLAGS:
{
bool in_output = false;
@ -129,9 +128,9 @@ void ParseTestExpectation(
}
}
void UpdateTestExpectation(const std::string& filename,
const std::string& expectation,
const std::string& actual) {
void UpdateTestExpectation(const std::string &filename,
const std::string &expectation,
const std::string &actual) {
// Read the entire file into a string.
std::ifstream in(filename);
std::string str;
@ -148,10 +147,8 @@ void UpdateTestExpectation(const std::string& filename,
WriteToFile(filename, str);
}
void DiffDocuments(std::string path,
std::string path_section,
rapidjson::Document& expected,
rapidjson::Document& actual) {
void DiffDocuments(std::string path, std::string path_section,
rapidjson::Document &expected, rapidjson::Document &actual) {
std::string joined_actual_output = ToString(actual);
std::string joined_expected_output = ToString(expected);
printf("[FAILED] %s (section %s)\n", path.c_str(), path_section.c_str());
@ -190,7 +187,7 @@ void DiffDocuments(std::string path,
path_section.c_str(), joined_actual_output.c_str());
}
void VerifySerializeToFrom(IndexFile* file) {
void VerifySerializeToFrom(IndexFile *file) {
std::string expected = file->ToString();
std::string serialized = ccls::Serialize(SerializeFormat::Json, *file);
std::unique_ptr<IndexFile> result =
@ -199,14 +196,14 @@ void VerifySerializeToFrom(IndexFile* file) {
std::string actual = result->ToString();
if (expected != actual) {
fprintf(stderr, "Serialization failure\n");
//assert(false);
// assert(false);
}
}
std::string FindExpectedOutputForFilename(
std::string filename,
const std::unordered_map<std::string, std::string>& expected) {
for (const auto& entry : expected) {
const std::unordered_map<std::string, std::string> &expected) {
for (const auto &entry : expected) {
if (EndsWith(entry.first, filename))
return entry.second;
}
@ -217,17 +214,17 @@ std::string FindExpectedOutputForFilename(
return "{}";
}
IndexFile* FindDbForPathEnding(
const std::string& path,
const std::vector<std::unique_ptr<IndexFile>>& dbs) {
for (auto& db : dbs) {
IndexFile *
FindDbForPathEnding(const std::string &path,
const std::vector<std::unique_ptr<IndexFile>> &dbs) {
for (auto &db : dbs) {
if (EndsWith(db->path, path))
return db.get();
}
return nullptr;
}
bool RunIndexTests(const std::string& filter_path, bool enable_update) {
bool RunIndexTests(const std::string &filter_path, bool enable_update) {
gTestOutputMode = true;
std::string version = LLVM_VERSION_STRING;
@ -248,7 +245,7 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
// this can be done by constructing ClangIndex index(1, 1);
GetFilesInFolder(
"index_tests", true /*recursive*/, true /*add_folder_to_path*/,
[&](const std::string& path) {
[&](const std::string &path) {
bool is_fail_allowed = false;
if (EndsWithAny(path, {".m", ".mm"})) {
@ -291,13 +288,13 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
VFS vfs;
auto dbs = ccls::idx::Index(&vfs, "", path, flags, {});
for (const auto& entry : all_expected_output) {
const std::string& expected_path = entry.first;
for (const auto &entry : all_expected_output) {
const std::string &expected_path = entry.first;
std::string expected_output = text_replacer.Apply(entry.second);
// FIXME: promote to utils, find and remove duplicates (ie,
// ccls_call_tree.cc, maybe something in project.cc).
auto basename = [](const std::string& path) -> std::string {
auto basename = [](const std::string &path) -> std::string {
size_t last_index = path.find_last_of('/');
if (last_index == std::string::npos)
return path;
@ -305,10 +302,10 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
};
// Get output from index operation.
IndexFile* db = FindDbForPathEnding(expected_path, dbs);
IndexFile *db = FindDbForPathEnding(expected_path, dbs);
if (db && !db->diagnostics_.empty()) {
printf("For %s\n", path.c_str());
for (const lsDiagnostic& diagnostic : db->diagnostics_) {
for (const lsDiagnostic &diagnostic : db->diagnostics_) {
printf(" ");
if (diagnostic.severity)
switch (*diagnostic.severity) {
@ -353,9 +350,8 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
DiffDocuments(path, expected_path, expected, actual);
puts("\n");
if (enable_update) {
printf(
"[Enter to continue - type u to update test, a to update "
"all]");
printf("[Enter to continue - type u to update test, a to update "
"all]");
char c = 'u';
if (!update_all) {
c = getchar();

View File

@ -2,4 +2,4 @@
#include <string>
bool RunIndexTests(const std::string& filter_path, bool enable_update);
bool RunIndexTests(const std::string &filter_path, bool enable_update);

View File

@ -18,27 +18,21 @@ struct BaseThreadQueue {
// std::lock accepts two or more arguments. We define an overload for one
// argument.
namespace std {
template <typename Lockable>
void lock(Lockable& l) {
l.lock();
}
} // namespace std
template <typename Lockable> void lock(Lockable &l) { l.lock(); }
} // namespace std
template <typename... Queue>
struct MultiQueueLock {
template <typename... Queue> struct MultiQueueLock {
MultiQueueLock(Queue... lockable) : tuple_{lockable...} { lock(); }
~MultiQueueLock() { unlock(); }
void lock() { lock_impl(typename std::index_sequence_for<Queue...>{}); }
void unlock() { unlock_impl(typename std::index_sequence_for<Queue...>{}); }
private:
template <size_t... Is>
void lock_impl(std::index_sequence<Is...>) {
private:
template <size_t... Is> void lock_impl(std::index_sequence<Is...>) {
std::lock(std::get<Is>(tuple_)->mutex_...);
}
template <size_t... Is>
void unlock_impl(std::index_sequence<Is...>) {
template <size_t... Is> void unlock_impl(std::index_sequence<Is...>) {
(void)std::initializer_list<int>{
(std::get<Is>(tuple_)->mutex_.unlock(), 0)...};
}
@ -49,16 +43,15 @@ struct MultiQueueLock {
struct MultiQueueWaiter {
std::condition_variable_any cv;
static bool HasState(std::initializer_list<BaseThreadQueue*> queues) {
for (BaseThreadQueue* queue : queues) {
static bool HasState(std::initializer_list<BaseThreadQueue *> queues) {
for (BaseThreadQueue *queue : queues) {
if (!queue->IsEmpty())
return true;
}
return false;
}
template <typename... BaseThreadQueue>
void Wait(BaseThreadQueue... queues) {
template <typename... BaseThreadQueue> void Wait(BaseThreadQueue... queues) {
MultiQueueLock<BaseThreadQueue...> l(queues...);
while (!HasState({queues...}))
cv.wait(l);
@ -66,21 +59,19 @@ struct MultiQueueWaiter {
};
// A threadsafe-queue. http://stackoverflow.com/a/16075550
template <class T>
struct ThreadedQueue : public BaseThreadQueue {
public:
template <class T> struct ThreadedQueue : public BaseThreadQueue {
public:
ThreadedQueue() {
owned_waiter_ = std::make_unique<MultiQueueWaiter>();
waiter_ = owned_waiter_.get();
}
explicit ThreadedQueue(MultiQueueWaiter* waiter) : waiter_(waiter) {}
explicit ThreadedQueue(MultiQueueWaiter *waiter) : waiter_(waiter) {}
// Returns the number of elements in the queue. This is lock-free.
size_t Size() const { return total_count_; }
// Add an element to the queue.
template <void (std::deque<T>::*push)(T&&)>
void Push(T&& t, bool priority) {
template <void (std::deque<T>::*push)(T &&)> void Push(T &&t, bool priority) {
std::lock_guard<std::mutex> lock(mutex_);
if (priority)
(priority_.*push)(std::move(t));
@ -90,7 +81,7 @@ struct ThreadedQueue : public BaseThreadQueue {
waiter_->cv.notify_one();
}
void PushBack(T&& t, bool priority = false) {
void PushBack(T &&t, bool priority = false) {
Push<&std::deque<T>::push_back>(std::move(t), priority);
}
@ -123,7 +114,7 @@ struct ThreadedQueue : public BaseThreadQueue {
waiter_->cv.wait(lock,
[&]() { return !priority_.empty() || !queue_.empty(); });
auto execute = [&](std::deque<T>* q) {
auto execute = [&](std::deque<T> *q) {
auto val = std::move(q->front());
q->pop_front();
--total_count_;
@ -138,7 +129,7 @@ struct ThreadedQueue : public BaseThreadQueue {
// value if the queue is empty.
std::optional<T> TryPopFront() {
std::lock_guard<std::mutex> lock(mutex_);
auto execute = [&](std::deque<T>* q) {
auto execute = [&](std::deque<T> *q) {
auto val = std::move(q->front());
q->pop_front();
--total_count_;
@ -151,21 +142,20 @@ struct ThreadedQueue : public BaseThreadQueue {
return std::nullopt;
}
template <typename Fn>
void Iterate(Fn fn) {
template <typename Fn> void Iterate(Fn fn) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& entry : priority_)
for (auto &entry : priority_)
fn(entry);
for (auto& entry : queue_)
for (auto &entry : queue_)
fn(entry);
}
mutable std::mutex mutex_;
private:
private:
std::atomic<int> total_count_{0};
std::deque<T> priority_;
std::deque<T> queue_;
MultiQueueWaiter* waiter_;
MultiQueueWaiter *waiter_;
std::unique_ptr<MultiQueueWaiter> owned_waiter_;
};

View File

@ -7,16 +7,16 @@ using namespace llvm;
#include <siphash.h>
#include <algorithm>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <algorithm>
#include <functional>
#include <string.h>
#include <unordered_map>
using namespace std::placeholders;
void TrimInPlace(std::string& s) {
void TrimInPlace(std::string &s) {
auto f = [](char c) { return !isspace(c); };
s.erase(s.begin(), std::find_if(s.begin(), s.end(), f));
s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end());
@ -34,7 +34,8 @@ uint64_t HashUsr(std::string_view s) {
// k is an arbitrary key. Don't change it.
const uint8_t k[16] = {0xd0, 0xe5, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52,
0x61, 0x79, 0xea, 0x70, 0xca, 0x70, 0xf0, 0x0d};
(void)siphash(reinterpret_cast<const uint8_t*>(s.data()), s.size(), k, out, 8);
(void)siphash(reinterpret_cast<const uint8_t *>(s.data()), s.size(), k, out,
8);
return ret;
}
@ -52,20 +53,20 @@ bool StartsWith(std::string_view s, std::string_view prefix) {
std::equal(prefix.begin(), prefix.end(), s.begin());
}
bool EndsWithAny(std::string_view s, const std::vector<std::string>& ss) {
bool EndsWithAny(std::string_view s, const std::vector<std::string> &ss) {
return std::any_of(ss.begin(), ss.end(), std::bind(EndsWith, s, _1));
}
bool FindAnyPartial(const std::string& value,
const std::vector<std::string>& values) {
bool FindAnyPartial(const std::string &value,
const std::vector<std::string> &values) {
return std::any_of(std::begin(values), std::end(values),
[&value](const std::string& v) {
[&value](const std::string &v) {
return value.find(v) != std::string::npos;
});
}
std::vector<std::string> SplitString(const std::string& str,
const std::string& delimiter) {
std::vector<std::string> SplitString(const std::string &str,
const std::string &delimiter) {
// http://stackoverflow.com/a/13172514
std::vector<std::string> strings;
@ -82,10 +83,10 @@ std::vector<std::string> SplitString(const std::string& str,
return strings;
}
std::string LowerPathIfInsensitive(const std::string& path) {
std::string LowerPathIfInsensitive(const std::string &path) {
#if defined(_WIN32)
std::string ret = path;
for (char& c : ret)
for (char &c : ret)
c = tolower(c);
return ret;
#else
@ -93,14 +94,14 @@ std::string LowerPathIfInsensitive(const std::string& path) {
#endif
}
void EnsureEndsInSlash(std::string& path) {
void EnsureEndsInSlash(std::string &path) {
if (path.empty() || path[path.size() - 1] != '/')
path += '/';
}
std::string EscapeFileName(std::string path) {
bool slash = path.size() && path.back() == '/';
for (char& c : path)
for (char &c : path)
if (c == '\\' || c == '/' || c == ':')
c = '@';
if (slash)
@ -108,11 +109,12 @@ std::string EscapeFileName(std::string path) {
return path;
}
std::optional<std::string> ReadContent(const std::string& filename) {
std::optional<std::string> ReadContent(const std::string &filename) {
char buf[4096];
std::string ret;
FILE* f = fopen(filename.c_str(), "rb");
if (!f) return {};
FILE *f = fopen(filename.c_str(), "rb");
if (!f)
return {};
size_t n;
while ((n = fread(buf, 1, sizeof buf, f)) > 0)
ret.append(buf, n);
@ -120,8 +122,8 @@ std::optional<std::string> ReadContent(const std::string& filename) {
return ret;
}
void WriteToFile(const std::string& filename, const std::string& content) {
FILE* f = fopen(filename.c_str(), "wb");
void WriteToFile(const std::string &filename, const std::string &content) {
FILE *f = fopen(filename.c_str(), "wb");
if (!f ||
(content.size() && fwrite(content.c_str(), content.size(), 1, f) != 1)) {
LOG_S(ERROR) << "failed to write to " << filename << ' ' << strerror(errno);
@ -130,7 +132,7 @@ void WriteToFile(const std::string& filename, const std::string& content) {
fclose(f);
}
std::optional<int64_t> LastWriteTime(const std::string& filename) {
std::optional<int64_t> LastWriteTime(const std::string &filename) {
sys::fs::file_status Status;
if (sys::fs::status(filename, Status))
return {};
@ -139,8 +141,7 @@ std::optional<int64_t> LastWriteTime(const std::string& filename) {
// Find discontinous |search| in |content|.
// Return |found| and the count of skipped chars before found.
int ReverseSubseqMatch(std::string_view pat,
std::string_view text,
int ReverseSubseqMatch(std::string_view pat, std::string_view text,
int case_sensitivity) {
if (case_sensitivity == 1)
case_sensitivity = std::any_of(pat.begin(), pat.end(), isupper) ? 2 : 0;
@ -155,6 +156,4 @@ int ReverseSubseqMatch(std::string_view pat,
return -1;
}
std::string GetDefaultResourceDirectory() {
return DEFAULT_RESOURCE_DIRECTORY;
}
std::string GetDefaultResourceDirectory() { return DEFAULT_RESOURCE_DIRECTORY; }

View File

@ -13,7 +13,7 @@ namespace llvm {
class StringRef;
}
void TrimInPlace(std::string& s);
void TrimInPlace(std::string &s);
std::string Trim(std::string s);
uint64_t HashUsr(std::string_view s);
@ -22,22 +22,21 @@ uint64_t HashUsr(llvm::StringRef s);
// Returns true if |value| starts/ends with |start| or |ending|.
bool StartsWith(std::string_view value, std::string_view start);
bool EndsWith(std::string_view value, std::string_view ending);
bool EndsWithAny(std::string_view s, const std::vector<std::string>& ss);
bool FindAnyPartial(const std::string& value,
const std::vector<std::string>& values);
bool EndsWithAny(std::string_view s, const std::vector<std::string> &ss);
bool FindAnyPartial(const std::string &value,
const std::vector<std::string> &values);
std::vector<std::string> SplitString(const std::string& str,
const std::string& delimiter);
std::vector<std::string> SplitString(const std::string &str,
const std::string &delimiter);
std::string LowerPathIfInsensitive(const std::string& path);
std::string LowerPathIfInsensitive(const std::string &path);
template <typename TValues, typename TMap>
std::string StringJoinMap(const TValues& values,
const TMap& map,
const std::string& sep = ", ") {
std::string StringJoinMap(const TValues &values, const TMap &map,
const std::string &sep = ", ") {
std::string result;
bool first = true;
for (auto& entry : values) {
for (auto &entry : values) {
if (!first)
result += sep;
first = false;
@ -47,24 +46,23 @@ std::string StringJoinMap(const TValues& values,
}
template <typename TValues>
std::string StringJoin(const TValues& values, const std::string& sep = ", ") {
return StringJoinMap(values, [](const std::string& entry) { return entry; },
std::string StringJoin(const TValues &values, const std::string &sep = ", ") {
return StringJoinMap(values, [](const std::string &entry) { return entry; },
sep);
}
// Ensures that |path| ends in a slash.
void EnsureEndsInSlash(std::string& path);
void EnsureEndsInSlash(std::string &path);
// Converts a file path to one that can be used as filename.
// e.g. foo/bar.c => foo_bar.c
std::string EscapeFileName(std::string path);
std::optional<std::string> ReadContent(const std::string& filename);
void WriteToFile(const std::string& filename, const std::string& content);
std::optional<int64_t> LastWriteTime(const std::string& filename);
std::optional<std::string> ReadContent(const std::string &filename);
void WriteToFile(const std::string &filename, const std::string &content);
std::optional<int64_t> LastWriteTime(const std::string &filename);
int ReverseSubseqMatch(std::string_view pat,
std::string_view text,
int ReverseSubseqMatch(std::string_view pat, std::string_view text,
int case_sensitivity);
// http://stackoverflow.com/a/38140932
@ -76,25 +74,24 @@ int ReverseSubseqMatch(std::string_view pat,
// };
// MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3)
inline void hash_combine(std::size_t& seed) {}
inline void hash_combine(std::size_t &seed) {}
template <typename T, typename... Rest>
inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
inline void hash_combine(std::size_t &seed, const T &v, Rest... rest) {
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
hash_combine(seed, rest...);
}
#define MAKE_HASHABLE(type, ...) \
namespace std { \
template <> \
struct hash<type> { \
std::size_t operator()(const type& t) const { \
std::size_t ret = 0; \
hash_combine(ret, __VA_ARGS__); \
return ret; \
} \
}; \
#define MAKE_HASHABLE(type, ...) \
namespace std { \
template <> struct hash<type> { \
std::size_t operator()(const type &t) const { \
std::size_t ret = 0; \
hash_combine(ret, __VA_ARGS__); \
return ret; \
} \
}; \
}
std::string GetDefaultResourceDirectory();

View File

@ -17,7 +17,7 @@ constexpr int kMaxDiff = 20;
// |kMaxColumnAlignSize|.
constexpr int kMaxColumnAlignSize = 200;
lsPosition GetPositionForOffset(const std::string& content, int offset) {
lsPosition GetPositionForOffset(const std::string &content, int offset) {
if (offset >= content.size())
offset = (int)content.size() - 1;
@ -32,7 +32,7 @@ lsPosition GetPositionForOffset(const std::string& content, int offset) {
return {line, col};
}
std::vector<std::string> ToLines(const std::string& content) {
std::vector<std::string> ToLines(const std::string &content) {
std::vector<std::string> result;
std::istringstream lines(content);
std::string line;
@ -45,7 +45,7 @@ std::vector<std::string> ToLines(const std::string& content) {
// Myers' O(ND) diff algorithm.
// Costs: insertion=1, deletion=1, no substitution.
// If the distance is larger than threshold, returns threshould + 1.
int MyersDiff(const char* a, int la, const char* b, int lb, int threshold) {
int MyersDiff(const char *a, int la, const char *b, int lb, int threshold) {
assert(threshold <= kMaxDiff);
static int v_static[2 * kMaxColumnAlignSize + 2];
const char *ea = a + la, *eb = b + lb;
@ -61,7 +61,7 @@ int MyersDiff(const char* a, int la, const char* b, int lb, int threshold) {
if (la + lb > 2 * kMaxColumnAlignSize)
return std::min(abs(la - lb), threshold + 1);
int* v = v_static + lb;
int *v = v_static + lb;
v[1] = 0;
for (int di = 0; di <= threshold; di++) {
int low = -di + 2 * std::max(0, di - lb),
@ -80,7 +80,7 @@ int MyersDiff(const char* a, int la, const char* b, int lb, int threshold) {
return threshold + 1;
}
int MyersDiff(const std::string& a, const std::string& b, int threshold) {
int MyersDiff(const std::string &a, const std::string &b, int threshold) {
return MyersDiff(a.data(), a.size(), b.data(), b.size(), threshold);
}
@ -107,7 +107,7 @@ std::vector<int> EditDistanceVector(std::string a, std::string b) {
// Find matching position of |a[column]| in |b|.
// This is actually a single step of Hirschberg's sequence alignment algorithm.
int AlignColumn(const std::string& a, int column, std::string b, bool is_end) {
int AlignColumn(const std::string &a, int column, std::string b, bool is_end) {
int head = 0, tail = 0;
while (head < (int)a.size() && head < (int)b.size() && a[head] == b[head])
head++;
@ -149,12 +149,10 @@ int AlignColumn(const std::string& a, int column, std::string b, bool is_end) {
// Find matching buffer line of index_lines[line].
// By symmetry, this can also be used to find matching index line of a buffer
// line.
std::optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
const std::vector<int>& index_to_buffer,
int line,
int* column,
const std::vector<std::string>& buffer_lines,
bool is_end) {
std::optional<int>
FindMatchingLine(const std::vector<std::string> &index_lines,
const std::vector<int> &index_to_buffer, int line, int *column,
const std::vector<std::string> &buffer_lines, bool is_end) {
// If this is a confident mapping, returns.
if (index_to_buffer[line] >= 0) {
int ret = index_to_buffer[line];
@ -179,7 +177,7 @@ std::optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
// Search for lines [up,down] and use Myers's diff algorithm to find the best
// match (least edit distance).
int best = up, best_dist = kMaxDiff + 1;
const std::string& needle = index_lines[line];
const std::string &needle = index_lines[line];
for (int i = up; i <= down; i++) {
int dist = MyersDiff(needle, buffer_lines[i], kMaxDiff);
if (dist < best_dist) {
@ -193,17 +191,17 @@ std::optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
return best;
}
} // namespace
} // namespace
WorkingFile::WorkingFile(const std::string& filename,
const std::string& buffer_content)
WorkingFile::WorkingFile(const std::string &filename,
const std::string &buffer_content)
: filename(filename), buffer_content(buffer_content) {
OnBufferContentUpdated();
// SetIndexContent gets called when the file is opened.
}
void WorkingFile::SetIndexContent(const std::string& index_content) {
void WorkingFile::SetIndexContent(const std::string &index_content) {
index_lines = ToLines(index_content);
index_to_buffer.clear();
@ -234,7 +232,7 @@ void WorkingFile::ComputeLineMapping() {
// For index line i, set index_to_buffer[i] to -1 if line i is duplicated.
int i = 0;
for (auto& line : index_lines) {
for (auto &line : index_lines) {
uint64_t h = HashUsr(line);
auto it = hash_to_unique.find(h);
if (it == hash_to_unique.end()) {
@ -251,7 +249,7 @@ void WorkingFile::ComputeLineMapping() {
// For buffer line i, set buffer_to_index[i] to -1 if line i is duplicated.
i = 0;
hash_to_unique.clear();
for (auto& line : buffer_lines) {
for (auto &line : buffer_lines) {
uint64_t h = HashUsr(line);
auto it = hash_to_unique.find(h);
if (it == hash_to_unique.end()) {
@ -300,9 +298,8 @@ void WorkingFile::ComputeLineMapping() {
buffer_to_index[index_to_buffer[i]] = i;
}
std::optional<int> WorkingFile::GetBufferPosFromIndexPos(int line,
int* column,
bool is_end) {
std::optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int *column,
bool is_end) {
if (line < 0 || line >= (int)index_lines.size()) {
LOG_S(WARNING) << "bad index_line (got " << line << ", expected [0, "
<< index_lines.size() << ")) in " << filename;
@ -315,9 +312,8 @@ std::optional<int> WorkingFile::GetBufferPosFromIndexPos(int line,
buffer_lines, is_end);
}
std::optional<int> WorkingFile::GetIndexPosFromBufferPos(int line,
int* column,
bool is_end) {
std::optional<int> WorkingFile::GetIndexPosFromBufferPos(int line, int *column,
bool is_end) {
// See GetBufferLineFromIndexLine for additional comments.
if (line < 0 || line >= (int)buffer_lines.size())
return std::nullopt;
@ -329,9 +325,8 @@ std::optional<int> WorkingFile::GetIndexPosFromBufferPos(int line,
}
std::string WorkingFile::FindClosestCallNameInBuffer(
lsPosition position,
int* active_parameter,
lsPosition* completion_position) const {
lsPosition position, int *active_parameter,
lsPosition *completion_position) const {
*active_parameter = 0;
int offset = GetOffsetForPosition(position, buffer_content);
@ -378,10 +373,8 @@ std::string WorkingFile::FindClosestCallNameInBuffer(
}
lsPosition WorkingFile::FindStableCompletionSource(
lsPosition position,
bool* is_global_completion,
std::string* existing_completion,
lsPosition* replace_end_pos) const {
lsPosition position, bool *is_global_completion,
std::string *existing_completion, lsPosition *replace_end_pos) const {
*is_global_completion = true;
int start_offset = GetOffsetForPosition(position, buffer_content);
@ -410,7 +403,8 @@ lsPosition WorkingFile::FindStableCompletionSource(
*replace_end_pos = position;
for (int i = start_offset; i < buffer_content.size(); i++) {
char c = buffer_content[i];
if (!isalnum(c) && c != '_') break;
if (!isalnum(c) && c != '_')
break;
// We know that replace_end_pos and position are on the same line.
replace_end_pos->character++;
}
@ -419,41 +413,41 @@ lsPosition WorkingFile::FindStableCompletionSource(
return GetPositionForOffset(buffer_content, offset);
}
WorkingFile* WorkingFiles::GetFileByFilename(const std::string& filename) {
WorkingFile *WorkingFiles::GetFileByFilename(const std::string &filename) {
std::lock_guard<std::mutex> lock(files_mutex);
return GetFileByFilenameNoLock(filename);
}
WorkingFile* WorkingFiles::GetFileByFilenameNoLock(
const std::string& filename) {
for (auto& file : files) {
WorkingFile *
WorkingFiles::GetFileByFilenameNoLock(const std::string &filename) {
for (auto &file : files) {
if (file->filename == filename)
return file.get();
}
return nullptr;
}
void WorkingFiles::DoAction(const std::function<void()>& action) {
void WorkingFiles::DoAction(const std::function<void()> &action) {
std::lock_guard<std::mutex> lock(files_mutex);
action();
}
void WorkingFiles::DoActionOnFile(
const std::string& filename,
const std::function<void(WorkingFile* file)>& action) {
const std::string &filename,
const std::function<void(WorkingFile *file)> &action) {
std::lock_guard<std::mutex> lock(files_mutex);
WorkingFile* file = GetFileByFilenameNoLock(filename);
WorkingFile *file = GetFileByFilenameNoLock(filename);
action(file);
}
WorkingFile* WorkingFiles::OnOpen(const lsTextDocumentItem& open) {
WorkingFile *WorkingFiles::OnOpen(const lsTextDocumentItem &open) {
std::lock_guard<std::mutex> lock(files_mutex);
std::string filename = open.uri.GetPath();
std::string content = open.text;
// The file may already be open.
if (WorkingFile* file = GetFileByFilenameNoLock(filename)) {
if (WorkingFile *file = GetFileByFilenameNoLock(filename)) {
file->version = open.version;
file->buffer_content = content;
file->OnBufferContentUpdated();
@ -464,11 +458,11 @@ WorkingFile* WorkingFiles::OnOpen(const lsTextDocumentItem& open) {
return files[files.size() - 1].get();
}
void WorkingFiles::OnChange(const lsTextDocumentDidChangeParams& change) {
void WorkingFiles::OnChange(const lsTextDocumentDidChangeParams &change) {
std::lock_guard<std::mutex> lock(files_mutex);
std::string filename = change.textDocument.uri.GetPath();
WorkingFile* file = GetFileByFilenameNoLock(filename);
WorkingFile *file = GetFileByFilenameNoLock(filename);
if (!file) {
LOG_S(WARNING) << "Could not change " << filename
<< " because it was not open";
@ -479,7 +473,7 @@ void WorkingFiles::OnChange(const lsTextDocumentDidChangeParams& change) {
if (change.textDocument.version)
file->version = *change.textDocument.version;
for (const lsTextDocumentContentChangeEvent& diff : change.contentChanges) {
for (const lsTextDocumentContentChangeEvent &diff : change.contentChanges) {
// Per the spec replace everything if the rangeLength and range are not set.
// See https://github.com/Microsoft/language-server-protocol/issues/9.
if (!diff.range) {
@ -500,7 +494,7 @@ void WorkingFiles::OnChange(const lsTextDocumentDidChangeParams& change) {
}
}
void WorkingFiles::OnClose(const lsTextDocumentIdentifier& close) {
void WorkingFiles::OnClose(const lsTextDocumentIdentifier &close) {
std::lock_guard<std::mutex> lock(files_mutex);
std::string filename = close.uri.GetPath();
@ -516,13 +510,13 @@ void WorkingFiles::OnClose(const lsTextDocumentIdentifier& close) {
<< " because it was not open";
}
WorkingFiles::Snapshot WorkingFiles::AsSnapshot(
const std::vector<std::string>& filter_paths) {
WorkingFiles::Snapshot
WorkingFiles::AsSnapshot(const std::vector<std::string> &filter_paths) {
std::lock_guard<std::mutex> lock(files_mutex);
Snapshot result;
result.files.reserve(files.size());
for (const auto& file : files) {
for (const auto &file : files) {
if (filter_paths.empty() || FindAnyPartial(file->filename, filter_paths))
result.files.push_back({file->filename, file->buffer_content});
}

View File

@ -29,10 +29,10 @@ struct WorkingFile {
// lock!
std::vector<lsDiagnostic> diagnostics_;
WorkingFile(const std::string& filename, const std::string& buffer_content);
WorkingFile(const std::string &filename, const std::string &buffer_content);
// This should be called when the indexed content has changed.
void SetIndexContent(const std::string& index_content);
void SetIndexContent(const std::string &index_content);
// This should be called whenever |buffer_content| has changed.
void OnBufferContentUpdated();
@ -40,10 +40,12 @@ struct WorkingFile {
// Also resolves |column| if not NULL.
// When resolving a range, use is_end = false for begin() and is_end =
// true for end() to get a better alignment of |column|.
std::optional<int> GetBufferPosFromIndexPos(int line, int* column, bool is_end);
std::optional<int> GetBufferPosFromIndexPos(int line, int *column,
bool is_end);
// Finds the index line number which maps to buffer line number |line|.
// Also resolves |column| if not NULL.
std::optional<int> GetIndexPosFromBufferPos(int line, int* column, bool is_end);
std::optional<int> GetIndexPosFromBufferPos(int line, int *column,
bool is_end);
// TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into
// lex_utils.h/cc
@ -53,10 +55,9 @@ struct WorkingFile {
//
// |completion_position| will be point to a good code completion location to
// for fetching signatures.
std::string FindClosestCallNameInBuffer(
lsPosition position,
int* active_parameter,
lsPosition* completion_position = nullptr) const;
std::string
FindClosestCallNameInBuffer(lsPosition position, int *active_parameter,
lsPosition *completion_position = nullptr) const;
// Returns a relatively stable completion position (it jumps back until there
// is a non-alphanumeric character).
@ -66,11 +67,11 @@ struct WorkingFile {
// The out param |existing_completion| is set to any existing completion
// content the user has entered.
lsPosition FindStableCompletionSource(lsPosition position,
bool* is_global_completion,
std::string* existing_completion,
lsPosition* replace_end_pos) const;
bool *is_global_completion,
std::string *existing_completion,
lsPosition *replace_end_pos) const;
private:
private:
// Compute index_to_buffer and buffer_to_index.
void ComputeLineMapping();
};
@ -90,29 +91,29 @@ struct WorkingFiles {
//
// Find the file with the given filename.
WorkingFile* GetFileByFilename(const std::string& filename);
WorkingFile* GetFileByFilenameNoLock(const std::string& filename);
WorkingFile *GetFileByFilename(const std::string &filename);
WorkingFile *GetFileByFilenameNoLock(const std::string &filename);
// Run |action| under the lock.
void DoAction(const std::function<void()>& action);
void DoAction(const std::function<void()> &action);
// Run |action| on the file identified by |filename|. This executes under the
// lock.
void DoActionOnFile(const std::string& filename,
const std::function<void(WorkingFile* file)>& action);
void DoActionOnFile(const std::string &filename,
const std::function<void(WorkingFile *file)> &action);
WorkingFile* OnOpen(const lsTextDocumentItem& open);
void OnChange(const lsTextDocumentDidChangeParams& change);
void OnClose(const lsTextDocumentIdentifier& close);
WorkingFile *OnOpen(const lsTextDocumentItem &open);
void OnChange(const lsTextDocumentDidChangeParams &change);
void OnClose(const lsTextDocumentIdentifier &close);
// If |filter_paths| is non-empty, only files which contain any of the given
// strings. For example, {"foo", "bar"} means that every result has either the
// string "foo" or "bar" contained within it.
Snapshot AsSnapshot(const std::vector<std::string>& filter_paths);
Snapshot AsSnapshot(const std::vector<std::string> &filter_paths);
// Use unique_ptrs so we can handout WorkingFile ptrs and not have them
// invalidated if we resize files.
std::vector<std::unique_ptr<WorkingFile>> files;
std::mutex files_mutex; // Protects |files|.
std::mutex files_mutex; // Protects |files|.
};
int GetOffsetForPosition(lsPosition position, std::string_view content);