void t_hack_generator::generate_process_function()

in thrift/compiler/generate/t_hack_generator.cc [4667:4813]


void t_hack_generator::generate_process_function(
    const t_service* tservice, const t_function* tfunction, bool async) {
  // Open function
  indent(f_service_)
      << "protected" << (async ? " async" : "") << " function process_"
      << tfunction->name()
      << "(int $seqid, \\TProtocol $input, \\TProtocol $output): "
      << (async ? "Awaitable<void>" : "void") << " {\n";
  indent_up();

  std::string service_name = hack_name(tservice);
  std::string argsname = generate_function_helper_name(
      tservice, tfunction, PhpFunctionNameSuffix::ARGS);
  std::string resultname = generate_function_helper_name(
      tservice, tfunction, PhpFunctionNameSuffix::RESULT);
  const std::string& fn_name = tfunction->name();

  f_service_ << indent()
             << "$handler_ctx = $this->eventHandler_->getHandlerContext('"
             << fn_name << "');\n"
             << indent() << "$reply_type = \\TMessageType::REPLY;\n"
             << "\n"
             << indent() << "$this->eventHandler_->preRead($handler_ctx, '"
             << fn_name << "', dict[]);\n"
             << "\n"
             << indent() << "if ($input is \\TBinaryProtocolAccelerated) {\n"
             << indent() << "  $args = \\thrift_protocol_read_binary_struct("
             << "$input, '" << argsname << "');\n"
             << indent()
             << "} else if ($input is \\TCompactProtocolAccelerated) {"
             << "\n"
             << indent()
             << "  $args = \\thrift_protocol_read_compact_struct($input, '"
             << argsname << "');\n"
             << indent() << "} else {\n"
             << indent() << "  $args = " << argsname
             << "::withDefaultValues();\n"
             << indent() << "  $args->read($input);\n"
             << indent() << "}\n";
  f_service_ << indent() << "$input->readMessageEnd();\n";
  f_service_ << indent() << "$this->eventHandler_->postRead($handler_ctx, '"
             << fn_name << "', $args);\n";

  // Declare result for non oneway function
  if (tfunction->qualifier() != t_function_qualifier::one_way) {
    f_service_ << indent() << "$result = " << resultname
               << "::withDefaultValues();\n";
  }

  // Try block for a function with exceptions
  f_service_ << indent() << "try {\n";
  indent_up();

  // Generate the function call
  indent(f_service_) << "$this->eventHandler_->preExec($handler_ctx, '"
                     << service_name << "', '" << fn_name << "', $args);\n";

  f_service_ << indent();
  if (tfunction->qualifier() != t_function_qualifier::one_way &&
      !tfunction->get_returntype()->is_void()) {
    f_service_ << "$result->success = ";
  }
  f_service_ << (async ? "await " : "") << "$this->handler->"
             << tfunction->name() << "(";
  auto delim = "";
  for (const auto& param : tfunction->get_paramlist()->fields()) {
    f_service_ << delim << "$args->" << param.name();
    delim = ", ";
  }
  f_service_ << ");\n";

  if (tfunction->qualifier() != t_function_qualifier::one_way) {
    indent(f_service_) << "$this->eventHandler_->postExec($handler_ctx, '"
                       << fn_name << "', $result);\n";
  }

  indent_down();
  int exc_num = 0;
  for (const auto& x : t_throws::or_empty(tfunction->exceptions())->fields()) {
    f_service_ << indent() << "} catch (" << hack_name(x.get_type()) << " $exc"
               << exc_num << ") {\n";
    if (tfunction->qualifier() != t_function_qualifier::one_way) {
      indent_up();
      f_service_ << indent()
                 << "$this->eventHandler_->handlerException($handler_ctx, '"
                 << fn_name << "', $exc" << exc_num << ");\n"
                 << indent() << "$result->" << x.name() << " = $exc" << exc_num
                 << ";\n";
      indent_down();
    }
    ++exc_num;
  }
  f_service_
      << indent() << "} catch (\\Exception $ex) {\n"
      << indent() << "  $reply_type = \\TMessageType::EXCEPTION;\n"
      << indent() << "  $this->eventHandler_->handlerError($handler_ctx, '"
      << fn_name << "', $ex);\n"
      << indent()
      << "  $result = new \\TApplicationException($ex->getMessage().\"\\n\".$ex->getTraceAsString());\n"
      << indent() << "}\n";

  // Shortcut out here for oneway functions
  if (tfunction->qualifier() == t_function_qualifier::one_way) {
    f_service_ << indent() << "return;\n";
    indent_down();
    f_service_ << indent() << "}\n";
    return;
  }

  f_service_ << indent() << "$this->eventHandler_->preWrite($handler_ctx, '"
             << fn_name << "', $result);\n";

  f_service_ << indent() << "if ($output is \\TBinaryProtocolAccelerated)\n";
  scope_up(f_service_);

  f_service_ << indent() << "\\thrift_protocol_write_binary($output, '"
             << tfunction->name()
             << "', $reply_type, $result, $seqid, $output->isStrictWrite());\n";

  scope_down(f_service_);
  f_service_ << indent()
             << "else if ($output is \\TCompactProtocolAccelerated)\n";
  scope_up(f_service_);

  f_service_ << indent() << "\\thrift_protocol_write_compact($output, '"
             << tfunction->name() << "', $reply_type, $result, $seqid);\n";

  scope_down(f_service_);
  f_service_ << indent() << "else\n";
  scope_up(f_service_);

  // Serialize the request header
  f_service_ << indent() << "$output->writeMessageBegin(\"" << tfunction->name()
             << "\", $reply_type, $seqid);\n"
             << indent() << "$result->write($output);\n"
             << indent() << "$output->writeMessageEnd();\n"
             << indent() << "$output->getTransport()->flush();\n";

  scope_down(f_service_);

  f_service_ << indent() << "$this->eventHandler_->postWrite($handler_ctx, '"
             << fn_name << "', $result);\n";

  // Close function
  indent_down();
  f_service_ << indent() << "}\n";
}