From bd2aecb775704b6d2ec65bf4e6d48d00d15d05de Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Fri, 19 Mar 2021 19:52:39 +0100 Subject: [PATCH] Fixed dependency generation for template parameters --- src/puml/class_diagram_generator.h | 10 ++++---- src/uml/class_diagram_model.h | 2 +- src/uml/class_diagram_visitor.h | 38 ++++++++++++++++++++---------- tests/t00013/.clanguml | 1 + tests/t00013/t00013.cc | 17 ++++++++++++- tests/t00013/test_case.h | 4 +++- 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/src/puml/class_diagram_generator.h b/src/puml/class_diagram_generator.h index bd6bc799..30196af2 100644 --- a/src/puml/class_diagram_generator.h +++ b/src/puml/class_diagram_generator.h @@ -185,14 +185,14 @@ public: for (const auto &r : c.relationships) { std::string destination; - if (r.type == relationship_t::kInstantiation) { - destination = m_model.usr_to_name( - m_config.using_namespace, r.destination); - } - else if (r.destination.find("#") != std::string::npos || + if (r.destination.find("#") != std::string::npos || r.destination.find("@") != std::string::npos) { destination = m_model.usr_to_name( m_config.using_namespace, r.destination); + if (destination.empty()) { + ostr << "' "; + destination = r.destination; + } } else { destination = r.destination; diff --git a/src/uml/class_diagram_model.h b/src/uml/class_diagram_model.h index 39ee4cb2..42631573 100644 --- a/src/uml/class_diagram_model.h +++ b/src/uml/class_diagram_model.h @@ -231,7 +231,7 @@ struct diagram { return c.full_name(using_namespaces); } - return usr; + return ""; } }; } diff --git a/src/uml/class_diagram_visitor.h b/src/uml/class_diagram_visitor.h index 2f36e536..8ad0b75a 100644 --- a/src/uml/class_diagram_visitor.h +++ b/src/uml/class_diagram_visitor.h @@ -218,8 +218,8 @@ static enum CXChildVisitResult method_parameter_visitor( enum CXChildVisitResult ret = CXChildVisit_Break; switch (cursor.kind()) { case CXCursor_ParmDecl: { - spdlog::debug( - "Analyzing method parameter: {}, {}", cursor, cursor.type()); + spdlog::debug("Analyzing method parameter: {}, {}, {}", cursor, + cursor.type(), cursor.type().named_type()); auto t = cursor.type(); method_parameter mp; @@ -228,21 +228,35 @@ static enum CXChildVisitResult method_parameter_visitor( mp.default_value = cursor.default_value(); ctx->element.parameters.emplace_back(std::move(mp)); + std::string rdestination{}; - if (t.is_relationship() && - ctx->ctx->config.should_include(t.referenced().spelling()) && - (t.referenced().spelling() != ctx->parent_class->name)) { + if (t.is_relationship()) { + if (t.is_template_instantiation()) { + rdestination = t.referenced().instantiation_template(); + } + else { + rdestination = t.referenced().spelling(); + } - class_relationship r; - r.type = relationship_t::kDependency; - r.destination = t.referenced().spelling(); + if (ctx->ctx->config.should_include(rdestination) && + rdestination != ctx->parent_class->name) { - assert(ctx->parent_class != nullptr); + spdlog::debug("ADDING DEPENDENCY TO {} \n\tCURSOR={} " + "\n\tREFTYPE={} \n\tTYPEDECL={}", + rdestination, cursor, t.referenced(), + t.referenced().type_declaration().usr()); - ctx->parent_class->add_relationship(std::move(r)); + class_relationship r; + r.type = relationship_t::kDependency; + r.destination = t.referenced().type_declaration().usr(); + + assert(ctx->parent_class != nullptr); + + ctx->parent_class->add_relationship(std::move(r)); + } + + ret = CXChildVisit_Continue; } - - ret = CXChildVisit_Continue; } break; default: ret = CXChildVisit_Continue; diff --git a/tests/t00013/.clanguml b/tests/t00013/.clanguml index 578a0fee..0b71bf39 100644 --- a/tests/t00013/.clanguml +++ b/tests/t00013/.clanguml @@ -10,3 +10,4 @@ diagrams: include: namespaces: - clanguml::t00013 + - ABCD diff --git a/tests/t00013/t00013.cc b/tests/t00013/t00013.cc index 731b17b8..a6ead09f 100644 --- a/tests/t00013/t00013.cc +++ b/tests/t00013/t00013.cc @@ -4,6 +4,11 @@ #include #include +namespace ABCD { +template struct F { + T f; +}; +} namespace clanguml { namespace t00013 { @@ -26,15 +31,25 @@ struct D { void print(R *r) {} }; +template struct E { + T e; +}; + +using namespace ABCD; class R { public: int get_a(A *a) { return a->a; } int get_b(B &b) { return b.b; } - // TODO: int get_b(const B &b) { return b.b; } + // TODO: int get_const_b(const B &b) { return b.b; } int get_c(C c) { return c.c; } int get_d(D &&d) { return d.d; } // Dependency relationship should be rendered only once int get_d2(D &&d) { return d.d; } + + template T get_e(E &e) { return e.e; } + int get_int_e(E &e) { return e.e; } + + template T get_f(const F &f) { return f.f; } }; } } diff --git a/tests/t00013/test_case.h b/tests/t00013/test_case.h index a4261c09..8eec8546 100644 --- a/tests/t00013/test_case.h +++ b/tests/t00013/test_case.h @@ -24,7 +24,6 @@ TEST_CASE("t00013", "[test-case][class]") REQUIRE(diagram->name == "t00013_class"); - REQUIRE(diagram->include.namespaces.size() == 1); REQUIRE_THAT(diagram->include.namespaces, VectorContains(std::string{"clanguml::t00013"})); @@ -32,6 +31,7 @@ TEST_CASE("t00013", "[test-case][class]") REQUIRE(diagram->should_include("clanguml::t00013::A")); REQUIRE(diagram->should_include("clanguml::t00013::B")); + REQUIRE(diagram->should_include("ABCD::F")); auto model = generate_class_diagram(db, diagram); @@ -50,6 +50,8 @@ TEST_CASE("t00013", "[test-case][class]") REQUIRE_THAT(puml, IsDependency(_A("R"), _A("B"))); REQUIRE_THAT(puml, IsDependency(_A("R"), _A("C"))); REQUIRE_THAT(puml, IsDependency(_A("R"), _A("D"))); + REQUIRE_THAT(puml, IsDependency(_A("R"), _A("E"))); + REQUIRE_THAT(puml, IsDependency(_A("R"), _A("ABCD::F"))); REQUIRE_THAT(puml, IsDependency(_A("D"), _A("R"))); save_puml(