mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-04 14:17:07 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									b64b8b5493
								
							
						
					
					
						commit
						6c5f1d9c88
					
				@ -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;
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -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_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user