Refactored and unified JSON generators output (#223)

This commit is contained in:
Bartek Kryza
2023-12-27 22:04:02 +01:00
parent edfaabd4fa
commit 9d73c9e3ff
47 changed files with 533 additions and 341 deletions

View File

@@ -191,7 +191,7 @@ void generator::generate(const package &p, nlohmann::json &parent) const
package_object["type"] = to_string(config().package_type());
package_object["name"] = p.name();
package_object["display_name"] = p.full_name(false);
package_object["display_name"] = p.name();
}
}

View File

@@ -42,7 +42,7 @@ void to_json(nlohmann::json &j, const element &c)
j = json{{"id", std::to_string(c.id())},
{"name", detail::render_name(c.name())},
{"namespace", c.get_namespace().to_string()}, {"type", c.type_name()},
{"display_name", detail::render_name(c.full_name(false))}};
{"display_name", detail::render_name(c.full_name(true))}};
if (const auto &comment = c.comment(); comment)
j["comment"] = comment.value();

View File

@@ -35,13 +35,13 @@
namespace clanguml::common::model {
using nlohmann::json;
void to_json(nlohmann::json &j, const source_location &sl);
void to_json(json &j, const source_location &sl);
void to_json(nlohmann::json &j, const element &c);
void to_json(json &j, const element &c);
void to_json(nlohmann::json &j, const template_parameter &c);
void to_json(json &j, const template_parameter &c);
void to_json(nlohmann::json &j, const relationship &c);
void to_json(json &j, const relationship &c);
} // namespace clanguml::common::model
namespace clanguml::common::generators::json {

View File

@@ -123,8 +123,11 @@ public:
*
* @return Fully qualified elements name.
*/
std::string full_name(bool /*relative*/) const override
std::string full_name(bool relative) const override
{
if (relative)
return name();
return name_and_ns();
}

View File

@@ -60,26 +60,49 @@ void generator::generate(const package &p, nlohmann::json &parent) const
{
LOG_DBG("Generating package {}", p.full_name(false));
nlohmann::json j;
j["id"] = std::to_string(p.id());
j["name"] = p.name();
j["type"] = to_string(config().package_type());
j["display_name"] = p.full_name(false);
j["is_deprecated"] = p.is_deprecated();
if (!p.file().empty())
j["source_location"] =
dynamic_cast<const common::model::source_location &>(p);
if (const auto &comment = p.comment(); comment)
j["comment"] = comment.value();
const auto &uns = config().using_namespace();
if (!uns.starts_with({p.full_name(false)})) {
nlohmann::json j;
j["id"] = std::to_string(p.id());
j["name"] = p.name();
j["type"] = to_string(config().package_type());
j["display_name"] = p.name();
switch (config().package_type()) {
case config::package_type_t::kNamespace:
j["namespace"] = p.get_namespace().to_string();
break;
case config::package_type_t::kModule:
j["namespace"] = p.get_namespace().to_string();
break;
case config::package_type_t::kDirectory:
j["path"] = p.get_namespace().to_string();
break;
}
for (const auto &subpackage : p) {
auto &pkg = dynamic_cast<package &>(*subpackage);
if (model().should_include(pkg)) {
generate(pkg, j);
j["is_deprecated"] = p.is_deprecated();
if (!p.file().empty())
j["source_location"] =
dynamic_cast<const common::model::source_location &>(p);
if (const auto &comment = p.comment(); comment)
j["comment"] = comment.value();
for (const auto &subpackage : p) {
auto &pkg = dynamic_cast<package &>(*subpackage);
if (model().should_include(pkg)) {
generate(pkg, j);
}
}
parent["elements"].push_back(std::move(j));
}
else {
for (const auto &subpackage : p) {
auto &pkg = dynamic_cast<package &>(*subpackage);
if (model().should_include(pkg)) {
generate(pkg, parent);
}
}
}
parent["elements"].push_back(std::move(j));
}
void generator::generate_diagram(nlohmann::json &parent) const

View File

@@ -33,14 +33,12 @@ namespace clanguml::sequence_diagram::model {
void to_json(nlohmann::json &j, const participant &c)
{
j["name"] = generators::json::render_name(c.full_name(false));
j["id"] = std::to_string(c.id());
to_json(j, dynamic_cast<const participant::element &>(c));
j["type"] = c.type_name();
if (!c.file().empty())
j["source_location"] =
dynamic_cast<const common::model::source_location &>(c);
if (const auto &comment = c.comment(); comment)
j["comment"] = comment.value();
if (c.type_name() == "method") {
j["name"] = dynamic_cast<const method &>(c).method_name();
}
}
void to_json(nlohmann::json &j, const activity &c)
@@ -105,11 +103,8 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
msg["name"] = message;
msg["type"] = "message";
msg["from"]["activity_name"] =
generators::json::render_name(from.value().full_name(false));
msg["from"]["activity_id"] = std::to_string(from.value().id());
msg["to"]["activity_id"] = std::to_string(to.value().id());
msg["to"]["activity_name"] = to.value().full_name(false);
if (const auto &cmt = m.comment(); cmt.has_value())
msg["comment"] = cmt.value();
@@ -132,7 +127,6 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
}
else {
msg["from"]["participant_id"] = std::to_string(from.value().id());
msg["from"]["participant_name"] = from.value().full_name(false);
}
}
else if (from.value().type_name() == "lambda") {
@@ -553,43 +547,92 @@ common::id_t generator::generate_participant(
const auto &participant =
model().get_participant<model::participant>(participant_id).value();
if (participant.type_name() == "method") {
participant_id = model()
.get_participant<model::method>(participant_id)
.value()
.class_id();
const auto participant_type = participant.type_name();
if (is_participant_generated(participant_id))
return participant_id;
if (participant_type == "method") {
auto class_participant_id =
model()
.get_participant<model::method>(participant_id)
.value()
.class_id();
const auto &class_participant =
model().get_participant<model::participant>(participant_id).value();
if (!is_participant_generated(class_participant_id)) {
const auto &class_participant =
model()
.get_participant<model::participant>(class_participant_id)
.value();
parent["participants"].push_back(class_participant);
generated_participants_.emplace(participant_id);
generated_participants_.emplace(class_participant_id);
json_["participants"].push_back(class_participant);
json_["participants"].back()["activities"].push_back(participant);
return class_participant_id;
}
else {
if (!is_participant_generated(participant_id)) {
for (auto &p : json_["participants"]) {
if (p.at("id") == std::to_string(class_participant_id)) {
generated_participants_.emplace(participant_id);
p["activities"].push_back(participant);
return class_participant_id;
}
}
}
}
}
else if ((participant.type_name() == "function" ||
participant.type_name() == "function_template") &&
else if ((participant_type == "function" ||
participant_type == "function_template") &&
config().combine_free_functions_into_file_participants()) {
// Create a single participant for all functions declared in a
// single file
// participant_id will become activity_id within a file participant
const auto &function_participant =
model().get_participant<model::function>(participant_id).value();
nlohmann::json j = function_participant;
j["name"] = util::path_to_url(
config().make_path_relative(function_participant.file()).string());
const auto file_participant_id =
common::to_id(function_participant.file_relative());
participant_id = common::to_id(function_participant.file_relative());
if (!is_participant_generated(file_participant_id)) {
nlohmann::json p = function_participant;
if (is_participant_generated(participant_id))
return participant_id;
const auto file_path =
config().make_path_relative(function_participant.file());
j["id"] = std::to_string(participant_id);
p["display_name"] = util::path_to_url(file_path.string());
p["name"] = file_path.filename();
parent["participants"].push_back(j);
if (is_participant_generated(file_participant_id))
return participant_id;
p["id"] = std::to_string(file_participant_id);
p["type"] = "file";
p.erase("source_location");
generated_participants_.emplace(participant_id);
p["activities"].push_back(participant);
json_["participants"].push_back(p);
generated_participants_.emplace(file_participant_id);
return file_participant_id;
}
else {
if (!is_participant_generated(participant_id)) {
for (auto &p : json_["participants"]) {
if (p.at("id") == std::to_string(file_participant_id)) {
generated_participants_.emplace(participant_id);
p["activities"].push_back(participant);
}
}
}
return file_participant_id;
}
}
else {
parent["participants"].push_back(participant);
json_["participants"].push_back(participant);
}
generated_participants_.emplace(participant_id);
@@ -614,7 +657,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
if (config().participants_order.has_value) {
for (const auto &p : config().participants_order()) {
LOG_DBG("Pregenerating participant {}", p);
generate_participant(parent, p);
generate_participant(json_, p);
}
}
@@ -661,7 +704,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
block_statements_stack_.pop_back();
json_["sequences"].push_back(std::move(sequence));
parent["sequences"].push_back(std::move(sequence));
}
for (const auto &to_location : config().to()) {
@@ -697,7 +740,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
block_statements_stack_.pop_back();
json_["sequences"].push_back(std::move(sequence));
parent["sequences"].push_back(std::move(sequence));
}
for (const auto &sf : config().from()) {
@@ -757,7 +800,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
sequence["return_type"] = from.value().return_type();
}
json_["sequences"].push_back(std::move(sequence));
parent["sequences"].push_back(std::move(sequence));
}
else {
// TODO: Add support for other sequence start location types
@@ -765,6 +808,6 @@ void generator::generate_diagram(nlohmann::json &parent) const
}
}
parent.update(json_);
parent["participants"] = json_["participants"];
}
} // namespace clanguml::sequence_diagram::generators::json

View File

@@ -239,6 +239,8 @@ private:
mutable std::set<common::id_t> generated_participants_;
// Needed to add "participants" array in a temporary object accessible from
// all methods of the generator
mutable nlohmann::json json_;
mutable std::vector<std::reference_wrapper<nlohmann::json>>

View File

@@ -69,7 +69,10 @@ std::string class_::full_name(bool relative) const
std::ostringstream ostr;
ostr << name_and_ns();
if (relative)
ostr << name();
else
ostr << name_and_ns();
render_template_params(ostr, using_namespace(), relative);
std::string res;
@@ -102,7 +105,7 @@ function::function(const common::model::namespace_ &using_namespace)
std::string function::full_name(bool relative) const
{
return fmt::format("{}({}){}", element::full_name(relative),
return fmt::format("{}({}){}", participant::full_name(relative),
fmt::join(parameters_, ","), is_const() ? " const" : "");
}
@@ -195,8 +198,12 @@ void method::set_class_full_name(const std::string &name)
const auto &method::class_full_name() const { return class_full_name_; }
std::string method::full_name(bool /*relative*/) const
std::string method::full_name(bool relative) const
{
if (relative)
return fmt::format("{}({}){}", method_name(),
fmt::join(parameters(), ","), is_const() ? " const" : "");
return fmt::format("{}::{}({}){}", class_full_name(), method_name(),
fmt::join(parameters(), ","), is_const() ? " const" : "");
}

View File

@@ -88,7 +88,13 @@ public:
*
* @return Type name of the diagram element.
*/
std::string type_name() const override { return "class"; }
std::string type_name() const override
{
if (is_lambda())
return "lambda";
return "class";
}
/**
* @brief Check if class is a struct.

View File

@@ -1083,10 +1083,6 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
bool translation_unit_visitor::TraverseVarDecl(clang::VarDecl *decl)
{
LOG_TRACE("Traversing cxx variable declaration at {} [caller_id = {}]",
decl->getBeginLoc().printToString(source_manager()),
context().caller_id());
if (decl->isStaticLocal())
within_static_variable_declaration_++;

View File

@@ -18,7 +18,7 @@
#pragma once
namespace clanguml::version {
static constexpr auto CLANG_UML_JSON_GENERATOR_SCHEMA_VERSION = 1U;
static constexpr auto CLANG_UML_JSON_GENERATOR_SCHEMA_VERSION = 2U;
static constexpr auto CLANG_UML_VERSION = "@GIT_VERSION@";
static constexpr auto CLANG_UML_LIBCLANG_VERSION = "@LIBCLANG_VERSION_STRING@";
} // namespace clanguml::version

View File

@@ -93,6 +93,17 @@ TEST_CASE("t00002", "[test-case][class]")
using namespace json;
const auto &A = get_element(j, "A");
CHECK(A.has_value());
CHECK(A.value()["type"] == "class");
CHECK(A.value()["name"] == "A");
CHECK(A.value()["display_name"] == "A");
CHECK(A.value()["namespace"] == "clanguml::t00002");
CHECK(A.value()["source_location"]["file"] == "t00002.cc");
CHECK(A.value()["source_location"]["line"] == 7);
REQUIRE(HasTitle(j, "Basic class diagram example"));
REQUIRE(IsClass(j, "A"));
REQUIRE(IsClass(j, "B"));

View File

@@ -98,10 +98,9 @@ TEST_CASE("t00006", "[test-case][class]")
REQUIRE(IsClass(j, "NN"));
REQUIRE(IsClass(j, "NNN"));
REQUIRE(IsAggregation(
j, "R", "custom_container<clanguml::t00006::E>", "e"));
REQUIRE(IsInstantiation(
j, "custom_container<T>", "custom_container<clanguml::t00006::E>"));
REQUIRE(IsAggregation(j, "R", "custom_container<E>", "e"));
REQUIRE(
IsInstantiation(j, "custom_container<T>", "custom_container<E>"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -62,8 +62,8 @@ TEST_CASE("t00025", "[test-case][class]")
REQUIRE(IsClass(j, "Target1"));
REQUIRE(IsClass(j, "Target2"));
REQUIRE(IsClassTemplate(j, "Proxy<T>"));
REQUIRE(IsDependency(j, "Proxy<clanguml::t00025::Target1>", "Target1"));
REQUIRE(IsDependency(j, "Proxy<clanguml::t00025::Target2>", "Target2"));
REQUIRE(IsDependency(j, "Proxy<Target1>", "Target1"));
REQUIRE(IsDependency(j, "Proxy<Target2>", "Target2"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -67,12 +67,9 @@ TEST_CASE("t00027", "[test-case][class]")
REQUIRE(IsAbstractClass(j, "ShapeDecorator"));
REQUIRE(IsClassTemplate(j, "Line<T<>...>"));
REQUIRE(IsInstantiation(
j, "Line<T<>...>", "Line<clanguml::t00027::Color>"));
REQUIRE(IsInstantiation(j, "Line<T<>...>",
"Line<clanguml::t00027::Color,clanguml::t00027::Weight>"));
REQUIRE(IsAggregation(
j, "Window", "Text<clanguml::t00027::Color>", "description"));
REQUIRE(IsInstantiation(j, "Line<T<>...>", "Line<Color>"));
REQUIRE(IsInstantiation(j, "Line<T<>...>", "Line<Color,Weight>"));
REQUIRE(IsAggregation(j, "Window", "Text<Color>", "description"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -69,9 +69,7 @@ TEST_CASE("t00032", "[test-case][class]")
using namespace json;
REQUIRE(IsBaseClass(j, "A",
"Overload<clanguml::t00032::TBase,int,clanguml::t00032::A,clanguml:"
":t00032::B,clanguml::t00032::C>"));
REQUIRE(IsBaseClass(j, "A", "Overload<TBase,int,A,B,C>"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -61,13 +61,9 @@ TEST_CASE("t00033", "[test-case][class]")
using namespace json;
REQUIRE(IsClass(j,
"A<clanguml::t00033::B<std::unique_ptr<clanguml::t00033::C<"
"clanguml::t00033::D>>>>"));
REQUIRE(IsDependency(j,
"A<clanguml::t00033::B<std::unique_ptr<clanguml::t00033::C<"
"clanguml::t00033::D>>>>",
"B<std::unique_ptr<clanguml::t00033::C<clanguml::t00033::D>>>"));
REQUIRE(IsClass(j, "A<B<std::unique_ptr<C<D>>>>"));
REQUIRE(IsDependency(
j, "A<B<std::unique_ptr<C<D>>>>", "B<std::unique_ptr<C<D>>>"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -17,7 +17,7 @@ struct B {
A<int> a_int;
};
}
} // namespace ns111
} // namespace ns11
} // namespace ns1
@@ -29,8 +29,8 @@ struct C { };
struct D { };
}
}
} // namespace ns22
} // namespace ns2
namespace ns3 {
namespace ns33 {

View File

@@ -55,16 +55,20 @@ TEST_CASE("t00036", "[test-case][class]")
auto j = generate_class_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsClass(j, "ns1::ns11::A<T>"));
REQUIRE(IsClass(j, "ns1::ns11::A<int>"));
REQUIRE(IsClass(j, "ns1::ns11::ns111::B"));
REQUIRE(IsClass(j, "ns2::ns22::C"));
REQUIRE(IsEnum(j, "ns1::E"));
REQUIRE(IsPackage(j, "ns1"));
REQUIRE(IsPackage(j, "ns1::ns11"));
REQUIRE(IsPackage(j, "ns1::ns11::ns111"));
REQUIRE(IsPackage(j, "ns2"));
REQUIRE(IsNamespacePackage(j, "ns1"s));
REQUIRE(IsNamespacePackage(j, "ns1"s, "ns11"s));
REQUIRE(IsNamespacePackage(j, "ns1"s, "ns11"s, "ns111"s));
REQUIRE(IsNamespacePackage(j, "ns2"s));
REQUIRE(IsNamespacePackage(j, "ns2"s, "ns22"s));
REQUIRE(IsNamespacePackage(j, "ns3"s));
REQUIRE(IsNamespacePackage(j, "ns3"s, "ns33"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -75,8 +75,7 @@ TEST_CASE("t00044", "[test-case][class]")
REQUIRE(IsClassTemplate(j, "signal_handler<T,A>"));
REQUIRE(IsClassTemplate(j, "signal_handler<Ret(Args...),A>"));
REQUIRE(IsClassTemplate(j, "signal_handler<void(int),bool>"));
REQUIRE(IsClassTemplate(
j, "sink<clanguml::t00044::signal_handler<Ret(Args...),A>>"));
REQUIRE(IsClassTemplate(j, "sink<signal_handler<Ret(Args...),A>>"));
REQUIRE(IsClass(j, "R"));
save_json(config.output_directory(), diagram->name + ".json", j);

View File

@@ -75,8 +75,7 @@ TEST_CASE("t00058", "[test-case][class]")
using namespace json;
REQUIRE(IsClass(j, "A<int,int,double,std::string>"));
REQUIRE(IsClass(
j, "B<int,std::string,int,double,clanguml::t00058::A<int,int>>"));
REQUIRE(IsClass(j, "B<int,std::string,int,double,A<int,int>>"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -48,6 +48,12 @@ TEST_CASE("t00071", "[test-case][class]")
auto j = generate_class_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsModulePackage(j, "app"s));
REQUIRE(IsModulePackage(j, "app"s, "lib1"s));
REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod1"s));
REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod2"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -61,19 +61,20 @@ TEST_CASE("t00072", "[test-case][class]")
auto j = generate_class_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsClass(j, "clanguml::t00072::A"));
REQUIRE(IsClass(j, "clanguml::t00072::B"));
REQUIRE(IsClass(j, "clanguml::t00072::C"));
REQUIRE(IsClass(j, "clanguml::t00072::D"));
REQUIRE(IsEnum(j, "clanguml::t00072::detail::CCC"));
REQUIRE(IsEnum(j, "clanguml::t00072::detail::BBB"));
REQUIRE(IsClass(j, "A"));
REQUIRE(IsClass(j, "B"));
REQUIRE(IsClass(j, "C"));
REQUIRE(IsClass(j, "D"));
REQUIRE(IsEnum(j, "detail::CCC"));
REQUIRE(IsEnum(j, "detail::BBB"));
REQUIRE(IsPackage(j, "app", "module"));
REQUIRE(IsPackage(j, "app:lib1", "module"));
REQUIRE(IsPackage(j, "app:lib2", "module"));
REQUIRE(IsPackage(j, "app:lib1.mod1", "module"));
REQUIRE(IsPackage(j, "app:lib1.mod2", "module"));
REQUIRE(IsModulePackage(j, "app"s));
REQUIRE(IsModulePackage(j, "app"s, ":lib1"s));
REQUIRE(IsModulePackage(j, "app"s, ":lib1"s, "mod1"s));
REQUIRE(IsModulePackage(j, "app"s, ":lib1"s, "mod2"s));
REQUIRE(IsModulePackage(j, "app"s, ":lib2"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -58,6 +58,28 @@ TEST_CASE("t20001", "[test-case][sequence]")
using namespace json;
const auto &A = get_participant(j, "A");
CHECK(A.has_value());
CHECK(A.value()["type"] == "class");
CHECK(A.value()["name"] == "A");
CHECK(A.value()["display_name"] == "A");
CHECK(A.value()["namespace"] == "clanguml::t20001");
CHECK(A.value()["source_location"]["file"] == "t20001.cc");
CHECK(A.value()["source_location"]["line"] == 13);
const auto &tmain = get_participant(j, "tmain()");
CHECK(tmain.has_value());
CHECK(tmain.value()["type"] == "function");
CHECK(tmain.value()["name"] == "tmain");
CHECK(tmain.value()["display_name"] == "tmain()");
CHECK(tmain.value()["namespace"] == "clanguml::t20001");
CHECK(tmain.value()["source_location"]["file"] == "t20001.cc");
CHECK(tmain.value()["source_location"]["line"] == 61);
REQUIRE(HasTitle(j, "Basic sequence diagram example"));
REQUIRE(IsFunctionParticipant(j, "tmain()"));
@@ -76,6 +98,7 @@ TEST_CASE("t20001", "[test-case][sequence]")
save_json(config.output_directory(), diagram->name + ".json", j);
}
{
auto src = generate_sequence_mermaid(diagram, *model);
mermaid::SequenceDiagramAliasMatcher _A(src);

View File

@@ -58,9 +58,8 @@ TEST_CASE("t20014", "[test-case][sequence]")
FindMessage(j, "B", "A", "a1(int,int)"),
FindMessage(j, "tmain()", "B", "b2(int,int)"),
FindMessage(j, "B", "A", "a2(int,int)"),
FindMessage(
j, "tmain()", "C<clanguml::t20014::B,int>", "c1(int,int)"),
FindMessage(j, "C<clanguml::t20014::B,int>", "B", "b1(int,int)")};
FindMessage(j, "tmain()", "C<B,int>", "c1(int,int)"),
FindMessage(j, "C<B,int>", "B", "b1(int,int)")};
REQUIRE(std::is_sorted(messages.begin(), messages.end()));

View File

@@ -57,6 +57,14 @@ TEST_CASE("t20017", "[test-case][sequence]")
using namespace json;
const auto &t20017_cc = get_participant(j, "t20017.cc");
CHECK(t20017_cc.has_value());
CHECK(t20017_cc.value()["type"] == "file");
CHECK(t20017_cc.value()["name"] == "t20017.cc");
CHECK(t20017_cc.value()["display_name"] == "t20017.cc");
std::vector<int> messages = {
FindMessage(j, File("t20017.cc"), File("include/t20017_a.h"),
"a3(int,int)"),

View File

@@ -62,10 +62,9 @@ TEST_CASE("t20018", "[test-case][sequence]")
using namespace json;
std::vector<int> messages = {
FindMessage(j, "tmain()",
"Answer<clanguml::t20018::Factorial<5>,120>", "print()"),
FindMessage(j, "Answer<clanguml::t20018::Factorial<5>,120>",
"Factorial<5>", "print(int)"),
FindMessage(j, "tmain()", "Answer<Factorial<5>,120>", "print()"),
FindMessage(
j, "Answer<Factorial<5>,120>", "Factorial<5>", "print(int)"),
FindMessage(j, "Factorial<5>", "Factorial<4>", "print(int)"),
FindMessage(j, "Factorial<4>", "Factorial<3>", "print(int)"),
FindMessage(j, "Factorial<3>", "Factorial<2>", "print(int)"),

View File

@@ -50,10 +50,10 @@ TEST_CASE("t20019", "[test-case][sequence]")
using namespace json;
std::vector<int> messages = {
FindMessage(j, "tmain()", "Base<clanguml::t20019::D1>", "name()"),
FindMessage(j, "Base<clanguml::t20019::D1>", "D1", "impl()"),
FindMessage(j, "tmain()", "Base<clanguml::t20019::D2>", "name()"),
FindMessage(j, "Base<clanguml::t20019::D2>", "D2", "impl()")};
FindMessage(j, "tmain()", "Base<D1>", "name()"),
FindMessage(j, "Base<D1>", "D1", "impl()"),
FindMessage(j, "tmain()", "Base<D2>", "name()"),
FindMessage(j, "Base<D2>", "D2", "impl()")};
REQUIRE(std::is_sorted(messages.begin(), messages.end()));

View File

@@ -88,17 +88,12 @@ TEST_CASE("t20029", "[test-case][sequence]")
using namespace json;
REQUIRE(!j["participants"].is_null());
std::vector<int> messages = {
FindMessage(j, "tmain()", "ConnectionPool", "connect()"),
FindMessage(j, "tmain()",
"Encoder<clanguml::t20029::Retrier<clanguml::t20029::ConnectionPool>>",
"send(std::string &&)")/*,
FindMessage(j,
"Encoder<clanguml::t20029::Retrier<clanguml::t20029::"
"ConnectionPool>>",
"encode_b64(std::string &&)", "encode_b64(std::string &&)"),
FindMessage(j, "Retrier<clanguml::t20029::ConnectionPool>",
"ConnectionPool", "send(const std::string &)")*/};
FindMessage(j, "tmain()", "Encoder<Retrier<ConnectionPool>>",
"send(std::string &&)")};
REQUIRE(std::is_sorted(messages.begin(), messages.end()));

