Added test case for context filter with radius option
This commit is contained in:
@@ -175,6 +175,15 @@ public:
|
||||
template <typename ElementT>
|
||||
opt_ref<ElementT> find(diagram_element::id_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Get reference to vector of elements of specific type
|
||||
*
|
||||
* @tparam ElementT Type of elements view
|
||||
* @return Reference to elements vector
|
||||
*/
|
||||
template <typename ElementT>
|
||||
const common::reference_vector<ElementT> &elements() const;
|
||||
|
||||
/**
|
||||
* @brief Add element to the diagram at a specified nested path.
|
||||
*
|
||||
@@ -383,6 +392,12 @@ opt_ref<ElementT> diagram::find(diagram_element::id_t id) const
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename ElementT>
|
||||
const common::reference_vector<ElementT> &diagram::elements() const
|
||||
{
|
||||
return element_view<ElementT>::view();
|
||||
}
|
||||
|
||||
//
|
||||
// Template method specialization pre-declarations...
|
||||
//
|
||||
|
||||
@@ -535,7 +535,7 @@ tvl::value_t access_filter::match(
|
||||
}
|
||||
|
||||
context_filter::context_filter(
|
||||
filter_t type, std::vector<config::context_config> context, unsigned radius)
|
||||
filter_t type, std::vector<config::context_config> context)
|
||||
: filter_visitor{type}
|
||||
, context_{std::move(context)}
|
||||
{
|
||||
@@ -548,10 +548,10 @@ void context_filter::initialize_effective_context(
|
||||
|
||||
auto &effective_context = effective_contexts_[idx];
|
||||
|
||||
// First add to effective context all elements matching context_
|
||||
// First add to effective context all elements matching context_ patterns
|
||||
const auto &context = context_.at(idx);
|
||||
const auto &context_matches =
|
||||
static_cast<const class_diagram::model::diagram &>(d)
|
||||
dynamic_cast<const class_diagram::model::diagram &>(d)
|
||||
.find<class_diagram::model::class_>(context.pattern);
|
||||
|
||||
for (const auto &maybe_match : context_matches) {
|
||||
@@ -572,65 +572,19 @@ void context_filter::initialize_effective_context(
|
||||
current_iteration_context.clear();
|
||||
|
||||
// For each class in the model
|
||||
for (const auto &c :
|
||||
static_cast<const class_diagram::model::diagram &>(d).classes()) {
|
||||
// Return a positive match if the element e is in a direct
|
||||
// relationship with any of the effective context elements ...
|
||||
for (const relationship &rel : c.get().relationships()) {
|
||||
for (const auto &ec : effective_context) {
|
||||
if (d.should_include(rel.type()) && rel.destination() == ec)
|
||||
current_iteration_context.emplace(c.get().id());
|
||||
}
|
||||
}
|
||||
// ... or vice-versa
|
||||
for (const auto &ec : effective_context) {
|
||||
const auto &maybe_class =
|
||||
static_cast<const class_diagram::model::diagram &>(d)
|
||||
.find<class_diagram::model::class_>(ec);
|
||||
find_elements_in_direct_relationship<class_diagram::model::class_>(
|
||||
d, effective_context, current_iteration_context);
|
||||
|
||||
if (!maybe_class)
|
||||
continue;
|
||||
find_elements_inheritance_relationship(
|
||||
d, effective_context, current_iteration_context);
|
||||
|
||||
for (const relationship &rel :
|
||||
maybe_class.value().relationships()) {
|
||||
// For each enum in the model
|
||||
find_elements_in_relationship_with_enum(
|
||||
d, effective_context, current_iteration_context);
|
||||
|
||||
if (d.should_include(rel.type()) &&
|
||||
rel.destination() == c.get().id())
|
||||
current_iteration_context.emplace(c.get().id());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any of the elements parents are already in the
|
||||
// effective context...
|
||||
for (const class_diagram::model::class_parent &p :
|
||||
c.get().parents()) {
|
||||
for (const auto &ec : effective_context) {
|
||||
const auto &maybe_parent =
|
||||
static_cast<const class_diagram::model::diagram &>(d)
|
||||
.find<class_diagram::model::class_>(ec);
|
||||
if (!maybe_parent)
|
||||
continue;
|
||||
|
||||
if (d.should_include(relationship_t::kExtension) &&
|
||||
maybe_parent.value().full_name(false) == p.name())
|
||||
current_iteration_context.emplace(c.get().id());
|
||||
}
|
||||
}
|
||||
|
||||
// .. or vice-versa
|
||||
for (const auto &ec : effective_context) {
|
||||
const auto &maybe_child =
|
||||
static_cast<const class_diagram::model::diagram &>(d)
|
||||
.find<class_diagram::model::class_>(ec);
|
||||
|
||||
for (const class_diagram::model::class_parent &p :
|
||||
maybe_child.value().parents()) {
|
||||
if (p.name() == c.get().full_name(false)) {
|
||||
current_iteration_context.emplace(c.get().id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For each concept in the model
|
||||
find_elements_in_direct_relationship<class_diagram::model::concept_>(
|
||||
d, effective_context, current_iteration_context);
|
||||
|
||||
for (auto id : current_iteration_context) {
|
||||
if (effective_context.count(id) == 0) {
|
||||
@@ -642,6 +596,71 @@ 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> ¤t_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,
|
||||
std::set<id_t> &effective_context,
|
||||
std::set<clanguml::common::id_t> ¤t_iteration_context) const
|
||||
{
|
||||
const auto &cd = dynamic_cast<const class_diagram::model::diagram &>(d);
|
||||
|
||||
for (const auto &c : cd.classes()) {
|
||||
// Check if any of the elements parents are already in the
|
||||
// effective context...
|
||||
for (const class_diagram::model::class_parent &p : c.get().parents()) {
|
||||
for (const auto &ec : effective_context) {
|
||||
const auto &maybe_parent =
|
||||
cd.find<class_diagram::model::class_>(ec);
|
||||
if (!maybe_parent)
|
||||
continue;
|
||||
|
||||
if (d.should_include(relationship_t::kExtension) &&
|
||||
maybe_parent.value().full_name(false) == p.name())
|
||||
current_iteration_context.emplace(c.get().id());
|
||||
}
|
||||
}
|
||||
|
||||
// .. or vice-versa
|
||||
for (const auto &ec : effective_context) {
|
||||
const auto &maybe_child = cd.find<class_diagram::model::class_>(ec);
|
||||
|
||||
// The element might not exist because it might have been
|
||||
// something other than a class
|
||||
if (!maybe_child)
|
||||
continue;
|
||||
|
||||
for (const auto &p : maybe_child.value().parents()) {
|
||||
if (p.name() == c.get().full_name(false)) {
|
||||
current_iteration_context.emplace(c.get().id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void context_filter::initialize(const diagram &d) const
|
||||
{
|
||||
if (initialized_)
|
||||
@@ -651,7 +670,7 @@ void context_filter::initialize(const diagram &d) const
|
||||
|
||||
// Prepare effective_contexts_
|
||||
for (auto i = 0U; i < context_.size(); i++) {
|
||||
effective_contexts_.push_back({});
|
||||
effective_contexts_.push_back({}); // NOLINT
|
||||
initialize_effective_context(d, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,8 +447,7 @@ private:
|
||||
* to any of the elements specified in context.
|
||||
*/
|
||||
struct context_filter : public filter_visitor {
|
||||
context_filter(filter_t type, std::vector<config::context_config> context,
|
||||
unsigned radius = 1);
|
||||
context_filter(filter_t type, std::vector<config::context_config> context);
|
||||
|
||||
~context_filter() override = default;
|
||||
|
||||
@@ -459,6 +458,50 @@ private:
|
||||
|
||||
void initialize_effective_context(const diagram &d, unsigned idx) const;
|
||||
|
||||
template <typename ElementT>
|
||||
void find_elements_in_direct_relationship(const diagram &d,
|
||||
std::set<id_t> &effective_context,
|
||||
std::set<clanguml::common::id_t> ¤t_iteration_context) const
|
||||
{
|
||||
static_assert(std::is_same_v<ElementT, class_diagram::model::class_> ||
|
||||
std::is_same_v<ElementT, class_diagram::model::concept_>,
|
||||
"ElementT must be either class_ or concept_");
|
||||
|
||||
const auto &cd = dynamic_cast<const class_diagram::model::diagram &>(d);
|
||||
|
||||
for (const auto &el : cd.elements<ElementT>()) {
|
||||
for (const relationship &rel : el.get().relationships()) {
|
||||
for (const auto &ec : effective_context) {
|
||||
if (d.should_include(rel.type()) && rel.destination() == ec)
|
||||
current_iteration_context.emplace(el.get().id());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &ec : effective_context) {
|
||||
const auto &maybe_concept = cd.find<ElementT>(ec);
|
||||
|
||||
if (!maybe_concept)
|
||||
continue;
|
||||
|
||||
for (const relationship &rel :
|
||||
maybe_concept.value().relationships()) {
|
||||
|
||||
if (d.should_include(rel.type()) &&
|
||||
rel.destination() == el.get().id())
|
||||
current_iteration_context.emplace(el.get().id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void find_elements_inheritance_relationship(const diagram &d,
|
||||
std::set<id_t> &effective_context,
|
||||
std::set<clanguml::common::id_t> ¤t_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> ¤t_iteration_context) const;
|
||||
|
||||
std::vector<config::context_config> context_;
|
||||
|
||||
/*!
|
||||
|
||||
@@ -426,7 +426,7 @@ template <> struct convert<context_config> {
|
||||
using namespace std::string_literals;
|
||||
if (node.IsMap() && has_key(node, "match")) {
|
||||
rhs.radius = node["match"]["radius"].as<unsigned>();
|
||||
rhs.pattern = node["match"]["radius"].as<string_or_regex>();
|
||||
rhs.pattern = node["match"]["pattern"].as<string_or_regex>();
|
||||
}
|
||||
else {
|
||||
rhs.radius = 1;
|
||||
|
||||
45
tests/t00068/.clang-uml
Normal file
45
tests/t00068/.clang-uml
Normal file
@@ -0,0 +1,45 @@
|
||||
compilation_database_dir: ..
|
||||
output_directory: diagrams
|
||||
diagrams:
|
||||
t00068_r0_class:
|
||||
type: class
|
||||
title: AAA context of radius 0
|
||||
glob:
|
||||
- ../../tests/t00068/t00068.cc
|
||||
include:
|
||||
namespaces:
|
||||
- clanguml::t00068
|
||||
context:
|
||||
- match:
|
||||
radius: 0
|
||||
pattern: clanguml::t00068::AAA
|
||||
using_namespace:
|
||||
- clanguml::t00068
|
||||
t00068_r1_class:
|
||||
type: class
|
||||
title: AAA context of radius 1
|
||||
glob:
|
||||
- ../../tests/t00068/t00068.cc
|
||||
include:
|
||||
namespaces:
|
||||
- clanguml::t00068
|
||||
context:
|
||||
- match:
|
||||
radius: 1
|
||||
pattern: clanguml::t00068::AAA
|
||||
using_namespace:
|
||||
- clanguml::t00068
|
||||
t00068_r2_class:
|
||||
type: class
|
||||
title: AAA context of radius 2
|
||||
glob:
|
||||
- ../../tests/t00068/t00068.cc
|
||||
include:
|
||||
namespaces:
|
||||
- clanguml::t00068
|
||||
context:
|
||||
- match:
|
||||
radius: 2
|
||||
pattern: clanguml::t00068::AAA
|
||||
using_namespace:
|
||||
- clanguml::t00068
|
||||
32
tests/t00068/t00068.cc
Normal file
32
tests/t00068/t00068.cc
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml {
|
||||
namespace t00068 {
|
||||
|
||||
struct B { };
|
||||
|
||||
struct BB {
|
||||
std::vector<B> b;
|
||||
};
|
||||
|
||||
enum class AKind { OneA, TwoA, ThreeA };
|
||||
|
||||
struct A { };
|
||||
|
||||
struct AA : public A { };
|
||||
|
||||
struct AAA : public AA {
|
||||
BB *bb;
|
||||
AKind akind;
|
||||
};
|
||||
|
||||
struct R {
|
||||
AAA *aaa;
|
||||
};
|
||||
|
||||
struct RR {
|
||||
std::shared_ptr<R> r;
|
||||
};
|
||||
}
|
||||
}
|
||||
195
tests/t00068/test_case.h
Normal file
195
tests/t00068/test_case.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* tests/t00068/test_case.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
* 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("t00068_r0", "[test-case][class][t00068]")
|
||||
{
|
||||
auto [config, db] = load_config("t00068");
|
||||
|
||||
auto diagram = config.diagrams["t00068_r0_class"];
|
||||
|
||||
auto model = generate_class_diagram(*db, diagram);
|
||||
|
||||
REQUIRE(model->name() == "t00068_r0_class");
|
||||
|
||||
{
|
||||
auto src = generate_class_puml(diagram, *model);
|
||||
AliasMatcher _A(src);
|
||||
|
||||
REQUIRE_THAT(src, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(src, EndsWith("@enduml\n"));
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("A")));
|
||||
REQUIRE_THAT(src, !IsClass(_A("AA")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AAA")));
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("B")));
|
||||
REQUIRE_THAT(src, !IsClass(_A("BB")));
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("R")));
|
||||
REQUIRE_THAT(src, !IsClass(_A("RR")));
|
||||
|
||||
REQUIRE_THAT(src, !IsEnum(_A("AKind")));
|
||||
|
||||
save_puml(config.output_directory(), diagram->name + ".puml", src);
|
||||
}
|
||||
|
||||
{
|
||||
auto j = generate_class_json(diagram, *model);
|
||||
|
||||
using namespace json;
|
||||
|
||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||
}
|
||||
|
||||
{
|
||||
auto src = generate_class_mermaid(diagram, *model);
|
||||
|
||||
mermaid::AliasMatcher _A(src);
|
||||
using mermaid::IsClass;
|
||||
using mermaid::IsEnum;
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("A")));
|
||||
REQUIRE_THAT(src, !IsClass(_A("AA")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AAA")));
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("B")));
|
||||
REQUIRE_THAT(src, !IsClass(_A("BB")));
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("R")));
|
||||
REQUIRE_THAT(src, !IsClass(_A("RR")));
|
||||
|
||||
REQUIRE_THAT(src, !IsEnum(_A("AKind")));
|
||||
|
||||
save_mermaid(config.output_directory(), diagram->name + ".mmd", src);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("t00068_r1", "[test-case][class][t00068]")
|
||||
{
|
||||
auto [config, db] = load_config("t00068");
|
||||
|
||||
auto diagram = config.diagrams["t00068_r1_class"];
|
||||
|
||||
auto model = generate_class_diagram(*db, diagram);
|
||||
|
||||
REQUIRE(model->name() == "t00068_r1_class");
|
||||
|
||||
{
|
||||
auto src = generate_class_puml(diagram, *model);
|
||||
AliasMatcher _A(src);
|
||||
|
||||
REQUIRE_THAT(src, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(src, EndsWith("@enduml\n"));
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("A")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AA")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AAA")));
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("B")));
|
||||
REQUIRE_THAT(src, IsClass(_A("BB")));
|
||||
|
||||
REQUIRE_THAT(src, IsClass(_A("R")));
|
||||
REQUIRE_THAT(src, !IsClass(_A("RR")));
|
||||
|
||||
REQUIRE_THAT(src, IsEnum(_A("AKind")));
|
||||
|
||||
save_puml(config.output_directory(), diagram->name + ".puml", src);
|
||||
}
|
||||
|
||||
{
|
||||
auto j = generate_class_json(diagram, *model);
|
||||
|
||||
using namespace json;
|
||||
|
||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||
}
|
||||
|
||||
{
|
||||
auto src = generate_class_mermaid(diagram, *model);
|
||||
|
||||
mermaid::AliasMatcher _A(src);
|
||||
using mermaid::IsClass;
|
||||
|
||||
REQUIRE_THAT(src, !IsClass(_A("A")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AA")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AAA")));
|
||||
|
||||
save_mermaid(config.output_directory(), diagram->name + ".mmd", src);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("t00068_r2", "[test-case][class][t00068]")
|
||||
{
|
||||
auto [config, db] = load_config("t00068");
|
||||
|
||||
auto diagram = config.diagrams["t00068_r2_class"];
|
||||
|
||||
auto model = generate_class_diagram(*db, diagram);
|
||||
|
||||
REQUIRE(model->name() == "t00068_r2_class");
|
||||
|
||||
{
|
||||
auto src = generate_class_puml(diagram, *model);
|
||||
AliasMatcher _A(src);
|
||||
|
||||
REQUIRE_THAT(src, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(src, EndsWith("@enduml\n"));
|
||||
|
||||
REQUIRE_THAT(src, IsClass(_A("A")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AA")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AAA")));
|
||||
|
||||
REQUIRE_THAT(src, IsClass(_A("B")));
|
||||
REQUIRE_THAT(src, IsClass(_A("BB")));
|
||||
|
||||
REQUIRE_THAT(src, IsClass(_A("R")));
|
||||
REQUIRE_THAT(src, IsClass(_A("RR")));
|
||||
|
||||
REQUIRE_THAT(src, IsEnum(_A("AKind")));
|
||||
|
||||
save_puml(config.output_directory(), diagram->name + ".puml", src);
|
||||
}
|
||||
|
||||
{
|
||||
auto j = generate_class_json(diagram, *model);
|
||||
|
||||
using namespace json;
|
||||
|
||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||
}
|
||||
|
||||
{
|
||||
auto src = generate_class_mermaid(diagram, *model);
|
||||
|
||||
mermaid::AliasMatcher _A(src);
|
||||
using mermaid::IsClass;
|
||||
using mermaid::IsEnum;
|
||||
|
||||
REQUIRE_THAT(src, IsClass(_A("A")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AA")));
|
||||
REQUIRE_THAT(src, IsClass(_A("AAA")));
|
||||
|
||||
REQUIRE_THAT(src, IsClass(_A("B")));
|
||||
REQUIRE_THAT(src, IsClass(_A("BB")));
|
||||
|
||||
REQUIRE_THAT(src, IsClass(_A("R")));
|
||||
REQUIRE_THAT(src, IsClass(_A("RR")));
|
||||
|
||||
save_mermaid(config.output_directory(), diagram->name + ".mmd", src);
|
||||
}
|
||||
}
|
||||
@@ -384,6 +384,7 @@ using namespace clanguml::test::matchers;
|
||||
#endif
|
||||
#include "t00066/test_case.h"
|
||||
#include "t00067/test_case.h"
|
||||
#include "t00068/test_case.h"
|
||||
|
||||
///
|
||||
/// Sequence diagram tests
|
||||
|
||||
@@ -198,6 +198,9 @@ test_cases:
|
||||
- name: t00067
|
||||
title: Class method type filter test case
|
||||
description:
|
||||
- name: t00068
|
||||
title: Context filter radius parameter test case
|
||||
description:
|
||||
Sequence diagrams:
|
||||
- name: t20001
|
||||
title: Basic sequence diagram test case
|
||||
|
||||
@@ -29,16 +29,16 @@ TEST_CASE("{{ name }}", "[test-case][{{ type }}]")
|
||||
REQUIRE(model->name() == "{{ name }}_{{ type }}");
|
||||
|
||||
{
|
||||
auto puml = generate_{{ type }}_puml(diagram, *model);
|
||||
AliasMatcher _A(puml);
|
||||
auto src = generate_{{ type }}_puml(diagram, *model);
|
||||
AliasMatcher _A(src);
|
||||
|
||||
REQUIRE_THAT(puml, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
||||
REQUIRE_THAT(src, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(src, EndsWith("@enduml\n"));
|
||||
|
||||
{{ examples }}
|
||||
|
||||
save_puml(
|
||||
config.output_directory(), diagram->name + ".puml", puml);
|
||||
config.output_directory(), diagram->name + ".puml", src);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -49,4 +49,12 @@ TEST_CASE("{{ name }}", "[test-case][{{ type }}]")
|
||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||
}
|
||||
|
||||
{
|
||||
auto src = generate_class_mermaid(diagram, *model);
|
||||
|
||||
mermaid::AliasMatcher _A(src);
|
||||
using mermaid::IsClass;
|
||||
|
||||
save_mermaid(config.output_directory(), diagram->name + ".mmd", src);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user