From ce02432178c626acdb23283515134cd1ed6905c0 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Thu, 27 May 2021 00:31:44 +0200 Subject: [PATCH] Added alias resolution for PlantUML annotations --- src/puml/class_diagram_generator.h | 29 +++++++++++++++++++++++++---- src/util/error.h | 8 ++++++++ src/util/util.cc | 25 +++++++++++++++++++++++++ src/util/util.h | 13 +++++++++++++ tests/t00002/.clanguml | 3 +++ tests/t00012/.clanguml | 3 +++ 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/puml/class_diagram_generator.h b/src/puml/class_diagram_generator.h index 63ee28d5..8547299f 100644 --- a/src/puml/class_diagram_generator.h +++ b/src/puml/class_diagram_generator.h @@ -327,8 +327,18 @@ public: { ostr << "@startuml" << std::endl; - for (const auto &b : m_config.puml.before) - ostr << b << std::endl; + for (const auto &b : m_config.puml.before) { + std::string note{b}; + std::tuple alias_match; + while (util::find_element_alias(note, alias_match)) { + auto alias = m_model.to_alias(m_config.using_namespace, + ns_relative( + m_config.using_namespace, std::get<0>(alias_match))); + note.replace( + std::get<1>(alias_match), std::get<2>(alias_match), alias); + } + ostr << note << std::endl; + } if (m_config.should_include_entities("classes")) { for (const auto &c : m_model.classes) { @@ -353,8 +363,19 @@ public: ostr << std::endl; } - for (const auto &b : m_config.puml.after) - ostr << b << std::endl; + // Process aliases in any of the puml directives + for (const auto &b : m_config.puml.after) { + std::string note{b}; + std::tuple alias_match; + while (util::find_element_alias(note, alias_match)) { + auto alias = m_model.to_alias(m_config.using_namespace, + ns_relative( + m_config.using_namespace, std::get<0>(alias_match))); + note.replace( + std::get<1>(alias_match), std::get<2>(alias_match), alias); + } + ostr << note << std::endl; + } ostr << "@enduml" << std::endl; } diff --git a/src/util/error.h b/src/util/error.h index 661b7967..21ff6773 100644 --- a/src/util/error.h +++ b/src/util/error.h @@ -20,10 +20,18 @@ #include namespace clanguml::error { + struct uml_alias_missing : public virtual std::runtime_error { uml_alias_missing(const std::string &message) : std::runtime_error(message) { } }; + +struct substring_delimiter_not_found : public virtual std::runtime_error { + substring_delimiter_not_found(const std::string &message) + : std::runtime_error(message) + { + } +}; } diff --git a/src/util/util.cc b/src/util/util.cc index 05dbe246..88133b89 100644 --- a/src/util/util.cc +++ b/src/util/util.cc @@ -19,6 +19,8 @@ #include +#include + namespace clanguml { namespace util { @@ -101,5 +103,28 @@ std::string unqualify(const std::string &s) return fmt::format("{}", fmt::join(toks, " ")); } + +bool find_element_alias( + const std::string &input, std::tuple &result) +{ + + std::regex alias_regex("(@A\\([^\\).]+\\))"); + + auto alias_it = + std::sregex_iterator(input.begin(), input.end(), alias_regex); + auto end_it = std::sregex_iterator(); + + if (alias_it == end_it) + return false; + + std::smatch match = *alias_it; + std::string alias = match.str().substr(3, match.str().size() - 4); + + std::get<0>(result) = alias; + std::get<1>(result) = match.position(); + std::get<2>(result) = match.length(); + + return true; +} } } diff --git a/src/util/util.h b/src/util/util.h index f29e6858..a20fa8e4 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -91,5 +91,18 @@ std::string ns_relative( * @return Unqualified type spelling. */ std::string unqualify(const std::string &s); + +/** + * @brief Find element alias in Puml note + * + * Finds aliases of the form @A(entity_name) in the Puml notes + * or directives. + * The match, if any, is returned in the result tuple: + * (entity_name, offset, length) + * + * @return True if match was found + */ +bool find_element_alias( + const std::string &input, std::tuple &result); } } diff --git a/tests/t00002/.clanguml b/tests/t00002/.clanguml index 7c842001..7e8d802a 100644 --- a/tests/t00002/.clanguml +++ b/tests/t00002/.clanguml @@ -10,3 +10,6 @@ diagrams: include: namespaces: - clanguml::t00002 + plantuml: + after: + - 'note left of @A(A) : Base abstract interface.' diff --git a/tests/t00012/.clanguml b/tests/t00012/.clanguml index 82c7f1be..a841c472 100644 --- a/tests/t00012/.clanguml +++ b/tests/t00012/.clanguml @@ -10,3 +10,6 @@ diagrams: include: namespaces: - clanguml::t00012 + plantuml: + after: + - 'note right of @A(C>>>,3,3,3>) : Long template annotation'