dogen::formatters::file class_implementation_formatter_stitch( assistant& a, const formattables::class_info& c) { { auto sbf(a.make_scoped_boilerplate_formatter()); a.add_helper_methods(c); { auto snf(a.make_scoped_namespace_formatter(c.namespaces())); const bool no_arg(!c.is_parent() && c.parents().empty() && c.properties().empty()); a.stream() << std::endl; a.stream() << "std::ostream& operator<<(std::ostream& s, const " << c.name() << "&" << (no_arg ? "" : " v") << ") {" << std::endl; if (c.is_parent() || !c.parents().empty()) { a.stream() << " v.to_stream(s);" << std::endl; a.stream() << " return(s);" << std::endl; } else io::inserter_implementation_helper_stitch(a, c, false/*inside_class*/); a.stream() << "}" << std::endl; a.stream() << std::endl; } // snf } // sbf return a.make_file(); }
dogen::formatters::file class_implementation_formatter_stitch( formatters::entity_formatting_assistant& fa, const formattables::class_info& c) { { auto sbf(fa.make_scoped_boilerplate_formatter()); if (!c.properties().empty()) { fa.stream() << "namespace {" << std::endl; fa.add_helper_methods(); fa.stream() << std::endl; fa.stream() << "}" << std::endl; fa.stream() << std::endl; } { auto snf(fa.make_scoped_namespace_formatter()); /* * Default constructor. */ if (!c.is_parent()) { fa.stream() << std::endl; fa.stream() << c.name() << "_generator::" << c.name() << "_generator() : position_(0) { }" << std::endl; } /* * Populate method. */ if (!c.is_immutable()) { bool no_args(c.properties().empty() && c.parents().empty()); if (no_args) { fa.stream() << std::endl; fa.stream() << "void " << c.name() << "_generator::" << std::endl; fa.stream() << "populate(const unsigned int /*position*/, result_type& /*v*/) {" << std::endl; } else { fa.stream() << std::endl; fa.stream() << "void " << c.name() << "_generator::" << std::endl; fa.stream() << "populate(const unsigned int position, result_type& v) {" << std::endl; } for (const auto p : c.parents()) { fa.stream() << " " << p.qualified_name() << "_generator::populate(position, v);" << std::endl; } unsigned int i(0); for (const auto p : c.properties()) { fa.stream() << " v." << p.name() << "(create_" << p.type().complete_identifiable_name() << "(position + " << i << "));" << std::endl; ++i; } fa.stream() << "}" << std::endl; } /* * Create method. */ if (!c.is_parent()) { const bool no_arg(c.all_properties().empty()); fa.stream() << std::endl; fa.stream() << c.name() << "_generator::result_type" << std::endl; fa.stream() << c.name() << "_generator::create(const unsigned int" << (no_arg ? "/*position*/" : " position") << ") {" << std::endl; if (c.is_immutable()) { fa.stream() << " return " << c.name() << "(" << std::endl; // FIXME: hack if (c.properties().empty()) fa.stream() << std::endl; else { dogen::formatters::sequence_formatter sf(c.properties().size()); for (const auto p : c.properties()) { fa.stream() << " create_" << p.type().complete_identifiable_name() << "(position + " << sf.current_position() << ")" << sf.postfix() << std::endl; sf.next(); } } fa.stream() << " );" << std::endl; } else { fa.stream() << " " << c.name() << " r;" << std::endl; if (!c.all_properties().empty()) fa.stream() << " " << c.name() << "_generator::populate(position, r);" << std::endl; fa.stream() << " return r;" << std::endl; } fa.stream() << "}" << std::endl; } /* * Create method ptr. */ fa.stream() << std::endl; fa.stream() << c.name() << "_generator::result_type*" << std::endl; fa.stream() << c.name() << "_generator::create_ptr(const unsigned int position) {" << std::endl; if (c.leaves().empty()) { if (c.is_immutable()) fa.stream() << " return new " << c.name() << "(create(position));" << std::endl; else { fa.stream() << " " << c.name() << "* p = new " << c.name() << "();" << std::endl; fa.stream() << " " << c.name() << "_generator::populate(position, *p);" << std::endl; fa.stream() << " return p;" << std::endl; } } else { auto leaves(c.leaves()); const auto front(leaves.front()); leaves.pop_front(); unsigned int i(0); unsigned int total(leaves.size()); for (const auto l : leaves) { fa.stream() << " if ((position % " << total << ") == " << i++ << ")" << std::endl; fa.stream() << " return " << l << "_generator::create_ptr(position);" << std::endl; } fa.stream() << " return " << front << "_generator::create_ptr(position);" << std::endl; } fa.stream() << "}" << std::endl; /* * Function operator */ if (!c.is_parent()) { fa.stream() << std::endl; fa.stream() << c.name() << "_generator::result_type" << std::endl; fa.stream() << c.name() << "_generator::operator()() {" << std::endl; fa.stream() << " return create(position_++);" << std::endl; fa.stream() << "}" << std::endl; } fa.stream() << std::endl; } // snf } // sbf return fa.make_file(); }
dogen::formatters::file class_header_formatter_stitch( formatters::entity_formatting_assistant& fa, const formattables::class_info& c) { { auto sbf(fa.make_scoped_boilerplate_formatter()); { auto snf(fa.make_scoped_namespace_formatter()); fa.stream() << std::endl; fa.comment(c.documentation()); if (c.parents().empty()) { fa.stream() << "class " << c.name() << " " << fa.make_final_keyword_text(c) << "{" << std::endl; } else if (c.parents().size() == 1) { fa.stream() << "class " << c.name() << " " << fa.make_final_keyword_text(c) << ": public " << c.parents().front().qualified_name() << " {" << std::endl; } else { dogen::formatters::sequence_formatter sf(c.parents().size()); for (const auto p : c.parents()) { fa.stream() << " public " << p.qualified_name() << sf.postfix() << std::endl; sf.next(); } } fa.stream() << "public:" << std::endl; /* * Compiler generated constructors and destructors. */ if (!c.requires_manual_default_constructor()) fa.stream() << " " << c.name() << "() = default;" << std::endl; fa.stream() << " " << c.name() << "(const " << c.name() << "&) = default;" << std::endl; if (!c.requires_manual_move_constructor()) fa.stream() << " " << c.name() << "(" << c.name() << "&&) = default;" << std::endl; if (!c.is_parent() && c.parents().empty()) fa.stream() << " ~" << c.name() << "() = default;" << std::endl; if (c.is_immutable()) fa.stream() << " " << c.name() << "& operator=(const " << c.name() << "&) = delete;" << std::endl; else if (c.all_properties().empty()) fa.stream() << " " << c.name() << "& operator=(const " << c.name() << "&) = default;" << std::endl; fa.stream() << std::endl; /* * Manually generated default constructor. */ if (c.requires_manual_default_constructor()) { fa.stream() << "public:" << std::endl; fa.stream() << " " << c.name() << "();" << std::endl; fa.stream() << std::endl; } /* * Manually generated destructor. * * according to MEC++, item 33, base classes should always be * abstract. this avoids all sorts of tricky problems with * assignment and swap. * * incidentally, this also fixes some strange clang errors: * undefined reference to `vtable. */ if (c.is_parent()) { fa.stream() << " virtual ~" << c.name() << "() noexcept = 0;" << std::endl; fa.stream() << std::endl; } else if (c.parents().size() != 0) { fa.stream() << " virtual ~" << c.name() << "() noexcept { }" << std::endl; fa.stream() << std::endl; } /* * Manually generated move constructor. */ if (c.requires_manual_move_constructor()) { fa.stream() << "public:" << std::endl; fa.stream() << " " << c.name() << "(" << c.name() << "&& rhs);" << std::endl; fa.stream() << std::endl; } /* * Manually generated complete constructor. */ if (!fa.is_complete_constructor_disabled() && !c.all_properties().empty()) { fa.stream() << "public:" << std::endl; const auto prop_count(c.all_properties().size()); if (prop_count == 1) { const auto p(*c.all_properties().begin()); fa.stream() << " explicit " << c.name() << "(const " << p.type().complete_name() << fa.make_by_ref_text(p) << " " << p.name() << ");" << std::endl; } else { fa.stream() << " " << c.name() << "(" << std::endl; dogen::formatters::sequence_formatter sf(prop_count); sf.postfix_configuration().last(");"); for (const auto& p : c.all_properties()) { fa.stream() << " const " << p.type().complete_name() << fa.make_by_ref_text(p) << " " << p.name() << sf.postfix() << std::endl; sf.next(); } } fa.stream() << std::endl; } /* * Friends */ if (fa.is_serialization_enabled()) { fa.stream() << "private:" << std::endl; fa.stream() << " template<typename Archive>" << std::endl; fa.stream() << " friend void boost::serialization::save(Archive& ar, const " << c.name() << "& v, unsigned int version);" << std::endl; fa.stream() << std::endl; fa.stream() << " template<typename Archive>" << std::endl; fa.stream() << " friend void boost::serialization::load(Archive& ar, " << c.name() << "& v, unsigned int version);" << std::endl; fa.stream() << std::endl; } /* * Visitation. */ if (c.is_visitable()) { fa.stream() << "public:" << std::endl; fa.stream() << " virtual void accept(const " << c.name() << "_visitor& v) const = 0;" << std::endl; fa.stream() << " virtual void accept(" << c.name() << "_visitor& v) const = 0;" << std::endl; fa.stream() << " virtual void accept(const " << c.name() << "_visitor& v) = 0;" << std::endl; fa.stream() << " virtual void accept(" << c.name() << "_visitor& v) = 0;" << std::endl; fa.stream() << std::endl; } else if (c.is_original_parent_visitable() && !c.is_parent()) { fa.stream() << "public:" << std::endl; fa.stream() << " virtual void accept(const " << c.original_parent_name() << "_visitor& v) const override {" << std::endl; fa.stream() << " v.visit(*this);" << std::endl; fa.stream() << " }" << std::endl; fa.stream() << std::endl; fa.stream() << " virtual void accept(" << c.original_parent_name() << "_visitor& v) const override {" << std::endl; fa.stream() << " v.visit(*this);" << std::endl; fa.stream() << " }" << std::endl; fa.stream() << std::endl; fa.stream() << " virtual void accept(const " << c.original_parent_name() << "_visitor& v) override {" << std::endl; fa.stream() << " v.visit(*this);" << std::endl; fa.stream() << " }" << std::endl; fa.stream() << std::endl; fa.stream() << " virtual void accept(" << c.original_parent_name() << "_visitor& v) override {" << std::endl; fa.stream() << " v.visit(*this);" << std::endl; fa.stream() << " }" << std::endl; fa.stream() << std::endl; } /* * Streaming */ if (fa.is_io_enabled()) { if (c.is_parent()) { fa.stream() << "public:" << std::endl; fa.stream() << " virtual void to_stream(std::ostream& s) const;" << std::endl; fa.stream() << std::endl; } else if (!c.parents().empty()) { fa.stream() << "public:" << std::endl; fa.stream() << " void to_stream(std::ostream& s) const override;" << std::endl; fa.stream() << std::endl; } } /* * Getters and setters. */ if (!c.properties().empty()) { fa.stream() << "public:" << std::endl; for (const auto p : c.properties()) { fa.comment_start_method_group(p.documentation(), !p.is_immutable()); if (p.type().is_primitive() || p.type().is_enumeration()) { fa.stream() << " " << p.type().complete_name() << " " << p.name() << "() const;" << std::endl; if (p.is_immutable()) { fa.stream() << std::endl; continue; } fa.stream() << " " << fa.make_setter_return_type(c.name(), p) << " " << p.name() << "(const " << p.type().complete_name() << fa.make_by_ref_text(p) << " v);" << std::endl; } else { fa.stream() << " const " << p.type().complete_name() << "& " << p.name() << "() const;" << std::endl; if (p.is_immutable()) { fa.stream() << std::endl; continue; } fa.stream() << " " << p.type().complete_name() << fa.make_by_ref_text(p) << " " << p.name() << "();" << std::endl; fa.stream() << " " << fa.make_setter_return_type(c.name(), p) << " " << p.name() << "(const " << p.type().complete_name() << fa.make_by_ref_text(p) << " v);" << std::endl; fa.stream() << " " << fa.make_setter_return_type(c.name(), p) << " " << p.name() << "(const " << p.type().complete_name() << "&& v);" << std::endl; } fa.comment_end_method_group(p.documentation(), !p.is_immutable()); fa.stream() << std::endl; } } /* * Equality. * * Equality is only public in leaf classes - MEC++-33. */ if (c.is_parent()) { fa.stream() << "protected:" << std::endl; fa.stream() << " bool compare(const " << c.name() << "& rhs) const;" << std::endl; } else { fa.stream() << "public:" << std::endl; fa.stream() << " bool operator==(const " << c.name() << "& rhs) const;" << std::endl; fa.stream() << " bool operator!=(const " << c.name() << "& rhs) const {" << std::endl; fa.stream() << " return !this->operator==(rhs);" << std::endl; fa.stream() << " }" << std::endl; fa.stream() << std::endl; } if (c.is_parent() || !c.parents().empty()) { fa.stream() << "public:" << std::endl; if (c.is_parent() && c.parents().empty()) { fa.stream() << " virtual bool equals(const " << c.name() << "& other) const = 0;" << std::endl; } else if (c.is_parent()) { fa.stream() << " virtual bool equals(const " << c.original_parent_name_qualified() << "& other) const = 0;" << std::endl; } else if (!c.parents().empty()) { fa.stream() << " bool equals(const " << c.original_parent_name_qualified() << "& other) const override;" << std::endl; } fa.stream() << std::endl; } /* * Swap and assignment. * * Swap and assignment are only public in leaf classes - MEC++-33 */ if ((!c.all_properties().empty() || c.is_parent()) && !c.is_immutable()) { if (c.is_parent()) { fa.stream() << "protected:" << std::endl; } else { fa.stream() << "public:" << std::endl; } fa.stream() << " void swap(" << c.name() << "& other) noexcept;" << std::endl; if (!c.is_parent() && !c.is_immutable()) { fa.stream() << " " << c.name() << "& operator=(" << c.name() << " other);" << std::endl; } fa.stream() << std::endl; } /* * Member variables. */ if (!c.properties().empty()) { fa.stream() << "private:" << std::endl; for (const auto& p : c.properties()) { fa.stream() << " " << p.type().complete_name() << " " << fa.make_member_variable_name(p) << ";" << std::endl; } } fa.stream() << "};" << std::endl; fa.stream() << std::endl; /* * Destructor implementation. */ if (c.is_parent()) { fa.stream() << "inline " << c.name() << "::~" << c.name() << "() noexcept { }" << std::endl; fa.stream() << std::endl; } /* * Global inserter operator implementation */ if (fa.is_io_enabled() && fa.is_io_integrated()) { fa.stream() << " std::ostream& operator<<(std::ostream& s, const " << c.name() << "& v);" << std::endl; fa.stream() << std::endl; } /* * Global equality operator implementation. */ if (c.is_parent()) { fa.stream() << "inline bool operator==(const " << c.name() << "& lhs, const " << c.name() << "& rhs) {" << std::endl; fa.stream() << " return lhs.equals(rhs);" << std::endl; fa.stream() << "}" << std::endl; fa.stream() << std::endl; } } if (!c.all_properties().empty() && !c.is_parent() && !c.is_immutable()) { fa.stream() << std::endl; fa.stream() << "namespace std {" << std::endl; fa.stream() << std::endl; fa.stream() << "template<>" << std::endl; fa.stream() << "inline void swap(" << std::endl; fa.stream() << " " << c.qualified_name() << "& lhs," << std::endl; fa.stream() << " " << c.qualified_name() << "& rhs) {" << std::endl; fa.stream() << " lhs.swap(rhs);" << std::endl; fa.stream() << "}" << std::endl; fa.stream() << std::endl; fa.stream() << "}" << std::endl; } // snf fa.stream() << std::endl; } // sbf return fa.make_file(); }