Added support for iterating over diagram elements from inja templates (fixes #54)

This commit is contained in:
Bartek Kryza
2022-09-15 23:36:29 +02:00
parent 693a09e20d
commit 17db587426
20 changed files with 115 additions and 20 deletions

View File

@@ -489,6 +489,8 @@ void generator::generate_relationships(
void generator::generate(std::ostream &ostr) const void generator::generate(std::ostream &ostr) const
{ {
update_context();
ostr << "@startuml" << '\n'; ostr << "@startuml" << '\n';
generate_plantuml_directives(ostr, m_config.puml().before); generate_plantuml_directives(ostr, m_config.puml().before);

View File

@@ -42,6 +42,8 @@ public:
class_ &operator=(const class_ &) = delete; class_ &operator=(const class_ &) = delete;
class_ &operator=(class_ &&) = delete; class_ &operator=(class_ &&) = delete;
std::string type_name() const override { return "class"; }
bool is_struct() const; bool is_struct() const;
void is_struct(bool is_struct); void is_struct(bool is_struct);

View File

@@ -271,6 +271,28 @@ std::string diagram::to_alias(
throw error::uml_alias_missing(fmt::format("Missing alias for {}", id)); throw error::uml_alias_missing(fmt::format("Missing alias for {}", id));
} }
inja::json diagram::context() const {
inja::json ctx;
ctx["name"] = name();
ctx["type"] = "class";
inja::json::array_t elements{};
// Add classes
for(const auto &c : classes()) {
elements.emplace_back(c.get().context());
}
// Add enums
for(const auto &e : enums()) {
elements.emplace_back(e.get().context());
}
ctx["elements"] = elements;
return ctx;
}
} }
namespace clanguml::common::model { namespace clanguml::common::model {

View File

@@ -87,6 +87,8 @@ public:
bool has_element( bool has_element(
const clanguml::common::model::diagram_element::id_t id) const override; const clanguml::common::model::diagram_element::id_t id) const override;
inja::json context() const override;
private: private:
common::reference_vector<class_> classes_; common::reference_vector<class_> classes_;

View File

@@ -34,6 +34,8 @@ public:
enum_ &operator=(const enum_ &) = delete; enum_ &operator=(const enum_ &) = delete;
enum_ &operator=(enum_ &&) = delete; enum_ &operator=(enum_ &&) = delete;
std::string type_name() const override { return "enum"; }
// TODO: Do we need this? // TODO: Do we need this?
friend bool operator==(const enum_ &l, const enum_ &r); friend bool operator==(const enum_ &l, const enum_ &r);

View File

@@ -69,6 +69,8 @@ public:
template <typename E> template <typename E>
void generate_link(std::ostream &ostr, const E &e) const; void generate_link(std::ostream &ostr, const E &e) const;
void update_context() const;
protected: protected:
const inja::json &context() const; const inja::json &context() const;
@@ -85,7 +87,7 @@ protected:
ConfigType &m_config; ConfigType &m_config;
DiagramType &m_model; DiagramType &m_model;
mutable std::set<std::string> m_generated_aliases; mutable std::set<std::string> m_generated_aliases;
inja::json m_context; mutable inja::json m_context;
mutable inja::Environment m_env; mutable inja::Environment m_env;
}; };
@@ -372,9 +374,11 @@ template <typename C, typename D> void generator<C, D>::init_context()
m_context["git"]["commit"] = m_config.git().commit; m_context["git"]["commit"] = m_config.git().commit;
m_context["git"]["toplevel"] = m_config.git().toplevel; m_context["git"]["toplevel"] = m_config.git().toplevel;
} }
}
m_context["diagram"]["name"] = m_config.name; template <typename C, typename D> void generator<C, D>::update_context() const
m_context["diagram"]["type"] = to_string(m_config.type()); {
m_context["diagram"] = m_model.context();
} }
template <typename C, typename D> void generator<C, D>::init_env() template <typename C, typename D> void generator<C, D>::init_env()

View File

@@ -74,6 +74,8 @@ public:
virtual bool should_include( virtual bool should_include(
const namespace_ &ns, const std::string &name) const; const namespace_ &ns, const std::string &name) const;
virtual inja::json context() const = 0;
private: private:
std::string name_; std::string name_;
std::unique_ptr<diagram_filter> filter_; std::unique_ptr<diagram_filter> filter_;

View File

@@ -48,6 +48,8 @@ public:
std::string name() const { return name_; } std::string name() const { return name_; }
virtual std::string type_name() const { return "__undefined__"; };
virtual std::string full_name(bool /*relative*/) const { return name(); } virtual std::string full_name(bool /*relative*/) const { return name(); }
std::vector<relationship> &relationships(); std::vector<relationship> &relationships();

View File

