From 5be5172bd3097199c44ff9650144c13002ee0394 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Thu, 4 Mar 2021 22:59:14 +0100 Subject: [PATCH] Added relationship discovery through smart pointers --- src/uml/class_diagram_visitor.h | 17 +++++++--- tests/t00007/.clanguml | 12 +++++++ tests/t00007/t00007.cc | 21 ++++++++++++ tests/t00007/test_case.h | 60 +++++++++++++++++++++++++++++++++ tests/test_cases.cc | 1 + 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 tests/t00007/.clanguml create mode 100644 tests/t00007/t00007.cc create mode 100644 tests/t00007/test_case.h diff --git a/src/uml/class_diagram_visitor.h b/src/uml/class_diagram_visitor.h index 2f2c1a66..4ea7af41 100644 --- a/src/uml/class_diagram_visitor.h +++ b/src/uml/class_diagram_visitor.h @@ -103,8 +103,9 @@ scope_t cx_access_specifier_to_scope(CX_CXXAccessSpecifier as) return res; } -void find_relationships( - cx::type t, std::vector> &relationships) +void find_relationships(cx::type t, + std::vector> &relationships, + relationship_t relationship_hint = relationship_t::kNone) { relationship_t relationship_type = relationship_t::kNone; @@ -130,7 +131,12 @@ void find_relationships( find_relationships(template_arguments[0], relationships); } else if (name.find("std::shared_ptr") == 0) { - find_relationships(template_arguments[0], relationships); + find_relationships(template_arguments[0], relationships, + relationship_t::kAssociation); + } + else if (name.find("std::weak_ptr") == 0) { + find_relationships(template_arguments[0], relationships, + relationship_t::kAssociation); } else if (name.find("std::vector") == 0) { find_relationships(template_arguments[0], relationships); @@ -145,7 +151,10 @@ void find_relationships( } } else if (t.kind() == CXType_Record) { - relationships.emplace_back(t, relationship_t::kOwnership); + if (relationship_hint != relationship_t::kNone) + relationships.emplace_back(t, relationship_hint); + else + relationships.emplace_back(t, relationship_t::kOwnership); } else if (t.kind() == CXType_Pointer) { relationships.emplace_back(t, relationship_t::kAssociation); diff --git a/tests/t00007/.clanguml b/tests/t00007/.clanguml new file mode 100644 index 00000000..6bd80b76 --- /dev/null +++ b/tests/t00007/.clanguml @@ -0,0 +1,12 @@ +compilation_database_dir: .. +output_directory: puml +diagrams: + t00007_class: + type: class + glob: + - ../../tests/t00007/t00007.cc + using_namespace: + - clanguml::t00007 + include: + namespaces: + - clanguml::t00007 diff --git a/tests/t00007/t00007.cc b/tests/t00007/t00007.cc new file mode 100644 index 00000000..35ea0ce9 --- /dev/null +++ b/tests/t00007/t00007.cc @@ -0,0 +1,21 @@ +#include + +namespace clanguml { +namespace t00007 { +class A { +}; + +class B { +}; + +class C { +}; + +class R { +public: + std::unique_ptr a; + std::shared_ptr b; + std::weak_ptr c; +}; +} +} diff --git a/tests/t00007/test_case.h b/tests/t00007/test_case.h new file mode 100644 index 00000000..8f6a7840 --- /dev/null +++ b/tests/t00007/test_case.h @@ -0,0 +1,60 @@ +/** + * tests/t00007/test_case.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. + */ + +TEST_CASE("Test t00007", "[unit-test]") +{ + spdlog::set_level(spdlog::level::debug); + + auto [config, db] = load_config("t00007"); + + auto diagram = config.diagrams["t00007_class"]; + + REQUIRE(diagram->name == "t00007_class"); + + REQUIRE(diagram->include.namespaces.size() == 1); + REQUIRE_THAT(diagram->include.namespaces, + VectorContains(std::string{"clanguml::t00007"})); + + REQUIRE(diagram->exclude.namespaces.size() == 0); + + REQUIRE(diagram->should_include("clanguml::t00007::A")); + REQUIRE(diagram->should_include("clanguml::t00007::B")); + REQUIRE(diagram->should_include("clanguml::t00007::C")); + REQUIRE(diagram->should_include("clanguml::t00007::D")); + REQUIRE(diagram->should_include("clanguml::t00007::E")); + + auto model = generate_class_diagram(db, diagram); + + REQUIRE(model.name == "t00007_class"); + + auto puml = generate_class_puml(diagram, model); + + 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, IsComposition("R", "A", "a")); + REQUIRE_THAT(puml, IsAssociation("R", "B", "b")); + REQUIRE_THAT(puml, IsAssociation("R", "C", "c")); + + save_puml( + "./" + config.output_directory + "/" + diagram->name + ".puml", puml); +} diff --git a/tests/test_cases.cc b/tests/test_cases.cc index d308fd7a..75efc94d 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -115,3 +115,4 @@ using clanguml::test::matchers::Static; #include "t00004/test_case.h" #include "t00005/test_case.h" #include "t00006/test_case.h" +#include "t00007/test_case.h"