Fixed handling of enums in class diagram context filter (#275)

This commit is contained in:
Bartek Kryza
2024-05-31 19:09:28 +02:00
parent 9ad5336d83
commit 1283364ef4
6 changed files with 69 additions and 42 deletions

View File

@@ -401,7 +401,10 @@ opt_ref<ElementT> diagram::find(const std::string &name) const
for (const auto &element : element_view<ElementT>::view()) { for (const auto &element : element_view<ElementT>::view()) {
const auto full_name = element.get().full_name(false); const auto full_name = element.get().full_name(false);
if (full_name == name) { auto full_name_escaped = full_name;
util::replace_all(full_name_escaped, "##", "::");
if (name == full_name || name == full_name_escaped) {
return {element}; return {element};
} }
} }
@@ -417,8 +420,10 @@ std::vector<opt_ref<ElementT>> diagram::find(
for (const auto &element : element_view<ElementT>::view()) { for (const auto &element : element_view<ElementT>::view()) {
const auto full_name = element.get().full_name(false); const auto full_name = element.get().full_name(false);
auto full_name_escaped = full_name;
util::replace_all(full_name_escaped, "##", "::");
if (pattern == full_name) { if (pattern == full_name || pattern == full_name_escaped) {
result.emplace_back(element); result.emplace_back(element);
} }
} }

View File

@@ -669,6 +669,24 @@ void context_filter::initialize_effective_context(
effective_context.emplace(maybe_match.value().id()); effective_context.emplace(maybe_match.value().id());
} }
const auto &context_enum_matches =
dynamic_cast<const class_diagram::model::diagram &>(d)
.find<class_diagram::model::enum_>(context.pattern);
for (const auto &maybe_match : context_enum_matches) {
if (maybe_match)
effective_context.emplace(maybe_match.value().id());
}
const auto &context_concept_matches =
dynamic_cast<const class_diagram::model::diagram &>(d)
.find<class_diagram::model::concept_>(context.pattern);
for (const auto &maybe_match : context_concept_matches) {
if (maybe_match)
effective_context.emplace(maybe_match.value().id());
}
// Now repeat radius times - extend the effective context with elements // Now repeat radius times - extend the effective context with elements
// matching in direct relationship to what is in context // matching in direct relationship to what is in context
auto radius_counter = context.radius; auto radius_counter = context.radius;
@@ -688,14 +706,14 @@ void context_filter::initialize_effective_context(
find_elements_inheritance_relationship( find_elements_inheritance_relationship(
d, effective_context, current_iteration_context); d, effective_context, current_iteration_context);
// For each enum in the model
find_elements_in_relationship_with_enum(
d, effective_context, current_iteration_context);
// For each concept in the model // For each concept in the model
find_elements_in_direct_relationship<class_diagram::model::concept_>( find_elements_in_direct_relationship<class_diagram::model::concept_>(
d, effective_context, current_iteration_context); d, effective_context, current_iteration_context);
// For each enum in the model
find_elements_in_direct_relationship<class_diagram::model::enum_>(
d, effective_context, current_iteration_context);
for (auto id : current_iteration_context) { for (auto id : current_iteration_context) {
if (effective_context.count(id) == 0) { if (effective_context.count(id) == 0) {
// Found new element to add to context // Found new element to add to context
@@ -706,31 +724,6 @@ void context_filter::initialize_effective_context(
} }
} }
void context_filter::find_elements_in_relationship_with_enum(const diagram &d,
std::set<id_t> &effective_context,
std::set<clanguml::common::id_t> &current_iteration_context) const
{
const auto &cd = dynamic_cast<const class_diagram::model::diagram &>(d);
for (const auto &enm : cd.enums()) {
for (const auto &ec : effective_context) {
const auto &maybe_class = cd.find<class_diagram::model::class_>(ec);
if (!maybe_class)
continue;
for (const relationship &rel :
maybe_class.value().relationships()) {
if (d.should_include(rel.type()) &&
rel.destination() == enm.get().id())
current_iteration_context.emplace(enm.get().id());
}
}
}
}
void context_filter::find_elements_inheritance_relationship(const diagram &d, void context_filter::find_elements_inheritance_relationship(const diagram &d,
std::set<id_t> &effective_context, std::set<id_t> &effective_context,
std::set<clanguml::common::id_t> &current_iteration_context) const std::set<clanguml::common::id_t> &current_iteration_context) const

View File

@@ -496,27 +496,34 @@ private:
std::set<clanguml::common::id_t> &current_iteration_context) const std::set<clanguml::common::id_t> &current_iteration_context) const
{ {
static_assert(std::is_same_v<ElementT, class_diagram::model::class_> || static_assert(std::is_same_v<ElementT, class_diagram::model::class_> ||
std::is_same_v<ElementT, class_diagram::model::enum_> ||
std::is_same_v<ElementT, class_diagram::model::concept_>, std::is_same_v<ElementT, class_diagram::model::concept_>,
"ElementT must be either class_ or concept_"); "ElementT must be either class_ or enum_ or concept_");
const auto &cd = dynamic_cast<const class_diagram::model::diagram &>(d); const auto &cd = dynamic_cast<const class_diagram::model::diagram &>(d);
for (const auto &el : cd.elements<ElementT>()) { for (const auto &el : cd.elements<ElementT>()) {
// First search all elements of type ElementT in the diagram
// which have a relationship to any of the effective_context
// elements
for (const relationship &rel : el.get().relationships()) { for (const relationship &rel : el.get().relationships()) {
for (const auto &ec : effective_context) { for (const auto &element_id : effective_context) {
if (d.should_include(rel.type()) && rel.destination() == ec) if (d.should_include(rel.type()) &&
rel.destination() == element_id)
current_iteration_context.emplace(el.get().id()); current_iteration_context.emplace(el.get().id());
} }
} }
for (const auto &ec : effective_context) { // Now search current effective_context elements and add any
const auto &maybe_concept = cd.find<ElementT>(ec); // elements of any type in the diagram which to that element
for (const auto element_id : effective_context) {
const auto &maybe_element = cd.get(element_id);
if (!maybe_concept) if (!maybe_element)
continue; continue;
for (const relationship &rel : for (const relationship &rel :
maybe_concept.value().relationships()) { maybe_element.value().relationships()) {
if (d.should_include(rel.type()) && if (d.should_include(rel.type()) &&
rel.destination() == el.get().id()) rel.destination() == el.get().id())
@@ -530,10 +537,6 @@ private:
std::set<id_t> &effective_context, std::set<id_t> &effective_context,
std::set<clanguml::common::id_t> &current_iteration_context) const; std::set<clanguml::common::id_t> &current_iteration_context) const;
void find_elements_in_relationship_with_enum(const diagram &d,
std::set<id_t> &effective_context,
std::set<clanguml::common::id_t> &current_iteration_context) const;
std::vector<config::context_config> context_; std::vector<config::context_config> context_;
/*! /*!

View File

@@ -10,6 +10,8 @@ diagrams:
- clanguml::t00041 - clanguml::t00041
context: context:
- clanguml::t00041::RR - clanguml::t00041::RR
- clanguml::t00041::Color
- clanguml::t00041::T::Direction
subclasses: subclasses:
- clanguml::t00041::ns1::N - clanguml::t00041::ns1::N
exclude: exclude:

View File

@@ -29,6 +29,10 @@ struct RR : public R {
F *f; F *f;
detail::G *g; detail::G *g;
enum K { One, Two, Three };
K k;
void foo(H *h) { } void foo(H *h) { }
}; };
@@ -42,4 +46,15 @@ struct NN : public N { };
struct NM : public N { }; struct NM : public N { };
} }
enum class Color { Red, Green, Blue };
struct S {
Color c;
};
struct T {
enum class Direction { Left, Right };
Direction d;
};
} // namespace clanguml::t00041 } // namespace clanguml::t00041

View File

@@ -40,10 +40,16 @@ TEST_CASE("t00041")
REQUIRE(IsClass(src, "RRR")); REQUIRE(IsClass(src, "RRR"));
REQUIRE(!IsClass(src, "detail::G")); REQUIRE(!IsClass(src, "detail::G"));
REQUIRE(!IsClass(src, "H")); REQUIRE(!IsClass(src, "H"));
REQUIRE(IsClass(src, "S"));
REQUIRE(IsClass(src, "T"));
REQUIRE(IsBaseClass(src, "R", "RR")); REQUIRE(IsBaseClass(src, "R", "RR"));
REQUIRE(IsBaseClass(src, "RR", "RRR")); REQUIRE(IsBaseClass(src, "RR", "RRR"));
REQUIRE(IsEnum(src, "RR::K"));
REQUIRE(IsEnum(src, "Color"));
REQUIRE(IsEnum(src, "T::Direction"));
REQUIRE(IsAssociation<Public>(src, "D", "RR", "rr")); REQUIRE(IsAssociation<Public>(src, "D", "RR", "rr"));
REQUIRE(IsAssociation<Public>(src, "RR", "E", "e")); REQUIRE(IsAssociation<Public>(src, "RR", "E", "e"));
REQUIRE(IsAssociation<Public>(src, "RR", "F", "f")); REQUIRE(IsAssociation<Public>(src, "RR", "F", "f"));
@@ -54,5 +60,8 @@ TEST_CASE("t00041")
REQUIRE(IsClass(src, {"ns1", "NM"})); REQUIRE(IsClass(src, {"ns1", "NM"}));
REQUIRE(IsBaseClass(src, "ns1::N", "ns1::NN")); REQUIRE(IsBaseClass(src, "ns1::N", "ns1::NN"));
REQUIRE(IsBaseClass(src, "ns1::N", "ns1::NM")); REQUIRE(IsBaseClass(src, "ns1::N", "ns1::NM"));
REQUIRE(IsInnerClass(src, "T", "T::Direction"));
REQUIRE(IsAggregation<Public>(src, "S", "Color", "c"));
}); });
} }