@@ -40,6 +40,7 @@ inja::json element::context() const
{ {
inja::json ctx; inja::json ctx;
ctx["name"] = name(); ctx["name"] = name();
ctx["type"] = type_name();
ctx["alias"] = alias(); ctx["alias"] = alias();
ctx["full_name"] = full_name(false); ctx["full_name"] = full_name(false);
ctx["namespace"] = get_namespace().to_string(); ctx["namespace"] = get_namespace().to_string();

View File

@@ -71,7 +71,7 @@ public:
return dynamic_cast<nested_trait<T, Path> &>(parent.value()) return dynamic_cast<nested_trait<T, Path> &>(parent.value())
.template add_element<V>(std::move(p)); .template add_element<V>(std::move(p));
else { else {
spdlog::error("No parent element found at: {}", path.to_string()); spdlog::info("No parent element found at: {}", path.to_string());
throw std::runtime_error( throw std::runtime_error(
"No parent element found for " + path.to_string()); "No parent element found for " + path.to_string());
} }

View File

@@ -42,6 +42,8 @@ public:
package &operator=(const package &) = delete; package &operator=(const package &) = delete;
package &operator=(package &&) = delete; package &operator=(package &&) = delete;
std::string type_name() const override { return "package"; }
std::string full_name(bool relative) const override; std::string full_name(bool relative) const override;
bool is_deprecated() const; bool is_deprecated() const;

View File

@@ -135,6 +135,22 @@ diagram::files() const
return files_; return files_;
} }
inja::json diagram::context() const {
inja::json ctx;
ctx["name"] = name();
ctx["type"] = "include";
inja::json::array_t elements{};
// Add files and directories
for(const auto &f : files()) {
elements.emplace_back(f.get().context());
}
ctx["elements"] = elements;
return ctx;
}
} }
namespace clanguml::common::model { namespace clanguml::common::model {

View File

@@ -59,6 +59,8 @@ public:
const common::reference_vector<common::model::source_file> &files() const; const common::reference_vector<common::model::source_file> &files() const;
inja::json context() const override;
private: private:
common::reference_vector<common::model::source_file> files_; common::reference_vector<common::model::source_file> files_;
}; };

View File

@@ -94,6 +94,22 @@ std::string diagram::to_alias(
return {}; return {};
} }
inja::json diagram::context() const {
inja::json ctx;
ctx["name"] = name();
ctx["type"] = "package";
inja::json::array_t elements{};
for(const auto &p : packages()) {
elements.emplace_back(p.get().context());
}
ctx["elements"] = elements;
return ctx;
}
} }
namespace clanguml::common::model { namespace clanguml::common::model {

View File

@@ -59,6 +59,8 @@ public:
std::string to_alias( std::string to_alias(
const clanguml::common::model::diagram_element::id_t) const; const clanguml::common::model::diagram_element::id_t) const;
inja::json context() const override;
private: private:
common::reference_vector<clanguml::common::model::package> packages_; common::reference_vector<clanguml::common::model::package> packages_;
}; };

View File

@@ -45,6 +45,18 @@ std::string diagram::to_alias(const std::string &full_name) const
return full_name; return full_name;
} }
inja::json diagram::context() const {
inja::json ctx;
ctx["name"] = name();
ctx["type"] = "sequence";
inja::json::array_t elements{};
ctx["elements"] = elements;
return ctx;
}
} }
namespace clanguml::common::model { namespace clanguml::common::model {

View File

@@ -45,6 +45,8 @@ public:
std::string to_alias(const std::string &full_name) const; std::string to_alias(const std::string &full_name) const;
inja::json context() const override;
bool started{false}; bool started{false};
std::map<int64_t, activity> sequences; std::map<int64_t, activity> sequences;

View File

@@ -242,16 +242,17 @@ using namespace clanguml::test::matchers;
#include "t00047/test_case.h" #include "t00047/test_case.h"
#include "t00048/test_case.h" #include "t00048/test_case.h"
#include "t00049/test_case.h" #include "t00049/test_case.h"
#include "t00050/test_case.h"
//// ///
//// Sequence diagram tests /// Sequence diagram tests
//// ///
#include "t20001/test_case.h" #include "t20001/test_case.h"
#include "t20002/test_case.h" #include "t20002/test_case.h"
//// ///
//// Package diagram tests /// Package diagram tests
//// ///
#include "t30001/test_case.h" #include "t30001/test_case.h"
#include "t30002/test_case.h" #include "t30002/test_case.h"
#include "t30003/test_case.h" #include "t30003/test_case.h"
@@ -261,21 +262,21 @@ using namespace clanguml::test::matchers;
#include "t30007/test_case.h" #include "t30007/test_case.h"
#include "t30008/test_case.h" #include "t30008/test_case.h"
//// ///
//// Include diagram tests /// Include diagram tests
//// ///
#include "t40001/test_case.h" #include "t40001/test_case.h"
#include "t40002/test_case.h" #include "t40002/test_case.h"
#include "t40003/test_case.h" #include "t40003/test_case.h"
//// ///
//// Other tests (e.g. configuration file) /// Other tests (e.g. configuration file)
//// ///
#include "t90000/test_case.h" #include "t90000/test_case.h"
// ///
// Main test function /// Main test function
// ///
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Catch::Session session; Catch::Session session;

View File

@@ -367,7 +367,7 @@ ContainsMatcher IsLayoutHint(std::string const &from, std::string const &hint,
} }
ContainsMatcher HasNote(std::string const &cls, std::string const &position, ContainsMatcher HasNote(std::string const &cls, std::string const &position,
std::string const &note, std::string const &note = "",
CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
{ {
return ContainsMatcher(CasedString( return ContainsMatcher(CasedString(

View File

@@ -144,6 +144,9 @@ test_cases:
- name: t00049 - name: t00049
title: Test case configurable type aliases title: Test case configurable type aliases
description: description:
- name: t00050
title: Test case for generating notes from comments using jinja templates
description:
Sequence diagrams: Sequence diagrams:
- name: t20001 - name: t20001
title: Basic sequence diagram test case title: Basic sequence diagram test case