mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-03 22:04:24 +00:00 
			
		
		
		
	Better deserialization error messages
This commit is contained in:
		
							parent
							
								
									556f32ec1b
								
							
						
					
					
						commit
						162f995344
					
				@ -238,15 +238,30 @@ void LaunchStdinLoop(Config* config,
 | 
				
			|||||||
  WorkThread::StartThread("stdin", [request_times]() {
 | 
					  WorkThread::StartThread("stdin", [request_times]() {
 | 
				
			||||||
    auto* queue = QueueManager::instance();
 | 
					    auto* queue = QueueManager::instance();
 | 
				
			||||||
    while (true) {
 | 
					    while (true) {
 | 
				
			||||||
      std::unique_ptr<BaseIpcMessage> message =
 | 
					      std::variant<std::string, std::unique_ptr<BaseIpcMessage>> err_or_message =
 | 
				
			||||||
          MessageRegistry::instance()->ReadMessageFromStdin(
 | 
					          MessageRegistry::instance()->ReadMessageFromStdin(
 | 
				
			||||||
              g_log_stdin_stdout_to_stderr);
 | 
					              g_log_stdin_stdout_to_stderr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Message parsing can fail if we don't recognize the method.
 | 
					      // Message parsing can fail if we don't recognize the method.
 | 
				
			||||||
      if (!message)
 | 
					      auto* err = std::get_if<std::string>(&err_or_message);
 | 
				
			||||||
 | 
					      if (err) {
 | 
				
			||||||
 | 
					        // FIXME LanguageClient-neovim will error without the check, probably
 | 
				
			||||||
 | 
					        // because we do not support didChangeConfiguration and do not fill in
 | 
				
			||||||
 | 
					        // the |id| field.
 | 
				
			||||||
 | 
					        if (err->find("workspace/didChangeConfiguration") ==
 | 
				
			||||||
 | 
					            std::string::npos) {
 | 
				
			||||||
 | 
					          Out_Error out;
 | 
				
			||||||
 | 
					          // TODO We cannot fill in out.id because RequestMessage.id is not a base
 | 
				
			||||||
 | 
					          // field.
 | 
				
			||||||
 | 
					          out.error.code = lsErrorCodes::InvalidParams;
 | 
				
			||||||
 | 
					          out.error.message = std::move(*err);
 | 
				
			||||||
 | 
					          queue->WriteStdout(IpcId::Unknown, out);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Cache |method_id| so we can access it after moving |message|.
 | 
					      // Cache |method_id| so we can access it after moving |message|.
 | 
				
			||||||
 | 
					      auto& message = std::get<std::unique_ptr<BaseIpcMessage>>(err_or_message);
 | 
				
			||||||
      IpcId method_id = message->method_id;
 | 
					      IpcId method_id = message->method_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      (*request_times)[message->method_id] = Timer();
 | 
					      (*request_times)[message->method_id] = Timer();
 | 
				
			||||||
 | 
				
			|||||||
@ -113,8 +113,8 @@ optional<char> ReadCharFromStdinBlocking() {
 | 
				
			|||||||
  return nullopt;
 | 
					  return nullopt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unique_ptr<BaseIpcMessage> MessageRegistry::ReadMessageFromStdin(
 | 
					std::variant<std::string, std::unique_ptr<BaseIpcMessage>>
 | 
				
			||||||
    bool log_stdin_to_stderr) {
 | 
					MessageRegistry::ReadMessageFromStdin(bool log_stdin_to_stderr) {
 | 
				
			||||||
  optional<std::string> content =
 | 
					  optional<std::string> content =
 | 
				
			||||||
      ReadJsonRpcContentFrom(&ReadCharFromStdinBlocking);
 | 
					      ReadJsonRpcContentFrom(&ReadCharFromStdinBlocking);
 | 
				
			||||||
  if (!content) {
 | 
					  if (!content) {
 | 
				
			||||||
@ -138,7 +138,8 @@ std::unique_ptr<BaseIpcMessage> MessageRegistry::ReadMessageFromStdin(
 | 
				
			|||||||
  return Parse(json_reader);
 | 
					  return Parse(json_reader);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unique_ptr<BaseIpcMessage> MessageRegistry::Parse(Reader& visitor) {
 | 
					std::variant<std::string, std::unique_ptr<BaseIpcMessage>>
 | 
				
			||||||
 | 
					    MessageRegistry::Parse(Reader& visitor) {
 | 
				
			||||||
  if (!visitor.HasMember("jsonrpc") ||
 | 
					  if (!visitor.HasMember("jsonrpc") ||
 | 
				
			||||||
      std::string(visitor["jsonrpc"]->GetString()) != "2.0") {
 | 
					      std::string(visitor["jsonrpc"]->GetString()) != "2.0") {
 | 
				
			||||||
    LOG_S(FATAL) << "Bad or missing jsonrpc version";
 | 
					    LOG_S(FATAL) << "Bad or missing jsonrpc version";
 | 
				
			||||||
@ -148,19 +149,16 @@ std::unique_ptr<BaseIpcMessage> MessageRegistry::Parse(Reader& visitor) {
 | 
				
			|||||||
  std::string method;
 | 
					  std::string method;
 | 
				
			||||||
  ReflectMember(visitor, "method", method);
 | 
					  ReflectMember(visitor, "method", method);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (allocators.find(method) == allocators.end()) {
 | 
					  if (allocators.find(method) == allocators.end())
 | 
				
			||||||
    LOG_S(ERROR) << "Unable to find registered handler for method \"" << method
 | 
					    return std::string("Unable to find registered handler for method '") +
 | 
				
			||||||
                 << "\"";
 | 
					           method + "'";
 | 
				
			||||||
    return nullptr;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Allocator& allocator = allocators[method];
 | 
					  Allocator& allocator = allocators[method];
 | 
				
			||||||
  // FIXME Print error message for deserialization error
 | 
					 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    return allocator(visitor);
 | 
					    return allocator(visitor);
 | 
				
			||||||
  } catch (std::invalid_argument& e) {
 | 
					  } catch (std::invalid_argument& e) {
 | 
				
			||||||
    LOG_S(ERROR) << "Unable to deserialize request '" << method << "'";
 | 
					    return std::string("Unable to deserialize request '") + method + "' " +
 | 
				
			||||||
    return nullptr;
 | 
					           static_cast<JsonReader&>(visitor).GetPath() + " " + e.what();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -45,9 +45,10 @@ struct MessageRegistry {
 | 
				
			|||||||
      std::function<std::unique_ptr<BaseIpcMessage>(Reader& visitor)>;
 | 
					      std::function<std::unique_ptr<BaseIpcMessage>(Reader& visitor)>;
 | 
				
			||||||
  std::unordered_map<std::string, Allocator> allocators;
 | 
					  std::unordered_map<std::string, Allocator> allocators;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::unique_ptr<BaseIpcMessage> ReadMessageFromStdin(
 | 
					  std::variant<std::string, std::unique_ptr<BaseIpcMessage>>
 | 
				
			||||||
      bool log_stdin_to_stderr);
 | 
					      ReadMessageFromStdin(bool log_stdin_to_stderr);
 | 
				
			||||||
  std::unique_ptr<BaseIpcMessage> Parse(Reader& visitor);
 | 
					  std::variant<std::string, std::unique_ptr<BaseIpcMessage>> Parse(
 | 
				
			||||||
 | 
					      Reader& visitor);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user