/* * 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. */ #pragma once #include #include #include #include #include #include namespace apache { namespace thrift { namespace compiler { class t_program; class t_program_bundle; class t_generator { public: t_generator(t_program& p, source_manager& sm, t_program_bundle& pb) : program_(&p), source_mgr_(sm), program_bundle_(pb) {} virtual ~t_generator() = default; // Processes generator options. // out_path: A path to the output directory. // add_gen_dir: Specifies whether to add a generator-specific subdirectory // (usually gen-) to the output directory. void process_options( const std::map& options, std::string out_path, bool add_gen_dir); bool add_gen_dir() const { return add_gen_dir_; } /** * Called before generate_program to process options. * * @throws std::exception if the given options are invalid. */ virtual void process_options(const std::map&) {} virtual void fill_validator_visitors(ast_validator&) const {} // Generate the program. Overridden by subclasses to implement program // generation. virtual void generate_program() = 0; const t_program* get_program() const { return program_; } t_program* get_program() { return program_; } std::unordered_set get_genfiles() { return generated_files_; } void record_genfile(const std::string& filename) { generated_files_.insert(filename); } void record_genfile(const std::filesystem::path& filename) { generated_files_.insert(filename.string()); } /** * Get the current output directory */ virtual std::string get_out_dir() const { return get_out_path().string(); } virtual std::filesystem::path get_out_path() const { auto path = std::filesystem::path{out_path_}; if (add_gen_dir_) { path /= out_dir_base_; } path += std::filesystem::path::preferred_separator; return path; } protected: t_program* program_; source_manager& source_mgr_; t_program_bundle& program_bundle_; /** * Output type-specifc directory name ("gen-*"). */ std::string out_dir_base_; /** * The set of files generated by this generator. */ std::unordered_set generated_files_; private: std::string out_path_; bool add_gen_dir_ = false; }; /** * A factory for producing generator classes of a particular language. * * This class is also responsible for: * - Registering itself with the generator registry. * - Providing documentation for the generators it produces. */ class generator_factory { public: generator_factory( std::string name, std::string long_name, std::string documentation); virtual ~generator_factory() = default; // Creates a generator for the specified program. virtual std::unique_ptr make_generator( t_program& p, source_manager& sm, t_program_bundle& pb) = 0; const std::string& name() const { return name_; } const std::string& long_name() const { return long_name_; } const std::string& documentation() const { return documentation_; } private: std::string name_; std::string long_name_; std::string documentation_; }; namespace detail { template class generator_factory_impl : public generator_factory { public: using generator_factory::generator_factory; std::unique_ptr make_generator( t_program& p, source_manager& sm, t_program_bundle& pb) override { return std::unique_ptr(new Generator(p, sm, pb)); } }; } // namespace detail namespace generator_registry { void register_generator(const std::string& name, generator_factory* factory); std::unique_ptr make_generator( const std::string& name, t_program& p, source_manager& sm, t_program_bundle& pb); // A map from generator names to factories. using generator_map = std::map; generator_map& get_generators(); } // namespace generator_registry #define THRIFT_REGISTER_GENERATOR(name, long_name, doc) \ static detail::generator_factory_impl registerer( \ #name, long_name, doc) } // namespace compiler } // namespace thrift } // namespace apache