void t_haxe_generator::generate_service_client()

in compiler/cpp/src/thrift/generate/t_haxe_generator.cc [1794:2001]


void t_haxe_generator::generate_service_client(t_service* tservice) {
  string extends = "";
  string extends_client = "";
  if (tservice->get_extends() != nullptr) {
    extends = get_cap_name(type_name(tservice->get_extends()));
    extends_client = " extends " + extends + "Impl";
  }

  generate_rtti_decoration(f_service_);
  // build macro is inherited from interface
  indent(f_service_) << "class " << get_cap_name(service_name_) << "Impl" << extends_client
                     << " implements " << get_cap_name(service_name_) << " {" << '\n' << '\n';
  indent_up();

  indent(f_service_) << "public function new( iprot : TProtocol, oprot : TProtocol = null)" << '\n';
  scope_up(f_service_);
  if (extends.empty()) {
    f_service_ << indent() << "iprot_ = iprot;" << '\n';
    f_service_ << indent() << "if (oprot == null) {" << '\n';
    indent_up();
    f_service_ << indent() << "oprot_ = iprot;" << '\n';
    indent_down();
    f_service_ << indent() << "} else {" << '\n';
    indent_up();
    f_service_ << indent() << "oprot_ = oprot;" << '\n';
    indent_down();
    f_service_ << indent() << "}" << '\n';
  } else {
    f_service_ << indent() << "super(iprot, oprot);" << '\n';
  }
  scope_down(f_service_);
  f_service_ << '\n';

  if (extends.empty()) {
    f_service_ << indent() << "private var iprot_ : TProtocol;" << '\n' << indent()
               << "private var oprot_ : TProtocol;" << '\n' << indent()
               << "private var seqid_ : Int;" << '\n' << '\n';

    indent(f_service_) << "public function getInputProtocol() : TProtocol" << '\n';
    scope_up(f_service_);
    indent(f_service_) << "return this.iprot_;" << '\n';
    scope_down(f_service_);
    f_service_ << '\n';

    indent(f_service_) << "public function getOutputProtocol() : TProtocol" << '\n';
    scope_up(f_service_);
    indent(f_service_) << "return this.oprot_;" << '\n';
    scope_down(f_service_);
    f_service_ << '\n';
  }

  // Generate client method implementations
  vector<t_function*> functions = tservice->get_functions();
  vector<t_function*>::const_iterator f_iter;
  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
    string funname = (*f_iter)->get_name();

    // Open function
    generate_service_method_signature(*f_iter, false, true);

    indent_up();

    // Get the struct of function call params
    t_struct* arg_struct = (*f_iter)->get_arglist();

    string argsname = get_cap_name((*f_iter)->get_name() + "_args");
    vector<t_field*>::const_iterator fld_iter;
    const vector<t_field*>& fields = arg_struct->get_members();

    // Serialize the request
    string args = tmp("args");
    string calltype = (*f_iter)->is_oneway() ? "ONEWAY" : "CALL";
    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname
               << "\", TMessageType." << calltype << ", seqid_));" << '\n' << indent()
               << "var " << args << " : " << argsname << " = new " << argsname << "();" << '\n';

    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
      f_service_ << indent() << args << "." << (*fld_iter)->get_name() << " = "
                 << (*fld_iter)->get_name() << ";" << '\n';
    }

    f_service_ << indent() << args << ".write(oprot_);" << '\n' << indent()
               << "oprot_.writeMessageEnd();" << '\n';

    string retval = tmp("retval");
    if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) {
      f_service_ << indent() << "var " << retval << " : " << type_name((*f_iter)->get_returntype())
                 << " = " << render_default_value_for_type((*f_iter)->get_returntype(),true)
                 << ";" << '\n';
    }

    if ((*f_iter)->is_oneway()) {
      f_service_ << indent() << "oprot_.getTransport().flush();" << '\n';
    } else {
      indent(f_service_) << "oprot_.getTransport().flush(function(error:Dynamic) : Void {" << '\n';
      indent_up();
      indent(f_service_) << "try {" << '\n';
      indent_up();
      string appex = tmp("appex");
      indent(f_service_) << "var " << appex << " : TApplicationException;" << '\n';
      string resultname = get_cap_name((*f_iter)->get_name() + "_result");
      indent(f_service_) << "if (error != null) {" << '\n';
      indent_up();
      indent(f_service_) << "if (onError == null)" << '\n';
      indent_up();
      indent(f_service_) << "throw error;" << '\n';
      indent_down();
      indent(f_service_) << "onError(error);" << '\n';
      indent(f_service_) << "return;" << '\n';
      indent_down();
      indent(f_service_) << "}" << '\n' << '\n';
      string msg = tmp("msg");
      indent(f_service_) << "var " << msg << " : TMessage = iprot_.readMessageBegin();" << '\n';
      indent(f_service_) << "if (" << msg << ".type == TMessageType.EXCEPTION) {" << '\n';
      indent_up();
      indent(f_service_) << appex << " = TApplicationException.read(iprot_);" << '\n';
      indent(f_service_) << "iprot_.readMessageEnd();" << '\n';
      indent(f_service_) << "if (onError == null)" << '\n';
      indent_up();
      indent(f_service_) << "throw " << appex << ";" << '\n';
      indent_down();
      indent(f_service_) << "onError(" << appex << ");" << '\n';
      indent(f_service_) << "return;" << '\n';
      indent_down();
      indent(f_service_) << "}" << '\n' << '\n';
      string result = tmp("result");
      indent(f_service_) << "var " << result << " : " << resultname << " = new " << resultname << "();" << '\n';
      indent(f_service_) << "" << result << ".read(iprot_);" << '\n';
      indent(f_service_) << "iprot_.readMessageEnd();" << '\n';

      // Careful, only return _result if not a void function
      if (!(*f_iter)->get_returntype()->is_void()) {
        indent(f_service_) << "if (" << result << "." << generate_isset_check("success") << ") {" << '\n';
        indent_up();
        indent(f_service_) << "if (onSuccess != null)" << '\n';
        indent_up();
        indent(f_service_) << "onSuccess(" << result << ".success);" << '\n';
        indent_down();
        indent(f_service_) << retval << " = " << result << ".success;" << '\n';
        indent(f_service_) << "return;" << '\n';
        indent_down();
        indent(f_service_) << "}" << '\n' << '\n';
      }

      t_struct* xs = (*f_iter)->get_xceptions();
      const std::vector<t_field*>& xceptions = xs->get_members();
      vector<t_field*>::const_iterator x_iter;
      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
        indent(f_service_) << "if (" << result << "." << (*x_iter)->get_name() << " != null) {" << '\n';
        indent_up();
        indent(f_service_) << "if (onError == null)" << '\n';
        indent_up();
        indent(f_service_) << "throw " << result << "." << (*x_iter)->get_name() << ";" << '\n';
        indent_down();
        indent(f_service_) << "onError(" << result << "." << (*x_iter)->get_name() << ");" << '\n';
        indent(f_service_) << "return;" << '\n';
        indent_down();
        indent(f_service_) << "}" << '\n' << '\n';
      }

      // If you get here it's an exception, unless a void function
      if ((*f_iter)->get_returntype()->is_void()) {
        indent(f_service_) << "if (onSuccess != null)" << '\n';
        indent_up();
        indent(f_service_) << "onSuccess();" << '\n';
        indent_down();
        indent(f_service_) << "return;" << '\n';
      } else {
        indent(f_service_) << appex << " = new TApplicationException("
                           << "TApplicationException.MISSING_RESULT,"
                           << "\"" << (*f_iter)->get_name() << " failed: unknown result\");" << '\n';
        indent(f_service_) << "if (onError == null)" << '\n';
        indent_up();
        indent(f_service_) << "throw " << appex << ";" << '\n';
        indent_down();
        indent(f_service_) << "onError(" << appex << ");" << '\n';
        indent(f_service_) << "return;" << '\n';
      }

      indent_down();
      indent(f_service_) << '\n';
      indent(f_service_) << "} catch( e : TException) {" << '\n';
      indent_up();
      indent(f_service_) << "if (onError == null)" << '\n';
      indent_up();
      indent(f_service_) << "throw e;" << '\n';
      indent_down();
      indent(f_service_) << "onError(e);" << '\n';
      indent(f_service_) << "return;" << '\n';
      indent_down();
      indent(f_service_) << "}" << '\n';

      indent_down();
      indent(f_service_) << "});" << '\n' << '\n';
    }

    if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) {
      f_service_ << indent() << "return " << retval << ";" << '\n';
    }

    // Close function
    scope_down(f_service_);
    f_service_ << '\n';
  }

  indent_down();
  indent(f_service_) << "}" << '\n';
}