View File

@@ -56,20 +56,18 @@ TEST_CASE("t20034", "[test-case][sequence]")
using namespace json;
REQUIRE(HasMessageChain(j,
{{"D::d2()", "C::c3()", "void"}, {"C::c3()", "C::c2()", "void"},
{"C::c2()", "B::b2()", "void"},
{"B::b2()", "A::a2()", "void"}}));
{{"d2()", "c3()", "void"}, {"c3()", "c2()", "void"},
{"c2()", "b2()", "void"}, {"b2()", "a2()", "void"}}));
REQUIRE(HasMessageChain(j,
{{"D::d2()", "C::c4()", "void"}, {"C::c4()", "B::b4()", "void"},
{"B::b4()", "B::b2()", "void"},
{"B::b2()", "A::a2()", "void"}}));
REQUIRE(HasMessageChain(j, {{"D::d2()", "A::a2()", "void"}}));
{{"d2()", "c4()", "void"}, {"c4()", "b4()", "void"},
{"b4()", "b2()", "void"}, {"b2()", "a2()", "void"}}));
REQUIRE(HasMessageChain(j, {{"d2()", "a2()", "void"}}));
REQUIRE(HasMessageChain(j,
{{"D::d2()", "C::c1()", "void"}, {"C::c1()", "B::b1()", "void"},
{"B::b1()", "A::a2()", "void"}}));
{{"d2()", "c1()", "void"}, {"c1()", "b1()", "void"},
{"b1()", "a2()", "void"}}));
REQUIRE(HasMessageChain(j,
{{"D::d2()", "C::c2()", "void"}, {"C::c2()", "B::b2()", "void"},
{"B::b2()", "A::a2()", "void"}}));
{{"d2()", "c2()", "void"}, {"c2()", "b2()", "void"},
{"b2()", "a2()", "void"}}));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -56,16 +56,16 @@ TEST_CASE("t20036", "[test-case][sequence]")
using namespace json;
REQUIRE(HasMessageChain(j,
{{"C::c3()", "C::c2()", "void"}, {"C::c2()", "B::b2()", "void"},
{"B::b2()", "A::a2()", "void"}}));
{{"c3()", "c2()", "void"}, {"c2()", "b2()", "void"},
{"b2()", "a2()", "void"}}));
REQUIRE(HasMessageChain(
j, {{"c4()", "b2()", "void"}, {"b2()", "a2()", "void"}}));
REQUIRE(HasMessageChain(j, {{"d3()", "a2()", "void"}}));
REQUIRE(HasMessageChain(j,
{{"C::c4()", "B::b2()", "void"}, {"B::b2()", "A::a2()", "void"}}));
REQUIRE(HasMessageChain(j, {{"D::d3()", "A::a2()", "void"}}));
REQUIRE(HasMessageChain(j,
{{"D::d1()", "C::c2()", "void"}, {"C::c2()", "B::b2()", "void"},
{"B::b2()", "A::a2()", "void"}}));
REQUIRE(HasMessageChain(j,
{{"C::c1()", "B::b1()", "void"}, {"B::b1()", "A::a2()", "void"}}));
{{"d1()", "c2()", "void"}, {"c2()", "b2()", "void"},
{"b2()", "a2()", "void"}}));
REQUIRE(HasMessageChain(
j, {{"c1()", "b1()", "void"}, {"b1()", "a2()", "void"}}));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -70,19 +70,19 @@ TEST_CASE("t30001", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(HasTitle(j, "Basic package diagram example"));
REQUIRE(IsPackage(j, "A"));
REQUIRE(IsPackage(j, "A::AA"));
REQUIRE(IsPackage(j, "A::AA::AAA"));
REQUIRE(IsPackage(j, "A::AA::BBB"));
REQUIRE(IsPackage(j, "A::BB"));
REQUIRE(IsPackage(j, "B"));
REQUIRE(IsPackage(j, "B::AA"));
REQUIRE(IsPackage(j, "B::AA::AAA"));
REQUIRE(IsPackage(j, "B::AA::BBB"));
REQUIRE(IsPackage(j, "B::BB"));
REQUIRE(!IsNamespacePackage(j, "clanguml"s));
REQUIRE(!IsNamespacePackage(j, "t30001"s));
REQUIRE(IsNamespacePackage(j, "A"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "AAA"s));
REQUIRE(IsNamespacePackage(j, "B"s, "AA"s, "AAA"s));
REQUIRE(IsNamespacePackage(j, "B"s, "AA"s, "BBB"s));
REQUIRE(IsNamespacePackage(j, "B"s, "BB"s));
REQUIRE(IsNamespacePackage(j, "B"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -79,45 +79,48 @@ TEST_CASE("t30002", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "A::AA"));
REQUIRE(IsPackage(j, "A::AA::A1"));
REQUIRE(IsPackage(j, "A::AA::A2"));
REQUIRE(IsPackage(j, "A::AA::A3"));
REQUIRE(IsPackage(j, "A::AA::A4"));
REQUIRE(IsPackage(j, "A::AA::A5"));
REQUIRE(IsPackage(j, "A::AA::A6"));
REQUIRE(IsPackage(j, "A::AA::A7"));
REQUIRE(IsPackage(j, "A::AA::A8"));
REQUIRE(IsPackage(j, "A::AA::A9"));
REQUIRE(IsPackage(j, "A::AA::A10"));
REQUIRE(IsPackage(j, "A::AA::A11"));
REQUIRE(IsPackage(j, "A::AA::A12"));
REQUIRE(IsPackage(j, "A::AA::A13"));
REQUIRE(IsPackage(j, "A::AA::A14"));
REQUIRE(IsPackage(j, "A::AA::A15"));
REQUIRE(IsPackage(j, "A::AA::A16"));
REQUIRE(IsPackage(j, "A::AA::A17"));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A1"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A2"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A3"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A4"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A5"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A6"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A7"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A8"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A9"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A10"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A11"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A12"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A13"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A14"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A15"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A16"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A17"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A18"s));
REQUIRE(IsPackage(j, "B::BB::BBB"));
REQUIRE(IsNamespacePackage(j, "B"s, "BB"s, "BBB"s));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A1"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A2"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A3"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A4"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A5"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A6"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A7"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A8"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A9"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A10"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A11"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A12"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A13"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A14"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A15"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A16"));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::A17"));
REQUIRE(IsDependency(j, "BBB", "A1"));
REQUIRE(IsDependency(j, "BBB", "A2"));
REQUIRE(IsDependency(j, "BBB", "A3"));
REQUIRE(IsDependency(j, "BBB", "A4"));
REQUIRE(IsDependency(j, "BBB", "A5"));
REQUIRE(IsDependency(j, "BBB", "A6"));
REQUIRE(IsDependency(j, "BBB", "A7"));
REQUIRE(IsDependency(j, "BBB", "A8"));
REQUIRE(IsDependency(j, "BBB", "A9"));
REQUIRE(IsDependency(j, "BBB", "A10"));
REQUIRE(IsDependency(j, "BBB", "A11"));
REQUIRE(IsDependency(j, "BBB", "A12"));
REQUIRE(IsDependency(j, "BBB", "A13"));
REQUIRE(IsDependency(j, "BBB", "A14"));
REQUIRE(IsDependency(j, "BBB", "A15"));
REQUIRE(IsDependency(j, "BBB", "A16"));
REQUIRE(IsDependency(j, "BBB", "A17"));
REQUIRE(IsDependency(j, "BBB", "A18"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -50,15 +50,16 @@ TEST_CASE("t30003", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "ns1"));
REQUIRE(IsPackage(j, "ns1::ns2_v1_0_0"));
REQUIRE(IsPackage(j, "ns1::ns2_v0_9_0"));
REQUIRE(IsPackage(j, "ns3"));
REQUIRE(IsPackage(j, "ns3::ns1"));
REQUIRE(IsPackage(j, "ns3::ns1::ns2"));
REQUIRE(IsNamespacePackage(j, "ns1"s));
REQUIRE(IsNamespacePackage(j, "ns1"s, "ns2_v1_0_0"s));
REQUIRE(IsNamespacePackage(j, "ns1"s, "ns2_v0_9_0"s));
REQUIRE(IsNamespacePackage(j, "ns3"s));
REQUIRE(IsNamespacePackage(j, "ns3"s, "ns1"s));
REQUIRE(IsNamespacePackage(j, "ns3"s, "ns1"s, "ns2"s));
REQUIRE(IsDeprecated(j, "ns1::ns2_v0_9_0"));
REQUIRE(IsDeprecated(j, "ns2_v0_9_0"));
REQUIRE(IsDeprecated(j, "ns3"));
save_json(config.output_directory(), diagram->name + ".json", j);

View File

@@ -48,13 +48,14 @@ TEST_CASE("t30004", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "A"));
REQUIRE(IsPackage(j, "A::AAA"));
REQUIRE(IsPackage(j, "A::BBB"));
REQUIRE(IsPackage(j, "A::CCC"));
REQUIRE(!IsPackage(j, "A::DDD"));
REQUIRE(IsPackage(j, "A::EEE"));
REQUIRE(IsNamespacePackage(j, "A"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AAA"s));
REQUIRE(IsNamespacePackage(j, "A"s, "BBB"s));
REQUIRE(IsNamespacePackage(j, "A"s, "CCC"s));
REQUIRE(!IsNamespacePackage(j, "A"s, "DDD"s));
REQUIRE(IsNamespacePackage(j, "A"s, "EEE"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -49,19 +49,20 @@ TEST_CASE("t30005", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "A"));
REQUIRE(IsPackage(j, "A::AA"));
REQUIRE(IsPackage(j, "A::AA::AAA"));
REQUIRE(IsPackage(j, "B"));
REQUIRE(IsPackage(j, "B::BB"));
REQUIRE(IsPackage(j, "B::BB::BBB"));
REQUIRE(IsPackage(j, "C"));
REQUIRE(IsPackage(j, "C::CC"));
REQUIRE(IsPackage(j, "C::CC::CCC"));
REQUIRE(IsNamespacePackage(j, "A"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "AAA"s));
REQUIRE(IsNamespacePackage(j, "B"s));
REQUIRE(IsNamespacePackage(j, "B"s, "BB"s));
REQUIRE(IsNamespacePackage(j, "B"s, "BB"s, "BBB"s));
REQUIRE(IsNamespacePackage(j, "C"s));
REQUIRE(IsNamespacePackage(j, "C"s, "CC"s));
REQUIRE(IsNamespacePackage(j, "C"s, "CC"s, "CCC"s));
REQUIRE(IsDependency(j, "B::BB::BBB", "A::AA::AAA"));
REQUIRE(IsDependency(j, "C::CC::CCC", "A::AA::AAA"));
REQUIRE(IsDependency(j, "BBB", "AAA"));
REQUIRE(IsDependency(j, "CCC", "AAA"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -49,10 +49,11 @@ TEST_CASE("t30006", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "A"));
REQUIRE(IsPackage(j, "B"));
REQUIRE(IsPackage(j, "C"));
REQUIRE(IsNamespacePackage(j, "A"s));
REQUIRE(IsNamespacePackage(j, "B"s));
REQUIRE(IsNamespacePackage(j, "C"s));
REQUIRE(IsDependency(j, "A", "B"));
REQUIRE(IsDependency(j, "A", "C"));

View File

@@ -52,14 +52,15 @@ TEST_CASE("t30007", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "A"));
REQUIRE(IsPackage(j, "A::AA"));
REQUIRE(IsPackage(j, "B"));
REQUIRE(IsPackage(j, "C"));
REQUIRE(IsNamespacePackage(j, "A"s));
REQUIRE(IsNamespacePackage(j, "A"s, "AA"s));
REQUIRE(IsNamespacePackage(j, "B"s));
REQUIRE(IsNamespacePackage(j, "C"s));
REQUIRE(IsDependency(j, "A::AA", "B"));
REQUIRE(IsDependency(j, "A::AA", "C"));
REQUIRE(IsDependency(j, "AA", "B"));
REQUIRE(IsDependency(j, "AA", "C"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -58,22 +58,23 @@ TEST_CASE("t30008", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "dependants::A"));
REQUIRE(IsPackage(j, "dependants::B"));
REQUIRE(IsPackage(j, "dependants::C"));
REQUIRE(!IsPackage(j, "dependants::X"));
REQUIRE(IsNamespacePackage(j, "dependants"s, "A"s));
REQUIRE(IsNamespacePackage(j, "dependants"s, "B"s));
REQUIRE(IsNamespacePackage(j, "dependants"s, "C"s));
REQUIRE(!IsNamespacePackage(j, "dependants"s, "X"s));
REQUIRE(IsDependency(j, "dependants::B", "dependants::A"));
REQUIRE(IsDependency(j, "dependants::C", "dependants::B"));
REQUIRE(IsDependency(j, "B", "A"));
REQUIRE(IsDependency(j, "C", "B"));
REQUIRE(IsPackage(j, "dependencies::D"));
REQUIRE(IsPackage(j, "dependencies::E"));
REQUIRE(IsPackage(j, "dependencies::F"));
REQUIRE(!IsPackage(j, "dependencies::Y"));
REQUIRE(IsNamespacePackage(j, "dependencies"s, "D"s));
REQUIRE(IsNamespacePackage(j, "dependencies"s, "E"s));
REQUIRE(IsNamespacePackage(j, "dependencies"s, "F"s));
REQUIRE(!IsNamespacePackage(j, "dependencies"s, "Y"s));
REQUIRE(IsDependency(j, "dependencies::E", "dependencies::D"));
REQUIRE(IsDependency(j, "dependencies::F", "dependencies::E"));
REQUIRE(IsDependency(j, "E", "D"));
REQUIRE(IsDependency(j, "F", "E"));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -50,17 +50,18 @@ TEST_CASE("t30009", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "One"));
REQUIRE(IsPackage(j, "Two"));
REQUIRE(IsPackage(j, "One::A"));
REQUIRE(IsPackage(j, "One::B"));
REQUIRE(IsPackage(j, "One::C"));
REQUIRE(IsPackage(j, "One::D"));
REQUIRE(IsPackage(j, "Two::A"));
REQUIRE(IsPackage(j, "Two::B"));
REQUIRE(IsPackage(j, "Two::C"));
REQUIRE(IsPackage(j, "Two::D"));
REQUIRE(IsNamespacePackage(j, "One"s));
REQUIRE(IsNamespacePackage(j, "Two"s));
REQUIRE(IsNamespacePackage(j, "One"s, "A"s));
REQUIRE(IsNamespacePackage(j, "One"s, "B"s));
REQUIRE(IsNamespacePackage(j, "One"s, "C"s));
REQUIRE(IsNamespacePackage(j, "One"s, "D"s));
REQUIRE(IsNamespacePackage(j, "Two"s, "A"s));
REQUIRE(IsNamespacePackage(j, "Two"s, "B"s));
REQUIRE(IsNamespacePackage(j, "Two"s, "C"s));
REQUIRE(IsNamespacePackage(j, "Two"s, "D"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -54,6 +54,13 @@ TEST_CASE("t30010", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsDirectoryPackage(j, "app"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib1"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib2"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib3"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib4"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -54,6 +54,18 @@ TEST_CASE("t30011", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsDirectoryPackage(j, "app"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib1"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib2"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib3"s));
REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib4"s));
REQUIRE(IsDependency(j, "app"s, "lib1"s));
REQUIRE(IsDependency(j, "app"s, "lib2"s));
REQUIRE(IsDependency(j, "app"s, "lib3"s));
REQUIRE(IsDependency(j, "app"s, "lib4"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -49,12 +49,13 @@ TEST_CASE("t30012", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "t30012.app", "module"));
REQUIRE(IsPackage(j, "t30012.app.lib1", "module"));
REQUIRE(IsPackage(j, "t30012.app.lib2", "module"));
REQUIRE(IsPackage(j, "t30012.app.lib1.mod1", "module"));
REQUIRE(IsPackage(j, "t30012.app.lib1.mod2", "module"));
REQUIRE(IsModulePackage(j, "app"s));
REQUIRE(IsModulePackage(j, "app"s, "lib1"s));
REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod1"s));
REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod2"s));
REQUIRE(IsModulePackage(j, "app"s, "lib2"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -82,26 +82,26 @@ TEST_CASE("t30013", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
REQUIRE(IsPackage(j, "t30013.app", "module"));
REQUIRE(IsPackage(j, "t30013.mod1", "module"));
REQUIRE(IsPackage(j, "t30013.mod2", "module"));
REQUIRE(IsPackage(j, "t30013.mod3", "module"));
REQUIRE(IsPackage(j, "t30013.mod4", "module"));
REQUIRE(IsPackage(j, "t30013.mod5", "module"));
REQUIRE(IsPackage(j, "t30013.mod6", "module"));
REQUIRE(IsPackage(j, "t30013.mod7", "module"));
REQUIRE(IsPackage(j, "t30013.mod8", "module"));
REQUIRE(IsPackage(j, "t30013.mod9", "module"));
REQUIRE(IsPackage(j, "t30013.mod10", "module"));
REQUIRE(IsPackage(j, "t30013.mod11", "module"));
REQUIRE(IsPackage(j, "t30013.mod12", "module"));
REQUIRE(IsPackage(j, "t30013.mod13", "module"));
REQUIRE(IsPackage(j, "t30013.mod14", "module"));
REQUIRE(IsPackage(j, "t30013.mod15", "module"));
REQUIRE(IsPackage(j, "t30013.mod16", "module"));
REQUIRE(IsPackage(j, "t30013.mod17", "module"));
REQUIRE(IsPackage(j, "t30013.mod18", "module"));
using namespace std::string_literals;
REQUIRE(IsModulePackage(j, "app"s));
REQUIRE(IsModulePackage(j, "mod1"s));
REQUIRE(IsModulePackage(j, "mod2"s));
REQUIRE(IsModulePackage(j, "mod3"s));
REQUIRE(IsModulePackage(j, "mod4"s));
REQUIRE(IsModulePackage(j, "mod5"s));
REQUIRE(IsModulePackage(j, "mod6"s));
REQUIRE(IsModulePackage(j, "mod7"s));
REQUIRE(IsModulePackage(j, "mod8"s));
REQUIRE(IsModulePackage(j, "mod9"s));
REQUIRE(IsModulePackage(j, "mod10"s));
REQUIRE(IsModulePackage(j, "mod11"s));
REQUIRE(IsModulePackage(j, "mod12"s));
REQUIRE(IsModulePackage(j, "mod13"s));
REQUIRE(IsModulePackage(j, "mod14"s));
REQUIRE(IsModulePackage(j, "mod15"s));
REQUIRE(IsModulePackage(j, "mod16"s));
REQUIRE(IsModulePackage(j, "mod17"s));
REQUIRE(IsModulePackage(j, "mod18"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -49,12 +49,13 @@ TEST_CASE("t30014", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "t30014.app", "module"));
REQUIRE(IsPackage(j, "t30014.app:lib1", "module"));
REQUIRE(IsPackage(j, "t30014.app:lib2", "module"));
REQUIRE(IsPackage(j, "t30014.app:lib1.mod1", "module"));
REQUIRE(!IsPackage(j, "t30014.app:lib1.mod2", "module"));
REQUIRE(IsModulePackage(j, "app"s));
REQUIRE(IsModulePackage(j, "app"s, ":lib1"s));
REQUIRE(IsModulePackage(j, "app"s, ":lib2"s));
REQUIRE(IsModulePackage(j, "app"s, ":lib1"s, "mod1"s));
REQUIRE(!IsModulePackage(j, "app"s, ":lib1"s, "mod2"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -83,27 +83,28 @@ TEST_CASE("t30015", "[test-case][package]")
auto j = generate_package_json(diagram, *model);
using namespace json;
using namespace std::string_literals;
REQUIRE(IsPackage(j, "t30015.app", "module"));
REQUIRE(IsPackage(j, "t30015.lib1", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod1", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod2", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod3", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod4", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod5", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod6", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod7", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod8", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod9", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod10", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod11", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod12", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod13", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod14", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod15", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod16", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod17", "module"));
REQUIRE(IsPackage(j, "t30015.lib1:mod18", "module"));
REQUIRE(IsModulePackage(j, "app"s));
REQUIRE(IsModulePackage(j, "lib1"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod1"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod2"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod3"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod4"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod5"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod6"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod7"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod8"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod9"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod10"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod11"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod12"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod13"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod14"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod15"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod16"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod17"s));
REQUIRE(IsModulePackage(j, "lib1"s, ":mod18"s));
save_json(config.output_directory(), diagram->name + ".json", j);
}

View File

@@ -1227,8 +1227,8 @@ std::optional<nlohmann::json> get_participant(
if (!j.contains("participants"))
return {};
for (const nlohmann::json &e : j["participants"]) {
if (e["name"] == name)
for (const nlohmann::json &e : j.at("participants")) {
if (e["display_name"] == name)
return {e};
}
@@ -1259,36 +1259,6 @@ auto get_relationship(const nlohmann::json &j, const std::string &from,
std::string expand_name(const nlohmann::json &j, const std::string &name)
{
using clanguml::class_diagram::model::path_type;
using clanguml::common::model::path;
using config::package_type_t;
if (!j.contains("package_type") ||
j["package_type"] == to_string(package_type_t::kNamespace)) {
if (!j.contains("using_namespace"))
return name;
auto full_path = path{j["using_namespace"].get<std::string>()};
full_path |= path{name};
return full_path.to_string();
}
if (j["package_type"] == to_string(package_type_t::kModule)) {
return name;
// if (!j.contains("using_module"))
// return name;
//
// auto full_path =
// path{j["using_module"].get<std::string>(),
// path_type::kModule};
// full_path |= path{name, path_type::kModule};
//
// auto res = full_path.to_string();
//
// return res;
}
return name;
}
@@ -1350,6 +1320,65 @@ bool IsPackage(const nlohmann::json &j, const std::string &name,
return e && e->at("type") == type;
}
struct NamespacePackage { };
struct ModulePackage { };
struct DirectoryPackage { };
template <typename PackageT> std::string package_type_name();
template <> std::string package_type_name<NamespacePackage>()
{
return "namespace";
}
template <> std::string package_type_name<ModulePackage>() { return "module"; }
template <> std::string package_type_name<DirectoryPackage>()
{
return "directory";
}
template <typename PackageT, typename... Args>
bool IsPackagePath(
const nlohmann::json &j, const std::string &head, Args... args)
{
if constexpr (sizeof...(Args) == 0) {
auto e = get_element(j, expand_name(j, head));
return e && e->at("type") == package_type_name<PackageT>();
}
else {
auto e = get_element(j, head);
if (!e.has_value())
return false;
return IsPackagePath<PackageT>(*e, args...);
}
}
template <typename... Args>
bool IsNamespacePackage(
const nlohmann::json &j, const std::string &head, Args... args)
{
return IsPackagePath<NamespacePackage>(
j, head, std::forward<Args>(args)...);
}
template <typename... Args>
bool IsDirectoryPackage(
const nlohmann::json &j, const std::string &head, Args... args)
{
return IsPackagePath<DirectoryPackage>(
j, head, std::forward<Args>(args)...);
}
template <typename... Args>
bool IsModulePackage(
const nlohmann::json &j, const std::string &head, Args... args)
{
return IsPackagePath<ModulePackage>(j, head, std::forward<Args>(args)...);
}
bool IsFolder(const nlohmann::json &j, const std::string &name)
{
auto e = get_element(j, name);
@@ -1624,11 +1653,30 @@ struct message_test_spec_t {
void from_json(const nlohmann::json &j, message_test_spec_t &p)
{
j.at("from").at("activity_name").get_to(p.from);
j.at("to").at("activity_name").get_to(p.to);
j.at("from").at("activity_id").get_to(p.from);
j.at("to").at("activity_id").get_to(p.to);
j.at("return_type").get_to(p.return_type);
}
std::string get_activity_id(
const nlohmann::json &j, const std::string &display_name)
{
for (const auto &p : j["participants"]) {
if (p.contains("activities")) {
for (const auto &a : p["activities"]) {
if (a["display_name"] == display_name) {
return a["id"];
}
}
}
else if (p["display_name"] == display_name) {
return p["id"];
}
}
return {};
}
bool HasMessageChain(
const nlohmann::json &j, std::vector<message_test_spec_t> msgs)
{
@@ -1637,8 +1685,8 @@ bool HasMessageChain(
std::back_inserter(full_name_messages),
[&j](const message_test_spec_t &m) {
auto res = m;
res.from = expand_name(j, m.from);
res.to = expand_name(j, m.to);
res.from = get_activity_id(j, m.from);
res.to = get_activity_id(j, m.to);
return res;
});