1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <iomanip> 20 #include <map> 21 #include <memory> 22 #include <sstream> 23 #include <string> 24 #include <type_traits> 25 #include <unordered_map> 26 #include <utility> 27 #include <vector> 28 29 #include <thrift/compiler/detail/mustache/mstch.h> 30 #include <thrift/compiler/generate/t_generator.h> 31 32 namespace apache { 33 namespace thrift { 34 namespace compiler { 35 36 class mstch_base; 37 class mstch_generators; 38 39 enum ELEMENT_POSITION { 40 NONE = 0, 41 FIRST = 1, 42 LAST = 2, 43 FIRST_AND_LAST = 3, 44 }; 45 46 struct mstch_cache { 47 std::map<std::string, std::string> parsed_options_; 48 std::unordered_map<std::string, std::shared_ptr<mstch_base>> enums_; 49 std::unordered_map<std::string, std::shared_ptr<mstch_base>> structs_; 50 std::unordered_map<std::string, std::shared_ptr<mstch_base>> services_; 51 std::unordered_map<std::string, std::shared_ptr<mstch_base>> programs_; 52 clearmstch_cache53 void clear() { 54 enums_.clear(); 55 structs_.clear(); 56 services_.clear(); 57 programs_.clear(); 58 } 59 }; 60 61 class enum_value_generator { 62 public: 63 virtual ~enum_value_generator() = default; 64 virtual std::shared_ptr<mstch_base> generate( 65 t_enum_value const* enum_value, 66 std::shared_ptr<mstch_generators const> generators, 67 std::shared_ptr<mstch_cache> cache, 68 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 69 int32_t index = 0) const; 70 }; 71 72 class enum_generator { 73 public: 74 virtual ~enum_generator() = default; 75 virtual std::shared_ptr<mstch_base> generate( 76 t_enum const* enm, 77 std::shared_ptr<mstch_generators const> generators, 78 std::shared_ptr<mstch_cache> cache, 79 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 80 int32_t index = 0) const; 81 }; 82 83 class const_value_generator { 84 public: 85 const_value_generator() = default; 86 virtual ~const_value_generator() = default; 87 virtual std::shared_ptr<mstch_base> generate( 88 t_const_value const* const_value, 89 std::shared_ptr<mstch_generators const> generators, 90 std::shared_ptr<mstch_cache> cache, 91 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 92 int32_t index = 0, 93 t_const const* current_const = nullptr, 94 t_type const* expected_type = nullptr) const; 95 virtual std::shared_ptr<mstch_base> generate( 96 std::pair<t_const_value*, t_const_value*> const& value_pair, 97 std::shared_ptr<mstch_generators const> generators, 98 std::shared_ptr<mstch_cache> cache, 99 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 100 int32_t index = 0, 101 t_const const* current_const = nullptr, 102 std::pair<const t_type*, const t_type*> const& expected_types = { 103 nullptr, nullptr}) const; 104 }; 105 106 class type_generator { 107 public: 108 type_generator() = default; 109 virtual ~type_generator() = default; 110 virtual std::shared_ptr<mstch_base> generate( 111 t_type const* type, 112 std::shared_ptr<mstch_generators const> generators, 113 std::shared_ptr<mstch_cache> cache, 114 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 115 int32_t index = 0) const; 116 }; 117 118 struct field_generator_context { 119 const t_struct* strct = nullptr; 120 const t_field* prev = nullptr; 121 const t_field* next = nullptr; 122 int isset_index = -1; 123 }; 124 125 class field_generator { 126 public: 127 field_generator() = default; 128 virtual ~field_generator() = default; 129 virtual std::shared_ptr<mstch_base> generate( 130 t_field const* field, 131 std::shared_ptr<mstch_generators const> generators, 132 std::shared_ptr<mstch_cache> cache, 133 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 134 int32_t index = 0, 135 field_generator_context const* field_context = nullptr) const; 136 }; 137 138 class annotation_generator { 139 public: 140 annotation_generator() = default; 141 virtual ~annotation_generator() = default; 142 virtual std::shared_ptr<mstch_base> generate( 143 const t_annotation& annotation, 144 std::shared_ptr<mstch_generators const> generators, 145 std::shared_ptr<mstch_cache> cache, 146 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 147 int32_t index = 0) const; 148 }; 149 150 class structured_annotation_generator { 151 public: 152 structured_annotation_generator() = default; 153 virtual ~structured_annotation_generator() = default; 154 virtual std::shared_ptr<mstch_base> generate( 155 const t_const* annotValue, 156 std::shared_ptr<mstch_generators const> generators, 157 std::shared_ptr<mstch_cache> cache, 158 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 159 int32_t index = 0) const; 160 }; 161 162 class struct_generator { 163 public: 164 struct_generator() = default; 165 virtual ~struct_generator() = default; 166 virtual std::shared_ptr<mstch_base> generate( 167 t_struct const* strct, 168 std::shared_ptr<mstch_generators const> generators, 169 std::shared_ptr<mstch_cache> cache, 170 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 171 int32_t index = 0) const; 172 }; 173 174 class function_generator { 175 public: 176 function_generator() = default; 177 virtual ~function_generator() = default; 178 virtual std::shared_ptr<mstch_base> generate( 179 t_function const* function, 180 std::shared_ptr<mstch_generators const> generators, 181 std::shared_ptr<mstch_cache> cache, 182 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 183 int32_t index = 0) const; 184 }; 185 186 class service_generator { 187 public: 188 service_generator() = default; 189 virtual ~service_generator() = default; 190 virtual std::shared_ptr<mstch_base> generate( 191 t_service const* service, 192 std::shared_ptr<mstch_generators const> generators, 193 std::shared_ptr<mstch_cache> cache, 194 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 195 int32_t index = 0) const; 196 197 std::shared_ptr<mstch_base> generate_cached( 198 t_program const* program, 199 t_service const* service, 200 std::shared_ptr<mstch_generators const> generators, 201 std::shared_ptr<mstch_cache> cache, 202 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 203 int32_t index = 0) const { 204 std::string service_id = program->path() + service->get_name(); 205 auto itr = cache->services_.find(service_id); 206 if (itr == cache->services_.end()) { 207 itr = cache->services_.emplace_hint( 208 itr, service_id, generate(service, generators, cache, pos, index)); 209 } 210 return itr->second; 211 } 212 }; 213 214 class typedef_generator { 215 public: 216 typedef_generator() = default; 217 virtual ~typedef_generator() = default; 218 virtual std::shared_ptr<mstch_base> generate( 219 t_typedef const* typedf, 220 std::shared_ptr<mstch_generators const> generators, 221 std::shared_ptr<mstch_cache> cache, 222 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 223 int32_t index = 0) const; 224 }; 225 226 class const_generator { 227 public: 228 const_generator() = default; 229 virtual ~const_generator() = default; 230 virtual std::shared_ptr<mstch_base> generate( 231 t_const const* cnst, 232 std::shared_ptr<mstch_generators const> generators, 233 std::shared_ptr<mstch_cache> cache, 234 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 235 int32_t index = 0, 236 t_const const* current_const = nullptr, 237 t_type const* expected_type = nullptr, 238 t_field const* field = nullptr) const; 239 }; 240 241 class program_generator { 242 public: 243 program_generator() = default; 244 virtual ~program_generator() = default; 245 virtual std::shared_ptr<mstch_base> generate( 246 t_program const* program, 247 std::shared_ptr<mstch_generators const> generators, 248 std::shared_ptr<mstch_cache> cache, 249 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 250 int32_t index = 0) const; 251 252 std::shared_ptr<mstch_base> generate_cached( 253 t_program const* program, 254 std::shared_ptr<mstch_generators const> generators, 255 std::shared_ptr<mstch_cache> cache, 256 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE, 257 int32_t index = 0) { 258 const auto& id = program->path(); 259 auto itr = cache->programs_.find(id); 260 if (itr == cache->programs_.end()) { 261 itr = cache->programs_.emplace_hint( 262 itr, id, generate(program, generators, cache, pos, index)); 263 } 264 return itr->second; 265 } 266 }; 267 268 class mstch_generators { 269 public: mstch_generators()270 mstch_generators() 271 : enum_value_generator_(std::make_unique<enum_value_generator>()), 272 enum_generator_(std::make_unique<enum_generator>()), 273 const_value_generator_(std::make_unique<const_value_generator>()), 274 type_generator_(std::make_unique<type_generator>()), 275 field_generator_(std::make_unique<field_generator>()), 276 annotation_generator_(std::make_unique<annotation_generator>()), 277 structured_annotation_generator_( 278 std::make_unique<structured_annotation_generator>()), 279 struct_generator_(std::make_unique<struct_generator>()), 280 function_generator_(std::make_unique<function_generator>()), 281 service_generator_(std::make_unique<service_generator>()), 282 typedef_generator_(std::make_unique<typedef_generator>()), 283 const_generator_(std::make_unique<const_generator>()), 284 program_generator_(std::make_unique<program_generator>()) {} 285 ~mstch_generators() = default; 286 set_enum_value_generator(std::unique_ptr<enum_value_generator> g)287 void set_enum_value_generator(std::unique_ptr<enum_value_generator> g) { 288 enum_value_generator_ = std::move(g); 289 } 290 set_enum_generator(std::unique_ptr<enum_generator> g)291 void set_enum_generator(std::unique_ptr<enum_generator> g) { 292 enum_generator_ = std::move(g); 293 } 294 set_const_value_generator(std::unique_ptr<const_value_generator> g)295 void set_const_value_generator(std::unique_ptr<const_value_generator> g) { 296 const_value_generator_ = std::move(g); 297 } 298 set_type_generator(std::unique_ptr<type_generator> g)299 void set_type_generator(std::unique_ptr<type_generator> g) { 300 type_generator_ = std::move(g); 301 } 302 set_field_generator(std::unique_ptr<field_generator> g)303 void set_field_generator(std::unique_ptr<field_generator> g) { 304 field_generator_ = std::move(g); 305 } 306 set_annotation_generator(std::unique_ptr<annotation_generator> g)307 void set_annotation_generator(std::unique_ptr<annotation_generator> g) { 308 annotation_generator_ = std::move(g); 309 } 310 set_struct_generator(std::unique_ptr<struct_generator> g)311 void set_struct_generator(std::unique_ptr<struct_generator> g) { 312 struct_generator_ = std::move(g); 313 } 314 set_function_generator(std::unique_ptr<function_generator> g)315 void set_function_generator(std::unique_ptr<function_generator> g) { 316 function_generator_ = std::move(g); 317 } 318 set_service_generator(std::unique_ptr<service_generator> g)319 void set_service_generator(std::unique_ptr<service_generator> g) { 320 service_generator_ = std::move(g); 321 } 322 set_typedef_generator(std::unique_ptr<typedef_generator> g)323 void set_typedef_generator(std::unique_ptr<typedef_generator> g) { 324 typedef_generator_ = std::move(g); 325 } 326 set_const_generator(std::unique_ptr<const_generator> g)327 void set_const_generator(std::unique_ptr<const_generator> g) { 328 const_generator_ = std::move(g); 329 } 330 set_program_generator(std::unique_ptr<program_generator> g)331 void set_program_generator(std::unique_ptr<program_generator> g) { 332 program_generator_ = std::move(g); 333 } 334 335 std::unique_ptr<enum_value_generator> enum_value_generator_; 336 std::unique_ptr<enum_generator> enum_generator_; 337 std::unique_ptr<const_value_generator> const_value_generator_; 338 std::unique_ptr<type_generator> type_generator_; 339 std::unique_ptr<field_generator> field_generator_; 340 std::unique_ptr<annotation_generator> annotation_generator_; 341 std::unique_ptr<structured_annotation_generator> 342 structured_annotation_generator_; 343 std::unique_ptr<struct_generator> struct_generator_; 344 std::unique_ptr<function_generator> function_generator_; 345 std::unique_ptr<service_generator> service_generator_; 346 std::unique_ptr<typedef_generator> typedef_generator_; 347 std::unique_ptr<const_generator> const_generator_; 348 std::unique_ptr<program_generator> program_generator_; 349 }; 350 351 class mstch_base : public mstch::object { 352 protected: 353 // A range of t_field* to avoid copying between std::vector<t_field*> 354 // and std::vector<t_field const*>. 355 class field_range { 356 public: field_range(const std::vector<t_field * > & fields)357 /* implicit */ field_range(const std::vector<t_field*>& fields) noexcept 358 : begin_(const_cast<const t_field* const*>(fields.data())), 359 end_(const_cast<const t_field* const*>( 360 fields.data() + fields.size())) {} field_range(const std::vector<t_field const * > & fields)361 /* implicit */ field_range( 362 const std::vector<t_field const*>& fields) noexcept 363 : begin_(fields.data()), end_(fields.data() + fields.size()) {} size()364 constexpr size_t size() const noexcept { return end_ - begin_; } begin()365 constexpr const t_field* const* begin() const noexcept { return begin_; } end()366 constexpr const t_field* const* end() const noexcept { return end_; } 367 368 private: 369 const t_field* const* begin_; 370 const t_field* const* end_; 371 }; 372 373 public: mstch_base(std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)374 mstch_base( 375 std::shared_ptr<mstch_generators const> generators, 376 std::shared_ptr<mstch_cache> cache, 377 ELEMENT_POSITION const pos) 378 : generators_(generators), cache_(cache), pos_(pos) { 379 register_methods( 380 this, 381 { 382 {"first?", &mstch_base::first}, 383 {"last?", &mstch_base::last}, 384 }); 385 } 386 virtual ~mstch_base() = default; 387 first()388 mstch::node first() { 389 return pos_ == ELEMENT_POSITION::FIRST || 390 pos_ == ELEMENT_POSITION::FIRST_AND_LAST; 391 } last()392 mstch::node last() { 393 return pos_ == ELEMENT_POSITION::LAST || 394 pos_ == ELEMENT_POSITION::FIRST_AND_LAST; 395 } 396 annotations(t_named const * annotated)397 mstch::node annotations(t_named const* annotated) { 398 return generate_annotations(annotated->annotations()); 399 } 400 structured_annotations(t_named const * annotated)401 mstch::node structured_annotations(t_named const* annotated) { 402 return generate_elements( 403 annotated->structured_annotations(), 404 generators_->structured_annotation_generator_.get()); 405 } 406 element_position(size_t index,size_t length)407 static ELEMENT_POSITION element_position(size_t index, size_t length) { 408 ELEMENT_POSITION pos = ELEMENT_POSITION::NONE; 409 if (index == 0) { 410 pos = ELEMENT_POSITION::FIRST; 411 } 412 if (index == length - 1) { 413 pos = ELEMENT_POSITION::LAST; 414 } 415 if (length == 1) { 416 pos = ELEMENT_POSITION::FIRST_AND_LAST; 417 } 418 return pos; 419 } 420 421 template <typename Container, typename Generator, typename... Args> generate_elements(Container const & container,Generator const * generator,Args const &...args)422 mstch::array generate_elements( 423 Container const& container, 424 Generator const* generator, 425 Args const&... args) { 426 mstch::array a; 427 size_t i = 0; 428 for (auto&& element : container) { 429 auto pos = element_position(i, container.size()); 430 a.push_back( 431 generator->generate(element, generators_, cache_, pos, i, args...)); 432 ++i; 433 } 434 return a; 435 } 436 437 template <typename C, typename... Args> generate_services(C const & container,Args const &...args)438 mstch::array generate_services(C const& container, Args const&... args) { 439 return generate_elements( 440 container, generators_->service_generator_.get(), args...); 441 } 442 443 template <typename C, typename... Args> generate_annotations(C const & container,Args const &...args)444 mstch::array generate_annotations(C const& container, Args const&... args) { 445 return generate_elements( 446 container, generators_->annotation_generator_.get(), args...); 447 } 448 449 template <typename C, typename... Args> generate_enum_values(C const & container,Args const &...args)450 mstch::array generate_enum_values(C const& container, Args const&... args) { 451 return generate_elements( 452 container, generators_->enum_value_generator_.get(), args...); 453 } 454 455 template <typename C, typename... Args> generate_consts(C const & container,Args const &...args)456 mstch::array generate_consts(C const& container, Args const&... args) { 457 return generate_elements( 458 container, generators_->const_value_generator_.get(), args...); 459 } 460 generate_fields(const field_range & fields)461 virtual mstch::array generate_fields(const field_range& fields) { 462 return generate_elements(fields, generators_->field_generator_.get()); 463 } 464 465 template <typename C, typename... Args> generate_functions(C const & container,Args const &...args)466 mstch::array generate_functions(C const& container, Args const&... args) { 467 return generate_elements( 468 container, generators_->function_generator_.get(), args...); 469 } 470 471 template <typename C, typename... Args> generate_typedefs(C const & container,Args const &...args)472 mstch::array generate_typedefs(C const& container, Args const&... args) { 473 return generate_elements( 474 container, generators_->typedef_generator_.get(), args...); 475 } 476 477 template <typename C, typename... Args> generate_types(C const & container,Args const &...args)478 mstch::array generate_types(C const& container, Args const&... args) { 479 return generate_elements( 480 container, generators_->type_generator_.get(), args...); 481 } 482 483 template <typename Item, typename Generator, typename Cache> generate_element_cached(Item const & item,Generator const * generator,Cache & c,std::string const & id,size_t element_index,size_t element_count)484 mstch::node generate_element_cached( 485 Item const& item, 486 Generator const* generator, 487 Cache& c, 488 std::string const& id, 489 size_t element_index, 490 size_t element_count) { 491 std::string elem_id = id + item->get_name(); 492 auto pos = element_position(element_index, element_count); 493 auto itr = c.find(elem_id); 494 if (itr == c.end()) { 495 itr = c.emplace_hint( 496 itr, 497 elem_id, 498 generator->generate(item, generators_, cache_, pos, element_index)); 499 } 500 return itr->second; 501 } 502 503 template <typename Container, typename Generator, typename Cache> generate_elements_cached(Container const & container,Generator const * generator,Cache & c,std::string const & id)504 mstch::array generate_elements_cached( 505 Container const& container, 506 Generator const* generator, 507 Cache& c, 508 std::string const& id) { 509 mstch::array a; 510 for (size_t i = 0; i < container.size(); ++i) { 511 a.push_back(generate_element_cached( 512 container[i], generator, c, id, i, container.size())); 513 } 514 return a; 515 } 516 517 bool has_option(const std::string& option) const; 518 std::string get_option(const std::string& option) const; 519 520 // Registers has_option(option) under the given name. 521 void register_has_option(std::string key, std::string option); 522 523 protected: 524 std::shared_ptr<mstch_generators const> generators_; 525 std::shared_ptr<mstch_cache> cache_; 526 ELEMENT_POSITION const pos_; 527 }; 528 529 class mstch_enum_value : public mstch_base { 530 public: 531 using node_type = t_enum_value; mstch_enum_value(t_enum_value const * enm_value,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)532 mstch_enum_value( 533 t_enum_value const* enm_value, 534 std::shared_ptr<mstch_generators const> generators, 535 std::shared_ptr<mstch_cache> cache, 536 ELEMENT_POSITION pos) 537 : mstch_base(generators, cache, pos), enm_value_(enm_value) { 538 register_methods( 539 this, 540 { 541 {"enum_value:name", &mstch_enum_value::name}, 542 {"enum_value:value", &mstch_enum_value::value}, 543 }); 544 } name()545 mstch::node name() { return enm_value_->get_name(); } value()546 mstch::node value() { return std::to_string(enm_value_->get_value()); } 547 548 protected: 549 t_enum_value const* enm_value_; 550 }; 551 552 class mstch_enum : public mstch_base { 553 public: 554 using node_type = t_enum; mstch_enum(t_enum const * enm,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)555 mstch_enum( 556 t_enum const* enm, 557 std::shared_ptr<mstch_generators const> generators, 558 std::shared_ptr<mstch_cache> cache, 559 ELEMENT_POSITION pos) 560 : mstch_base(generators, cache, pos), enm_(enm) { 561 register_methods( 562 this, 563 { 564 {"enum:name", &mstch_enum::name}, 565 {"enum:values", &mstch_enum::values}, 566 {"enum:structured_annotations", 567 &mstch_enum::structured_annotations}, 568 }); 569 } 570 name()571 mstch::node name() { return enm_->get_name(); } 572 mstch::node values(); structured_annotations()573 mstch::node structured_annotations() { 574 return mstch_base::structured_annotations(enm_); 575 } 576 577 protected: 578 t_enum const* enm_; 579 }; 580 581 class mstch_const_value : public mstch_base { 582 public: 583 using cv = t_const_value::t_const_value_type; mstch_const_value(t_const_value const * const_value,t_const const * current_const,t_type const * expected_type,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index)584 mstch_const_value( 585 t_const_value const* const_value, 586 t_const const* current_const, 587 t_type const* expected_type, 588 std::shared_ptr<mstch_generators const> generators, 589 std::shared_ptr<mstch_cache> cache, 590 ELEMENT_POSITION pos, 591 int32_t index) 592 : mstch_base(generators, cache, pos), 593 const_value_(const_value), 594 current_const_(current_const), 595 expected_type_(expected_type), 596 type_(const_value->get_type()), 597 index_(index) { 598 register_methods( 599 this, 600 { 601 {"value:bool?", &mstch_const_value::is_bool}, 602 {"value:double?", &mstch_const_value::is_double}, 603 {"value:integer?", &mstch_const_value::is_integer}, 604 {"value:enum?", &mstch_const_value::is_enum}, 605 {"value:enum_value?", &mstch_const_value::has_enum_value}, 606 {"value:string?", &mstch_const_value::is_string}, 607 {"value:string_multi_line?", 608 &mstch_const_value::is_string_multi_line}, 609 {"value:base?", &mstch_const_value::is_base}, 610 {"value:map?", &mstch_const_value::is_map}, 611 {"value:list?", &mstch_const_value::is_list}, 612 {"value:container?", &mstch_const_value::is_container}, 613 {"value:empty_container?", &mstch_const_value::is_empty_container}, 614 {"value:value", &mstch_const_value::value}, 615 {"value:integer_value", &mstch_const_value::integer_value}, 616 {"value:double_value", &mstch_const_value::double_value}, 617 {"value:bool_value", &mstch_const_value::bool_value}, 618 {"value:nonzero?", &mstch_const_value::is_non_zero}, 619 {"value:enum_name", &mstch_const_value::enum_name}, 620 {"value:enum_value_name", &mstch_const_value::enum_value_name}, 621 {"value:string_value", &mstch_const_value::string_value}, 622 {"value:list_elements", &mstch_const_value::list_elems}, 623 {"value:map_elements", &mstch_const_value::map_elems}, 624 {"value:const_struct", &mstch_const_value::const_struct}, 625 {"value:const_struct?", &mstch_const_value::is_const_struct}, 626 {"value:const_struct_type", &mstch_const_value::const_struct_type}, 627 {"value:referenceable?", &mstch_const_value::referenceable}, 628 {"value:owning_const", &mstch_const_value::owning_const}, 629 {"value:enable_referencing", 630 &mstch_const_value::enable_referencing}, 631 }); 632 } 633 format_double_string(const double d)634 std::string format_double_string(const double d) { 635 std::ostringstream oss; 636 oss << std::setprecision(std::numeric_limits<double>::digits10) << d; 637 return oss.str(); 638 } is_bool()639 mstch::node is_bool() { return type_ == cv::CV_BOOL; } is_double()640 mstch::node is_double() { return type_ == cv::CV_DOUBLE; } is_integer()641 mstch::node is_integer() { 642 return type_ == cv::CV_INTEGER && !const_value_->is_enum(); 643 } is_enum()644 mstch::node is_enum() { 645 return type_ == cv::CV_INTEGER && const_value_->is_enum(); 646 } has_enum_value()647 mstch::node has_enum_value() { 648 return const_value_->get_enum_value() != nullptr; 649 } is_string()650 mstch::node is_string() { return type_ == cv::CV_STRING; } is_string_multi_line()651 mstch::node is_string_multi_line() { 652 return type_ == cv::CV_STRING && 653 const_value_->get_string().find("\n") != std::string::npos; 654 } is_base()655 mstch::node is_base() { 656 return type_ == cv::CV_BOOL || type_ == cv::CV_DOUBLE || 657 type_ == cv::CV_INTEGER || type_ == cv::CV_STRING; 658 } is_map()659 mstch::node is_map() { return type_ == cv::CV_MAP; } is_list()660 mstch::node is_list() { return type_ == cv::CV_LIST; } is_container()661 mstch::node is_container() { 662 return type_ == cv::CV_MAP || type_ == cv::CV_LIST; 663 } is_empty_container()664 mstch::node is_empty_container() { 665 return (type_ == cv::CV_MAP && const_value_->get_map().empty()) || 666 (type_ == cv::CV_LIST && const_value_->get_list().empty()); 667 } 668 mstch::node value(); 669 mstch::node integer_value(); 670 mstch::node double_value(); 671 mstch::node bool_value(); 672 mstch::node is_non_zero(); 673 mstch::node enum_name(); 674 mstch::node enum_value_name(); 675 mstch::node string_value(); 676 mstch::node list_elems(); 677 mstch::node map_elems(); 678 mstch::node const_struct(); referenceable()679 mstch::node referenceable() { 680 return current_const_ && const_value_->get_owner() && 681 current_const_ != const_value_->get_owner() && same_type_as_expected(); 682 } 683 mstch::node owning_const(); enable_referencing()684 mstch::node enable_referencing() { 685 return mstch::map{{"value:enable_referencing?", true}}; 686 } 687 mstch::node is_const_struct(); 688 mstch::node const_struct_type(); 689 690 protected: 691 t_const_value const* const_value_; 692 t_const const* current_const_; 693 t_type const* expected_type_; 694 cv const type_; 695 int32_t index_; 696 same_type_as_expected()697 virtual bool same_type_as_expected() const { return false; } 698 }; 699 700 class mstch_const_value_key_mapped_pair : public mstch_base { 701 public: mstch_const_value_key_mapped_pair(std::pair<t_const_value *,t_const_value * > const & pair_values,t_const const * current_const,std::pair<const t_type *,const t_type * > const & expected_types,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index)702 mstch_const_value_key_mapped_pair( 703 std::pair<t_const_value*, t_const_value*> const& pair_values, 704 t_const const* current_const, 705 std::pair<const t_type*, const t_type*> const& expected_types, 706 std::shared_ptr<mstch_generators const> generators, 707 std::shared_ptr<mstch_cache> cache, 708 ELEMENT_POSITION pos, 709 int32_t index) 710 : mstch_base(generators, cache, pos), 711 pair_(pair_values), 712 current_const_(current_const), 713 expected_types_(expected_types), 714 index_(index) { 715 register_methods( 716 this, 717 { 718 {"element:key", &mstch_const_value_key_mapped_pair::element_key}, 719 {"element:value", 720 &mstch_const_value_key_mapped_pair::element_value}, 721 }); 722 } 723 mstch::node element_key(); 724 mstch::node element_value(); 725 726 protected: 727 std::pair<t_const_value*, t_const_value*> const pair_; 728 t_const const* current_const_; 729 std::pair<const t_type*, const t_type*> const expected_types_; 730 int32_t index_; 731 }; 732 733 class mstch_type : public mstch_base { 734 public: mstch_type(t_type const * type,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)735 mstch_type( 736 t_type const* type, 737 std::shared_ptr<mstch_generators const> generators, 738 std::shared_ptr<mstch_cache> cache, 739 ELEMENT_POSITION pos) 740 : mstch_base(generators, cache, pos), 741 type_(type), 742 resolved_type_(type->get_true_type()) { 743 register_methods( 744 this, 745 { 746 {"type:name", &mstch_type::name}, 747 {"type:void?", &mstch_type::is_void}, 748 {"type:string?", &mstch_type::is_string}, 749 {"type:binary?", &mstch_type::is_binary}, 750 {"type:bool?", &mstch_type::is_bool}, 751 {"type:byte?", &mstch_type::is_byte}, 752 {"type:i16?", &mstch_type::is_i16}, 753 {"type:i32?", &mstch_type::is_i32}, 754 {"type:i64?", &mstch_type::is_i64}, 755 {"type:double?", &mstch_type::is_double}, 756 {"type:float?", &mstch_type::is_float}, 757 {"type:floating_point?", &mstch_type::is_floating_point}, 758 {"type:struct?", &mstch_type::is_struct}, 759 {"type:union?", &mstch_type::is_union}, 760 {"type:enum?", &mstch_type::is_enum}, 761 {"type:sink?", &mstch_type::is_sink}, 762 {"type:sink_has_first_response?", 763 &mstch_type::sink_has_first_response}, 764 {"type:stream_or_sink?", &mstch_type::is_stream_or_sink}, 765 {"type:streamresponse?", &mstch_type::is_streamresponse}, 766 {"type:stream_has_first_response?", 767 &mstch_type::stream_has_first_response}, 768 {"type:service?", &mstch_type::is_service}, 769 {"type:base?", &mstch_type::is_base}, 770 {"type:container?", &mstch_type::is_container}, 771 {"type:list?", &mstch_type::is_list}, 772 {"type:set?", &mstch_type::is_set}, 773 {"type:map?", &mstch_type::is_map}, 774 {"type:typedef?", &mstch_type::is_typedef}, 775 {"type:struct", &mstch_type::get_struct}, 776 {"type:enum", &mstch_type::get_enum}, 777 {"type:list_elem_type", &mstch_type::get_list_type}, 778 {"type:set_elem_type", &mstch_type::get_set_type}, 779 {"type:sink_elem_type", &mstch_type::get_sink_elem_type}, 780 {"type:sink_final_response_type", 781 &mstch_type::get_sink_final_reponse_type}, 782 {"type:sink_first_response_type", 783 &mstch_type::get_sink_first_response_type}, 784 {"type:stream_elem_type", &mstch_type::get_stream_elem_type}, 785 {"type:stream_first_response_type", 786 &mstch_type::get_stream_first_response_type}, 787 {"type:key_type", &mstch_type::get_key_type}, 788 {"type:value_type", &mstch_type::get_value_type}, 789 {"type:typedef_type", &mstch_type::get_typedef_type}, 790 {"type:typedef", &mstch_type::get_typedef}, 791 {"type:interaction?", &mstch_type::is_interaction}, 792 }); 793 } 794 name()795 mstch::node name() { return type_->get_name(); } is_void()796 mstch::node is_void() { return resolved_type_->is_void(); } is_string()797 mstch::node is_string() { return resolved_type_->is_string(); } is_binary()798 mstch::node is_binary() { return resolved_type_->is_binary(); } is_bool()799 mstch::node is_bool() { return resolved_type_->is_bool(); } is_byte()800 mstch::node is_byte() { return resolved_type_->is_byte(); } is_i16()801 mstch::node is_i16() { return resolved_type_->is_i16(); } is_i32()802 mstch::node is_i32() { return resolved_type_->is_i32(); } is_i64()803 mstch::node is_i64() { return resolved_type_->is_i64(); } is_double()804 mstch::node is_double() { return resolved_type_->is_double(); } is_float()805 mstch::node is_float() { return resolved_type_->is_float(); } is_floating_point()806 mstch::node is_floating_point() { 807 return resolved_type_->is_floating_point(); 808 } is_struct()809 mstch::node is_struct() { 810 return resolved_type_->is_struct() || resolved_type_->is_xception(); 811 } is_union()812 mstch::node is_union() { return resolved_type_->is_union(); } is_enum()813 mstch::node is_enum() { return resolved_type_->is_enum(); } is_sink()814 mstch::node is_sink() { return resolved_type_->is_sink(); } sink_has_first_response()815 mstch::node sink_has_first_response() { 816 return resolved_type_->is_sink() && 817 dynamic_cast<const t_sink*>(resolved_type_)->sink_has_first_response(); 818 } is_stream_or_sink()819 mstch::node is_stream_or_sink() { 820 return resolved_type_->is_streamresponse() || resolved_type_->is_sink(); 821 } is_streamresponse()822 mstch::node is_streamresponse() { 823 return resolved_type_->is_streamresponse(); 824 } stream_has_first_response()825 mstch::node stream_has_first_response() { 826 return resolved_type_->is_streamresponse() && 827 dynamic_cast<const t_stream_response*>(resolved_type_) 828 ->first_response_type() != boost::none; 829 } is_service()830 mstch::node is_service() { return resolved_type_->is_service(); } is_base()831 mstch::node is_base() { return resolved_type_->is_base_type(); } is_container()832 mstch::node is_container() { return resolved_type_->is_container(); } is_list()833 mstch::node is_list() { return resolved_type_->is_list(); } is_set()834 mstch::node is_set() { return resolved_type_->is_set(); } is_map()835 mstch::node is_map() { return resolved_type_->is_map(); } is_typedef()836 mstch::node is_typedef() { return type_->is_typedef(); } get_type_namespace(t_program const *)837 virtual std::string get_type_namespace(t_program const*) { return ""; } 838 mstch::node get_struct(); 839 mstch::node get_enum(); 840 mstch::node get_list_type(); 841 mstch::node get_set_type(); 842 mstch::node get_key_type(); 843 mstch::node get_value_type(); 844 mstch::node get_typedef_type(); 845 mstch::node get_typedef(); 846 mstch::node get_sink_first_response_type(); 847 mstch::node get_sink_elem_type(); 848 mstch::node get_sink_final_reponse_type(); 849 mstch::node get_stream_elem_type(); 850 mstch::node get_stream_first_response_type(); is_interaction()851 mstch::node is_interaction() { return type_->is_service(); } 852 853 protected: 854 t_type const* type_; 855 t_type const* resolved_type_; 856 }; 857 858 class mstch_field : public mstch_base { 859 public: mstch_field(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)860 mstch_field( 861 t_field const* field, 862 std::shared_ptr<mstch_generators const> generators, 863 std::shared_ptr<mstch_cache> cache, 864 ELEMENT_POSITION pos, 865 int32_t index, 866 field_generator_context const* field_context) 867 : mstch_base(generators, cache, pos), 868 field_(field), 869 index_(index), 870 field_context_(field_context) { 871 register_methods( 872 this, 873 { 874 {"field:name", &mstch_field::name}, 875 {"field:key", &mstch_field::key}, 876 {"field:value", &mstch_field::value}, 877 {"field:type", &mstch_field::type}, 878 {"field:index", &mstch_field::index}, 879 {"field:required?", &mstch_field::is_required}, 880 {"field:optional?", &mstch_field::is_optional}, 881 {"field:opt_in_req_out?", &mstch_field::is_optInReqOut}, 882 {"field:annotations", &mstch_field::annotations}, 883 {"field:structured_annotations", 884 &mstch_field::structured_annotations}, 885 }); 886 } name()887 mstch::node name() { return field_->get_name(); } key()888 mstch::node key() { return std::to_string(field_->get_key()); } 889 mstch::node value(); 890 mstch::node type(); index()891 mstch::node index() { return std::to_string(index_); } is_required()892 mstch::node is_required() { 893 return field_->get_req() == t_field::e_req::required; 894 } is_optional()895 mstch::node is_optional() { 896 return field_->get_req() == t_field::e_req::optional; 897 } is_optInReqOut()898 mstch::node is_optInReqOut() { 899 return field_->get_req() == t_field::e_req::opt_in_req_out; 900 } annotations()901 mstch::node annotations() { return mstch_base::annotations(field_); } structured_annotations()902 mstch::node structured_annotations() { 903 return mstch_base::structured_annotations(field_); 904 } 905 906 protected: 907 t_field const* field_; 908 int32_t index_; 909 field_generator_context const* field_context_; 910 }; 911 912 class mstch_annotation : public mstch_base { 913 public: mstch_annotation(const std::string & key,const annotation_value & val,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index)914 mstch_annotation( 915 const std::string& key, 916 const annotation_value& val, 917 std::shared_ptr<mstch_generators const> generators, 918 std::shared_ptr<mstch_cache> cache, 919 ELEMENT_POSITION pos, 920 int32_t index) 921 : mstch_base(generators, cache, pos), 922 key_(key), 923 val_(val), 924 index_(index) { 925 register_methods( 926 this, 927 { 928 {"annotation:key", &mstch_annotation::key}, 929 {"annotation:value", &mstch_annotation::value}, 930 }); 931 } key()932 mstch::node key() { return key_; } value()933 mstch::node value() { return val_.value; } 934 935 protected: 936 const std::string key_; 937 const annotation_value val_; 938 int32_t index_; 939 }; 940 941 class mstch_structured_annotation : public mstch_base { 942 public: mstch_structured_annotation(const t_const & cnst,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index)943 mstch_structured_annotation( 944 const t_const& cnst, 945 std::shared_ptr<mstch_generators const> generators, 946 std::shared_ptr<mstch_cache> cache, 947 ELEMENT_POSITION pos, 948 int32_t index) 949 : mstch_base(generators, cache, pos), cnst_(cnst), index_(index) { 950 register_methods( 951 this, 952 {{"structured_annotation:const", 953 &mstch_structured_annotation::constant}, 954 {"structured_annotation:const_struct?", 955 &mstch_structured_annotation::is_const_struct}}); 956 } constant()957 mstch::node constant() { 958 return generators_->const_generator_->generate( 959 &cnst_, 960 generators_, 961 cache_, 962 pos_, 963 index_, 964 &cnst_, 965 cnst_.type()->get_true_type()); 966 } 967 is_const_struct()968 mstch::node is_const_struct() { 969 return cnst_.type()->get_true_type()->is_struct(); 970 } 971 972 protected: 973 const t_const& cnst_; 974 int32_t index_; 975 }; 976 977 class mstch_struct : public mstch_base { 978 public: mstch_struct(t_struct const * strct,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)979 mstch_struct( 980 t_struct const* strct, 981 std::shared_ptr<mstch_generators const> generators, 982 std::shared_ptr<mstch_cache> cache, 983 ELEMENT_POSITION pos) 984 : mstch_base(generators, cache, pos), strct_(strct) { 985 register_methods( 986 this, 987 { 988 {"struct:name", &mstch_struct::name}, 989 {"struct:fields?", &mstch_struct::has_fields}, 990 {"struct:fields", &mstch_struct::fields}, 991 {"struct:exception?", &mstch_struct::is_exception}, 992 {"struct:union?", &mstch_struct::is_union}, 993 {"struct:plain?", &mstch_struct::is_plain}, 994 {"struct:annotations", &mstch_struct::annotations}, 995 {"struct:thrift_uri", &mstch_struct::thrift_uri}, 996 {"struct:structured_annotations", 997 &mstch_struct::structured_annotations}, 998 {"struct:exception_kind", &mstch_struct::exception_kind}, 999 {"struct:exception_safety", &mstch_struct::exception_safety}, 1000 {"struct:exception_blame", &mstch_struct::exception_blame}, 1001 }); 1002 1003 // Populate field_context_generator for each field. 1004 auto ctx = field_generator_context{}; 1005 ctx.strct = strct_; 1006 auto fields = strct->fields(); 1007 for (auto it = fields.begin(); it != fields.end(); it++) { 1008 const auto* field = &*it; 1009 if (cpp2::field_has_isset(field)) { 1010 ctx.isset_index++; 1011 } 1012 ctx.next = (it + 1) != fields.end() ? &*(it + 1) : nullptr; 1013 context_map[field] = ctx; 1014 ctx.prev = field; 1015 } 1016 } name()1017 mstch::node name() { return strct_->get_name(); } has_fields()1018 mstch::node has_fields() { return strct_->has_fields(); } 1019 mstch::node fields(); is_exception()1020 mstch::node is_exception() { return strct_->is_xception(); } is_union()1021 mstch::node is_union() { return strct_->is_union(); } is_plain()1022 mstch::node is_plain() { 1023 return !strct_->is_xception() && !strct_->is_union(); 1024 } annotations()1025 mstch::node annotations() { return mstch_base::annotations(strct_); } 1026 mstch::node thrift_uri(); structured_annotations()1027 mstch::node structured_annotations() { 1028 return mstch_base::structured_annotations(strct_); 1029 } 1030 1031 mstch::node exception_safety(); 1032 1033 mstch::node exception_blame(); 1034 1035 mstch::node exception_kind(); 1036 generate_fields(const field_range & fields)1037 mstch::array generate_fields(const field_range& fields) override { 1038 mstch::array a; 1039 size_t i = 0; 1040 for (const auto* field : fields) { 1041 auto pos = element_position(i, fields.size()); 1042 a.push_back(generators_->field_generator_.get()->generate( 1043 field, generators_, cache_, pos, i, &context_map[field])); 1044 ++i; 1045 } 1046 return a; 1047 } 1048 1049 protected: 1050 t_struct const* strct_; 1051 // Although mstch_fields can be generated from different orders than the IDL 1052 // order, field_generator_context should be always computed in the IDL order, 1053 // as the context does not change by reordering. Without the map, each 1054 // different reordering recomputes field_generator_context, and each 1055 // field takes O(N) to loop through node_list_view<t_field> or 1056 // std::vector<t_field*> to find the exact t_field to compute 1057 // field_generator_context. 1058 std::unordered_map<t_field const*, field_generator_context> context_map; 1059 }; 1060 1061 class mstch_function : public mstch_base { 1062 public: mstch_function(t_function const * function,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)1063 mstch_function( 1064 t_function const* function, 1065 std::shared_ptr<mstch_generators const> generators, 1066 std::shared_ptr<mstch_cache> cache, 1067 ELEMENT_POSITION pos) 1068 : mstch_base(generators, cache, pos), function_(function) { 1069 register_methods( 1070 this, 1071 { 1072 {"function:name", &mstch_function::name}, 1073 {"function:oneway?", &mstch_function::oneway}, 1074 {"function:return_type", &mstch_function::return_type}, 1075 {"function:exceptions", &mstch_function::exceptions}, 1076 {"function:stream_exceptions", &mstch_function::stream_exceptions}, 1077 {"function:sink_exceptions", &mstch_function::sink_exceptions}, 1078 {"function:sink_final_response_exceptions", 1079 &mstch_function::sink_final_response_exceptions}, 1080 {"function:exceptions?", &mstch_function::has_exceptions}, 1081 {"function:stream_exceptions?", 1082 &mstch_function::has_streamexceptions}, 1083 {"function:sink_exceptions?", &mstch_function::has_sinkexceptions}, 1084 {"function:sink_final_response_exceptions?", 1085 &mstch_function::has_sink_final_response_exceptions}, 1086 {"function:args", &mstch_function::arg_list}, 1087 {"function:comma", &mstch_function::has_args}, 1088 {"function:priority", &mstch_function::priority}, 1089 {"function:returns_sink?", &mstch_function::returns_sink}, 1090 {"function:returns_streams?", &mstch_function::returns_stream}, 1091 {"function:returns_stream?", &mstch_function::returns_stream}, 1092 {"function:stream_has_first_response?", 1093 &mstch_function::stream_has_first_response}, 1094 {"function:annotations", &mstch_function::annotations}, 1095 {"function:starts_interaction?", 1096 &mstch_function::starts_interaction}, 1097 {"function:structured_annotations", 1098 &mstch_function::structured_annotations}, 1099 {"function:qualifier", &mstch_function::qualifier}, 1100 }); 1101 } 1102 name()1103 mstch::node name() { return function_->get_name(); } oneway()1104 mstch::node oneway() { 1105 return function_->qualifier() == t_function_qualifier::one_way; 1106 } has_exceptions()1107 mstch::node has_exceptions() { 1108 return function_->get_xceptions()->has_fields(); 1109 } has_streamexceptions()1110 mstch::node has_streamexceptions() { 1111 return function_->get_stream_xceptions()->has_fields(); 1112 } has_sinkexceptions()1113 mstch::node has_sinkexceptions() { 1114 return function_->get_sink_xceptions()->has_fields(); 1115 } has_sink_final_response_exceptions()1116 mstch::node has_sink_final_response_exceptions() { 1117 return function_->get_sink_final_response_xceptions()->has_fields(); 1118 } stream_has_first_response()1119 mstch::node stream_has_first_response() { 1120 const auto& rettype = *function_->return_type(); 1121 auto stream = dynamic_cast<const t_stream_response*>(&rettype); 1122 return stream && stream->first_response_type() != boost::none; 1123 } has_args()1124 mstch::node has_args() { 1125 if (function_->get_paramlist()->has_fields()) { 1126 return std::string(", "); 1127 } 1128 return std::string(); 1129 } priority()1130 mstch::node priority() { 1131 return function_->get_annotation("priority", "NORMAL"); 1132 } returns_sink()1133 mstch::node returns_sink() { return function_->returns_sink(); } annotations()1134 mstch::node annotations() { return mstch_base::annotations(function_); } 1135 1136 mstch::node return_type(); 1137 mstch::node exceptions(); 1138 mstch::node stream_exceptions(); 1139 mstch::node sink_exceptions(); 1140 mstch::node sink_final_response_exceptions(); 1141 mstch::node arg_list(); 1142 mstch::node returns_stream(); starts_interaction()1143 mstch::node starts_interaction() { 1144 return function_->get_returntype()->is_service(); 1145 } 1146 structured_annotations()1147 mstch::node structured_annotations() { 1148 return mstch_base::structured_annotations(function_); 1149 } 1150 qualifier()1151 mstch::node qualifier() { 1152 auto q = function_->qualifier(); 1153 switch (q) { 1154 case t_function_qualifier::one_way: 1155 return std::string("OneWay"); 1156 case t_function_qualifier::idempotent: 1157 return std::string("Idempotent"); 1158 case t_function_qualifier::read_only: 1159 return std::string("ReadOnly"); 1160 default: 1161 return std::string("Unspecified"); 1162 } 1163 } 1164 1165 protected: 1166 t_function const* function_; 1167 }; 1168 1169 class mstch_service : public mstch_base { 1170 public: mstch_service(t_service const * service,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)1171 mstch_service( 1172 t_service const* service, 1173 std::shared_ptr<mstch_generators const> generators, 1174 std::shared_ptr<mstch_cache> cache, 1175 ELEMENT_POSITION pos) 1176 : mstch_base(generators, cache, pos), service_(service) { 1177 register_methods( 1178 this, 1179 { 1180 {"service:name", &mstch_service::name}, 1181 {"service:functions", &mstch_service::functions}, 1182 {"service:functions?", &mstch_service::has_functions}, 1183 {"service:extends", &mstch_service::extends}, 1184 {"service:extends?", &mstch_service::has_extends}, 1185 {"service:streams?", &mstch_service::has_streams}, 1186 {"service:sinks?", &mstch_service::has_sinks}, 1187 {"service:annotations", &mstch_service::annotations}, 1188 {"service:parent", &mstch_service::parent}, 1189 {"service:interaction?", &mstch_service::is_interaction}, 1190 {"service:interactions", &mstch_service::interactions}, 1191 {"service:interactions?", &mstch_service::has_interactions}, 1192 {"service:structured_annotations", 1193 &mstch_service::structured_annotations}, 1194 {"interaction:serial?", &mstch_service::is_serial_interaction}, 1195 }); 1196 } 1197 get_service_namespace(t_program const *)1198 virtual std::string get_service_namespace(t_program const*) { return {}; } 1199 name()1200 mstch::node name() { return service_->get_name(); } has_functions()1201 mstch::node has_functions() { return !get_functions().empty(); } has_extends()1202 mstch::node has_extends() { return service_->get_extends() != nullptr; } 1203 mstch::node functions(); 1204 mstch::node extends(); annotations()1205 mstch::node annotations() { return mstch_base::annotations(service_); } 1206 parent()1207 mstch::node parent() { 1208 return cache_->parsed_options_["parent_service_name"]; 1209 } 1210 has_streams()1211 mstch::node has_streams() { 1212 auto& funcs = get_functions(); 1213 return std::any_of(funcs.cbegin(), funcs.cend(), [](auto const& func) { 1214 return func->returns_stream(); 1215 }); 1216 } 1217 has_sinks()1218 mstch::node has_sinks() { 1219 auto& funcs = get_functions(); 1220 return std::any_of(funcs.cbegin(), funcs.cend(), [](auto const& func) { 1221 return func->returns_sink(); 1222 }); 1223 } 1224 has_interactions()1225 mstch::node has_interactions() { 1226 auto& funcs = get_functions(); 1227 return std::any_of(funcs.cbegin(), funcs.cend(), [](auto const& func) { 1228 return func->get_returntype()->is_service(); 1229 }); 1230 } interactions()1231 mstch::node interactions() { 1232 if (!service_->is_interaction()) { 1233 cache_->parsed_options_["parent_service_name"] = service_->get_name(); 1234 } 1235 std::vector<t_service const*> interactions; 1236 for (auto const* function : get_functions()) { 1237 if (function->get_returntype()->is_service()) { 1238 interactions.push_back( 1239 dynamic_cast<t_service const*>(function->get_returntype())); 1240 } 1241 } 1242 return generate_services(interactions); 1243 } structured_annotations()1244 mstch::node structured_annotations() { 1245 return mstch_base::structured_annotations(service_); 1246 } is_interaction()1247 mstch::node is_interaction() { return service_->is_interaction(); } is_serial_interaction()1248 mstch::node is_serial_interaction() { 1249 return service_->is_serial_interaction(); 1250 } 1251 1252 virtual ~mstch_service() = default; 1253 1254 protected: 1255 t_service const* service_; 1256 1257 mstch::node generate_cached_extended_service(const t_service* service); get_functions()1258 virtual const std::vector<t_function*>& get_functions() const { 1259 return service_->get_functions(); 1260 } 1261 }; 1262 1263 class mstch_typedef : public mstch_base { 1264 public: mstch_typedef(t_typedef const * typedf,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)1265 mstch_typedef( 1266 t_typedef const* typedf, 1267 std::shared_ptr<mstch_generators const> generators, 1268 std::shared_ptr<mstch_cache> cache, 1269 ELEMENT_POSITION pos) 1270 : mstch_base(generators, cache, pos), typedf_(typedf) { 1271 register_methods( 1272 this, 1273 { 1274 {"typedef:type", &mstch_typedef::type}, 1275 {"typedef:is_same_type", &mstch_typedef::is_same_type}, 1276 {"typedef:name", &mstch_typedef::name}, 1277 {"typedef:structured_annotations", 1278 &mstch_typedef::structured_annotations}, 1279 }); 1280 } 1281 mstch::node type(); name()1282 mstch::node name() { return typedf_->name(); } is_same_type()1283 mstch::node is_same_type() { 1284 return typedf_->get_name() == typedf_->get_type()->get_name(); 1285 } structured_annotations()1286 mstch::node structured_annotations() { 1287 return mstch_base::structured_annotations(typedf_); 1288 } 1289 1290 protected: 1291 t_typedef const* typedf_; 1292 }; 1293 1294 class mstch_const : public mstch_base { 1295 public: mstch_const(t_const const * cnst,t_const const * current_const,t_type const * expected_type,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index,t_field const * field)1296 mstch_const( 1297 t_const const* cnst, 1298 t_const const* current_const, 1299 t_type const* expected_type, 1300 std::shared_ptr<mstch_generators const> generators, 1301 std::shared_ptr<mstch_cache> cache, 1302 ELEMENT_POSITION pos, 1303 int32_t index, 1304 t_field const* field) 1305 : mstch_base(generators, cache, pos), 1306 cnst_(cnst), 1307 current_const_(current_const), 1308 expected_type_(expected_type), 1309 index_(index), 1310 field_(field) { 1311 register_methods( 1312 this, 1313 { 1314 {"constant:name", &mstch_const::name}, 1315 {"constant:index", &mstch_const::index}, 1316 {"constant:type", &mstch_const::type}, 1317 {"constant:value", &mstch_const::value}, 1318 {"constant:program", &mstch_const::program}, 1319 }); 1320 } name()1321 mstch::node name() { return cnst_->get_name(); } index()1322 mstch::node index() { return index_; } 1323 mstch::node type(); 1324 mstch::node value(); 1325 mstch::node program(); 1326 1327 protected: 1328 t_const const* cnst_; 1329 t_const const* current_const_; 1330 t_type const* expected_type_; 1331 int32_t index_; 1332 t_field const* field_; 1333 }; 1334 1335 class mstch_program : public mstch_base { 1336 public: mstch_program(t_program const * program,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos)1337 mstch_program( 1338 t_program const* program, 1339 std::shared_ptr<mstch_generators const> generators, 1340 std::shared_ptr<mstch_cache> cache, 1341 ELEMENT_POSITION pos) 1342 : mstch_base(generators, cache, pos), program_(program) { 1343 register_methods( 1344 this, 1345 { 1346 {"program:name", &mstch_program::name}, 1347 {"program:path", &mstch_program::path}, 1348 {"program:includePrefix", &mstch_program::include_prefix}, 1349 {"program:structs", &mstch_program::structs}, 1350 {"program:enums", &mstch_program::enums}, 1351 {"program:services", &mstch_program::services}, 1352 {"program:typedefs", &mstch_program::typedefs}, 1353 {"program:constants", &mstch_program::constants}, 1354 {"program:enums?", &mstch_program::has_enums}, 1355 {"program:structs?", &mstch_program::has_structs}, 1356 {"program:unions?", &mstch_program::has_unions}, 1357 {"program:services?", &mstch_program::has_services}, 1358 {"program:typedefs?", &mstch_program::has_typedefs}, 1359 {"program:constants?", &mstch_program::has_constants}, 1360 {"program:thrift_uris?", &mstch_program::has_thrift_uris}, 1361 }); 1362 register_has_option("program:frozen?", "frozen"); 1363 register_has_option("program:json?", "json"); 1364 register_has_option("program:nimble?", "nimble"); 1365 register_has_option("program:any?", "any"); 1366 register_has_option( 1367 "program:unstructured_annotations_in_metadata?", 1368 "deprecated_unstructured_annotations_in_metadata"); 1369 } 1370 get_program_namespace(t_program const *)1371 virtual std::string get_program_namespace(t_program const*) { return {}; } 1372 name()1373 mstch::node name() { return program_->name(); } path()1374 mstch::node path() { return program_->path(); } include_prefix()1375 mstch::node include_prefix() { return program_->include_prefix(); } has_enums()1376 mstch::node has_enums() { return !program_->enums().empty(); } has_structs()1377 mstch::node has_structs() { 1378 return !program_->structs().empty() || !program_->xceptions().empty(); 1379 } has_services()1380 mstch::node has_services() { return !program_->services().empty(); } has_typedefs()1381 mstch::node has_typedefs() { return !program_->typedefs().empty(); } has_constants()1382 mstch::node has_constants() { return !program_->consts().empty(); } has_unions()1383 mstch::node has_unions() { 1384 auto& structs = program_->structs(); 1385 return std::any_of( 1386 structs.cbegin(), structs.cend(), std::mem_fn(&t_struct::is_union)); 1387 } 1388 1389 mstch::node has_thrift_uris(); 1390 mstch::node structs(); 1391 mstch::node enums(); 1392 mstch::node services(); 1393 mstch::node typedefs(); 1394 mstch::node constants(); 1395 1396 protected: 1397 t_program const* program_; 1398 1399 virtual const std::vector<t_struct*>& get_program_objects(); 1400 virtual const std::vector<t_enum*>& get_program_enums(); 1401 }; 1402 1403 } // namespace compiler 1404 } // namespace thrift 1405 } // namespace apache 1406