thrift/compiler/generate/t_mstch_objects.cc (647 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <thrift/compiler/generate/t_mstch_objects.h>
namespace apache {
namespace thrift {
namespace compiler {
bool mstch_base::has_option(const std::string& option) const {
return cache_->parsed_options_.find(option) != cache_->parsed_options_.end();
}
std::string mstch_base::get_option(const std::string& option) const {
auto itr = cache_->parsed_options_.find(option);
if (itr != cache_->parsed_options_.end()) {
return itr->second;
}
return {};
}
void mstch_base::register_has_option(std::string key, std::string option) {
register_method(
std::move(key), [this, option = std::move(option)]() -> mstch::node {
return has_option(option);
});
}
std::shared_ptr<mstch_base> enum_value_generator::generate(
t_enum_value const* enum_value,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_enum_value>(enum_value, generators, cache, pos);
}
std::shared_ptr<mstch_base> enum_generator::generate(
t_enum const* enm,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_enum>(enm, generators, cache, pos);
}
std::shared_ptr<mstch_base> const_value_generator::generate(
t_const_value const* const_value,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t index,
t_const const* current_const,
t_type const* expected_type) const {
return std::make_shared<mstch_const_value>(
const_value, current_const, expected_type, generators, cache, pos, index);
}
std::shared_ptr<mstch_base> const_value_generator::generate(
std::pair<t_const_value*, t_const_value*> const& value_pair,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t index,
t_const const* current_const,
std::pair<const t_type*, const t_type*> const& expected_types) const {
return std::make_shared<mstch_const_value_key_mapped_pair>(
value_pair, current_const, expected_types, generators, cache, pos, index);
}
std::shared_ptr<mstch_base> type_generator::generate(
t_type const* type,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_type>(type, generators, cache, pos);
}
std::shared_ptr<mstch_base> field_generator::generate(
t_field const* field,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t index,
field_generator_context const* field_context) const {
return std::make_shared<mstch_field>(
field, generators, cache, pos, index, field_context);
}
std::shared_ptr<mstch_base> annotation_generator::generate(
const t_annotation& annotation,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t index) const {
return std::make_shared<mstch_annotation>(
annotation.first, annotation.second, generators, cache, pos, index);
}
std::shared_ptr<mstch_base> structured_annotation_generator::generate(
const t_const* annotValue,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t index) const {
return std::make_shared<mstch_structured_annotation>(
*annotValue, generators, cache, pos, index);
}
std::shared_ptr<mstch_base> struct_generator::generate(
t_struct const* strct,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_struct>(strct, generators, cache, pos);
}
std::shared_ptr<mstch_base> function_generator::generate(
t_function const* function,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_function>(function, generators, cache, pos);
}
std::shared_ptr<mstch_base> service_generator::generate(
t_service const* service,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_service>(service, generators, cache, pos);
}
std::shared_ptr<mstch_base> typedef_generator::generate(
t_typedef const* typedf,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_typedef>(typedf, generators, cache, pos);
}
std::shared_ptr<mstch_base> const_generator::generate(
t_const const* cnst,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t index,
t_const const* current_const,
t_type const* expected_type,
t_field const* field) const {
return std::make_shared<mstch_const>(
cnst, current_const, expected_type, generators, cache, pos, index, field);
}
std::shared_ptr<mstch_base> program_generator::generate(
t_program const* program,
std::shared_ptr<mstch_generators const> generators,
std::shared_ptr<mstch_cache> cache,
ELEMENT_POSITION pos,
int32_t /*index*/) const {
return std::make_shared<mstch_program>(program, generators, cache, pos);
}
mstch::node mstch_enum::values() {
return generate_enum_values(enm_->get_enum_values());
}
mstch::node mstch_type::get_struct() {
if (type_->is_struct() || type_->is_xception()) {
std::string id =
type_->program()->name() + get_type_namespace(type_->program());
return generate_elements_cached(
std::vector<t_struct const*>{dynamic_cast<t_struct const*>(type_)},
generators_->struct_generator_.get(),
cache_->structs_,
id);
}
return mstch::node();
}
mstch::node mstch_type::get_enum() {
if (resolved_type_->is_enum()) {
std::string id =
type_->program()->name() + get_type_namespace(type_->program());
return generate_elements_cached(
std::vector<t_enum const*>{dynamic_cast<t_enum const*>(resolved_type_)},
generators_->enum_generator_.get(),
cache_->enums_,
id);
}
return mstch::node();
}
mstch::node mstch_type::get_list_type() {
if (resolved_type_->is_list()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_list*>(resolved_type_)->get_elem_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_set_type() {
if (resolved_type_->is_set()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_set*>(resolved_type_)->get_elem_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_key_type() {
if (resolved_type_->is_map()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_map*>(resolved_type_)->get_key_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_value_type() {
if (resolved_type_->is_map()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_map*>(resolved_type_)->get_val_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_typedef_type() {
if (type_->is_typedef()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_typedef*>(type_)->get_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_typedef() {
if (type_->is_typedef()) {
return generators_->typedef_generator_->generate(
dynamic_cast<const t_typedef*>(type_), generators_, cache_, pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_sink_elem_type() {
if (type_->is_sink()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_sink*>(type_)->get_sink_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_sink_final_reponse_type() {
if (type_->is_sink()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_sink*>(type_)->get_final_response_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_sink_first_response_type() {
if (type_->is_sink()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_sink*>(type_)->get_first_response_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_stream_elem_type() {
if (type_->is_streamresponse()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_stream_response*>(type_)->get_elem_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_type::get_stream_first_response_type() {
if (resolved_type_->is_streamresponse()) {
return generators_->type_generator_->generate(
dynamic_cast<const t_stream_response*>(resolved_type_)
->get_first_response_type(),
generators_,
cache_,
pos_);
}
return mstch::node();
}
mstch::node mstch_field::value() {
if (field_->get_value()) {
return generators_->const_value_generator_->generate(
field_->get_value(), generators_, cache_, pos_);
}
return mstch::node();
}
mstch::node mstch_const_value_key_mapped_pair::element_key() {
return generators_->const_value_generator_->generate(
pair_.first,
generators_,
cache_,
pos_,
index_,
current_const_,
expected_types_.first);
}
mstch::node mstch_const_value_key_mapped_pair::element_value() {
return generators_->const_value_generator_->generate(
pair_.second,
generators_,
cache_,
pos_,
index_,
current_const_,
expected_types_.second);
}
mstch::node mstch_const_value::value() {
switch (type_) {
case cv::CV_DOUBLE:
return format_double_string(const_value_->get_double());
case cv::CV_BOOL:
return std::to_string(const_value_->get_bool());
case cv::CV_INTEGER:
return std::to_string(const_value_->get_integer());
case cv::CV_STRING:
return const_value_->get_string();
default:
return mstch::node();
}
}
mstch::node mstch_const_value::integer_value() {
if (type_ == cv::CV_INTEGER) {
return std::to_string(const_value_->get_integer());
}
return mstch::node();
}
mstch::node mstch_const_value::double_value() {
if (type_ == cv::CV_DOUBLE) {
return format_double_string(const_value_->get_double());
}
return mstch::node();
}
mstch::node mstch_const_value::bool_value() {
if (type_ == cv::CV_BOOL) {
return const_value_->get_bool() == true;
}
return mstch::node();
}
mstch::node mstch_const_value::is_non_zero() {
switch (type_) {
case cv::CV_DOUBLE:
return const_value_->get_double() != 0.0;
case cv::CV_BOOL:
return const_value_->get_bool() == true;
case cv::CV_INTEGER:
return const_value_->get_integer() != 0;
default:
return mstch::node();
}
}
mstch::node mstch_const_value::enum_name() {
if (type_ == cv::CV_INTEGER && const_value_->is_enum()) {
return const_value_->get_enum()->get_name();
}
return mstch::node();
}
mstch::node mstch_const_value::enum_value_name() {
if (type_ == cv::CV_INTEGER && const_value_->is_enum()) {
return const_value_->get_enum_value()->get_name();
}
return mstch::node();
}
mstch::node mstch_const_value::string_value() {
if (type_ == cv::CV_STRING) {
std::string string_val = const_value_->get_string();
for (auto itr = string_val.begin(); itr != string_val.end(); ++itr) {
if (*itr == '"') {
itr = string_val.insert(itr, '\\');
++itr;
}
}
return string_val;
}
return mstch::node();
}
mstch::node mstch_const_value::list_elems() {
if (type_ == cv::CV_LIST) {
const t_type* expected_type = nullptr;
if (expected_type_) {
if (expected_type_->is_list()) {
expected_type =
dynamic_cast<const t_list*>(expected_type_)->get_elem_type();
} else if (expected_type_->is_set()) {
expected_type =
dynamic_cast<const t_set*>(expected_type_)->get_elem_type();
}
}
return generate_consts(
const_value_->get_list(), current_const_, expected_type);
}
return mstch::node();
}
mstch::node mstch_const_value::map_elems() {
if (type_ == cv::CV_MAP) {
std::pair<const t_type*, const t_type*> expected_types;
if (expected_type_ && expected_type_->is_map()) {
const auto* m = dynamic_cast<const t_map*>(expected_type_);
expected_types = {m->get_key_type(), m->get_val_type()};
}
return generate_consts(
const_value_->get_map(), current_const_, expected_types);
}
return mstch::node();
}
mstch::node mstch_const_value::is_const_struct() {
if (!const_value_->ttype()) {
return false;
}
const auto* type = const_value_->ttype()->deref().get_true_type();
return type->is_struct() || type->is_xception();
}
mstch::node mstch_const_value::const_struct_type() {
if (!const_value_->ttype()) {
return {};
}
const auto* type = const_value_->ttype()->deref().get_true_type();
if (type->is_struct() || type->is_xception()) {
return generators_->type_generator_->generate(type, generators_, cache_);
}
return {};
}
mstch::node mstch_const_value::const_struct() {
std::vector<t_const*> constants;
std::vector<const t_field*> fields;
mstch::array a;
const auto* type = const_value_->ttype()->deref().get_true_type();
if (type->is_struct() || type->is_xception()) {
auto const* strct = dynamic_cast<t_struct const*>(type);
for (auto member : const_value_->get_map()) {
auto const* field = strct->get_field_by_name(member.first->get_string());
assert(field != nullptr);
constants.push_back(new t_const(
nullptr,
field->get_type(),
field->get_name(),
member.second->clone()));
fields.push_back(field);
}
}
for (size_t i = 0; i < constants.size(); ++i) {
auto pos = element_position(i, constants.size());
a.push_back(generators_->const_generator_->generate(
constants[i],
generators_,
cache_,
pos,
fields[i]->get_key(),
current_const_,
constants[i]->get_type(),
fields[i]));
}
return a;
}
mstch::node mstch_const_value::owning_const() {
return generators_->const_generator_->generate(
const_value_->get_owner(), generators_, cache_, pos_);
}
mstch::node mstch_field::type() {
return generators_->type_generator_->generate(
field_->get_type(), generators_, cache_, pos_);
}
mstch::node mstch_struct::fields() {
return generate_fields(strct_->get_members());
}
mstch::node mstch_struct::exception_safety() {
if (!strct_->is_xception()) {
return std::string("");
}
const auto* t_ex_ptr = dynamic_cast<const t_exception*>(strct_);
auto s = t_ex_ptr->safety();
switch (s) {
case t_error_safety::safe:
return std::string("SAFE");
default:
return std::string("UNSPECIFIED");
}
}
mstch::node mstch_struct::exception_blame() {
if (!strct_->is_xception()) {
return std::string("");
}
const auto* t_ex_ptr = dynamic_cast<const t_exception*>(strct_);
auto s = t_ex_ptr->blame();
switch (s) {
case t_error_blame::server:
return std::string("SERVER");
case t_error_blame::client:
return std::string("CLIENT");
default:
return std::string("UNSPECIFIED");
}
}
mstch::node mstch_struct::exception_kind() {
if (!strct_->is_xception()) {
return std::string("");
}
const auto* t_ex_ptr = dynamic_cast<const t_exception*>(strct_);
auto s = t_ex_ptr->kind();
switch (s) {
case t_error_kind::transient:
return std::string("TRANSIENT");
case t_error_kind::stateful:
return std::string("STATEFUL");
case t_error_kind::permanent:
return std::string("PERMANENT");
default:
return std::string("UNSPECIFIED");
}
}
const std::vector<const t_field*>& mstch_struct::get_members_in_key_order() {
if (strct_->fields().size() == fields_in_key_order_.size()) {
// Already reordered.
return fields_in_key_order_;
}
fields_in_key_order_ = strct_->fields().copy();
// Sort by increasing key.
std::sort(
fields_in_key_order_.begin(),
fields_in_key_order_.end(),
[](const auto* lhs, const auto* rhs) {
return lhs->get_key() < rhs->get_key();
});
return fields_in_key_order_;
}
mstch::node mstch_function::return_type() {
return generators_->type_generator_->generate(
function_->get_returntype(), generators_, cache_, pos_);
}
mstch::node mstch_function::exceptions() {
return generate_fields(function_->get_xceptions()->get_members());
}
mstch::node mstch_function::stream_exceptions() {
return generate_fields(function_->get_stream_xceptions()->get_members());
}
mstch::node mstch_function::sink_exceptions() {
return generate_fields(function_->get_sink_xceptions()->get_members());
}
mstch::node mstch_function::sink_final_response_exceptions() {
return generate_fields(
function_->get_sink_final_response_xceptions()->get_members());
}
mstch::node mstch_function::arg_list() {
return generate_fields(function_->get_paramlist()->get_members());
}
mstch::node mstch_function::returns_stream() {
return function_->returns_stream();
}
mstch::node mstch_service::functions() {
return generate_functions(get_functions());
}
mstch::node mstch_service::extends() {
auto const* extends = service_->get_extends();
if (extends) {
return generate_cached_extended_service(extends);
}
return mstch::node();
}
mstch::node mstch_service::generate_cached_extended_service(
const t_service* service) {
std::string id =
service->program()->name() + get_service_namespace(service->program());
size_t element_index = 0;
size_t element_count = 1;
return generate_element_cached(
service,
generators_->service_generator_.get(),
cache_->services_,
id,
element_index,
element_count);
}
mstch::node mstch_typedef::type() {
return generators_->type_generator_->generate(
typedf_->get_type(), generators_, cache_, pos_);
}
mstch::node mstch_const::type() {
return generators_->type_generator_->generate(
cnst_->get_type(), generators_, cache_, pos_);
}
mstch::node mstch_const::value() {
return generators_->const_value_generator_->generate(
cnst_->get_value(), generators_, cache_, pos_, 0, cnst_, expected_type_);
}
mstch::node mstch_const::program() {
return generators_->program_generator_->generate(
cnst_->get_program(), generators_, cache_, pos_);
}
mstch::node mstch_program::has_thrift_uris() {
for (const auto& strct : program_->structs()) {
if (!strct->uri().empty()) {
return true;
}
}
return false;
}
mstch::node mstch_program::structs() {
std::string id = program_->name() + get_program_namespace(program_);
return generate_elements_cached(
get_program_objects(),
generators_->struct_generator_.get(),
cache_->structs_,
id);
}
mstch::node mstch_program::enums() {
std::string id = program_->name() + get_program_namespace(program_);
return generate_elements_cached(
get_program_enums(),
generators_->enum_generator_.get(),
cache_->enums_,
id);
}
mstch::node mstch_program::services() {
std::string id = program_->name() + get_program_namespace(program_);
return generate_elements_cached(
program_->services(),
generators_->service_generator_.get(),
cache_->services_,
id);
}
mstch::node mstch_program::typedefs() {
return generate_typedefs(program_->typedefs());
}
mstch::node mstch_program::constants() {
mstch::array a;
const auto& container = program_->consts();
for (size_t i = 0; i < container.size(); ++i) {
auto pos = element_position(i, container.size());
a.push_back(generators_->const_generator_->generate(
container[i],
generators_,
cache_,
pos,
i,
container[i],
container[i]->get_type()));
}
return a;
}
const std::vector<t_struct*>& mstch_program::get_program_objects() {
return program_->objects();
}
const std::vector<t_enum*>& mstch_program::get_program_enums() {
return program_->enums();
}
} // namespace compiler
} // namespace thrift
} // namespace apache