mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-03 22:04:24 +00:00 
			
		
		
		
	Implement code actions using clang FixIts
- Also make server check client version and show an error message if they do not match.
This commit is contained in:
		
							parent
							
								
									440c6c5325
								
							
						
					
					
						commit
						f3d00dea23
					
				@ -26,6 +26,7 @@ be productive with cquery. Here's a list of implemented features:
 | 
				
			|||||||
  * global symbol search
 | 
					  * global symbol search
 | 
				
			||||||
  * hover
 | 
					  * hover
 | 
				
			||||||
  * diagnostics
 | 
					  * diagnostics
 | 
				
			||||||
 | 
					  * code actions (clang FixIts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Setup - build cquery, install extension, setup project
 | 
					# Setup - build cquery, install extension, setup project
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "libclangmm/Utility.h"
 | 
					#include "libclangmm/Utility.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lsRange GetLsRangeForFixIt(const CXSourceRange& range) {
 | 
				
			||||||
 | 
					  CXSourceLocation start = clang_getRangeStart(range);
 | 
				
			||||||
 | 
					  CXSourceLocation end = clang_getRangeEnd(range);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unsigned int start_line, start_column;
 | 
				
			||||||
 | 
					  clang_getSpellingLocation(start, nullptr, &start_line, &start_column, nullptr);
 | 
				
			||||||
 | 
					  unsigned int end_line, end_column;
 | 
				
			||||||
 | 
					  clang_getSpellingLocation(end, nullptr, &end_line, &end_column, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lsRange(
 | 
				
			||||||
 | 
					    lsPosition(start_line - 1, start_column - 1) /*start*/,
 | 
				
			||||||
 | 
					    lsPosition(end_line - 1, end_column) /*end*/);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic) {
 | 
					optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic) {
 | 
				
			||||||
  // Skip diagnostics in system headers.
 | 
					  // Skip diagnostics in system headers.
 | 
				
			||||||
  CXSourceLocation diag_loc = clang_getDiagnosticLocation(diagnostic);
 | 
					  CXSourceLocation diag_loc = clang_getDiagnosticLocation(diagnostic);
 | 
				
			||||||
@ -45,7 +63,19 @@ optional<lsDiagnostic> BuildDiagnostic(CXDiagnostic diagnostic) {
 | 
				
			|||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: integrate FixIts (ie, textDocument/codeAction)
 | 
					  // Report fixits
 | 
				
			||||||
 | 
					  unsigned num_fixits = clang_getDiagnosticNumFixIts(diagnostic);
 | 
				
			||||||
 | 
					  if (num_fixits > 0)
 | 
				
			||||||
 | 
					    std::cerr << "!!!! Got " << num_fixits << " fixits" << std::endl;
 | 
				
			||||||
 | 
					  for (unsigned i = 0; i < num_fixits; ++i) {
 | 
				
			||||||
 | 
					    CXSourceRange replacement_range;
 | 
				
			||||||
 | 
					    CXString text = clang_getDiagnosticFixIt(diagnostic, i, &replacement_range);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lsTextEdit edit;
 | 
				
			||||||
 | 
					    edit.newText = clang::ToString(text);
 | 
				
			||||||
 | 
					    edit.range = GetLsRangeForFixIt(replacement_range);
 | 
				
			||||||
 | 
					    ls_diagnostic.fixits_.push_back(edit);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  clang_disposeDiagnostic(diagnostic);
 | 
					  clang_disposeDiagnostic(diagnostic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,11 +31,15 @@
 | 
				
			|||||||
// ie, a fully linear view of a function with inline function calls expanded.
 | 
					// ie, a fully linear view of a function with inline function calls expanded.
 | 
				
			||||||
// We can probably use vscode decorators to achieve it.
 | 
					// We can probably use vscode decorators to achieve it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: implement ThreadPool type which monitors CPU usage / number of work items
 | 
				
			||||||
 | 
					// per second completed and scales up/down number of running threads.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<std::string> kEmptyArgs;
 | 
					std::vector<std::string> kEmptyArgs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Expected client version. We show an error if this doesn't match.
 | 
				
			||||||
 | 
					const int kExpectedClientVersion = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -898,6 +902,7 @@ void RegisterMessageTypes() {
 | 
				
			|||||||
  MessageRegistry::instance()->Register<Ipc_TextDocumentHover>();
 | 
					  MessageRegistry::instance()->Register<Ipc_TextDocumentHover>();
 | 
				
			||||||
  MessageRegistry::instance()->Register<Ipc_TextDocumentReferences>();
 | 
					  MessageRegistry::instance()->Register<Ipc_TextDocumentReferences>();
 | 
				
			||||||
  MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentSymbol>();
 | 
					  MessageRegistry::instance()->Register<Ipc_TextDocumentDocumentSymbol>();
 | 
				
			||||||
 | 
					  MessageRegistry::instance()->Register<Ipc_TextDocumentCodeAction>();
 | 
				
			||||||
  MessageRegistry::instance()->Register<Ipc_TextDocumentCodeLens>();
 | 
					  MessageRegistry::instance()->Register<Ipc_TextDocumentCodeLens>();
 | 
				
			||||||
  MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
 | 
					  MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
 | 
				
			||||||
  MessageRegistry::instance()->Register<Ipc_WorkspaceSymbol>();
 | 
					  MessageRegistry::instance()->Register<Ipc_WorkspaceSymbol>();
 | 
				
			||||||
@ -1103,6 +1108,11 @@ void ParseFile(IndexerConfig* config,
 | 
				
			|||||||
      diag.params.uri = lsDocumentUri::FromPath(new_index->path);
 | 
					      diag.params.uri = lsDocumentUri::FromPath(new_index->path);
 | 
				
			||||||
      diag.params.diagnostics = new_index->diagnostics;
 | 
					      diag.params.diagnostics = new_index->diagnostics;
 | 
				
			||||||
      IpcManager::instance()->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diag);
 | 
					      IpcManager::instance()->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Cache diagnostics so we can show fixits.
 | 
				
			||||||
 | 
					      WorkingFile* working_file = working_files->GetFileByFilename(new_index->path);
 | 
				
			||||||
 | 
					      if (working_file)
 | 
				
			||||||
 | 
					        working_file->diagnostics = new_index->diagnostics;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1418,6 +1428,19 @@ bool QueryDbMainLoop(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
          *config = *request->params.initializationOptions;
 | 
					          *config = *request->params.initializationOptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Check client version.
 | 
				
			||||||
 | 
					          if (config->clientVersion != kExpectedClientVersion) {
 | 
				
			||||||
 | 
					            Out_ShowLogMessage out;
 | 
				
			||||||
 | 
					            out.display_type = Out_ShowLogMessage::DisplayType::Show;
 | 
				
			||||||
 | 
					            out.params.type = lsMessageType::Error;
 | 
				
			||||||
 | 
					            out.params.message = "cquery client (v" + std::to_string(config->clientVersion) + ") and server (v" + std::to_string(kExpectedClientVersion) + ") version mismatch. Please update ";
 | 
				
			||||||
 | 
					            if (config->clientVersion > kExpectedClientVersion)
 | 
				
			||||||
 | 
					              out.params.message += "the cquery binary.";
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					              out.params.message += "your extension client (VSIX file).";
 | 
				
			||||||
 | 
					            out.Write(std::cout);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // Make sure cache directory is valid.
 | 
					          // Make sure cache directory is valid.
 | 
				
			||||||
          if (config->cacheDirectory.empty()) {
 | 
					          if (config->cacheDirectory.empty()) {
 | 
				
			||||||
            std::cerr << "No cache directory" << std::endl;
 | 
					            std::cerr << "No cache directory" << std::endl;
 | 
				
			||||||
@ -1486,6 +1509,8 @@ bool QueryDbMainLoop(
 | 
				
			|||||||
        response.result.capabilities.hoverProvider = true;
 | 
					        response.result.capabilities.hoverProvider = true;
 | 
				
			||||||
        response.result.capabilities.referencesProvider = true;
 | 
					        response.result.capabilities.referencesProvider = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response.result.capabilities.codeActionProvider = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        response.result.capabilities.documentSymbolProvider = true;
 | 
					        response.result.capabilities.documentSymbolProvider = true;
 | 
				
			||||||
        response.result.capabilities.workspaceSymbolProvider = true;
 | 
					        response.result.capabilities.workspaceSymbolProvider = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1716,7 +1741,7 @@ bool QueryDbMainLoop(
 | 
				
			|||||||
        if (file)
 | 
					        if (file)
 | 
				
			||||||
          params.position = file->FindStableCompletionSource(params.position);
 | 
					          params.position = file->FindStableCompletionSource(params.position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CompletionManager::OnComplete callback = std::bind([code_complete_cache](BaseIpcMessage* message, NonElidedVector<lsCompletionItem> results, NonElidedVector<lsDiagnostic> diagnostics) {
 | 
					        CompletionManager::OnComplete callback = std::bind([working_files, code_complete_cache](BaseIpcMessage* message, NonElidedVector<lsCompletionItem> results, NonElidedVector<lsDiagnostic> diagnostics) {
 | 
				
			||||||
          auto msg = static_cast<Ipc_TextDocumentComplete*>(message);
 | 
					          auto msg = static_cast<Ipc_TextDocumentComplete*>(message);
 | 
				
			||||||
          auto ipc = IpcManager::instance();
 | 
					          auto ipc = IpcManager::instance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1725,13 +1750,21 @@ bool QueryDbMainLoop(
 | 
				
			|||||||
          complete_response.result.isIncomplete = false;
 | 
					          complete_response.result.isIncomplete = false;
 | 
				
			||||||
          complete_response.result.items = results;
 | 
					          complete_response.result.items = results;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Emit completion results.
 | 
				
			||||||
          ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, complete_response);
 | 
					          ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, complete_response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Emit diagnostics.
 | 
				
			||||||
          Out_TextDocumentPublishDiagnostics diagnostic_response;
 | 
					          Out_TextDocumentPublishDiagnostics diagnostic_response;
 | 
				
			||||||
          diagnostic_response.params.uri = msg->params.textDocument.uri;
 | 
					          diagnostic_response.params.uri = msg->params.textDocument.uri;
 | 
				
			||||||
          diagnostic_response.params.diagnostics = diagnostics;
 | 
					          diagnostic_response.params.diagnostics = diagnostics;
 | 
				
			||||||
          ipc->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diagnostic_response);
 | 
					          ipc->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diagnostic_response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Cache diagnostics so we can show fixits.
 | 
				
			||||||
 | 
					          WorkingFile* working_file = working_files->GetFileByFilename(msg->params.textDocument.uri.GetPath());
 | 
				
			||||||
 | 
					          if (working_file)
 | 
				
			||||||
 | 
					            working_file->diagnostics = diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Cache completion results so if the user types backspace we can respond faster.
 | 
				
			||||||
          code_complete_cache->cached_path = msg->params.textDocument.uri.GetPath();
 | 
					          code_complete_cache->cached_path = msg->params.textDocument.uri.GetPath();
 | 
				
			||||||
          code_complete_cache->cached_completion_position = msg->params.position;
 | 
					          code_complete_cache->cached_completion_position = msg->params.position;
 | 
				
			||||||
          code_complete_cache->cached_results = results;
 | 
					          code_complete_cache->cached_results = results;
 | 
				
			||||||
@ -2021,6 +2054,50 @@ bool QueryDbMainLoop(
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case IpcId::TextDocumentCodeAction: {
 | 
				
			||||||
 | 
					        // NOTE: This code snippet will generate some FixIts for testing:
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        //    struct origin { int x, int y };
 | 
				
			||||||
 | 
					        //    void foo() {
 | 
				
			||||||
 | 
					        //      point origin = {
 | 
				
			||||||
 | 
					        //        x: 0.0,
 | 
				
			||||||
 | 
					        //        y: 0.0
 | 
				
			||||||
 | 
					        //      };
 | 
				
			||||||
 | 
					        //    }
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        auto msg = static_cast<Ipc_TextDocumentCodeAction*>(message.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        WorkingFile* working_file = working_files->GetFileByFilename(msg->params.textDocument.uri.GetPath());
 | 
				
			||||||
 | 
					        if (!working_file) {
 | 
				
			||||||
 | 
					          // TODO: send error response.
 | 
				
			||||||
 | 
					          std::cerr << "[error] textDocument/codeAction could not find working file" << std::endl;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int target_line = msg->params.range.start.line;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Out_TextDocumentCodeAction response;
 | 
				
			||||||
 | 
					        response.id = msg->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (lsDiagnostic& diag : working_file->diagnostics) {
 | 
				
			||||||
 | 
					          // clang does not provide accurate ennough column reporting for
 | 
				
			||||||
 | 
					          // diagnostics to do good column filtering, so report all
 | 
				
			||||||
 | 
					          // diagnostics on the line.
 | 
				
			||||||
 | 
					          if (!diag.fixits_.empty() && diag.range.start.line == target_line) {
 | 
				
			||||||
 | 
					            Out_TextDocumentCodeAction::Command command;
 | 
				
			||||||
 | 
					            command.title = "FixIt: " + diag.message;
 | 
				
			||||||
 | 
					            command.command = "cquery._applyFixIt";
 | 
				
			||||||
 | 
					            command.arguments.textDocumentUri = msg->params.textDocument.uri;
 | 
				
			||||||
 | 
					            command.arguments.edits = diag.fixits_;
 | 
				
			||||||
 | 
					            response.result.push_back(command);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response.Write(std::cerr);
 | 
				
			||||||
 | 
					        ipc->SendOutMessageToClient(IpcId::TextDocumentCodeAction, response);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case IpcId::TextDocumentCodeLens: {
 | 
					      case IpcId::TextDocumentCodeLens: {
 | 
				
			||||||
        auto msg = static_cast<Ipc_TextDocumentCodeLens*>(message.get());
 | 
					        auto msg = static_cast<Ipc_TextDocumentCodeLens*>(message.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2374,6 +2451,7 @@ void LanguageServerStdinLoop(IndexerConfig* config, std::unordered_map<IpcId, Ti
 | 
				
			|||||||
    case IpcId::TextDocumentHover:
 | 
					    case IpcId::TextDocumentHover:
 | 
				
			||||||
    case IpcId::TextDocumentReferences:
 | 
					    case IpcId::TextDocumentReferences:
 | 
				
			||||||
    case IpcId::TextDocumentDocumentSymbol:
 | 
					    case IpcId::TextDocumentDocumentSymbol:
 | 
				
			||||||
 | 
					    case IpcId::TextDocumentCodeAction:
 | 
				
			||||||
    case IpcId::TextDocumentCodeLens:
 | 
					    case IpcId::TextDocumentCodeLens:
 | 
				
			||||||
    case IpcId::WorkspaceSymbol:
 | 
					    case IpcId::WorkspaceSymbol:
 | 
				
			||||||
    case IpcId::CqueryFreshenIndex:
 | 
					    case IpcId::CqueryFreshenIndex:
 | 
				
			||||||
 | 
				
			|||||||
@ -38,6 +38,8 @@ const char* IpcIdToString(IpcId id) {
 | 
				
			|||||||
    return "textDocument/references";
 | 
					    return "textDocument/references";
 | 
				
			||||||
  case IpcId::TextDocumentDocumentSymbol:
 | 
					  case IpcId::TextDocumentDocumentSymbol:
 | 
				
			||||||
    return "textDocument/documentSymbol";
 | 
					    return "textDocument/documentSymbol";
 | 
				
			||||||
 | 
					  case IpcId::TextDocumentCodeAction:
 | 
				
			||||||
 | 
					    return "textDocument/codeAction";
 | 
				
			||||||
  case IpcId::TextDocumentCodeLens:
 | 
					  case IpcId::TextDocumentCodeLens:
 | 
				
			||||||
    return "textDocument/codeLens";
 | 
					    return "textDocument/codeLens";
 | 
				
			||||||
  case IpcId::CodeLensResolve:
 | 
					  case IpcId::CodeLensResolve:
 | 
				
			||||||
 | 
				
			|||||||
@ -24,6 +24,7 @@ enum class IpcId : int {
 | 
				
			|||||||
  TextDocumentHover,
 | 
					  TextDocumentHover,
 | 
				
			||||||
  TextDocumentReferences,
 | 
					  TextDocumentReferences,
 | 
				
			||||||
  TextDocumentDocumentSymbol,
 | 
					  TextDocumentDocumentSymbol,
 | 
				
			||||||
 | 
					  TextDocumentCodeAction,
 | 
				
			||||||
  TextDocumentCodeLens,
 | 
					  TextDocumentCodeLens,
 | 
				
			||||||
  CodeLensResolve,
 | 
					  CodeLensResolve,
 | 
				
			||||||
  WorkspaceSymbol,
 | 
					  WorkspaceSymbol,
 | 
				
			||||||
 | 
				
			|||||||
@ -73,6 +73,9 @@ struct IndexerConfig {
 | 
				
			|||||||
  bool enableCacheWrite = true;
 | 
					  bool enableCacheWrite = true;
 | 
				
			||||||
  // If false, the index will not be loaded from a previous run.
 | 
					  // If false, the index will not be loaded from a previous run.
 | 
				
			||||||
  bool enableCacheRead = true;
 | 
					  bool enableCacheRead = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Version of the client.
 | 
				
			||||||
 | 
					  int clientVersion = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
MAKE_REFLECT_STRUCT(IndexerConfig,
 | 
					MAKE_REFLECT_STRUCT(IndexerConfig,
 | 
				
			||||||
  cacheDirectory,
 | 
					  cacheDirectory,
 | 
				
			||||||
@ -81,8 +84,9 @@ MAKE_REFLECT_STRUCT(IndexerConfig,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  maxWorkspaceSearchResults,
 | 
					  maxWorkspaceSearchResults,
 | 
				
			||||||
  indexerCount,
 | 
					  indexerCount,
 | 
				
			||||||
  enableIndexing, enableCacheWrite, enableCacheRead);
 | 
					  enableIndexing, enableCacheWrite, enableCacheRead,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  clientVersion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -330,6 +334,8 @@ struct lsCommand {
 | 
				
			|||||||
  // Actual command identifier.
 | 
					  // Actual command identifier.
 | 
				
			||||||
  std::string command;
 | 
					  std::string command;
 | 
				
			||||||
  // Arguments to run the command with.
 | 
					  // Arguments to run the command with.
 | 
				
			||||||
 | 
					  // **NOTE** This must be serialized as an array. Use
 | 
				
			||||||
 | 
					  // MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY.
 | 
				
			||||||
  T arguments;
 | 
					  T arguments;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
template<typename TVisitor, typename T>
 | 
					template<typename TVisitor, typename T>
 | 
				
			||||||
@ -591,6 +597,9 @@ struct lsDiagnostic {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // The diagnostic's message.
 | 
					  // The diagnostic's message.
 | 
				
			||||||
  std::string message;
 | 
					  std::string message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Non-serialized set of fixits.
 | 
				
			||||||
 | 
					  NonElidedVector<lsTextEdit> fixits_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, source, message);
 | 
					MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, source, message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1325,17 +1334,17 @@ struct lsSignatureHelp {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // The active signature. If omitted or the value lies outside the
 | 
					  // The active signature. If omitted or the value lies outside the
 | 
				
			||||||
  // range of `signatures` the value defaults to zero or is ignored if
 | 
					  // range of `signatures` the value defaults to zero or is ignored if
 | 
				
			||||||
  // `signatures.length === 0`. Whenever possible implementors should 
 | 
					  // `signatures.length === 0`. Whenever possible implementors should
 | 
				
			||||||
  // make an active decision about the active signature and shouldn't 
 | 
					  // make an active decision about the active signature and shouldn't
 | 
				
			||||||
  // rely on a default value.
 | 
					  // rely on a default value.
 | 
				
			||||||
  // In future version of the protocol this property might become
 | 
					  // In future version of the protocol this property might become
 | 
				
			||||||
  // mandantory to better express this.
 | 
					  // mandantory to better express this.
 | 
				
			||||||
  optional<int> activeSignature;
 | 
					  optional<int> activeSignature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // The active parameter of the active signature. If omitted or the value
 | 
					  // The active parameter of the active signature. If omitted or the value
 | 
				
			||||||
  // lies outside the range of `signatures[activeSignature].parameters` 
 | 
					  // lies outside the range of `signatures[activeSignature].parameters`
 | 
				
			||||||
  // defaults to 0 if the active signature has parameters. If 
 | 
					  // defaults to 0 if the active signature has parameters. If
 | 
				
			||||||
  // the active signature has no parameters it is ignored. 
 | 
					  // the active signature has no parameters it is ignored.
 | 
				
			||||||
  // In future version of the protocol this property might become
 | 
					  // In future version of the protocol this property might become
 | 
				
			||||||
  // mandantory to better express the active parameter if the
 | 
					  // mandantory to better express the active parameter if the
 | 
				
			||||||
  // active signature does have any.
 | 
					  // active signature does have any.
 | 
				
			||||||
@ -1422,6 +1431,44 @@ struct Out_TextDocumentReferences : public lsOutMessage<Out_TextDocumentReferenc
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
MAKE_REFLECT_STRUCT(Out_TextDocumentReferences, jsonrpc, id, result);
 | 
					MAKE_REFLECT_STRUCT(Out_TextDocumentReferences, jsonrpc, id, result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code action
 | 
				
			||||||
 | 
					struct Ipc_TextDocumentCodeAction : public IpcMessage<Ipc_TextDocumentCodeAction> {
 | 
				
			||||||
 | 
					  const static IpcId kIpcId = IpcId::TextDocumentCodeAction;
 | 
				
			||||||
 | 
					  // Contains additional diagnostic information about the context in which
 | 
				
			||||||
 | 
					  // a code action is run.
 | 
				
			||||||
 | 
					  struct lsCodeActionContext {
 | 
				
			||||||
 | 
						  // An array of diagnostics.
 | 
				
			||||||
 | 
						  NonElidedVector<lsDiagnostic> diagnostics;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  // Params for the CodeActionRequest
 | 
				
			||||||
 | 
					  struct lsCodeActionParams {
 | 
				
			||||||
 | 
						  // The document in which the command was invoked.
 | 
				
			||||||
 | 
						  lsTextDocumentIdentifier textDocument;
 | 
				
			||||||
 | 
						  // The range for which the command was invoked.
 | 
				
			||||||
 | 
					    lsRange range;
 | 
				
			||||||
 | 
						  // Context carrying additional information.
 | 
				
			||||||
 | 
					    lsCodeActionContext context;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  lsRequestId id;
 | 
				
			||||||
 | 
					  lsCodeActionParams params;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction::lsCodeActionContext, diagnostics);
 | 
				
			||||||
 | 
					MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction::lsCodeActionParams, textDocument, range, context);
 | 
				
			||||||
 | 
					MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction, id, params);
 | 
				
			||||||
 | 
					struct Out_TextDocumentCodeAction : public lsOutMessage<Out_TextDocumentCodeAction> {
 | 
				
			||||||
 | 
					  struct CommandArgs {
 | 
				
			||||||
 | 
					    lsDocumentUri textDocumentUri;
 | 
				
			||||||
 | 
					    NonElidedVector<lsTextEdit> edits;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  using Command = lsCommand<CommandArgs>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  lsRequestId id;
 | 
				
			||||||
 | 
					  NonElidedVector<Command> result;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(Out_TextDocumentCodeAction::CommandArgs, textDocumentUri, edits);
 | 
				
			||||||
 | 
					MAKE_REFLECT_STRUCT(Out_TextDocumentCodeAction, jsonrpc, id, result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// List symbols in a document.
 | 
					// List symbols in a document.
 | 
				
			||||||
struct lsDocumentSymbolParams {
 | 
					struct lsDocumentSymbolParams {
 | 
				
			||||||
  lsTextDocumentIdentifier textDocument;
 | 
					  lsTextDocumentIdentifier textDocument;
 | 
				
			||||||
 | 
				
			|||||||
@ -56,7 +56,17 @@ struct IndexFile;
 | 
				
			|||||||
    REFLECT_MEMBER_END(); \
 | 
					    REFLECT_MEMBER_END(); \
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _MAPPABLE_REFLECT_ARRAY(name) \
 | 
				
			||||||
 | 
					  Reflect(visitor, value.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reflects the struct so it is serialized as an array instead of an object.
 | 
				
			||||||
 | 
					// This currently only supports writers.
 | 
				
			||||||
 | 
					#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \
 | 
				
			||||||
 | 
					  inline void Reflect(Writer& visitor, type& value) { \
 | 
				
			||||||
 | 
					    visitor.StartArray(); \
 | 
				
			||||||
 | 
					    MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \
 | 
				
			||||||
 | 
					    visitor.EndArray(); \
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,8 @@ struct WorkingFile {
 | 
				
			|||||||
  // This map goes from buffer-line -> indices+1 in all_buffer_lines.
 | 
					  // This map goes from buffer-line -> indices+1 in all_buffer_lines.
 | 
				
			||||||
  // Note: The items in the value entry are 1-based liness.
 | 
					  // Note: The items in the value entry are 1-based liness.
 | 
				
			||||||
  std::unordered_map<std::string, std::vector<int>> all_buffer_lines_lookup;
 | 
					  std::unordered_map<std::string, std::vector<int>> all_buffer_lines_lookup;
 | 
				
			||||||
 | 
					  // A set of diagnostics that have been reported for this file.
 | 
				
			||||||
 | 
					  std::vector<lsDiagnostic> diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  WorkingFile(const std::string& filename, const std::string& buffer_content);
 | 
					  WorkingFile(const std::string& filename, const std::string& buffer_content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user