diff --git a/CHANGELOG.md b/CHANGELOG.md index b1e35da8..509f0d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG + * Enabled adding notes to class methods and members (#87) + * Improved rendering of template methods in class diagrams (#83) + ### 0.3.1 * Added relationship deduction from `auto` return types which are template specializations (#82) diff --git a/src/class_diagram/generators/plantuml/class_diagram_generator.cc b/src/class_diagram/generators/plantuml/class_diagram_generator.cc index 5b28bb70..971cc021 100644 --- a/src/class_diagram/generators/plantuml/class_diagram_generator.cc +++ b/src/class_diagram/generators/plantuml/class_diagram_generator.cc @@ -266,6 +266,26 @@ void generator::generate(const class_ &c, std::ostream &ostr) const ostr << "}" << '\n'; generate_notes(ostr, c); + + for (const auto &member : c.members()) + generate_member_notes(ostr, member, c.alias()); + + for (const auto &method : c.methods()) + generate_member_notes(ostr, method, c.alias()); +} + +void generator::generate_member_notes(std::ostream &ostr, + const class_element &member, const std::string &alias) const +{ + for (const auto &decorator : member.decorators()) { + auto note = std::dynamic_pointer_cast(decorator); + if (note && note->applies_to_diagram(m_config.name)) { + ostr << "note " << note->position << " of " << alias + << "::" << member.name() << '\n' + << note->text << '\n' + << "end note\n"; + } + } } void generator::generate_relationships( @@ -557,4 +577,5 @@ void generator::generate(std::ostream &ostr) const ostr << "@enduml" << '\n'; } + } // namespace clanguml::class_diagram::generators::plantuml diff --git a/src/class_diagram/generators/plantuml/class_diagram_generator.h b/src/class_diagram/generators/plantuml/class_diagram_generator.h index b49ca272..935269e7 100644 --- a/src/class_diagram/generators/plantuml/class_diagram_generator.h +++ b/src/class_diagram/generators/plantuml/class_diagram_generator.h @@ -45,6 +45,7 @@ using common_generator = clanguml::common::generators::plantuml::generator; using clanguml::class_diagram::model::class_; +using clanguml::class_diagram::model::class_element; using clanguml::class_diagram::model::enum_; using clanguml::common::model::access_t; using clanguml::common::model::package; @@ -75,6 +76,9 @@ public: void generate_relationships(const package &p, std::ostream &ostr) const; + void generate_member_notes(std::ostream &ostream, + const class_element &member, const std::string &basicString) const; + void generate(std::ostream &ostr) const override; private: diff --git a/tests/t00028/.clang-uml b/tests/t00028/.clang-uml index f62109b1..3588d932 100644 --- a/tests/t00028/.clang-uml +++ b/tests/t00028/.clang-uml @@ -10,3 +10,9 @@ diagrams: include: namespaces: - clanguml::t00028 + plantuml: + after: + - > + note left of {{ alias("R") }}::ccc + Reference to C. + end note diff --git a/tests/t00028/t00028.cc b/tests/t00028/t00028.cc index ca55afb1..e452c836 100644 --- a/tests/t00028/t00028.cc +++ b/tests/t00028/t00028.cc @@ -44,8 +44,10 @@ class R { { } + /// \uml{note[left] R contains an instance of A.} A aaa; + /// \uml{note:other_diagram[right] R contains an pointer to B.} B *bbb; C &ccc; diff --git a/tests/t00028/test_case.h b/tests/t00028/test_case.h index 1ec2fdcf..b5d85b9e 100644 --- a/tests/t00028/test_case.h +++ b/tests/t00028/test_case.h @@ -54,6 +54,12 @@ note.)"; REQUIRE_THAT(puml, HasNote(_A("F"), "bottom", "F enum note.")); REQUIRE_THAT(puml, !HasNote(_A("G"), "left", "G class note.")); REQUIRE_THAT(puml, HasNote(_A("R"), "right", "R class note.")); + REQUIRE_THAT(puml, + HasMemberNote(_A("R"), "aaa", "left", "R contains an instance of A.")); + REQUIRE_THAT( + puml, !HasMemberNote(_A("R"), "bbb", "right", "R class note.")); + REQUIRE_THAT( + puml, HasMemberNote(_A("R"), "ccc", "left", "Reference to C.")); save_puml(config.output_directory() + "/" + diagram->name + ".puml", puml); } diff --git a/tests/test_cases.h b/tests/test_cases.h index e4f549df..388e6ae7 100644 --- a/tests/test_cases.h +++ b/tests/test_cases.h @@ -438,6 +438,15 @@ ContainsMatcher HasNote(std::string const &cls, std::string const &position, fmt::format("note {} of {}", position, cls), caseSensitivity)); } +ContainsMatcher HasMemberNote(std::string const &cls, std::string const &member, + std::string const &position, std::string const ¬e = "", + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +{ + return ContainsMatcher( + CasedString(fmt::format("note {} of {}::{}", position, cls, member), + caseSensitivity)); +} + ContainsMatcher HasLink(std::string const &alias, std::string const &link, std::string const &tooltip, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)