std::string t_hack_generator::render_const_value_helper()

in thrift/compiler/generate/t_hack_generator.cc [1479:1720]


std::string t_hack_generator::render_const_value_helper(
    const t_type* type,
    const t_const_value* value,
    std::ostream& temp_var_initializations_out,
    t_name_generator& namer,
    bool immutable_collections) {
  std::ostringstream out;
  type = type->get_true_type();
  if (const auto* tbase_type = dynamic_cast<const t_base_type*>(type)) {
    switch (tbase_type->get_base()) {
      case t_base_type::TYPE_STRING:
      case t_base_type::TYPE_BINARY:
        out << render_string(value->get_string());
        break;
      case t_base_type::TYPE_BOOL:
        out << (value->get_integer() > 0 ? "true" : "false");
        break;
      case t_base_type::TYPE_BYTE:
      case t_base_type::TYPE_I16:
      case t_base_type::TYPE_I32:
      case t_base_type::TYPE_I64:
        out << value->get_integer();
        break;
      case t_base_type::TYPE_DOUBLE:
      case t_base_type::TYPE_FLOAT:
        if (value->get_type() == t_const_value::CV_INTEGER) {
          out << value->get_integer();
        } else {
          out << value->get_double();
        }
        if (out.str().find('.') == std::string::npos &&
            out.str().find('e') == std::string::npos) {
          out << ".0";
        }
        break;
      default:
        throw std::runtime_error(
            "compiler error: no const of base type " +
            t_base_type::t_base_name(tbase_type->get_base()));
    }
  } else if (const auto* tenum = dynamic_cast<const t_enum*>(type)) {
    const t_enum_value* val = tenum->find_value(value->get_integer());
    if (val != nullptr) {
      out << hack_name(tenum) << "::" << val->name();
    } else {
      out << hack_name(tenum) << "::coerce(" << value->get_integer() << ")";
    }
  } else if (const auto* tstruct = dynamic_cast<const t_struct*>(type)) {
    auto struct_name = hack_name(type);
    if (is_async_struct(tstruct)) {
      auto temp_val = namer(("$" + struct_name).c_str());
      int preserved_indent_size = get_indent();
      set_indent(2);
      temp_var_initializations_out << indent() << temp_val << " = "
                                   << hack_name(type)
                                   << "::withDefaultValues();\n";
      for (const auto& entry : value->get_map()) {
        const auto* field =
            tstruct->get_field_by_name(entry.first->get_string());
        if (field == nullptr) {
          throw std::runtime_error(
              "type error: " + type->name() + " has no field " +
              entry.first->get_string());
        }
        t_const_value* v = entry.second;
        std::stringstream inner;
        if (v) {
          auto* field_wrapper = find_hack_wrapper(*field);
          if (field_wrapper) {
            inner << indent() << temp_val << "->get_" << field->name()
                  << "()->setValue_DO_NOT_USE_THRIFT_INTERNAL(";
          } else {
            inner << indent() << temp_val << "->" << field->name() << " = ";
          }
          inner << render_const_value_helper(
              field->get_type(), v, temp_var_initializations_out, namer);
          if (field_wrapper) {
            inner << ");\n";
          } else {
            inner << ";\n";
          }
        }
        temp_var_initializations_out << inner.str() << "\n";
      }
      out << temp_val;

      set_indent(preserved_indent_size);
    } else {
      out << hack_name(type) << "::fromShape(\n";
      indent_up();
      indent(out) << "shape(\n";
      indent_up();

      for (const auto& entry : value->get_map()) {
        const auto* field =
            tstruct->get_field_by_name(entry.first->get_string());
        if (field == nullptr) {
          throw std::runtime_error(
              "type error: " + type->name() + " has no field " +
              entry.first->get_string());
        }
      }
      for (const auto& field : tstruct->fields()) {
        t_const_value* k = nullptr;
        t_const_value* v = nullptr;
        for (const auto& entry : value->get_map()) {
          if (field.name() == entry.first->get_string()) {
            k = entry.first;
            v = entry.second;
          }
        }
        if (v != nullptr) {
          indent(out) << render_const_value_helper(
                             &t_base_type::t_string(),
                             k,
                             temp_var_initializations_out,
                             namer)
                      << " => "
                      << render_const_value_helper(
                             field.get_type(),
                             v,
                             temp_var_initializations_out,
                             namer)
                      << ",\n";
        }
      }
      indent_down();
      indent(out) << ")\n";
      indent_down();
      indent(out) << ")";
    }
  } else if (const auto* tmap = dynamic_cast<const t_map*>(type)) {
    const t_type* ktype = tmap->get_key_type();
    const t_type* vtype = tmap->get_val_type();
    if (arrays_) {
      out << "dict[\n";
    } else if (no_use_hack_collections_) {
      out << "darray[\n";
    } else {
      out << (immutable_collections ? "Imm" : "") << "Map {\n";
    }
    indent_up();
    for (const auto& entry : value->get_map()) {
      out << indent();
      out << render_const_value_helper(
          ktype,
          entry.first,
          temp_var_initializations_out,
          namer,
          immutable_collections);
      out << " => ";
      out << render_const_value_helper(
          vtype,
          entry.second,
          temp_var_initializations_out,
          namer,
          immutable_collections);
      out << ",\n";
    }
    indent_down();
    if (arrays_ || no_use_hack_collections_) {
      indent(out) << "]";
    } else {
      indent(out) << "}";
    }
  } else if (const auto* tlist = dynamic_cast<const t_list*>(type)) {
    const t_type* etype = tlist->get_elem_type();
    if (arrays_) {
      out << "vec[\n";
    } else if (no_use_hack_collections_) {
      out << "varray[\n";
    } else {
      out << (immutable_collections ? "Imm" : "") << "Vector {\n";
    }
    indent_up();
    for (const auto* val : value->get_list()) {
      out << indent();
      out << render_const_value_helper(
          etype,
          val,
          temp_var_initializations_out,
          namer,
          immutable_collections);
      out << ",\n";
    }
    indent_down();
    if (arrays_ || no_use_hack_collections_) {
      indent(out) << "]";
    } else {
      indent(out) << "}";
    }
  } else if (const auto* tset = dynamic_cast<const t_set*>(type)) {
    const t_type* etype = tset->get_elem_type();
    indent_up();
    const auto& vals = value->get_list();
    if (arrays_) {
      out << "keyset[\n";
      for (const auto* val : vals) {
        out << indent();
        out << render_const_value_helper(
            etype,
            val,
            temp_var_initializations_out,
            namer,
            immutable_collections);
        out << ",\n";
      }
      indent_down();
      indent(out) << "]";
    } else if (arraysets_) {
      out << "dict[\n";
      for (const auto* val : vals) {
        out << indent();
        out << render_const_value_helper(
            etype,
            val,
            temp_var_initializations_out,
            namer,
            immutable_collections);
        out << " => true";
        out << ",\n";
      }
      indent_down();
      indent(out) << "]";
    } else {
      out << (immutable_collections ? "Imm" : "") << "Set {\n";
      for (const auto* val : vals) {
        out << indent();
        out << render_const_value_helper(
            etype,
            val,
            temp_var_initializations_out,
            namer,
            immutable_collections);
        out << ",\n";
      }
      indent_down();
      indent(out) << "}";
    }
  }
  return out.str();
}