Simplify IpcManager.

It no longer supports multi-process IPC; remove some of the extra code that was used to support that.
This commit is contained in:
Jacob Dufault 2017-12-04 00:13:35 -08:00
parent b64b8b5493
commit 6c5f1d9c88
4 changed files with 203 additions and 251 deletions

View File

@ -126,7 +126,7 @@ bool FindFileOrFail(QueryDatabase* db,
out.id = *id; out.id = *id;
out.error.code = lsErrorCodes::InternalError; out.error.code = lsErrorCodes::InternalError;
out.error.message = "Unable to find file " + absolute_path; out.error.message = "Unable to find file " + absolute_path;
IpcManager::instance()->SendOutMessageToClient(IpcId::Cout, out); IpcManager::WriteStdout(IpcId::Cout, out);
} }
return false; return false;
@ -141,8 +141,7 @@ void EmitInactiveLines(WorkingFile* working_file,
if (ls_skipped) if (ls_skipped)
out.params.inactiveRegions.push_back(*ls_skipped); out.params.inactiveRegions.push_back(*ls_skipped);
} }
IpcManager::instance()->SendOutMessageToClient( IpcManager::WriteStdout(IpcId::CqueryPublishInactiveRegions, out);
IpcId::CqueryPublishInactiveRegions, out);
} }
// Caches symbols for a single file for semantic highlighting to provide // Caches symbols for a single file for semantic highlighting to provide
@ -276,8 +275,7 @@ void EmitSemanticHighlighting(QueryDatabase* db,
out.params.uri = lsDocumentUri::FromPath(working_file->filename); out.params.uri = lsDocumentUri::FromPath(working_file->filename);
for (auto& entry : grouped_symbols) for (auto& entry : grouped_symbols)
out.params.symbols.push_back(entry.second); out.params.symbols.push_back(entry.second);
IpcManager::instance()->SendOutMessageToClient( IpcManager::WriteStdout(IpcId::CqueryPublishSemanticHighlighting, out);
IpcId::CqueryPublishSemanticHighlighting, out);
} }
optional<int> FindIncludeLine(const std::vector<std::string>& lines, optional<int> FindIncludeLine(const std::vector<std::string>& lines,
@ -522,11 +520,10 @@ void EmitDiagnostics(WorkingFiles* working_files,
std::string path, std::string path,
NonElidedVector<lsDiagnostic> diagnostics) { NonElidedVector<lsDiagnostic> diagnostics) {
// Emit diagnostics. // Emit diagnostics.
Out_TextDocumentPublishDiagnostics diagnostic_response; Out_TextDocumentPublishDiagnostics out;
diagnostic_response.params.uri = lsDocumentUri::FromPath(path); out.params.uri = lsDocumentUri::FromPath(path);
diagnostic_response.params.diagnostics = diagnostics; out.params.diagnostics = diagnostics;
IpcManager::instance()->SendOutMessageToClient( IpcManager::WriteStdout(IpcId::TextDocumentPublishDiagnostics, out);
IpcId::TextDocumentPublishDiagnostics, diagnostic_response);
// Cache diagnostics so we can show fixits. // Cache diagnostics so we can show fixits.
working_files->DoActionOnFile(path, [&](WorkingFile* working_file) { working_files->DoActionOnFile(path, [&](WorkingFile* working_file) {
@ -879,7 +876,7 @@ void EmitProgress(Config* config, QueueManager* queue) {
out.params.onIdMappedCount = queue->on_id_mapped.Size(); out.params.onIdMappedCount = queue->on_id_mapped.Size();
out.params.onIndexedCount = queue->on_indexed.Size(); out.params.onIndexedCount = queue->on_indexed.Size();
IpcManager::instance()->SendOutMessageToClient(IpcId::Cout, out); IpcManager::WriteStdout(IpcId::Cout, out);
} }
} }
@ -1486,7 +1483,7 @@ bool QueryDbMainLoop(Config* config,
bool did_work = false; bool did_work = false;
std::vector<std::unique_ptr<BaseIpcMessage>> messages = std::vector<std::unique_ptr<BaseIpcMessage>> messages =
ipc->GetMessages(IpcManager::Destination::Server); ipc->for_querydb.DequeueAll();
for (auto& message : messages) { for (auto& message : messages) {
did_work = true; did_work = true;
@ -1560,67 +1557,63 @@ bool QueryDbMainLoop(Config* config,
// TODO: query request->params.capabilities.textDocument and support // TODO: query request->params.capabilities.textDocument and support
// only things the client supports. // only things the client supports.
auto response = Out_InitializeResponse(); Out_InitializeResponse out;
response.id = request->id; out.id = request->id;
// response.result.capabilities.textDocumentSync = // out.result.capabilities.textDocumentSync =
// lsTextDocumentSyncOptions(); // lsTextDocumentSyncOptions();
// response.result.capabilities.textDocumentSync->openClose = true; // out.result.capabilities.textDocumentSync->openClose = true;
// response.result.capabilities.textDocumentSync->change = // out.result.capabilities.textDocumentSync->change =
// lsTextDocumentSyncKind::Full; // lsTextDocumentSyncKind::Full;
// response.result.capabilities.textDocumentSync->willSave = true; // out.result.capabilities.textDocumentSync->willSave = true;
// response.result.capabilities.textDocumentSync->willSaveWaitUntil = // out.result.capabilities.textDocumentSync->willSaveWaitUntil =
// true; // true;
response.result.capabilities.textDocumentSync = out.result.capabilities.textDocumentSync =
lsTextDocumentSyncKind::Incremental; lsTextDocumentSyncKind::Incremental;
response.result.capabilities.renameProvider = true; out.result.capabilities.renameProvider = true;
response.result.capabilities.completionProvider = out.result.capabilities.completionProvider = lsCompletionOptions();
lsCompletionOptions(); out.result.capabilities.completionProvider->resolveProvider = false;
response.result.capabilities.completionProvider->resolveProvider =
false;
// vscode doesn't support trigger character sequences, so we use ':' // vscode doesn't support trigger character sequences, so we use ':'
// for // for
// '::' and '>' for '->'. See // '::' and '>' for '->'. See
// https://github.com/Microsoft/language-server-protocol/issues/138. // https://github.com/Microsoft/language-server-protocol/issues/138.
response.result.capabilities.completionProvider->triggerCharacters = { out.result.capabilities.completionProvider->triggerCharacters = {
".", ":", ">", "#"}; ".", ":", ">", "#"};
response.result.capabilities.signatureHelpProvider = out.result.capabilities.signatureHelpProvider =
lsSignatureHelpOptions(); lsSignatureHelpOptions();
// NOTE: If updating signature help tokens make sure to also update // NOTE: If updating signature help tokens make sure to also update
// WorkingFile::FindClosestCallNameInBuffer. // WorkingFile::FindClosestCallNameInBuffer.
response.result.capabilities.signatureHelpProvider out.result.capabilities.signatureHelpProvider->triggerCharacters = {
->triggerCharacters = {"(", ","}; "(", ","};
response.result.capabilities.codeLensProvider = lsCodeLensOptions(); out.result.capabilities.codeLensProvider = lsCodeLensOptions();
response.result.capabilities.codeLensProvider->resolveProvider = out.result.capabilities.codeLensProvider->resolveProvider = false;
false;
response.result.capabilities.definitionProvider = true; out.result.capabilities.definitionProvider = true;
response.result.capabilities.documentHighlightProvider = true; out.result.capabilities.documentHighlightProvider = true;
response.result.capabilities.hoverProvider = true; out.result.capabilities.hoverProvider = true;
response.result.capabilities.referencesProvider = true; out.result.capabilities.referencesProvider = true;
response.result.capabilities.codeActionProvider = true; out.result.capabilities.codeActionProvider = true;
response.result.capabilities.documentSymbolProvider = true; out.result.capabilities.documentSymbolProvider = true;
response.result.capabilities.workspaceSymbolProvider = true; out.result.capabilities.workspaceSymbolProvider = true;
response.result.capabilities.documentLinkProvider = out.result.capabilities.documentLinkProvider =
lsDocumentLinkOptions(); lsDocumentLinkOptions();
response.result.capabilities.documentLinkProvider->resolveProvider = out.result.capabilities.documentLinkProvider->resolveProvider = false;
false;
ipc->SendOutMessageToClient(IpcId::Initialize, response); IpcManager::WriteStdout(IpcId::Initialize, out);
// Set project root. // Set project root.
config->projectRoot = config->projectRoot =
NormalizePath(request->params.rootUri->GetPath()); NormalizePath(request->params.rootUri->GetPath());
EnsureEndsInSlash(config->projectRoot); EnsureEndsInSlash(config->projectRoot);
MakeDirectoryRecursive( MakeDirectoryRecursive(config->cacheDirectory +
config->cacheDirectory + EscapeFileName(config->projectRoot)); EscapeFileName(config->projectRoot));
// Start indexer threads. // Start indexer threads.
if (config->indexerCount == 0) { if (config->indexerCount == 0) {
@ -1725,24 +1718,24 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_CqueryTypeHierarchyTree response; Out_CqueryTypeHierarchyTree out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
if (ref.idx.kind == SymbolKind::Type) { if (ref.idx.kind == SymbolKind::Type) {
response.result = BuildInheritanceHierarchyForType( out.result = BuildInheritanceHierarchyForType(
db, working_files, QueryTypeId(ref.idx.idx)); db, working_files, QueryTypeId(ref.idx.idx));
break; break;
} }
if (ref.idx.kind == SymbolKind::Func) { if (ref.idx.kind == SymbolKind::Func) {
response.result = BuildInheritanceHierarchyForFunc( out.result = BuildInheritanceHierarchyForFunc(
db, working_files, QueryFuncId(ref.idx.idx)); db, working_files, QueryFuncId(ref.idx.idx));
break; break;
} }
} }
ipc->SendOutMessageToClient(IpcId::CqueryTypeHierarchyTree, response); IpcManager::WriteStdout(IpcId::CqueryTypeHierarchyTree, out);
break; break;
} }
@ -1757,34 +1750,33 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_CqueryCallTree response; Out_CqueryCallTree out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
if (ref.idx.kind == SymbolKind::Func) { if (ref.idx.kind == SymbolKind::Func) {
response.result = BuildInitialCallTree(db, working_files, out.result = BuildInitialCallTree(db, working_files,
QueryFuncId(ref.idx.idx)); QueryFuncId(ref.idx.idx));
break; break;
} }
} }
ipc->SendOutMessageToClient(IpcId::CqueryCallTreeInitial, response); IpcManager::WriteStdout(IpcId::CqueryCallTreeInitial, out);
break; break;
} }
case IpcId::CqueryCallTreeExpand: { case IpcId::CqueryCallTreeExpand: {
auto msg = message->As<Ipc_CqueryCallTreeExpand>(); auto msg = message->As<Ipc_CqueryCallTreeExpand>();
Out_CqueryCallTree response; Out_CqueryCallTree out;
response.id = msg->id; out.id = msg->id;
auto func_id = db->usr_to_func.find(msg->params.usr); auto func_id = db->usr_to_func.find(msg->params.usr);
if (func_id != db->usr_to_func.end()) if (func_id != db->usr_to_func.end())
response.result = out.result = BuildExpandCallTree(db, working_files, func_id->second);
BuildExpandCallTree(db, working_files, func_id->second);
ipc->SendOutMessageToClient(IpcId::CqueryCallTreeExpand, response); IpcManager::WriteStdout(IpcId::CqueryCallTreeExpand, out);
break; break;
} }
@ -1799,18 +1791,18 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_LocationList response; Out_LocationList out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
if (ref.idx.kind == SymbolKind::Type) { if (ref.idx.kind == SymbolKind::Type) {
QueryType& type = db->types[ref.idx.idx]; QueryType& type = db->types[ref.idx.idx];
std::vector<QueryLocation> locations = std::vector<QueryLocation> locations =
ToQueryLocation(db, type.instances); ToQueryLocation(db, type.instances);
response.result = GetLsLocations(db, working_files, locations); out.result = GetLsLocations(db, working_files, locations);
} }
} }
ipc->SendOutMessageToClient(IpcId::CqueryVars, response); IpcManager::WriteStdout(IpcId::CqueryVars, out);
break; break;
} }
@ -1825,8 +1817,8 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_LocationList response; Out_LocationList out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
if (ref.idx.kind == SymbolKind::Func) { if (ref.idx.kind == SymbolKind::Func) {
@ -1840,10 +1832,10 @@ bool QueryDbMainLoop(Config* config,
GetCallersForAllDerivedFunctions(db, func)) GetCallersForAllDerivedFunctions(db, func))
locations.push_back(func_ref.loc); locations.push_back(func_ref.loc);
response.result = GetLsLocations(db, working_files, locations); out.result = GetLsLocations(db, working_files, locations);
} }
} }
ipc->SendOutMessageToClient(IpcId::CqueryCallers, response); IpcManager::WriteStdout(IpcId::CqueryCallers, out);
break; break;
} }
@ -1858,8 +1850,8 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_LocationList response; Out_LocationList out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
if (ref.idx.kind == SymbolKind::Type) { if (ref.idx.kind == SymbolKind::Type) {
@ -1868,7 +1860,7 @@ bool QueryDbMainLoop(Config* config,
continue; continue;
std::vector<QueryLocation> locations = std::vector<QueryLocation> locations =
ToQueryLocation(db, type.def->parents); ToQueryLocation(db, type.def->parents);
response.result = GetLsLocations(db, working_files, locations); out.result = GetLsLocations(db, working_files, locations);
} else if (ref.idx.kind == SymbolKind::Func) { } else if (ref.idx.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = db->funcs[ref.idx.idx];
optional<QueryLocation> location = optional<QueryLocation> location =
@ -1879,10 +1871,10 @@ bool QueryDbMainLoop(Config* config,
GetLsLocation(db, working_files, *location); GetLsLocation(db, working_files, *location);
if (!ls_loc) if (!ls_loc)
continue; continue;
response.result.push_back(*ls_loc); out.result.push_back(*ls_loc);
} }
} }
ipc->SendOutMessageToClient(IpcId::CqueryBase, response); IpcManager::WriteStdout(IpcId::CqueryBase, out);
break; break;
} }
@ -1897,23 +1889,23 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_LocationList response; Out_LocationList out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
if (ref.idx.kind == SymbolKind::Type) { if (ref.idx.kind == SymbolKind::Type) {
QueryType& type = db->types[ref.idx.idx]; QueryType& type = db->types[ref.idx.idx];
std::vector<QueryLocation> locations = std::vector<QueryLocation> locations =
ToQueryLocation(db, type.derived); ToQueryLocation(db, type.derived);
response.result = GetLsLocations(db, working_files, locations); out.result = GetLsLocations(db, working_files, locations);
} else if (ref.idx.kind == SymbolKind::Func) { } else if (ref.idx.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx]; QueryFunc& func = db->funcs[ref.idx.idx];
std::vector<QueryLocation> locations = std::vector<QueryLocation> locations =
ToQueryLocation(db, func.derived); ToQueryLocation(db, func.derived);
response.result = GetLsLocations(db, working_files, locations); out.result = GetLsLocations(db, working_files, locations);
} }
} }
ipc->SendOutMessageToClient(IpcId::CqueryDerived, response); IpcManager::WriteStdout(IpcId::CqueryDerived, out);
break; break;
} }
@ -1989,10 +1981,9 @@ bool QueryDbMainLoop(Config* config,
std::string path = msg->params.textDocument.uri.GetPath(); std::string path = msg->params.textDocument.uri.GetPath();
// Clear any diagnostics for the file. // Clear any diagnostics for the file.
Out_TextDocumentPublishDiagnostics diag; Out_TextDocumentPublishDiagnostics out;
diag.params.uri = msg->params.textDocument.uri; out.params.uri = msg->params.textDocument.uri;
IpcManager::instance()->SendOutMessageToClient( IpcManager::WriteStdout(IpcId::TextDocumentPublishDiagnostics, out);
IpcId::TextDocumentPublishDiagnostics, diag);
// Remove internal state. // Remove internal state.
working_files->OnClose(msg->params); working_files->OnClose(msg->params);
@ -2039,19 +2030,19 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_TextDocumentRename response; Out_TextDocumentRename out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
// Found symbol. Return references to rename. // Found symbol. Return references to rename.
std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx); std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx);
response.result = out.result =
BuildWorkspaceEdit(db, working_files, uses, msg->params.newName); BuildWorkspaceEdit(db, working_files, uses, msg->params.newName);
break; break;
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentRename, response); IpcManager::WriteStdout(IpcId::TextDocumentRename, out);
break; break;
} }
@ -2070,22 +2061,21 @@ bool QueryDbMainLoop(Config* config,
buffer_line = file->all_buffer_lines[msg->params.position.line]; buffer_line = file->all_buffer_lines[msg->params.position.line];
if (ShouldRunIncludeCompletion(buffer_line)) { if (ShouldRunIncludeCompletion(buffer_line)) {
Out_TextDocumentComplete complete_response; Out_TextDocumentComplete out;
complete_response.id = msg->id; out.id = msg->id;
{ {
std::unique_lock<std::mutex> lock( std::unique_lock<std::mutex> lock(
include_complete->completion_items_mutex, std::defer_lock); include_complete->completion_items_mutex, std::defer_lock);
if (include_complete->is_scanning) if (include_complete->is_scanning)
lock.lock(); lock.lock();
complete_response.result.items.assign( out.result.items.assign(include_complete->completion_items.begin(),
include_complete->completion_items.begin(),
include_complete->completion_items.end()); include_complete->completion_items.end());
if (lock) if (lock)
lock.unlock(); lock.unlock();
// Update textEdit params. // Update textEdit params.
for (lsCompletionItem& item : complete_response.result.items) { for (lsCompletionItem& item : out.result.items) {
item.textEdit->range.start.line = msg->params.position.line; item.textEdit->range.start.line = msg->params.position.line;
item.textEdit->range.start.character = 0; item.textEdit->range.start.character = 0;
item.textEdit->range.end.line = msg->params.position.line; item.textEdit->range.end.line = msg->params.position.line;
@ -2093,9 +2083,8 @@ bool QueryDbMainLoop(Config* config,
} }
} }
FilterCompletionResponse(&complete_response, buffer_line); FilterCompletionResponse(&out, buffer_line);
ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, IpcManager::WriteStdout(IpcId::TextDocumentCompletion, out);
complete_response);
} else { } else {
bool is_global_completion = false; bool is_global_completion = false;
std::string existing_completion; std::string existing_completion;
@ -2110,15 +2099,13 @@ bool QueryDbMainLoop(Config* config,
is_global_completion, existing_completion, is_global_completion, existing_completion,
msg](const NonElidedVector<lsCompletionItem>& results, msg](const NonElidedVector<lsCompletionItem>& results,
bool is_cached_result) { bool is_cached_result) {
Out_TextDocumentComplete complete_response; Out_TextDocumentComplete out;
complete_response.id = msg->id; out.id = msg->id;
complete_response.result.items = results; out.result.items = results;
// Emit completion results. // Emit completion results.
FilterCompletionResponse(&complete_response, FilterCompletionResponse(&out, existing_completion);
existing_completion); IpcManager::WriteStdout(IpcId::TextDocumentCompletion, out);
IpcManager::instance()->SendOutMessageToClient(
IpcId::TextDocumentCompletion, complete_response);
// Cache completion results. // Cache completion results.
if (!is_cached_result) { if (!is_cached_result) {
@ -2203,8 +2190,8 @@ bool QueryDbMainLoop(Config* config,
auto msg = message->As<Ipc_TextDocumentSignatureHelp>(); auto msg = message->As<Ipc_TextDocumentSignatureHelp>();
auto ipc = IpcManager::instance(); auto ipc = IpcManager::instance();
Out_TextDocumentSignatureHelp response; Out_TextDocumentSignatureHelp out;
response.id = msg->id; out.id = msg->id;
for (auto& result : results) { for (auto& result : results) {
if (result.label != search) if (result.label != search)
@ -2217,25 +2204,24 @@ bool QueryDbMainLoop(Config* config,
ls_param.label = parameter; ls_param.label = parameter;
signature.parameters.push_back(ls_param); signature.parameters.push_back(ls_param);
} }
response.result.signatures.push_back(signature); out.result.signatures.push_back(signature);
} }
// Guess the signature the user wants based on available parameter // Guess the signature the user wants based on available parameter
// count. // count.
response.result.activeSignature = 0; out.result.activeSignature = 0;
for (size_t i = 0; i < response.result.signatures.size(); ++i) { for (size_t i = 0; i < out.result.signatures.size(); ++i) {
if (active_param < response.result.signatures.size()) { if (active_param < out.result.signatures.size()) {
response.result.activeSignature = (int)i; out.result.activeSignature = (int)i;
break; break;
} }
} }
// Set signature to what we parsed from the working file. // Set signature to what we parsed from the working file.
response.result.activeParameter = active_param; out.result.activeParameter = active_param;
Timer timer; Timer timer;
ipc->SendOutMessageToClient(IpcId::TextDocumentSignatureHelp, IpcManager::WriteStdout(IpcId::TextDocumentSignatureHelp, out);
response);
if (!is_cached_result) { if (!is_cached_result) {
signature_cache->WithLock([&]() { signature_cache->WithLock([&]() {
@ -2276,8 +2262,8 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_TextDocumentDefinition response; Out_TextDocumentDefinition out;
response.id = msg->id; out.id = msg->id;
int target_line = msg->params.position.line + 1; int target_line = msg->params.position.line + 1;
int target_column = msg->params.position.character + 1; int target_column = msg->params.position.character + 1;
@ -2317,36 +2303,35 @@ bool QueryDbMainLoop(Config* config,
optional<lsLocation> ls_declaration = optional<lsLocation> ls_declaration =
GetLsLocation(db, working_files, declaration); GetLsLocation(db, working_files, declaration);
if (ls_declaration) if (ls_declaration)
response.result.push_back(*ls_declaration); out.result.push_back(*ls_declaration);
} }
// We found some declarations. Break so we don't add the definition // We found some declarations. Break so we don't add the definition
// location. // location.
if (!response.result.empty()) if (!out.result.empty())
break; break;
} }
if (def_loc) { if (def_loc) {
PushBack(&response.result, PushBack(&out.result, GetLsLocation(db, working_files, *def_loc));
GetLsLocation(db, working_files, *def_loc));
} }
if (!response.result.empty()) if (!out.result.empty())
break; break;
} }
// No symbols - check for includes. // No symbols - check for includes.
if (response.result.empty()) { if (out.result.empty()) {
for (const IndexInclude& include : file->def->includes) { for (const IndexInclude& include : file->def->includes) {
if (include.line == target_line) { if (include.line == target_line) {
lsLocation result; lsLocation result;
result.uri = lsDocumentUri::FromPath(include.resolved_path); result.uri = lsDocumentUri::FromPath(include.resolved_path);
response.result.push_back(result); out.result.push_back(result);
break; break;
} }
} }
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentDefinition, response); IpcManager::WriteStdout(IpcId::TextDocumentDefinition, out);
break; break;
} }
@ -2362,14 +2347,14 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_TextDocumentDocumentHighlight response; Out_TextDocumentDocumentHighlight out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
// Found symbol. Return references to highlight. // Found symbol. Return references to highlight.
std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx); std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx);
response.result.reserve(uses.size()); out.result.reserve(uses.size());
for (const QueryLocation& use : uses) { for (const QueryLocation& use : uses) {
if (use.path != file_id) if (use.path != file_id)
continue; continue;
@ -2382,13 +2367,12 @@ bool QueryDbMainLoop(Config* config,
lsDocumentHighlight highlight; lsDocumentHighlight highlight;
highlight.kind = lsDocumentHighlightKind::Text; highlight.kind = lsDocumentHighlightKind::Text;
highlight.range = ls_location->range; highlight.range = ls_location->range;
response.result.push_back(highlight); out.result.push_back(highlight);
} }
break; break;
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentHighlight, IpcManager::WriteStdout(IpcId::TextDocumentDocumentHighlight, out);
response);
break; break;
} }
@ -2403,8 +2387,8 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_TextDocumentHover response; Out_TextDocumentHover out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
@ -2414,14 +2398,14 @@ bool QueryDbMainLoop(Config* config,
if (!ls_range) if (!ls_range)
continue; continue;
response.result.contents.value = GetHoverForSymbol(db, ref.idx); out.result.contents.value = GetHoverForSymbol(db, ref.idx);
response.result.contents.language = file->def->language; out.result.contents.language = file->def->language;
response.result.range = *ls_range; out.result.range = *ls_range;
break; break;
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentHover, response); IpcManager::WriteStdout(IpcId::TextDocumentHover, out);
break; break;
} }
@ -2436,8 +2420,8 @@ bool QueryDbMainLoop(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_TextDocumentReferences response; Out_TextDocumentReferences out;
response.id = msg->id; out.id = msg->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, msg->params.position)) { FindSymbolsAtLocation(working_file, file, msg->params.position)) {
@ -2449,7 +2433,7 @@ bool QueryDbMainLoop(Config* config,
// Found symbol. Return references. // Found symbol. Return references.
std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx); std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx);
response.result.reserve(uses.size()); out.result.reserve(uses.size());
for (const QueryLocation& use : uses) { for (const QueryLocation& use : uses) {
if (excluded_declaration.has_value() && if (excluded_declaration.has_value() &&
use == *excluded_declaration) use == *excluded_declaration)
@ -2458,20 +2442,20 @@ bool QueryDbMainLoop(Config* config,
optional<lsLocation> ls_location = optional<lsLocation> ls_location =
GetLsLocation(db, working_files, use); GetLsLocation(db, working_files, use);
if (ls_location) if (ls_location)
response.result.push_back(*ls_location); out.result.push_back(*ls_location);
} }
break; break;
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentReferences, response); IpcManager::WriteStdout(IpcId::TextDocumentReferences, out);
break; break;
} }
case IpcId::TextDocumentDocumentSymbol: { case IpcId::TextDocumentDocumentSymbol: {
auto msg = message->As<Ipc_TextDocumentDocumentSymbol>(); auto msg = message->As<Ipc_TextDocumentDocumentSymbol>();
Out_TextDocumentDocumentSymbol response; Out_TextDocumentDocumentSymbol out;
response.id = msg->id; out.id = msg->id;
QueryFile* file; QueryFile* file;
if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(),
@ -2489,19 +2473,18 @@ bool QueryDbMainLoop(Config* config,
if (!location) if (!location)
continue; continue;
info->location = *location; info->location = *location;
response.result.push_back(*info); out.result.push_back(*info);
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentSymbol, IpcManager::WriteStdout(IpcId::TextDocumentDocumentSymbol, out);
response);
break; break;
} }
case IpcId::TextDocumentDocumentLink: { case IpcId::TextDocumentDocumentLink: {
auto msg = message->As<Ipc_TextDocumentDocumentLink>(); auto msg = message->As<Ipc_TextDocumentDocumentLink>();
Out_TextDocumentDocumentLink response; Out_TextDocumentDocumentLink out;
response.id = msg->id; out.id = msg->id;
if (config->showDocumentLinksOnIncludes) { if (config->showDocumentLinksOnIncludes) {
QueryFile* file; QueryFile* file;
@ -2534,11 +2517,11 @@ bool QueryDbMainLoop(Config* config,
lsDocumentLink link; lsDocumentLink link;
link.target = lsDocumentUri::FromPath(include.resolved_path); link.target = lsDocumentUri::FromPath(include.resolved_path);
link.range = *between_quotes; link.range = *between_quotes;
response.result.push_back(link); out.result.push_back(link);
} }
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentLink, response); IpcManager::WriteStdout(IpcId::TextDocumentDocumentLink, out);
break; break;
} }
@ -2570,8 +2553,8 @@ bool QueryDbMainLoop(Config* config,
break; break;
} }
Out_TextDocumentCodeAction response; Out_TextDocumentCodeAction out;
response.id = msg->id; out.id = msg->id;
// TODO: auto-insert namespace? // TODO: auto-insert namespace?
@ -2637,7 +2620,7 @@ bool QueryDbMainLoop(Config* config,
command.title = "Auto-Implement " + std::to_string(num_edits) + command.title = "Auto-Implement " + std::to_string(num_edits) +
" methods on " + type.def->short_name; " methods on " + type.def->short_name;
command.command = "cquery._autoImplement"; command.command = "cquery._autoImplement";
response.result.push_back(command); out.result.push_back(command);
break; break;
} }
@ -2665,7 +2648,7 @@ bool QueryDbMainLoop(Config* config,
if (edit->range.start.line >= default_line) if (edit->range.start.line >= default_line)
edit->newText.insert(0, "\n"); edit->newText.insert(0, "\n");
command.arguments.edits.push_back(*edit); command.arguments.edits.push_back(*edit);
response.result.push_back(command); out.result.push_back(command);
break; break;
} }
default: default:
@ -2673,7 +2656,7 @@ bool QueryDbMainLoop(Config* config,
} }
// Only show one auto-impl section. // Only show one auto-impl section.
if (!response.result.empty()) if (!out.result.empty())
break; break;
} }
@ -2762,7 +2745,7 @@ bool QueryDbMainLoop(Config* config,
" includes to insert"; " includes to insert";
command.command = "cquery._insertInclude"; command.command = "cquery._insertInclude";
command.arguments.textDocumentUri = msg->params.textDocument.uri; command.arguments.textDocumentUri = msg->params.textDocument.uri;
response.result.push_back(command); out.result.push_back(command);
} }
} }
@ -2775,19 +2758,19 @@ bool QueryDbMainLoop(Config* config,
command.command = "cquery._applyFixIt"; command.command = "cquery._applyFixIt";
command.arguments.textDocumentUri = msg->params.textDocument.uri; command.arguments.textDocumentUri = msg->params.textDocument.uri;
command.arguments.edits = diag.fixits_; command.arguments.edits = diag.fixits_;
response.result.push_back(command); out.result.push_back(command);
} }
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentCodeAction, response); IpcManager::WriteStdout(IpcId::TextDocumentCodeAction, out);
break; break;
} }
case IpcId::TextDocumentCodeLens: { case IpcId::TextDocumentCodeLens: {
auto msg = message->As<Ipc_TextDocumentCodeLens>(); auto msg = message->As<Ipc_TextDocumentCodeLens>();
Out_TextDocumentCodeLens response; Out_TextDocumentCodeLens out;
response.id = msg->id; out.id = msg->id;
lsDocumentUri file_as_uri = msg->params.textDocument.uri; lsDocumentUri file_as_uri = msg->params.textDocument.uri;
std::string path = file_as_uri.GetPath(); std::string path = file_as_uri.GetPath();
@ -2800,7 +2783,7 @@ bool QueryDbMainLoop(Config* config,
break; break;
CommonCodeLensParams common; CommonCodeLensParams common;
common.result = &response.result; common.result = &out.result;
common.db = db; common.db = db;
common.working_files = working_files; common.working_files = working_files;
common.working_file = working_files->GetFileByFilename(file->def->path); common.working_file = working_files->GetFileByFilename(file->def->path);
@ -2884,7 +2867,7 @@ bool QueryDbMainLoop(Config* config,
code_lens.command->arguments.uri = ls_base->uri; code_lens.command->arguments.uri = ls_base->uri;
code_lens.command->arguments.position = code_lens.command->arguments.position =
ls_base->range.start; ls_base->range.start;
response.result.push_back(code_lens); out.result.push_back(code_lens);
} }
} }
} }
@ -2918,7 +2901,7 @@ bool QueryDbMainLoop(Config* config,
}; };
} }
ipc->SendOutMessageToClient(IpcId::TextDocumentCodeLens, response); IpcManager::WriteStdout(IpcId::TextDocumentCodeLens, out);
break; break;
} }
@ -2929,8 +2912,8 @@ bool QueryDbMainLoop(Config* config,
// inspiration // inspiration
auto msg = message->As<Ipc_WorkspaceSymbol>(); auto msg = message->As<Ipc_WorkspaceSymbol>();
Out_WorkspaceSymbol response; Out_WorkspaceSymbol out;
response.id = msg->id; out.id = msg->id;
LOG_S(INFO) << "[querydb] Considering " << db->detailed_names.size() LOG_S(INFO) << "[querydb] Considering " << db->detailed_names.size()
<< " candidates for query " << msg->params.query; << " candidates for query " << msg->params.query;
@ -2947,13 +2930,13 @@ bool QueryDbMainLoop(Config* config,
continue; continue;
InsertSymbolIntoResult(db, working_files, db->symbols[i], InsertSymbolIntoResult(db, working_files, db->symbols[i],
&response.result); &out.result);
if (response.result.size() >= config->maxWorkspaceSearchResults) if (out.result.size() >= config->maxWorkspaceSearchResults)
break; break;
} }
} }
if (response.result.size() < config->maxWorkspaceSearchResults) { if (out.result.size() < config->maxWorkspaceSearchResults) {
for (int i = 0; i < db->detailed_names.size(); ++i) { for (int i = 0; i < db->detailed_names.size(); ++i) {
if (SubstringMatch(query, db->detailed_names[i])) { if (SubstringMatch(query, db->detailed_names[i])) {
// Do not show the same entry twice. // Do not show the same entry twice.
@ -2961,16 +2944,16 @@ bool QueryDbMainLoop(Config* config,
continue; continue;
InsertSymbolIntoResult(db, working_files, db->symbols[i], InsertSymbolIntoResult(db, working_files, db->symbols[i],
&response.result); &out.result);
if (response.result.size() >= config->maxWorkspaceSearchResults) if (out.result.size() >= config->maxWorkspaceSearchResults)
break; break;
} }
} }
} }
LOG_S(INFO) << "[querydb] Found " << response.result.size() LOG_S(INFO) << "[querydb] Found " << out.result.size()
<< " results for query " << query; << " results for query " << query;
ipc->SendOutMessageToClient(IpcId::WorkspaceSymbol, response); IpcManager::WriteStdout(IpcId::WorkspaceSymbol, out);
break; break;
} }
@ -3076,8 +3059,8 @@ void RunQueryDbThread(const std::string& bin_name,
FreeUnusedMemory(); FreeUnusedMemory();
if (!did_work) { if (!did_work) {
waiter->Wait({IpcManager::instance()->threaded_queue_for_server_.get(), waiter->Wait({&IpcManager::instance()->for_querydb, &queue->do_id_map,
&queue->do_id_map, &queue->on_indexed}); &queue->on_indexed});
} }
} }
} }
@ -3142,7 +3125,7 @@ void LaunchStdinLoop(Config* config,
// loop to exit the thread. If we keep parsing input stdin is likely // loop to exit the thread. If we keep parsing input stdin is likely
// closed so cquery will exit. // closed so cquery will exit.
LOG_S(INFO) << "cquery will exit when all threads are idle"; LOG_S(INFO) << "cquery will exit when all threads are idle";
ipc->SendMessage(IpcManager::Destination::Server, std::move(message)); ipc->for_querydb.Enqueue(std::move(message));
return WorkThread::Result::ExitThread; return WorkThread::Result::ExitThread;
} }
@ -3174,7 +3157,7 @@ void LaunchStdinLoop(Config* config,
case IpcId::CqueryDerived: case IpcId::CqueryDerived:
case IpcId::CqueryIndexFile: case IpcId::CqueryIndexFile:
case IpcId::CqueryQueryDbWaitForIdleIndexer: { case IpcId::CqueryQueryDbWaitForIdleIndexer: {
ipc->SendMessage(IpcManager::Destination::Server, std::move(message)); ipc->for_querydb.Enqueue(std::move(message));
break; break;
} }
@ -3195,42 +3178,32 @@ void LaunchStdoutThread(std::unordered_map<IpcId, Timer>* request_times,
WorkThread::StartThread("stdout", [=]() { WorkThread::StartThread("stdout", [=]() {
IpcManager* ipc = IpcManager::instance(); IpcManager* ipc = IpcManager::instance();
std::vector<std::unique_ptr<BaseIpcMessage>> messages = std::vector<IpcManager::StdoutMessage> messages =
ipc->GetMessages(IpcManager::Destination::Client); ipc->for_stdout.DequeueAll();
if (messages.empty()) { if (messages.empty()) {
waiter->Wait({ipc->threaded_queue_for_client_.get()}); waiter->Wait({&ipc->for_stdout});
return queue->HasWork() ? WorkThread::Result::MoreWork return queue->HasWork() ? WorkThread::Result::MoreWork
: WorkThread::Result::NoWork; : WorkThread::Result::NoWork;
} }
for (auto& message : messages) { for (auto& message : messages) {
switch (message->method_id) { if (ShouldDisplayIpcTiming(message.id)) {
case IpcId::Cout: { Timer time = (*request_times)[message.id];
auto msg = message->As<Ipc_Cout>(); time.ResetAndPrint("[e2e] Running " +
std::string(IpcIdToString(message.id)));
if (ShouldDisplayIpcTiming(msg->original_ipc_id)) {
Timer time = (*request_times)[msg->original_ipc_id];
time.ResetAndPrint("[e2e] Running " + std::string(IpcIdToString(
msg->original_ipc_id)));
} }
if (g_log_stdin_stdout_to_stderr) { if (g_log_stdin_stdout_to_stderr) {
std::string printed = "[COUT] |" + msg->content + "|\n"; std::ostringstream sstream;
std::cerr << printed; sstream << "[COUT] |";
sstream << message.content;
sstream << "|\n";
std::cerr << sstream.str();
std::cerr.flush(); std::cerr.flush();
} }
std::cout << msg->content; std::cout << message.content;
std::cout.flush(); std::cout.flush();
break;
}
default: {
LOG_S(FATAL) << "Exiting; unhandled IPC message "
<< IpcIdToString(message->method_id);
exit(1);
}
}
} }
return WorkThread::Result::MoreWork; return WorkThread::Result::MoreWork;

View File

@ -1,5 +1,9 @@
#include "ipc_manager.h" #include "ipc_manager.h"
#include "language_server_api.h"
#include <sstream>
IpcManager* IpcManager::instance_ = nullptr; IpcManager* IpcManager::instance_ = nullptr;
// static // static
@ -12,35 +16,16 @@ void IpcManager::CreateInstance(MultiQueueWaiter* waiter) {
instance_ = new IpcManager(waiter); instance_ = new IpcManager(waiter);
} }
ThreadedQueue<std::unique_ptr<BaseIpcMessage>>* IpcManager::GetThreadedQueue( // static
Destination destination) { void IpcManager::WriteStdout(IpcId id, lsBaseOutMessage& response) {
return destination == Destination::Client ? threaded_queue_for_client_.get()
: threaded_queue_for_server_.get();
}
void IpcManager::SendOutMessageToClient(IpcId id, lsBaseOutMessage& response) {
std::ostringstream sstream; std::ostringstream sstream;
response.Write(sstream); response.Write(sstream);
auto out = MakeUnique<Ipc_Cout>(); StdoutMessage out;
out->content = sstream.str(); out.content = sstream.str();
out->original_ipc_id = id; out.id = id;
GetThreadedQueue(Destination::Client)->Enqueue(std::move(out)); instance()->for_stdout.Enqueue(std::move(out));
} }
void IpcManager::SendMessage(Destination destination, IpcManager::IpcManager(MultiQueueWaiter* waiter)
std::unique_ptr<BaseIpcMessage> message) { : for_stdout(waiter), for_querydb(waiter) {}
GetThreadedQueue(destination)->Enqueue(std::move(message));
}
std::vector<std::unique_ptr<BaseIpcMessage>> IpcManager::GetMessages(
Destination destination) {
return GetThreadedQueue(destination)->DequeueAll();
}
IpcManager::IpcManager(MultiQueueWaiter* waiter) {
threaded_queue_for_client_ =
MakeUnique<ThreadedQueue<std::unique_ptr<BaseIpcMessage>>>(waiter);
threaded_queue_for_server_ =
MakeUnique<ThreadedQueue<std::unique_ptr<BaseIpcMessage>>>(waiter);
}

View File

@ -1,34 +1,28 @@
#pragma once #pragma once
#include "ipc.h" #include "ipc.h"
#include "language_server_api.h"
#include "threaded_queue.h" #include "threaded_queue.h"
#include <memory> #include <memory>
class lsBaseOutMessage;
struct IpcManager { struct IpcManager {
static IpcManager* instance_; struct StdoutMessage {
IpcId id;
std::string content;
};
ThreadedQueue<StdoutMessage> for_stdout;
ThreadedQueue<std::unique_ptr<BaseIpcMessage>> for_querydb;
static IpcManager* instance(); static IpcManager* instance();
static void CreateInstance(MultiQueueWaiter* waiter); static void CreateInstance(MultiQueueWaiter* waiter);
std::unique_ptr<ThreadedQueue<std::unique_ptr<BaseIpcMessage>>> static void WriteStdout(IpcId id, lsBaseOutMessage& response);
threaded_queue_for_client_;
std::unique_ptr<ThreadedQueue<std::unique_ptr<BaseIpcMessage>>>
threaded_queue_for_server_;
enum class Destination { Client, Server };
ThreadedQueue<std::unique_ptr<BaseIpcMessage>>* GetThreadedQueue(
Destination destination);
void SendOutMessageToClient(IpcId id, lsBaseOutMessage& response);
void SendMessage(Destination destination,
std::unique_ptr<BaseIpcMessage> message);
std::vector<std::unique_ptr<BaseIpcMessage>> GetMessages(
Destination destination);
private: private:
IpcManager(MultiQueueWaiter* waiter); explicit IpcManager(MultiQueueWaiter* waiter);
static IpcManager* instance_;
}; };

View File

@ -33,7 +33,7 @@ optional<Matcher> Matcher::Create(const std::string& search) {
out.params.type = lsMessageType::Error; out.params.type = lsMessageType::Error;
out.params.message = "cquery: Parsing EMCAScript regex \"" + search + out.params.message = "cquery: Parsing EMCAScript regex \"" + search +
"\" failed; " + e.what(); "\" failed; " + e.what();
IpcManager::instance()->SendOutMessageToClient(IpcId::Cout, out); IpcManager::WriteStdout(IpcId::Cout, out);
return nullopt; return nullopt;
} }
} }