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