diff --git a/src/puml/class_diagram_generator.h b/src/puml/class_diagram_generator.h index af593fb3..ffd35fd3 100644 --- a/src/puml/class_diagram_generator.h +++ b/src/puml/class_diagram_generator.h @@ -95,38 +95,15 @@ public: void generate(const class_ &c, std::ostream &ostr) const { + std::string class_type{"class"}; if (c.is_abstract()) - ostr << "abstract "; - else - ostr << "class "; + class_type = "abstract"; - ostr << ns_relative(m_config.using_namespace, c.name); + ostr << class_type << " \"" << c.full_name(m_config.using_namespace); - if (!c.templates.empty()) { - std::vector tnames; - std::transform(c.templates.cbegin(), c.templates.cend(), - std::back_inserter(tnames), [this](const auto &tmplt) { - std::vector res; + ostr << "\" as " << c.alias() << std::endl; - if (!tmplt.type.empty()) - res.push_back( - ns_relative(m_config.using_namespace, tmplt.type)); - - if (!tmplt.name.empty()) - res.push_back( - ns_relative(m_config.using_namespace, tmplt.name)); - - if (!tmplt.default_value.empty()) { - res.push_back("="); - res.push_back(tmplt.default_value); - } - - return fmt::format("{}", fmt::join(res, " ")); - }); - ostr << fmt::format("<{}>", fmt::join(tnames, ", ")); - } - - ostr << " {" << std::endl; + ostr << class_type << " " << c.alias() << " {" << std::endl; // // Process methods @@ -173,14 +150,20 @@ public: ostr << "}" << std::endl; for (const auto &b : c.bases) { - ostr << ns_relative(m_config.using_namespace, b.name) << " <|-- " - << ns_relative(m_config.using_namespace, c.name) << std::endl; + ostr << m_model.to_alias(m_config.using_namespace, + ns_relative(m_config.using_namespace, b.name)) + << " <|-- " + << m_model.to_alias(m_config.using_namespace, + ns_relative(m_config.using_namespace, c.name)) + << std::endl; } for (const auto &r : c.relationships) { - ostr << ns_relative(m_config.using_namespace, c.name) << " " - << to_string(r.type) << " " - << ns_relative(m_config.using_namespace, r.destination); + ostr << m_model.to_alias(m_config.using_namespace, + ns_relative(m_config.using_namespace, c.name)) + << " " << to_string(r.type) << " " + << m_model.to_alias(m_config.using_namespace, + ns_relative(m_config.using_namespace, r.destination)); if (!r.label.empty()) ostr << " : " << r.label; diff --git a/src/uml/class_diagram_model.cc b/src/uml/class_diagram_model.cc new file mode 100644 index 00000000..97b48ae8 --- /dev/null +++ b/src/uml/class_diagram_model.cc @@ -0,0 +1,27 @@ +/** + * src/uml/class_diagram_model.cc + * + * Copyright (c) 2021 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "class_diagram_model.h" + +namespace clanguml { +namespace model { +namespace class_diagram { +std::atomic_uint64_t element::m_nextId = 1; +} +} +} diff --git a/src/uml/class_diagram_model.h b/src/uml/class_diagram_model.h index e44e850a..131b9b53 100644 --- a/src/uml/class_diagram_model.h +++ b/src/uml/class_diagram_model.h @@ -17,12 +17,16 @@ */ #pragma once +#include "util/util.h" + #include #include #include +#include #include #include +#include #include #include @@ -42,9 +46,22 @@ enum class relationship_t { kAssociation }; -struct element { +class element { +public: + element() + : m_id{m_nextId++} + { + } std::string name; std::vector namespace_; + + std::string alias() const { return fmt::format("C_{:010}", m_id); } + +protected: + const uint64_t m_id{0}; + +private: + static std::atomic_uint64_t m_nextId; }; struct class_element { @@ -93,7 +110,8 @@ struct class_template { std::string default_value; }; -struct class_ : public element { +class class_ : public element { +public: bool is_struct{false}; bool is_template{false}; std::vector members; @@ -103,6 +121,42 @@ struct class_ : public element { std::vector relationships; std::vector templates; + std::string full_name( + const std::vector &using_namespaces) const + { + using namespace clanguml::util; + + std::ostringstream ostr; + ostr << ns_relative(using_namespaces, name); + + if (!templates.empty()) { + std::vector tnames; + std::transform(templates.cbegin(), templates.cend(), + std::back_inserter(tnames), + [&using_namespaces](const auto &tmplt) { + std::vector res; + + if (!tmplt.type.empty()) + res.push_back( + ns_relative(using_namespaces, tmplt.type)); + + if (!tmplt.name.empty()) + res.push_back( + ns_relative(using_namespaces, tmplt.name)); + + if (!tmplt.default_value.empty()) { + res.push_back("="); + res.push_back(tmplt.default_value); + } + + return fmt::format("{}", fmt::join(res, " ")); + }); + ostr << fmt::format("<{}>", fmt::join(tnames, ", ")); + } + + return ostr.str(); + } + bool is_abstract() const { // TODO check if all base abstract methods are overriden @@ -120,6 +174,18 @@ struct diagram { std::string name; std::vector classes; std::vector enums; + + std::string to_alias(const std::vector &using_namespaces, + const std::string &full_name) const + { + for (const auto &c : classes) { + if (c.full_name(using_namespaces) == full_name) { + return c.alias(); + } + } + + return full_name; + } }; } } diff --git a/src/util/util.cc b/src/util/util.cc index f608fabd..42169939 100644 --- a/src/util/util.cc +++ b/src/util/util.cc @@ -19,6 +19,23 @@ namespace clanguml { namespace util { + +const std::string WHITESPACE = " \n\r\t\f\v"; + +std::string ltrim(const std::string &s) +{ + size_t start = s.find_first_not_of(WHITESPACE); + return (start == std::string::npos) ? "" : s.substr(start); +} + +std::string rtrim(const std::string &s) +{ + size_t end = s.find_last_not_of(WHITESPACE); + return (end == std::string::npos) ? "" : s.substr(0, end + 1); +} + +std::string trim(const std::string &s) { return rtrim(ltrim(s)); } + std::vector split(std::string str, std::string delimiter) { std::vector result; diff --git a/src/util/util.h b/src/util/util.h index b5471ed6..4677e71f 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -24,6 +24,10 @@ namespace clanguml { namespace util { +std::string ltrim(const std::string &s); +std::string rtrim(const std::string &s); +std::string trim(const std::string &s); + /** * @brief Split a string using delimiter * diff --git a/tests/t00002/test_case.h b/tests/t00002/test_case.h index ee4a0930..bba481e9 100644 --- a/tests/t00002/test_case.h +++ b/tests/t00002/test_case.h @@ -40,21 +40,22 @@ TEST_CASE("Test t00002", "[unit-test]") REQUIRE(model.name == "t00002_class"); auto puml = generate_class_puml(diagram, model); + AliasMatcher _A(puml); REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsAbstractClass("A")); - REQUIRE_THAT(puml, IsClass("B")); - REQUIRE_THAT(puml, IsClass("C")); - REQUIRE_THAT(puml, IsClass("D")); - REQUIRE_THAT(puml, IsBaseClass("A", "B")); - REQUIRE_THAT(puml, IsBaseClass("A", "C")); - REQUIRE_THAT(puml, IsBaseClass("B", "D")); - REQUIRE_THAT(puml, IsBaseClass("C", "D")); + REQUIRE_THAT(puml, IsAbstractClass(_A("A"))); + REQUIRE_THAT(puml, IsClass(_A("B"))); + REQUIRE_THAT(puml, IsClass(_A("C"))); + REQUIRE_THAT(puml, IsClass(_A("D"))); + REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("B"))); + REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("C"))); + REQUIRE_THAT(puml, IsBaseClass(_A("B"), _A("D"))); + REQUIRE_THAT(puml, IsBaseClass(_A("C"), _A("D"))); REQUIRE_THAT(puml, IsMethod(Abstract(Public("foo_a")))); REQUIRE_THAT(puml, IsMethod(Abstract(Public("foo_c")))); - REQUIRE_THAT(puml, IsAssociation("D", "A", "as")); + REQUIRE_THAT(puml, IsAssociation(_A("D"), _A("A"), "as")); save_puml( "./" + config.output_directory + "/" + diagram->name + ".puml", puml); diff --git a/tests/t00003/test_case.h b/tests/t00003/test_case.h index 3093b6a0..c98052c8 100644 --- a/tests/t00003/test_case.h +++ b/tests/t00003/test_case.h @@ -39,10 +39,11 @@ TEST_CASE("Test t00003", "[unit-test]") REQUIRE(model.name == "t00003_class"); auto puml = generate_class_puml(diagram, model); + AliasMatcher _A(puml); REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, Contains("class A")); + REQUIRE_THAT(puml, IsClass(_A("A"))); REQUIRE_THAT(puml, IsMethod(Default(Public("A")))); REQUIRE_THAT(puml, IsMethod(Default(Public("~A")))); diff --git a/tests/t00004/test_case.h b/tests/t00004/test_case.h index 9281f1ba..475a62ee 100644 --- a/tests/t00004/test_case.h +++ b/tests/t00004/test_case.h @@ -41,16 +41,17 @@ TEST_CASE("Test t00004", "[unit-test]") REQUIRE(model.name == "t00004_class"); auto puml = generate_class_puml(diagram, model); + AliasMatcher _A(puml); REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsClass("A")); - REQUIRE_THAT(puml, IsClass("AA")); - REQUIRE_THAT(puml, IsClass("AAA")); + REQUIRE_THAT(puml, IsClass(_A("A"))); + REQUIRE_THAT(puml, IsClass(_A("AA"))); + REQUIRE_THAT(puml, IsClass(_A("AAA"))); REQUIRE_THAT(puml, IsEnum("Lights")); - REQUIRE_THAT(puml, IsInnerClass("A", "AA")); - REQUIRE_THAT(puml, IsInnerClass("AA", "AAA")); - REQUIRE_THAT(puml, IsInnerClass("AA", "Lights")); + REQUIRE_THAT(puml, IsInnerClass(_A("A"), _A("AA"))); + REQUIRE_THAT(puml, IsInnerClass(_A("AA"), _A("AAA"))); + REQUIRE_THAT(puml, IsInnerClass(_A("AA"), "Lights")); REQUIRE_THAT(puml, IsMethod(Const(Public("foo")))); REQUIRE_THAT(puml, IsMethod(Const(Public("foo2")))); diff --git a/tests/t00005/test_case.h b/tests/t00005/test_case.h index feed6641..ca705666 100644 --- a/tests/t00005/test_case.h +++ b/tests/t00005/test_case.h @@ -42,37 +42,38 @@ TEST_CASE("Test t00005", "[unit-test]") REQUIRE(model.name == "t00005_class"); auto puml = generate_class_puml(diagram, model); + AliasMatcher _A(puml); REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsClass("A")); - REQUIRE_THAT(puml, IsClass("B")); - REQUIRE_THAT(puml, IsClass("C")); - REQUIRE_THAT(puml, IsClass("D")); - REQUIRE_THAT(puml, IsClass("E")); - REQUIRE_THAT(puml, IsClass("F")); - REQUIRE_THAT(puml, IsClass("G")); - REQUIRE_THAT(puml, IsClass("H")); - REQUIRE_THAT(puml, IsClass("I")); - REQUIRE_THAT(puml, IsClass("J")); - REQUIRE_THAT(puml, IsClass("K")); - REQUIRE_THAT(puml, IsClass("R")); + REQUIRE_THAT(puml, IsClass(_A("A"))); + REQUIRE_THAT(puml, IsClass(_A("B"))); + REQUIRE_THAT(puml, IsClass(_A("C"))); + REQUIRE_THAT(puml, IsClass(_A("D"))); + REQUIRE_THAT(puml, IsClass(_A("E"))); + REQUIRE_THAT(puml, IsClass(_A("F"))); + REQUIRE_THAT(puml, IsClass(_A("G"))); + REQUIRE_THAT(puml, IsClass(_A("H"))); + REQUIRE_THAT(puml, IsClass(_A("I"))); + REQUIRE_THAT(puml, IsClass(_A("J"))); + REQUIRE_THAT(puml, IsClass(_A("K"))); + REQUIRE_THAT(puml, IsClass(_A("R"))); REQUIRE_THAT(puml, IsField(Public("int some_int"))); REQUIRE_THAT(puml, IsField(Public("int * some_int_pointer"))); REQUIRE_THAT(puml, IsField(Public("int ** some_int_pointer_pointer"))); - REQUIRE_THAT(puml, IsComposition("R", "A", "a")); - REQUIRE_THAT(puml, IsAssociation("R", "B", "b")); - REQUIRE_THAT(puml, IsAssociation("R", "C", "c")); - REQUIRE_THAT(puml, IsAssociation("R", "D", "d")); - REQUIRE_THAT(puml, IsAssociation("R", "E", "e")); - REQUIRE_THAT(puml, IsComposition("R", "F", "f")); - REQUIRE_THAT(puml, IsAssociation("R", "G", "g")); - REQUIRE_THAT(puml, IsAssociation("R", "H", "h")); - REQUIRE_THAT(puml, IsAssociation("R", "I", "i")); - REQUIRE_THAT(puml, IsAssociation("R", "J", "j")); - REQUIRE_THAT(puml, IsAssociation("R", "K", "k")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("A"), "a")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("B"), "b")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("C"), "c")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("D"), "d")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("E"), "e")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("F"), "f")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("G"), "g")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("H"), "h")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("I"), "i")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("J"), "j")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("K"), "k")); save_puml( "./" + config.output_directory + "/" + diagram->name + ".puml", puml); diff --git a/tests/t00006/test_case.h b/tests/t00006/test_case.h index 063c6c18..c2eb679a 100644 --- a/tests/t00006/test_case.h +++ b/tests/t00006/test_case.h @@ -43,42 +43,43 @@ TEST_CASE("Test t00006", "[unit-test]") REQUIRE(model.name == "t00006_class"); auto puml = generate_class_puml(diagram, model); + AliasMatcher _A(puml); REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsClass("A")); - REQUIRE_THAT(puml, IsClass("B")); - REQUIRE_THAT(puml, IsClass("C")); - REQUIRE_THAT(puml, IsClass("D")); - REQUIRE_THAT(puml, IsClass("E")); - REQUIRE_THAT(puml, IsClass("F")); - REQUIRE_THAT(puml, IsClass("G")); - REQUIRE_THAT(puml, IsClass("H")); - REQUIRE_THAT(puml, IsClass("I")); - REQUIRE_THAT(puml, IsClass("J")); - REQUIRE_THAT(puml, IsClass("K")); - REQUIRE_THAT(puml, IsClass("L")); - REQUIRE_THAT(puml, IsClass("M")); - REQUIRE_THAT(puml, IsClass("N")); - REQUIRE_THAT(puml, IsClass("NN")); - REQUIRE_THAT(puml, IsClass("NNN")); + REQUIRE_THAT(puml, IsClass(_A("A"))); + REQUIRE_THAT(puml, IsClass(_A("B"))); + REQUIRE_THAT(puml, IsClass(_A("C"))); + REQUIRE_THAT(puml, IsClass(_A("D"))); + REQUIRE_THAT(puml, IsClass(_A("E"))); + REQUIRE_THAT(puml, IsClass(_A("F"))); + REQUIRE_THAT(puml, IsClass(_A("G"))); + REQUIRE_THAT(puml, IsClass(_A("H"))); + REQUIRE_THAT(puml, IsClass(_A("I"))); + REQUIRE_THAT(puml, IsClass(_A("J"))); + REQUIRE_THAT(puml, IsClass(_A("K"))); + REQUIRE_THAT(puml, IsClass(_A("L"))); + REQUIRE_THAT(puml, IsClass(_A("M"))); + REQUIRE_THAT(puml, IsClass(_A("N"))); + REQUIRE_THAT(puml, IsClass(_A("NN"))); + REQUIRE_THAT(puml, IsClass(_A("NNN"))); - REQUIRE_THAT(puml, IsComposition("R", "A", "a")); - REQUIRE_THAT(puml, IsAssociation("R", "B", "b")); - REQUIRE_THAT(puml, IsComposition("R", "C", "c")); - REQUIRE_THAT(puml, IsAssociation("R", "D", "d")); - REQUIRE_THAT(puml, IsComposition("R", "E", "e")); - REQUIRE_THAT(puml, IsComposition("R", "F", "f")); - REQUIRE_THAT(puml, IsAssociation("R", "G", "g")); - REQUIRE_THAT(puml, IsComposition("R", "H", "h")); - REQUIRE_THAT(puml, IsAssociation("R", "I", "i")); - REQUIRE_THAT(puml, IsComposition("R", "J", "j")); - REQUIRE_THAT(puml, IsAssociation("R", "K", "k")); - REQUIRE_THAT(puml, IsComposition("R", "L", "lm")); - REQUIRE_THAT(puml, IsComposition("R", "M", "lm")); - REQUIRE_THAT(puml, IsComposition("R", "N", "ns")); - REQUIRE_THAT(puml, IsComposition("R", "NN", "ns")); - REQUIRE_THAT(puml, IsComposition("R", "NNN", "ns")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("A"), "a")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("B"), "b")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("C"), "c")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("D"), "d")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("E"), "e")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("F"), "f")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("G"), "g")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("H"), "h")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("I"), "i")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("J"), "j")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("K"), "k")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("L"), "lm")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("M"), "lm")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("N"), "ns")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("NN"), "ns")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("NNN"), "ns")); save_puml( "./" + config.output_directory + "/" + diagram->name + ".puml", puml); diff --git a/tests/t00007/test_case.h b/tests/t00007/test_case.h index 8f6a7840..46fe8b2e 100644 --- a/tests/t00007/test_case.h +++ b/tests/t00007/test_case.h @@ -43,17 +43,18 @@ TEST_CASE("Test t00007", "[unit-test]") REQUIRE(model.name == "t00007_class"); auto puml = generate_class_puml(diagram, model); + AliasMatcher _A(puml); REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsClass("A")); - REQUIRE_THAT(puml, IsClass("B")); - REQUIRE_THAT(puml, IsClass("C")); - REQUIRE_THAT(puml, IsClass("R")); + REQUIRE_THAT(puml, IsClass(_A("A"))); + REQUIRE_THAT(puml, IsClass(_A("B"))); + REQUIRE_THAT(puml, IsClass(_A("C"))); + REQUIRE_THAT(puml, IsClass(_A("R"))); - REQUIRE_THAT(puml, IsComposition("R", "A", "a")); - REQUIRE_THAT(puml, IsAssociation("R", "B", "b")); - REQUIRE_THAT(puml, IsAssociation("R", "C", "c")); + REQUIRE_THAT(puml, IsComposition(_A("R"), _A("A"), "a")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("B"), "b")); + REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("C"), "c")); save_puml( "./" + config.output_directory + "/" + diagram->name + ".puml", puml); diff --git a/tests/t00008/test_case.h b/tests/t00008/test_case.h index eccdab3c..da16be04 100644 --- a/tests/t00008/test_case.h +++ b/tests/t00008/test_case.h @@ -40,6 +40,7 @@ TEST_CASE("Test t00008", "[unit-test]") REQUIRE(model.name == "t00008_class"); auto puml = generate_class_puml(diagram, model); + AliasMatcher _A(puml); REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); diff --git a/tests/test_cases.cc b/tests/test_cases.cc index d860343c..a79fc7f5 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -91,6 +91,7 @@ void save_puml(const std::string &path, const std::string &puml) } using clanguml::test::matchers::Abstract; +using clanguml::test::matchers::AliasMatcher; using clanguml::test::matchers::Const; using clanguml::test::matchers::Default; using clanguml::test::matchers::HasCall; diff --git a/tests/test_cases.h b/tests/test_cases.h index a3a26a7f..adc7c7bf 100644 --- a/tests/test_cases.h +++ b/tests/test_cases.h @@ -24,6 +24,7 @@ #include "uml/class_diagram_model.h" #include "uml/class_diagram_visitor.h" #include "uml/sequence_diagram_visitor.h" +#include "util/util.h" #include "catch.h" @@ -36,6 +37,7 @@ using Catch::Matchers::EndsWith; using Catch::Matchers::StartsWith; using Catch::Matchers::VectorContains; using clanguml::cx::compilation_database; +using namespace clanguml::util; std::pair load_config( const std::string &test_name); @@ -190,6 +192,36 @@ auto HasCallWithResponse(std::string const &from, std::string const &to, fmt::format("\"{}\" --> \"{}\"", to, from), caseSensitivity)); } +struct AliasMatcher { + AliasMatcher(const std::string &puml_) + : puml{split(puml_, "\n")} + { + } + + std::string operator()(const std::string &name) + { + std::vector patterns; + patterns.push_back("class \"" + name + "\" as "); + patterns.push_back("abstract \"" + name + "\" as "); + patterns.push_back("enum \"" + name + "\" as "); + + for (const auto &line : puml) { + for (const auto &pattern : patterns) { + const auto idx = line.find(pattern); + if (idx != std::string::npos) { + std::string res = line.substr(idx + pattern.size()); + return trim(res); + } + } + } + + throw std::runtime_error(fmt::format( + "Cannot find alias {} in {}", name, fmt::join(puml, "\n"))); + } + + const std::vector puml; +}; + ContainsMatcher IsClass(std::string const &str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) { @@ -200,8 +232,8 @@ ContainsMatcher IsClassTemplate(std::string const &str, std::string const &tmplt, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) { - return ContainsMatcher( - CasedString(fmt::format("class {}<{}>", str, tmplt), caseSensitivity)); + return ContainsMatcher(CasedString( + fmt::format("class \"{}<{}>\"", str, tmplt), caseSensitivity)); } ContainsMatcher IsEnum(std::string const &str,