dogen::formatters::artefact enum_header_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), true/*requires_header_guard*/, id); const auto& ye(a.as<yarn::enumeration>(static_artefact(), e)); { auto sbf(a.make_scoped_boilerplate_formatter()); { const auto ns(a.make_namespaces(e.name())); auto snf(a.make_scoped_namespace_formatter(ns)); a.stream() << std::endl; a.comment(e.documentation()); a.stream() << "enum class " << ye.name().simple() << " : " << a.get_qualified_name(ye.underlying_type()) << " {" << std::endl; dogen::formatters::sequence_formatter sf(ye.enumerators().size()); for (const auto& en : ye.enumerators()) { a.stream() << " " << en.name() << " = " << en.value() << sf.postfix() << a.comment_inline(en.documentation()) << std::endl; sf.next(); } a.stream() << "};" << std::endl; a.stream() << std::endl; } // snf a.stream() << std::endl; } // sbf return a.make_artefact(); }
std::list<std::string> enum_header_formatter::inclusion_dependencies( const formattables::inclusion_dependencies_builder_factory& f, const yarn::element& e) const { auto builder(f.make()); builder.add(e.name(), types::traits::enum_header_archetype()); return builder.build(); }
dogen::formatters::artefact enum_header_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), true/*requires_header_guard*/, id); const auto& ye(a.as<yarn::enumeration>(static_artefact(), e)); { auto sbf(a.make_scoped_boilerplate_formatter()); { const auto ns(a.make_namespaces(ye.name())); auto snf(a.make_scoped_namespace_formatter(ns)); a.stream() << std::endl; a.stream() << "class " << ye.name().simple() << "_generator {" << std::endl; a.stream() << "public:" << std::endl; a.stream() << " " << ye.name().simple() << "_generator();" << std::endl; a.stream() << std::endl; a.stream() << "public:" << std::endl; a.stream() << " typedef " << a.get_qualified_name(ye.name()) << " result_type;" << std::endl; a.stream() << std::endl; a.stream() << "public:" << std::endl; a.stream() << " static void populate(const unsigned int position, result_type& v);" << std::endl; a.stream() << " static result_type create(const unsigned int position);" << std::endl; a.stream() << " result_type operator()();" << std::endl; a.stream() << std::endl; a.stream() << "private:" << std::endl; a.stream() << " unsigned int position_;" << std::endl; a.stream() << "};" << std::endl; a.stream() << std::endl; } // snf a.stream() << std::endl; } // sbf return a.make_artefact(); }
dogen::formatters::artefact forward_declarations_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), true/*requires_header_guard*/, id); const auto arch(static_artefact()); const auto& fd(a.as<fabric::forward_declarations>(arch, e)); // FIXME: hack: legacy formatters do not support serialisation // forward declarations for some types. if (fd.is_enum() || fd.is_exception()) return dogen::formatters::artefact(); { auto sbf(a.make_scoped_boilerplate_formatter()); const auto qn(a.get_qualified_name(fd.name())); a.stream() << std::endl; a.stream() << "namespace boost {" << std::endl; a.stream() << "namespace serialization {" << std::endl; a.stream() << std::endl; a.stream() << "template<class Archive>" << std::endl; a.stream() << "void save(Archive& ar, const " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "template<class Archive>" << std::endl; a.stream() << "void load(Archive& ar, " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "} }" << std::endl; a.stream() << std::endl; } // sbf return a.make_artefact(); }
dogen::formatters::artefact exception_header_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), true/*requires_header_guard*/, id); const auto& ye(a.as<yarn::exception>(static_artefact(), e)); { auto sbf(a.make_scoped_boilerplate_formatter()); { const auto ns(a.make_namespaces(ye.name())); auto snf(a.make_scoped_namespace_formatter(ns)); a.stream() << std::endl; a.comment(ye.documentation()); a.stream() << "class " << ye.name().simple() << " : public virtual std::exception, public virtual boost::exception {" << std::endl; a.stream() << "public:" << std::endl; a.stream() << " " << ye.name().simple() << "() = default;" << std::endl; a.stream() << " ~" << ye.name().simple() << "() noexcept = default;" << std::endl; a.stream() << std::endl; a.stream() << "public:" << std::endl; a.stream() << " " << ye.name().simple() << "(const std::string& message) : message_(message) { }" << std::endl; a.stream() << std::endl; a.stream() << "public:" << std::endl; a.stream() << " const char* what() const noexcept { return(message_.c_str()); }" << std::endl; a.stream() << std::endl; a.stream() << "private:" << std::endl; a.stream() << " const std::string message_;" << std::endl; a.stream() << "};" << std::endl; a.stream() << std::endl; } // snf a.stream() << std::endl; } // sbf return a.make_artefact(); }
std::list<std::string> forward_declarations_formatter::inclusion_dependencies( const formattables::inclusion_dependencies_builder_factory& f, const yarn::element& e) const { auto builder(f.make()); using tp = formatters::types::traits; const auto tp_fn(tp::forward_declarations_archetype()); builder.add(e.name(), tp_fn); return builder.build(); }
dogen::formatters::artefact enum_header_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), true/*requires_header_guard*/, id); const auto& ye(a.as<yarn::enumeration>(static_artefact(), e)); { auto sbf(a.make_scoped_boilerplate_formatter()); a.stream() << std::endl; a.stream() << "template<class Archive>" << std::endl; a.stream() << "void serialize(Archive& ar, " << a.get_qualified_name(ye.name()) << "& v, unsigned int /*version*/){" << std::endl; a.stream() << " using boost::serialization::make_nvp;" << std::endl; a.stream() << " ar & make_nvp(\"" << ye.name().simple() << "\", v);" << std::endl; a.stream() << "}" << std::endl; a.stream() << std::endl; } // sbf return a.make_artefact(); }
dogen::formatters::artefact class_header_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), true/*requires_header_guard*/, id); const auto& o(a.as<yarn::object>(static_artefact(), e)); { const auto qn(a.get_qualified_name(o.name())); auto sbf(a.make_scoped_boilerplate_formatter()); if (!o.is_parent() && o.parent()) { const auto& pn(*o.parent()); const auto pqn(a.get_qualified_name(pn)); a.stream() << "namespace boost {" << std::endl; a.stream() << std::endl; a.stream() << "template<>struct" << std::endl; a.stream() << "is_virtual_base_of<" << std::endl; a.stream() << " " << pqn << "," << std::endl; a.stream() << " " << qn << std::endl; a.stream() << "> : public mpl::true_ {};" << std::endl; a.stream() << std::endl; a.stream() << "}" << std::endl; } a.stream() << std::endl; a.stream() << "BOOST_SERIALIZATION_SPLIT_FREE(" << qn << ")" << std::endl; if (o.is_parent()) { a.stream() << "BOOST_SERIALIZATION_ASSUME_ABSTRACT(" << qn << ")" << std::endl; a.stream() << std::endl; } a.stream() << "namespace boost {" << std::endl; a.stream() << "namespace serialization {" << std::endl; a.stream() << std::endl; a.stream() << "template<typename Archive>" << std::endl; a.stream() << "void save(Archive& ar, const " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "template<typename Archive>" << std::endl; a.stream() << "void load(Archive& ar, " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "} }" << std::endl; a.stream() << std::endl; } // sbf return a.make_artefact(); }
dogen::formatters::artefact enum_header_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), true/*requires_header_guard*/, id); const auto& ye(a.as<yarn::enumeration>(static_artefact(), e)); { auto sbf(a.make_scoped_boilerplate_formatter()); { const auto ns(a.make_namespaces(ye.name())); auto snf(a.make_scoped_namespace_formatter(ns)); a.stream() << std::endl; a.stream() << "#ifdef ODB_COMPILER" << std::endl; a.stream() << std::endl; a.stream() << "#endif" << std::endl; a.stream() << std::endl; } // snf a.stream() << std::endl; } // sbf return a.make_artefact(); }
dogen::formatters::artefact stitch_formatter:: format(const artefact_formatter_interface& stock_formatter, const context& ctx, const yarn::element& e) const { const auto al(stock_formatter.archetype_location()); const auto needs_guard(is_header(stock_formatter.inclusion_support_type())); const auto id(e.name().id()); assistant a(ctx, al, needs_guard, id); const auto& fp(a.artefact_properties().file_path()); auto stitch_template(fp); stitch_template.replace_extension(stitch_extension); /* * If the template does not yet exist, we should just create an * empty artefact. * * This scenario happens when creating a new model or when adding * a new artefact formatter for the first time. */ if (!boost::filesystem::exists(stitch_template)) { BOOST_LOG_SEV(lg, debug) << "Stitch template not found: " << fp.generic_string(); dogen::formatters::artefact r; r.overwrite(a.artefact_properties().overwrite()); return r; } /* * Since the template exists, we can instantiate it. */ auto r(instantiator_.instantiate(stitch_template)); r.overwrite(a.artefact_properties().overwrite()); r.dependencies().push_back(stitch_template); return r; }
dogen::formatters::artefact enum_formatter::format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), id); const auto& ye(a.as<yarn::enumeration>(static_artefact(), e)); { const auto sn(e.name().simple()); auto sbf(a.make_scoped_boilerplate_formatter()); { a.stream() << "using System;" << std::endl; a.stream() << "using System.Collections;" << std::endl; a.stream() << "using System.Collections.Generic;" << std::endl; a.stream() << std::endl; const auto ns(a.make_namespaces(e.name())); auto snf(a.make_scoped_namespace_formatter(ns)); a.stream() << " /// <summary>" << std::endl; a.stream() << " /// Generates sequences of " << sn << "." << std::endl; a.stream() << " /// </summary>" << std::endl; a.stream() << " public static class " << sn << "SequenceGenerator" << std::endl; a.stream() << " {" << std::endl; a.stream() << " static internal " << sn << " Create(uint position)" << std::endl; a.stream() << " {" << std::endl; a.stream() << " var result = (" << sn << ")(position % " << ye.enumerators().size() << ");" << std::endl; a.stream() << " return result;" << std::endl; a.stream() << " }" << std::endl; a.stream() << std::endl; a.stream() << " #region Enumerator" << std::endl; a.stream() << " private class " << sn << "Enumerator : IEnumerator, IEnumerator<" << sn << ">, IDisposable" << std::endl; a.stream() << " {" << std::endl; a.stream() << " #region Properties" << std::endl; a.stream() << " private uint _position;" << std::endl; a.stream() << " private " << sn << " _current;" << std::endl; a.stream() << " #endregion" << std::endl; a.stream() << std::endl; a.stream() << " private void PopulateCurrent()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " _current = " << sn << "SequenceGenerator.Create(_position);" << std::endl; a.stream() << " }" << std::endl; a.stream() << std::endl; a.stream() << " #region IDisposable" << std::endl; a.stream() << " public void Dispose()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " }" << std::endl; a.stream() << " #endregion" << std::endl; a.stream() << std::endl; a.stream() << " #region IEnumerator implementation" << std::endl; a.stream() << " public bool MoveNext()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " ++_position;" << std::endl; a.stream() << " PopulateCurrent();" << std::endl; a.stream() << " return true;" << std::endl; a.stream() << " }" << std::endl; a.stream() << std::endl; a.stream() << " public void Reset()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " _position = 0;" << std::endl; a.stream() << " PopulateCurrent();" << std::endl; a.stream() << " }" << std::endl; a.stream() << std::endl; a.stream() << " public object Current {" << std::endl; a.stream() << " get" << std::endl; a.stream() << " {" << std::endl; a.stream() << " return _current;" << std::endl; a.stream() << " }" << std::endl; a.stream() << " }" << std::endl; a.stream() << std::endl; a.stream() << " " << sn << " IEnumerator<" << sn << ">.Current" << std::endl; a.stream() << " {" << std::endl; a.stream() << " get" << std::endl; a.stream() << " {" << std::endl; a.stream() << " return _current;" << std::endl; a.stream() << " }" << std::endl; a.stream() << " }" << std::endl; a.stream() << " #endregion" << std::endl; a.stream() << std::endl; a.stream() << " public " << sn << "Enumerator()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " PopulateCurrent();" << std::endl; a.stream() << " }" << std::endl; a.stream() << " }" << std::endl; a.stream() << " #endregion" << std::endl; a.stream() << std::endl; a.stream() << " #region Enumerable" << std::endl; a.stream() << " private class " << sn << "Enumerable : IEnumerable, IEnumerable<" << sn << ">" << std::endl; a.stream() << " {" << std::endl; a.stream() << " #region IEnumerable implementation" << std::endl; a.stream() << " public IEnumerator GetEnumerator()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " return new " << sn << "Enumerator();" << std::endl; a.stream() << " }" << std::endl; a.stream() << std::endl; a.stream() << " IEnumerator<" << sn << "> IEnumerable<" << sn << ">.GetEnumerator()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " return new " << sn << "Enumerator();" << std::endl; a.stream() << " }" << std::endl; a.stream() << " #endregion" << std::endl; a.stream() << " }" << std::endl; a.stream() << " #endregion" << std::endl; a.stream() << std::endl; a.stream() << " static public IEnumerable<" << sn << "> Sequence()" << std::endl; a.stream() << " {" << std::endl; a.stream() << " return new " << sn << "Enumerable();" << std::endl; a.stream() << " }" << std::endl; a.stream() << " }" << std::endl; } } // sbf return a.make_artefact(); }
inclusion_expander::element_inclusion_dependencies_type inclusion_expander::compute_inclusion_dependencies( const formatters::repository& frp, const inclusion_dependencies_builder_factory& idf, const yarn::element& e) const { const auto id(e.name().id()); BOOST_LOG_SEV(lg, debug) << "Creating inclusion dependencies for: " << id; /* * First we must obtain all formatters for the type of element we * are building includes for. They may or may not exist in the * formatters' collection - for example, we do not have any * formatters for concepts at present. If so, we're done. * * Note also that we must query the formatters by type index * rather than use the archetype configuration container * directly. This is due to element segmentation, as we may have * more than one element associated with an id. To generate the * inclusion dependencies we must make sure we pick the pair of * element and the formatters that support it. */ element_inclusion_dependencies_type r; const auto ti(std::type_index(typeid(e))); const auto i(frp.stock_artefact_formatters_by_type_index().find(ti)); if (i == frp.stock_artefact_formatters_by_type_index().end()) { BOOST_LOG_SEV(lg, debug) << "No formatters for type: " << ti.name(); return r; } for (const auto fmt : i->second) { const auto arch(fmt->archetype_location().archetype()); const auto fmtn(fmt->formatter_name()); BOOST_LOG_SEV(lg, debug) << "Providing for: " << arch << " using formatter: " << fmtn; /* * Obtain the formatter's list of inclusion dependencies. If * none, we're done. */ auto deps(fmt->inclusion_dependencies(idf, e)); if (deps.empty()) continue; /* * Ensure the dependencies are sorted according to a well * defined order and all duplicates are removed. Duplicates * arise because an element may refer to another element more * than once - e.g. std::list<T> as well as std::vector<T>. */ deps.sort(include_directive_comparer); deps.unique(); /* * Now slot in the results, ensuring our formatter name is * unique. We have guaranteed in the registrar that the * formatter name is unique, so no need to perform any * insertion checks here. */ r[arch] = deps; } BOOST_LOG_SEV(lg, debug) << "Finished creating inclusion dependencies for: " << id << ". Result: " << r; return r; }
void inclusion_expander::compute_inclusion_directives(const type_group& tg, const yarn::element& e, const formatter_list_type& formatters, const locator& l, inclusion_directives_container_type& idc) const { const auto& n(e.name()); const auto id(n.id()); /* * First we extract the data required to generated include * directives for this element. Note that we generate this setting * for _all elements_ even if the user did not specify any * meta-data (we do so via defaults). * * The question we are asking is: "does this element require any * inclusion directives at all, across all facets?". Not all * elements do; for example bool, int and so on don't require any * inclusions at all across all facets. If the user did not * override this, we default it to true because normally elements * require inclusion. */ const auto& a(e.annotation()); const bool required(make_top_level_inclusion_required(tg, a)); if (!required) { BOOST_LOG_SEV(lg, debug) << "Inclusion not required for element."; return; } /* * Now we start working at the formatter level. */ for (const auto& fmt : formatters) { const auto arch(fmt->archetype_location().archetype()); BOOST_LOG_SEV(lg, debug) << "Archetype: " << arch; /* * Does the archetype require an inclusion directive for this * specific formatter? Some elements require inclusion * directives for some archetypes, but not for others. For * example, we may need an include for serialising a * std::list, but in test data we make use of helpers and thus * not require an include. * * Again, we default this flag to true. */ const auto id_cfg(make_inclusion_directive_configuration(tg, arch, a)); if (!id_cfg.inclusion_required()) { BOOST_LOG_SEV(lg, debug) << "Inclusion directive not required " << " for archetype: " << arch; continue; } /* * Does the configuration provide a "hard-coded" inclusion * directive? That is, the archetype has an hard-coded * incantation for its include. This is the case for proxy * models such as boost, std etc where we can't compute the * inclusion directive. */ std::string directive; if (!id_cfg.inclusion_directive().empty()) directive = id_cfg.inclusion_directive(); else { /* * Finally, we have no alternative but to compute the * inclusion directive according to a well-defined * heuristic. */ const auto path(fmt->inclusion_path(l, n)); directive = to_inclusion_directive(path); } BOOST_LOG_SEV(lg, debug) << "Inclusion directive: " << directive; insert_inclusion_directive(id, arch, directive, idc); } }
dogen::formatters::artefact class_implementation_formatter:: format(const context& ctx, const yarn::element& e) const { const auto id(e.name().id()); assistant a(ctx, archetype_location(), false/*requires_header_guard*/, id); const auto& o(a.as<yarn::object>(static_artefact(), e)); { auto sbf(a.make_scoped_boilerplate_formatter()); a.add_helper_methods(o.name().id()); const auto qn(a.get_qualified_name(o.name())); const bool has_attributes(!o.local_attributes().empty()); const bool has_parent(o.parent()); const bool has_attributes_or_parent(has_attributes || has_parent); if (o.is_parent() || o.parent()) { a.stream() << std::endl; a.stream() << "BOOST_CLASS_TRACKING(" << std::endl; a.stream() << " " << qn << "," << std::endl; a.stream() << " boost::serialization::track_selectively)" << std::endl; } a.stream() << std::endl; a.stream() << "namespace boost {" << std::endl; a.stream() << "namespace serialization {" << std::endl; /* * Save function */ a.stream() << std::endl; a.stream() << "template<typename Archive>" << std::endl; a.stream() << "void save(Archive& " << (has_attributes_or_parent ? "ar" : "/*ar*/") << "," << std::endl; a.stream() << " const " << qn << "& " << (has_attributes_or_parent ? "v" : "/*v*/") << "," << std::endl; a.stream() << " const unsigned int /*version*/) {" << std::endl; if (o.parent()) { const auto& pn(*o.parent()); const auto pqn(a.get_qualified_name(pn)); a.stream() << " ar << make_nvp(\"" << pn.simple() << "\", base_object<" << pqn << ">(v));" << std::endl; } if (has_attributes && has_parent) a.stream() << std::endl; for (const auto attr : o.local_attributes()) { a.stream() << " ar << make_nvp(\"" << attr.name().simple() << "\", v." << a.make_member_variable_name(attr) << ");" << std::endl; } a.stream() << "}" << std::endl; a.stream() << std::endl; /* * Load function */ a.stream() << "template<typename Archive>" << std::endl; a.stream() << "void load(Archive& " << (has_attributes_or_parent ? "ar," : "/*ar*/,") << std::endl; a.stream() << " " << qn << "& " << (has_attributes_or_parent ? "v" : "/*v*/") << "," << std::endl; a.stream() << " const unsigned int /*version*/) {" << std::endl; if (o.parent()) { const auto& pn(*o.parent()); const auto pqn(a.get_qualified_name(pn)); a.stream() << " ar >> make_nvp(\"" << pn.simple() << "\", base_object<" << pqn << ">(v));" << std::endl; if (has_attributes && has_parent) a.stream() << std::endl; } for (const auto attr : o.local_attributes()) { a.stream() << " ar >> make_nvp(\"" << attr.name().simple() << "\", v." << a.make_member_variable_name(attr) << ");" << std::endl; } a.stream() << "}" << std::endl; a.stream() << std::endl; a.stream() << "} }" << std::endl; a.stream() << std::endl; a.stream() << "namespace boost {" << std::endl; a.stream() << "namespace serialization {" << std::endl; a.stream() << std::endl; a.stream() << "template void save(archive::polymorphic_oarchive& ar, const " << qn << "& v, unsigned int version);" << std::endl; a.stream() << "template void load(archive::polymorphic_iarchive& ar, " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "template void save(archive::text_oarchive& ar, const " << qn << "& v, unsigned int version);" << std::endl; a.stream() << "template void load(archive::text_iarchive& ar, " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "template void save(archive::binary_oarchive& ar, const " << qn << "& v, unsigned int version);" << std::endl; a.stream() << "template void load(archive::binary_iarchive& ar, " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "template void save(archive::xml_oarchive& ar, const " << qn << "& v, unsigned int version);" << std::endl; a.stream() << "template void load(archive::xml_iarchive& ar, " << qn << "& v, unsigned int version);" << std::endl; a.stream() << std::endl; a.stream() << "} }" << std::endl; } // sbf return a.make_artefact(); }