Merge pull request #285 from bkryza/refactor-id_t

This commit is contained in:
Bartek Kryza
2024-06-06 00:14:26 +02:00
committed by GitHub
65 changed files with 711 additions and 492 deletions

View File

@@ -163,7 +163,7 @@ format:
.PHONY: debug_tidy
tidy: debug_tidy
run-clang-tidy-15 -extra-arg=-Wno-unknown-warning-option -j $(NUMPROC) -p debug_tidy ./src
run-clang-tidy-17 -extra-arg=-Wno-unknown-warning-option -j $(NUMPROC) -p debug_tidy ./src
.PHONY: check-formatting
check-formatting:

View File

@@ -85,7 +85,7 @@ void to_json(nlohmann::json &j, const class_method &c)
void to_json(nlohmann::json &j, const class_parent &c)
{
j["is_virtual"] = c.is_virtual();
j["id"] = std::to_string(c.id());
j["id"] = std::to_string(c.id().value());
if (c.access() != common::model::access_t::kNone)
j["access"] = to_string(c.access());
j["name"] = c.name();
@@ -331,7 +331,7 @@ void generator::generate_relationships(
}
nlohmann::json rel = r;
rel["source"] = std::to_string(c.id());
rel["source"] = std::to_string(c.id().value());
parent["relationships"].push_back(rel);
}
@@ -340,7 +340,7 @@ void generator::generate_relationships(
common::model::relationship r(
relationship_t::kExtension, b.id(), b.access());
nlohmann::json rel = r;
rel["source"] = std::to_string(c.id());
rel["source"] = std::to_string(c.id().value());
parent["relationships"].push_back(rel);
}
}
@@ -362,7 +362,7 @@ void generator::generate_relationships(
}
nlohmann::json rel = r;
rel["source"] = std::to_string(c.id());
rel["source"] = std::to_string(c.id().value());
parent["relationships"].push_back(rel);
}
}
@@ -383,7 +383,7 @@ void generator::generate_relationships(
}
nlohmann::json rel = r;
rel["source"] = std::to_string(c.id());
rel["source"] = std::to_string(c.id().value());
parent["relationships"].push_back(rel);
}
}

View File

@@ -24,6 +24,7 @@
namespace clanguml::class_diagram::generators::mermaid {
using clanguml::common::eid_t;
using clanguml::common::generators::mermaid::indent;
using clanguml::common::generators::mermaid::render_name;
@@ -405,7 +406,7 @@ void generator::generate_relationships(
LOG_DBG("== Processing relationship {}", to_string(r.type()));
std::stringstream relstr;
clanguml::common::id_t destination{0};
eid_t destination{};
try {
destination = r.destination();
@@ -513,7 +514,7 @@ void generator::generate_relationships(
LOG_DBG("== Processing relationship {}", to_string(r.type()));
std::stringstream relstr;
clanguml::common::id_t destination{0};
eid_t destination{};
try {
destination = r.destination();
@@ -584,7 +585,7 @@ void generator::generate_relationships(const enum_ &e, std::ostream &ostr) const
if (!model().should_include(r.type()))
continue;
clanguml::common::id_t destination{0};
eid_t destination{};
std::stringstream relstr;
try {
destination = r.destination();

View File

@@ -488,7 +488,7 @@ void generator::generate_relationships(
plantuml_common::to_plantuml(r, config()));
std::stringstream relstr;
clanguml::common::id_t destination{0};
eid_t destination{};
try {
destination = r.destination();
@@ -583,7 +583,7 @@ void generator::generate_relationships(
LOG_DBG("== Processing relationship {}", to_string(r.type()));
std::stringstream relstr;
clanguml::common::id_t destination{0};
eid_t destination{};
try {
destination = r.destination();
@@ -664,7 +664,7 @@ void generator::generate_relationships(const enum_ &e, std::ostream &ostr) const
if (!model().should_include(r.type()))
continue;
clanguml::common::id_t destination{0};
eid_t destination{};
std::stringstream relstr;
try {
destination = r.destination();

View File

@@ -52,6 +52,7 @@ using clanguml::class_diagram::model::class_member;
using clanguml::class_diagram::model::class_method;
using clanguml::class_diagram::model::concept_;
using clanguml::class_diagram::model::enum_;
using clanguml::common::eid_t;
using clanguml::common::model::access_t;
using clanguml::common::model::package;
using clanguml::common::model::relationship;

View File

@@ -185,9 +185,7 @@ struct hash<std::reference_wrapper<clanguml::class_diagram::model::class_>> {
const std::reference_wrapper<clanguml::class_diagram::model::class_>
&key) const
{
using clanguml::common::id_t;
return std::hash<id_t>{}(key.get().id());
return std::hash<uint64_t>{}(key.get().id().value());
}
};
} // namespace std

View File

@@ -24,9 +24,9 @@ void class_parent::set_name(const std::string &name) { name_ = name; }
std::string class_parent::name() const { return name_; }
void class_parent::set_id(clanguml::common::id_t id) { id_ = id; }
void class_parent::set_id(eid_t id) { id_ = id; }
clanguml::common::id_t class_parent::id() const noexcept { return id_; }
eid_t class_parent::id() const noexcept { return id_; }
void class_parent::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; }

View File

@@ -25,6 +25,8 @@
namespace clanguml::class_diagram::model {
using clanguml::common::eid_t;
/**
* @brief Class parent relationship model.
*
@@ -59,14 +61,14 @@ public:
*
* @param id Id of the parent class.
*/
void set_id(clanguml::common::id_t id);
void set_id(eid_t id);
/**
* @brief Get the id of class parent.
*
* @return Id of the parent class.
*/
clanguml::common::id_t id() const noexcept;
eid_t id() const noexcept;
/**
* @brief Set whether the parent is virtual.
@@ -97,7 +99,7 @@ public:
common::model::access_t access() const;
private:
clanguml::common::id_t id_{};
eid_t id_{};
std::string name_;
bool is_virtual_{false};
common::model::access_t access_{common::model::access_t::kPublic};

View File

@@ -74,7 +74,7 @@ common::optional_ref<clanguml::common::model::diagram_element> diagram::get(
}
common::optional_ref<clanguml::common::model::diagram_element> diagram::get(
const clanguml::common::id_t id) const
const eid_t id) const
{
common::optional_ref<clanguml::common::model::diagram_element> res;
@@ -153,7 +153,7 @@ void diagram::get_parents(
}
}
bool diagram::has_element(clanguml::common::id_t id) const
bool diagram::has_element(eid_t id) const
{
const auto has_class = std::any_of(classes().begin(), classes().end(),
[id](const auto &c) { return c.get().id() == id; });
@@ -171,7 +171,7 @@ bool diagram::has_element(clanguml::common::id_t id) const
[id](const auto &c) { return c.get().id() == id; });
}
std::string diagram::to_alias(clanguml::common::id_t id) const
std::string diagram::to_alias(eid_t id) const
{
LOG_DBG("Looking for alias for {}", id);
@@ -224,12 +224,12 @@ inja::json diagram::context() const
void diagram::remove_redundant_dependencies()
{
using common::id_t;
using common::eid_t;
using common::model::relationship;
using common::model::relationship_t;
for (auto &c : element_view<class_>::view()) {
std::set<id_t> dependency_relationships_to_remove;
std::set<eid_t> dependency_relationships_to_remove;
for (auto &r : c.get().relationships()) {
if (r.type() != relationship_t::kDependency)

View File

@@ -103,7 +103,7 @@ public:
* @param id Element id.
* @return Optional reference to a diagram element.
*/
opt_ref<diagram_element> get(common::id_t id) const override;
opt_ref<diagram_element> get(eid_t id) const override;
/**
* @brief Get list of references to classes in the diagram model.
@@ -172,7 +172,7 @@ public:
* @param id Id of the element
* @return Optional reference to a diagram element
*/
template <typename ElementT> opt_ref<ElementT> find(common::id_t id) const;
template <typename ElementT> opt_ref<ElementT> find(eid_t id) const;
/**
* @brief Get reference to vector of elements of specific type
@@ -218,7 +218,7 @@ public:
* @param id Id of the diagram element.
* @return PlantUML alias.
*/
std::string to_alias(common::id_t id) const;
std::string to_alias(eid_t id) const;
/**
* @brief Given an initial set of classes, add all their parents to the
@@ -235,7 +235,7 @@ public:
* @param id Id of the element.
* @return True, if diagram contains an element with a specific id.
*/
bool has_element(common::id_t id) const override;
bool has_element(eid_t id) const override;
/**
* @brief Remove redundant dependency relationships
@@ -431,8 +431,7 @@ std::vector<opt_ref<ElementT>> diagram::find(
return result;
}
template <typename ElementT>
opt_ref<ElementT> diagram::find(common::id_t id) const
template <typename ElementT> opt_ref<ElementT> diagram::find(eid_t id) const
{
for (const auto &element : element_view<ElementT>::view()) {
if (element.get().id() == id) {

View File

@@ -123,14 +123,14 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
const auto *parent = enm->getParent();
// Id of parent class or struct in which this enum is potentially nested
std::optional<common::id_t> parent_id_opt;
std::optional<eid_t> parent_id_opt;
if (parent != nullptr) {
const auto *parent_record_decl =
clang::dyn_cast<clang::RecordDecl>(parent);
if (parent_record_decl != nullptr) {
int64_t local_id = parent_record_decl->getID();
eid_t local_id{parent_record_decl->getID()};
// First check if the parent has been added to the diagram as
// regular class
@@ -222,8 +222,8 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
if (!template_specialization.template_specialization_found()) {
// Only do this if we haven't found a better specialization during
// construction of the template specialization
const auto maybe_id =
id_mapper().get_global_id(cls->getSpecializedTemplate()->getID());
const eid_t ast_id{cls->getSpecializedTemplate()->getID()};
const auto maybe_id = id_mapper().get_global_id(ast_id);
if (maybe_id.has_value())
template_specialization.add_relationship(
{relationship_t::kInstantiation, maybe_id.value()});
@@ -621,8 +621,8 @@ void translation_unit_visitor::process_concept_specialization_relationships(
should_include(cpt)) {
const auto cpt_name = cpt->getNameAsString();
const auto maybe_id = id_mapper().get_global_id(cpt->getID());
const eid_t ast_id{cpt->getID()};
const auto maybe_id = id_mapper().get_global_id(ast_id);
if (!maybe_id)
return;
@@ -707,7 +707,8 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
if (cls->isTemplated() && (cls->getDescribedTemplate() != nullptr)) {
// If the described templated of this class is already in the model
// skip it:
if (id_mapper().get_global_id(cls->getDescribedTemplate()->getID()))
const eid_t ast_id{cls->getDescribedTemplate()->getID()};
if (id_mapper().get_global_id(ast_id))
return true;
}
@@ -868,7 +869,7 @@ void translation_unit_visitor::process_record_parent(
{
const auto *parent = cls->getParent();
std::optional<common::id_t> id_opt;
std::optional<eid_t> id_opt;
auto parent_ns = ns;
if (parent != nullptr) {
@@ -878,19 +879,19 @@ void translation_unit_visitor::process_record_parent(
if (parent_record_decl != nullptr) {
parent_ns = common::get_tag_namespace(*parent_record_decl);
int64_t local_id = parent_record_decl->getID();
eid_t ast_id{parent_record_decl->getID()};
// First check if the parent has been added to the diagram as
// regular class
id_opt = id_mapper().get_global_id(local_id);
id_opt = id_mapper().get_global_id(ast_id);
// If not, check if the parent template declaration is in the
// model
if (!id_opt) {
if (parent_record_decl->getDescribedTemplate() != nullptr) {
local_id =
ast_id =
parent_record_decl->getDescribedTemplate()->getID();
id_opt = id_mapper().get_global_id(local_id);
id_opt = id_mapper().get_global_id(ast_id);
}
}
}
@@ -916,7 +917,7 @@ void translation_unit_visitor::process_record_parent(
std::string destination_multiplicity_str{};
if (destination_multiplicity.has_value()) {
destination_multiplicity_str =
std::to_string(*destination_multiplicity); // NOLINT
std::to_string(*destination_multiplicity);
}
parent_class.value().add_relationship(
@@ -1672,8 +1673,8 @@ void translation_unit_visitor::add_relationships(class_ &c,
}
if (!mulitplicity_provided_in_comment &&
field.destination_multiplicity().has_value()) {
r.set_multiplicity_destination(std::to_string(
*field.destination_multiplicity())); // NOLINT
r.set_multiplicity_destination(
std::to_string(*field.destination_multiplicity()));
}
r.set_style(field.style_spec());
@@ -1993,7 +1994,9 @@ void translation_unit_visitor::resolve_local_to_global_ids()
// to elements
for (const auto &cls : diagram().classes()) {
for (auto &rel : cls.get().relationships()) {
const auto maybe_id = id_mapper().get_global_id(rel.destination());
if (!rel.destination().is_global()) {
const auto maybe_id =
id_mapper().get_global_id(rel.destination());
if (maybe_id) {
LOG_DBG("= Resolved instantiation destination from local "
"id {} to global id {}",
@@ -2002,9 +2005,12 @@ void translation_unit_visitor::resolve_local_to_global_ids()
}
}
}
}
for (const auto &cpt : diagram().concepts()) {
for (auto &rel : cpt.get().relationships()) {
const auto maybe_id = id_mapper().get_global_id(rel.destination());
if (!rel.destination().is_global()) {
const auto maybe_id =
id_mapper().get_global_id(rel.destination());
if (maybe_id) {
LOG_DBG("= Resolved instantiation destination from local "
"id {} to global id {}",
@@ -2013,9 +2019,12 @@ void translation_unit_visitor::resolve_local_to_global_ids()
}
}
}
}
for (const auto &enm : diagram().enums()) {
for (auto &rel : enm.get().relationships()) {
const auto maybe_id = id_mapper().get_global_id(rel.destination());
if (!rel.destination().is_global()) {
const auto maybe_id =
id_mapper().get_global_id(rel.destination());
if (maybe_id) {
LOG_DBG("= Resolved instantiation destination from local "
"id {} to global id {}",
@@ -2025,6 +2034,7 @@ void translation_unit_visitor::resolve_local_to_global_ids()
}
}
}
}
void translation_unit_visitor::finalize()
{
@@ -2166,7 +2176,7 @@ void translation_unit_visitor::add_concept(std::unique_ptr<concept_> &&c)
void translation_unit_visitor::find_instantiation_relationships(
common::model::template_element &template_instantiation_base,
const std::string &full_name, common::id_t templated_decl_id)
const std::string &full_name, eid_t templated_decl_id)
{
auto &template_instantiation = dynamic_cast<class_diagram::model::class_ &>(
template_instantiation_base);
@@ -2177,7 +2187,7 @@ void translation_unit_visitor::find_instantiation_relationships(
std::string best_match_full_name{};
auto full_template_name = template_instantiation.full_name(false);
int best_match{};
common::id_t best_match_id{0};
eid_t best_match_id{};
for (const auto templ : diagram().classes()) {
if (templ.get() == template_instantiation)
@@ -2196,9 +2206,9 @@ void translation_unit_visitor::find_instantiation_relationships(
}
auto templated_decl_global_id =
id_mapper().get_global_id(templated_decl_id).value_or(0);
id_mapper().get_global_id(templated_decl_id).value_or(eid_t{});
if (best_match_id > 0) {
if (best_match_id.value() > 0) {
destination = best_match_full_name;
template_instantiation.add_relationship(
{common::model::relationship_t::kInstantiation, best_match_id});

View File

@@ -45,6 +45,7 @@ using clanguml::class_diagram::model::concept_;
using clanguml::class_diagram::model::diagram;
using clanguml::class_diagram::model::enum_;
using clanguml::class_diagram::model::method_parameter;
using clanguml::common::eid_t;
using clanguml::common::model::access_t;
using clanguml::common::model::namespace_;
using clanguml::common::model::relationship;
@@ -149,7 +150,7 @@ public:
void find_instantiation_relationships(
common::model::template_element &template_instantiation_base,
const std::string &full_name, common::id_t templated_decl_id);
const std::string &full_name, eid_t templated_decl_id);
private:
/**
@@ -432,8 +433,7 @@ private:
template_builder_t template_builder_;
std::map<common::id_t,
std::unique_ptr<clanguml::class_diagram::model::class_>>
std::map<eid_t, std::unique_ptr<clanguml::class_diagram::model::class_>>
forward_declarations_;
std::map<int64_t /* local anonymous struct id */,

View File

@@ -415,49 +415,53 @@ bool is_subexpr_of(const clang::Stmt *parent_stmt, const clang::Stmt *sub_stmt)
[sub_stmt](const auto *e) { return is_subexpr_of(e, sub_stmt); });
}
template <> id_t to_id(const std::string &full_name)
template <> eid_t to_id(const std::string &full_name)
{
return static_cast<id_t>(std::hash<std::string>{}(full_name) >> 3U);
return static_cast<eid_t>(
static_cast<uint64_t>(std::hash<std::string>{}(full_name)));
}
id_t to_id(const clang::QualType &type, const clang::ASTContext &ctx)
eid_t to_id(const clang::QualType &type, const clang::ASTContext &ctx)
{
return to_id(common::to_string(type, ctx));
}
template <> id_t to_id(const clang::NamespaceDecl &declaration)
template <> eid_t to_id(const clang::NamespaceDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::RecordDecl &declaration)
template <> eid_t to_id(const clang::RecordDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::EnumDecl &declaration)
template <> eid_t to_id(const clang::EnumDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::TagDecl &declaration)
template <> eid_t to_id(const clang::TagDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::CXXRecordDecl &declaration)
template <> eid_t to_id(const clang::CXXRecordDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::EnumType &t) { return to_id(*t.getDecl()); }
template <> eid_t to_id(const clang::EnumType &t)
{
return to_id(*t.getDecl());
}
template <> id_t to_id(const std::filesystem::path &file)
template <> eid_t to_id(const std::filesystem::path &file)
{
return to_id(file.lexically_normal().string());
}
template <> id_t to_id(const clang::TemplateArgument &template_argument)
template <> eid_t to_id(const clang::TemplateArgument &template_argument)
{
if (template_argument.getKind() == clang::TemplateArgument::Type) {
if (const auto *enum_type =

View File

@@ -178,27 +178,27 @@ bool is_subexpr_of(const clang::Stmt *parent_stmt, const clang::Stmt *sub_stmt);
*
* @{
*/
template <typename T> id_t to_id(const T &declaration);
template <typename T> eid_t to_id(const T &declaration);
template <> id_t to_id(const std::string &full_name);
template <> eid_t to_id(const std::string &full_name);
id_t to_id(const clang::QualType &type, const clang::ASTContext &ctx);
eid_t to_id(const clang::QualType &type, const clang::ASTContext &ctx);
template <> id_t to_id(const clang::NamespaceDecl &declaration);
template <> eid_t to_id(const clang::NamespaceDecl &declaration);
template <> id_t to_id(const clang::CXXRecordDecl &declaration);
template <> eid_t to_id(const clang::CXXRecordDecl &declaration);
template <> id_t to_id(const clang::RecordDecl &declaration);
template <> eid_t to_id(const clang::RecordDecl &declaration);
template <> id_t to_id(const clang::EnumDecl &declaration);
template <> eid_t to_id(const clang::EnumDecl &declaration);
template <> id_t to_id(const clang::TagDecl &declaration);
template <> eid_t to_id(const clang::TagDecl &declaration);
template <> id_t to_id(const clang::EnumType &type);
template <> eid_t to_id(const clang::EnumType &type);
template <> id_t to_id(const clang::TemplateSpecializationType &type);
template <> eid_t to_id(const clang::TemplateSpecializationType &type);
template <> id_t to_id(const std::filesystem::path &type);
template <> eid_t to_id(const std::filesystem::path &type);
/** @} */ // end of to_id
/**

View File

@@ -22,7 +22,6 @@
#include "class_diagram/generators/plantuml/class_diagram_generator.h"
#include "cli/cli_handler.h"
#include "common/compilation_database.h"
#include "common/generators/generators.h"
#include "common/model/diagram_filter.h"
#include "config/config.h"
#include "include_diagram/generators/json/include_diagram_generator.h"

View File

@@ -31,7 +31,7 @@ void to_json(nlohmann::json &j, const source_location &sl)
void to_json(nlohmann::json &j, const element &c)
{
j = json{{"id", std::to_string(c.id())},
j = json{{"id", std::to_string(c.id().value())},
{"name", common::generators::json::render_name(c.name())},
{"namespace", c.get_namespace().to_string()}, {"type", c.type_name()},
{"display_name",
@@ -62,7 +62,7 @@ void to_json(nlohmann::json &j, const template_parameter &c)
void to_json(nlohmann::json &j, const relationship &c)
{
j["type"] = to_string(c.type());
j["destination"] = std::to_string(c.destination());
j["destination"] = std::to_string(c.destination().value());
if (!c.multiplicity_source().empty())
j["multiplicity_source"] = c.multiplicity_source();
if (!c.multiplicity_destination().empty())

View File

@@ -70,7 +70,7 @@ public:
* @return Optional reference to a diagram element.
*/
virtual common::optional_ref<clanguml::common::model::diagram_element> get(
common::id_t id) const = 0;
eid_t id) const = 0;
/**
* Return optional reference to a diagram_element by name and namespace.
@@ -152,7 +152,7 @@ public:
// Disallow std::string overload
bool should_include(const std::string &s) const = delete;
virtual bool has_element(const common::id_t /*id*/) const { return false; }
virtual bool has_element(const eid_t /*id*/) const { return false; }
virtual bool should_include(
const namespace_ &ns, const std::string &name) const;

View File

@@ -26,25 +26,26 @@ namespace clanguml::common::model {
diagram_element::diagram_element() = default;
common::id_t diagram_element::id() const { return id_; }
const eid_t &diagram_element::id() const { return id_; }
void diagram_element::set_id(common::id_t id) { id_ = id; }
void diagram_element::set_id(eid_t id) { id_ = id; }
std::optional<id_t> diagram_element::parent_element_id() const
std::optional<eid_t> diagram_element::parent_element_id() const
{
return parent_element_id_;
}
void diagram_element::set_parent_element_id(common::id_t id)
void diagram_element::set_parent_element_id(eid_t id)
{
parent_element_id_ = id;
}
std::string diagram_element::alias() const
{
assert(id_ >= 0);
// Only generate alias for global id's
assert(id_.is_global());
return fmt::format("C_{:022}", id_);
return fmt::format("C_{:022}", id_.value());
}
void diagram_element::add_relationship(relationship &&cr)

View File

@@ -53,28 +53,28 @@ public:
*
* @return Elements id.
*/
common::id_t id() const;
const eid_t &id() const;
/**
* Set elements id.
*
* @param id Elements id.
*/
void set_id(common::id_t id);
void set_id(eid_t id);
/**
* Get elements parent package id.
*
* @return Parent package id if element is nested.
*/
std::optional<id_t> parent_element_id() const;
std::optional<eid_t> parent_element_id() const;
/**
* Set elements parent package id.
*
* @param id Id of parent package.
*/
void set_parent_element_id(id_t id);
void set_parent_element_id(eid_t id);
/**
* @brief Return elements' diagram alias.
@@ -185,8 +185,8 @@ public:
void complete(bool completed);
private:
id_t id_{0};
std::optional<id_t> parent_element_id_{0};
eid_t id_{};
std::optional<eid_t> parent_element_id_{};
std::string name_;
std::vector<relationship> relationships_;
bool nested_{false};

View File

@@ -81,7 +81,7 @@ const clanguml::common::optional_ref<common::model::source_file> get(
}
template <>
clanguml::common::id_t destination_comparator<common::model::source_file>(
eid_t destination_comparator<common::model::source_file>(
const common::model::source_file &f)
{
return f.id();
@@ -690,7 +690,7 @@ void context_filter::initialize_effective_context(
// Now repeat radius times - extend the effective context with elements
// matching in direct relationship to what is in context
auto radius_counter = context.radius;
std::set<clanguml::common::id_t> current_iteration_context;
std::set<eid_t> current_iteration_context;
while (radius_counter > 0 && effective_context_extended) {
// If at any iteration the effective context was not extended - we
@@ -725,8 +725,8 @@ void context_filter::initialize_effective_context(
}
void context_filter::find_elements_inheritance_relationship(const diagram &d,
std::set<id_t> &effective_context,
std::set<clanguml::common::id_t> &current_iteration_context) const
std::set<eid_t> &effective_context,
std::set<eid_t> &current_iteration_context) const
{
const auto &cd = dynamic_cast<const class_diagram::model::diagram &>(d);

View File

@@ -37,6 +37,8 @@
namespace clanguml::common::model {
using clanguml::common::eid_t;
/**
* Diagram filters can be add in 2 modes:
* - inclusive - the elements that match are included in the diagram
@@ -55,14 +57,12 @@ template <typename ElementT, typename DiagramT>
const clanguml::common::optional_ref<ElementT> get(
const DiagramT &d, const std::string &full_name);
template <typename ElementT> int64_t destination_comparator(const ElementT &e)
template <typename ElementT> eid_t destination_comparator(const ElementT &e)
{
return e.id();
}
template <>
clanguml::common::id_t destination_comparator(
const common::model::source_file &f);
template <> eid_t destination_comparator(const common::model::source_file &f);
} // namespace detail
/**
@@ -492,8 +492,8 @@ private:
template <typename ElementT>
void find_elements_in_direct_relationship(const diagram &d,
std::set<id_t> &effective_context,
std::set<clanguml::common::id_t> &current_iteration_context) const
std::set<eid_t> &effective_context,
std::set<eid_t> &current_iteration_context) const
{
static_assert(std::is_same_v<ElementT, class_diagram::model::class_> ||
std::is_same_v<ElementT, class_diagram::model::enum_> ||
@@ -534,8 +534,8 @@ private:
}
void find_elements_inheritance_relationship(const diagram &d,
std::set<id_t> &effective_context,
std::set<clanguml::common::id_t> &current_iteration_context) const;
std::set<eid_t> &effective_context,
std::set<eid_t> &current_iteration_context) const;
std::vector<config::context_config> context_;
@@ -543,7 +543,7 @@ private:
* Represents all elements which should belong to the diagram based
* on this filter. It is populated by the initialize() method.
*/
mutable std::vector<std::set<clanguml::common::id_t>> effective_contexts_;
mutable std::vector<std::set<eid_t>> effective_contexts_;
/*! Flag to mark whether the filter context has been computed */
mutable bool initialized_{false};

View File

@@ -21,6 +21,8 @@
namespace clanguml::common::model {
using clanguml::common::eid_t;
/**
* Provides type based views over elements in a diagram.
*
@@ -58,7 +60,7 @@ public:
*
* @return
*/
common::optional_ref<T> get(clanguml::common::id_t id) const
common::optional_ref<T> get(eid_t id) const
{
for (const auto &e : elements_) {
if (e.get().id() == id) {

View File

@@ -89,9 +89,9 @@ struct hash<std::reference_wrapper<clanguml::common::model::package>> {
const std::reference_wrapper<clanguml::common::model::package> &key)
const
{
using clanguml::common::id_t;
using clanguml::common::eid_t;
return std::hash<id_t>{}(key.get().id());
return key.get().id().value();
}
};
} // namespace std

View File

@@ -22,7 +22,7 @@
namespace clanguml::common::model {
relationship::relationship(relationship_t type, int64_t destination,
relationship::relationship(relationship_t type, eid_t destination,
access_t access, std::string label, std::string multiplicity_source,
std::string multiplicity_destination)
: type_{type}
@@ -38,15 +38,12 @@ void relationship::set_type(relationship_t type) noexcept { type_ = type; }
relationship_t relationship::type() const noexcept { return type_; }
void relationship::set_destination(int64_t destination)
void relationship::set_destination(eid_t destination)
{
destination_ = destination;
}
clanguml::common::id_t relationship::destination() const
{
return destination_;
}
eid_t relationship::destination() const { return destination_; }
void relationship::set_multiplicity_source(
const std::string &multiplicity_source)

View File

@@ -25,6 +25,8 @@
namespace clanguml::common::model {
using clanguml::common::eid_t;
/**
* @brief Class representing any relationship other than inheritance
*
@@ -47,7 +49,7 @@ public:
* @param multiplicity_source Multiplicity at the source
* @param multiplicity_destination Multiplicity at the destination
*/
relationship(relationship_t type, clanguml::common::id_t destination,
relationship(relationship_t type, eid_t destination,
access_t access = access_t::kPublic, std::string label = "",
std::string multiplicity_source = "",
std::string multiplicity_destination = "");
@@ -74,14 +76,14 @@ public:
*
* @param destination Target element id.
*/
void set_destination(int64_t destination);
void set_destination(eid_t destination);
/**
* Get the id of the target element of this relationship.
*
* @return Target element id.
*/
clanguml::common::id_t destination() const;
eid_t destination() const;
/**
* Set the relationship multiplicity at the source.
@@ -144,7 +146,7 @@ public:
private:
relationship_t type_;
clanguml::common::id_t destination_;
eid_t destination_;
std::string multiplicity_source_;
std::string multiplicity_destination_;
std::string label_;

View File

@@ -210,9 +210,7 @@ struct hash<std::reference_wrapper<clanguml::common::model::source_file>> {
const std::reference_wrapper<clanguml::common::model::source_file> &key)
const
{
using clanguml::common::id_t;
return std::hash<id_t>{}(key.get().id());
return key.get().id().value();
}
};
} // namespace std

View File

@@ -505,7 +505,7 @@ std::string template_parameter::to_string(
}
bool template_parameter::find_nested_relationships(
std::vector<std::pair<int64_t, common::model::relationship_t>>
std::vector<std::pair<eid_t, common::model::relationship_t>>
&nested_relationships,
common::model::relationship_t hint,
const std::function<bool(const std::string &full_name)> &should_include)

View File

@@ -19,6 +19,7 @@
#include "common/model/enums.h"
#include "common/model/namespace.h"
#include "common/types.h"
#include <deque>
#include <optional>
@@ -28,6 +29,8 @@
namespace clanguml::common::model {
using clanguml::common::eid_t;
/**
* Type of template parameter or argument.
*/
@@ -165,14 +168,14 @@ public:
*
* @param id Id of parameter
*/
void set_id(const int64_t id) { id_ = id; }
void set_id(const eid_t &id) { id_ = id; }
/**
* Get id of the template parameter
*
* @return Id of the template parameter
*/
const std::optional<int64_t> &id() const { return id_; }
const std::optional<eid_t> &id() const { return id_; }
/**
* Set the name of the template parameter
@@ -388,7 +391,7 @@ public:
* @return
*/
bool find_nested_relationships(
std::vector<std::pair<int64_t, common::model::relationship_t>>
std::vector<std::pair<eid_t, common::model::relationship_t>>
&nested_relationships,
common::model::relationship_t hint,
const std::function<bool(const std::string &full_name)> &should_include)
@@ -532,7 +535,7 @@ private:
*/
std::vector<template_parameter> template_params_;
std::optional<int64_t> id_;
std::optional<eid_t> id_;
bool is_unexposed_{false};
};

View File

@@ -20,6 +20,75 @@
namespace clanguml::common {
eid_t::eid_t()
: value_{0ULL}
, is_global_{true}
{
}
eid_t::eid_t(int64_t id)
: value_{static_cast<type>(id)}
, is_global_{false}
{
}
eid_t::eid_t(type id)
: value_{id}
, is_global_{true}
{
}
eid_t &eid_t::operator=(int64_t ast_id)
{
// Can't assign ast_id if the id is already a global one
assert(!is_global_);
value_ = static_cast<uint64_t>(ast_id);
return *this;
}
bool eid_t::is_global() const { return is_global_; }
bool operator==(const eid_t &lhs, const eid_t &rhs)
{
return (lhs.is_global_ == rhs.is_global_) && (lhs.value_ == rhs.value_);
}
bool operator==(const eid_t &lhs, const uint64_t &v) { return lhs.value_ == v; }
bool operator!=(const eid_t &lhs, const uint64_t &v)
{
// This is sadly necessary to catch accidental comparisons to empty
// std::optional<id_t>:
//
// std::optional<id_t> id{};
// if(id != 0) { /* id is nullopt, not 0 - so this executes... */ }
//
assert(v != 0);
return lhs.value_ != v;
}
bool operator!=(const eid_t &lhs, const eid_t &rhs) { return !(lhs == rhs); }
bool operator<(const eid_t &lhs, const eid_t &rhs)
{
if (lhs.is_global_ != rhs.is_global_) {
return lhs.value_ < rhs.value_ + 1;
}
return lhs.value_ < rhs.value_; // Compare values if is_global_ are the same
}
eid_t::type eid_t::value() const { return value_; }
int64_t eid_t::ast_local_value() const
{
assert(!is_global_);
return static_cast<int64_t>(value_);
}
std::string to_string(const std::string &s) { return s; }
std::string to_string(const string_or_regex &sr) { return sr.to_string(); }

View File

@@ -29,13 +29,62 @@
namespace clanguml::common {
using id_t = int64_t;
/**
* @brief Universal class for representing all kinds of Id's in the diagram
* model.
*
* This class provides a convenient way of representing id's in the diagram
* model. The main problem it solves is that it allows to store both
* Clang AST ID's (obtained using getID() method), which are local to a single
* translation unit and have a type int64_t as well as global (across
* multiple translation units) id's used by clang-uml in the intermediate
* model (which are uint64_t).
*
* The class is aware which kind of value it holds and tries to ensure that
* mistakes such as using AST local ID in place where global id is needed
* do not happen.
*/
class eid_t {
public:
using type = uint64_t;
eid_t();
explicit eid_t(int64_t id);
explicit eid_t(type id);
eid_t(const eid_t &) = default;
eid_t(eid_t &&) noexcept = default;
eid_t &operator=(const eid_t &) = default;
eid_t &operator=(eid_t &&) noexcept = default;
eid_t &operator=(int64_t ast_id);
~eid_t() = default;
bool is_global() const;
friend bool operator==(const eid_t &lhs, const eid_t &rhs);
friend bool operator==(const eid_t &lhs, const uint64_t &v);
friend bool operator!=(const eid_t &lhs, const uint64_t &v);
friend bool operator!=(const eid_t &lhs, const eid_t &rhs);
friend bool operator<(const eid_t &lhs, const eid_t &rhs);
type value() const;
int64_t ast_local_value() const;
private:
type value_;
bool is_global_;
};
/**
* Type of output diagram format generator.
*/
enum class generator_type_t {
plantuml, /*!< Diagrams will be gnerated in PlantUML format */
plantuml, /*!< Diagrams will be generated in PlantUML format */
json, /*!< Diagrams will be generated in JSON format */
mermaid /*!< Diagrams will be generated in MermaidJS format */
};
@@ -293,3 +342,13 @@ using namespace_or_regex = common::or_regex<common::model::namespace_>;
struct path_or_regex : public or_regex<std::filesystem::path> { };
} // namespace clanguml::common
template <> class fmt::formatter<clanguml::common::eid_t> {
public:
constexpr auto parse(format_parse_context &ctx) { return ctx.begin(); }
template <typename Context>
constexpr auto format(clanguml::common::eid_t const &id, Context &ctx) const
{
return fmt::format_to(ctx.out(), "{}", id.value());
}
};

View File

@@ -20,17 +20,22 @@
namespace clanguml::common::visitor {
void ast_id_mapper::add(int64_t ast_id, id_t global_id)
void ast_id_mapper::add(int64_t ast_id, eid_t global_id)
{
id_map_.emplace(ast_id, global_id);
}
std::optional<id_t> ast_id_mapper::get_global_id(int64_t ast_id)
std::optional<eid_t> ast_id_mapper::get_global_id(eid_t ast_id)
{
if (id_map_.count(ast_id) == 0)
assert(!ast_id.is_global());
if (ast_id.is_global())
return {};
return id_map_.at(ast_id);
if (id_map_.count(ast_id.ast_local_value()) == 0)
return {};
return id_map_.at(ast_id.ast_local_value());
}
} // namespace clanguml::common::visitor

View File

@@ -24,6 +24,8 @@
namespace clanguml::common::visitor {
using clanguml::common::eid_t;
/**
* @brief Mapping between Clang AST identifier and `clang-uml` unique ids
*
@@ -40,8 +42,6 @@ namespace clanguml::common::visitor {
*/
class ast_id_mapper {
public:
using id_t = common::id_t;
ast_id_mapper() = default;
/**
@@ -50,7 +50,7 @@ public:
* @param ast_id Clang's local AST id.
* @param global_id Global element id.
*/
void add(int64_t ast_id, id_t global_id);
void add(int64_t ast_id, eid_t global_id);
/**
* Get global element id based on it's local Clang AST id, if exists.
@@ -58,11 +58,11 @@ public:
* @param ast_id Clang's local AST id.
* @return Global id, if exists.
*/
std::optional<id_t> get_global_id(int64_t ast_id);
std::optional<eid_t> get_global_id(eid_t ast_id);
private:
std::map</* Clang AST translation unit local id */ int64_t,
/* clang-uml global id */ id_t>
/* clang-uml global id */ eid_t>
id_map_;
};

View File

@@ -30,8 +30,8 @@ using common::model::namespace_;
using common::model::relationship_t;
using common::model::template_parameter;
using found_relationships_t = std::vector<
std::pair<clanguml::common::id_t, common::model::relationship_t>>;
using found_relationships_t =
std::vector<std::pair<eid_t, common::model::relationship_t>>;
namespace detail {
@@ -524,8 +524,8 @@ public:
const template_parameter &ct, found_relationships_t &relationships);
void find_instantiation_relationships(
common::model::template_element &template_instantiation,
common::id_t id, const std::string &qualified_name) const;
common::model::template_element &template_instantiation, eid_t id,
const std::string &qualified_name) const;
/**
* @brief Get reference to Clang AST to clang-uml id mapper
@@ -662,7 +662,7 @@ void template_builder<VisitorT>::build_from_template_declaration(
{relationship_t::kConstraint,
id_mapper()
.get_global_id(
named_concept->getID())
eid_t{named_concept->getID()})
.value(),
model::access_t::kNone,
ct.name().value()});
@@ -865,7 +865,7 @@ void template_builder<VisitorT>::build(
if constexpr (std::is_same_v<typename VisitorT::diagram_t,
class_diagram::model::diagram>) {
find_instantiation_relationships(template_instantiation,
template_decl->getID(), full_template_specialization_name);
eid_t{template_decl->getID()}, full_template_specialization_name);
}
template_instantiation.set_id(
@@ -910,7 +910,7 @@ void template_builder<VisitorT>::build_from_class_template_specialization(
if constexpr (std::is_same_v<typename VisitorT::diagram_t,
class_diagram::model::diagram>) {
find_instantiation_relationships(template_instantiation,
template_specialization.getID(), qualified_name);
eid_t{template_specialization.getID()}, qualified_name);
}
visitor_.set_source_location(*template_decl, template_instantiation);
@@ -918,7 +918,7 @@ void template_builder<VisitorT>::build_from_class_template_specialization(
template <typename VisitorT>
void template_builder<VisitorT>::find_instantiation_relationships(
common::model::template_element &template_instantiation, common::id_t id,
common::model::template_element &template_instantiation, eid_t id,
const std::string &qualified_name) const
{
visitor_.find_instantiation_relationships(

View File

@@ -42,8 +42,8 @@
namespace clanguml::common::visitor {
using found_relationships_t = std::vector<
std::pair<clanguml::common::id_t, common::model::relationship_t>>;
using found_relationships_t =
std::vector<std::pair<eid_t, common::model::relationship_t>>;
/**
* @brief Diagram translation unit visitor base class

View File

@@ -44,7 +44,7 @@ void generator::generate_relationships(
[this](const auto &r) { return model().should_include(r.type()); },
[&f, &parent](const auto &r) {
nlohmann::json rel = r;
rel["source"] = std::to_string(f.id());
rel["source"] = std::to_string(f.id().value());
parent["relationships"].push_back(std::move(rel));
});
}
@@ -53,7 +53,7 @@ void generator::generate_relationships(
void generator::generate(const source_file &f, nlohmann::json &parent) const
{
nlohmann::json j;
j["id"] = std::to_string(f.id());
j["id"] = std::to_string(f.id().value());
j["name"] = f.name();
auto display_name = f.full_name(false);
#if defined(_MSC_VER)

View File

@@ -35,7 +35,7 @@ common::optional_ref<common::model::diagram_element> diagram::get(
}
common::optional_ref<common::model::diagram_element> diagram::get(
const common::id_t id) const
const eid_t id) const
{
return find<source_file>(id);
}
@@ -51,7 +51,7 @@ void diagram::add_file(std::unique_ptr<common::model::source_file> &&f)
auto &ff = *f;
assert(!ff.name().empty());
assert(ff.id() != 0);
assert(ff.id().value() != 0);
element_view<source_file>::add(ff);

View File

@@ -28,6 +28,7 @@
namespace clanguml::include_diagram::model {
using clanguml::common::eid_t;
using clanguml::common::opt_ref;
using clanguml::common::model::diagram_element;
using clanguml::common::model::source_file;
@@ -68,7 +69,7 @@ public:
* @param id Element id.
* @return Optional reference to a diagram element.
*/
opt_ref<diagram_element> get(common::id_t id) const override;
opt_ref<diagram_element> get(eid_t id) const override;
/**
* @brief Add include diagram element, an include file.
@@ -100,7 +101,7 @@ public:
* @param id Id of the element
* @return Optional reference to a diagram element
*/
template <typename ElementT> opt_ref<ElementT> find(common::id_t id) const;
template <typename ElementT> opt_ref<ElementT> find(eid_t id) const;
/**
* @brief Convert element id to PlantUML alias.
@@ -158,8 +159,7 @@ opt_ref<ElementT> diagram::find(const std::string &name) const
return {};
}
template <typename ElementT>
opt_ref<ElementT> diagram::find(common::id_t id) const
template <typename ElementT> opt_ref<ElementT> diagram::find(eid_t id) const
{
for (const auto &element : element_view<ElementT>::view()) {
if (element.get().id() == id) {

View File

@@ -112,7 +112,7 @@ void translation_unit_visitor::include_visitor::InclusionDirective(
void translation_unit_visitor::include_visitor::process_internal_header(
const std::filesystem::path &include_path, bool is_system,
const common::id_t current_file_id)
const eid_t current_file_id)
{
// Make the path relative with respect to relative_to config option
auto relative_include_path =
@@ -151,8 +151,7 @@ void translation_unit_visitor::include_visitor::process_internal_header(
}
void translation_unit_visitor::include_visitor::process_external_system_header(
const std::filesystem::path &include_path,
const common::id_t current_file_id)
const std::filesystem::path &include_path, const eid_t current_file_id)
{
const auto file_name = include_path.filename();
const auto file_name_str = file_name.string();
@@ -177,7 +176,7 @@ void translation_unit_visitor::include_visitor::process_external_system_header(
}
}
std::optional<common::id_t>
std::optional<eid_t>
translation_unit_visitor::include_visitor::process_source_file(
const std::filesystem::path &file)
{

View File

@@ -35,6 +35,8 @@
namespace clanguml::include_diagram::visitor {
using clanguml::common::eid_t;
using visitor_specialization_t =
common::visitor::translation_unit_visitor<clanguml::config::include_diagram,
clanguml::include_diagram::model::diagram>;
@@ -104,7 +106,7 @@ public:
* @param current_file_id File id
*/
void process_internal_header(const std::filesystem::path &include_path,
bool is_system, common::id_t current_file_id);
bool is_system, eid_t current_file_id);
/**
* @brief Handle system header include directive
@@ -113,8 +115,7 @@ public:
* @param current_file_id File id
*/
void process_external_system_header(
const std::filesystem::path &include_path,
common::id_t current_file_id);
const std::filesystem::path &include_path, eid_t current_file_id);
/**
* @brief Handle a source file
@@ -125,7 +126,7 @@ public:
* @param file Absolute path to a source file
* @return Diagram element id, in case the file was added to the diagram
*/
std::optional<common::id_t> process_source_file(
std::optional<eid_t> process_source_file(
const std::filesystem::path &file);
};

View File

@@ -44,7 +44,7 @@ void generator::generate_relationships(
dynamic_cast<const package &>(*destination_package)))
continue;
rel["source"] = std::to_string(p.id());
rel["source"] = std::to_string(p.id().value());
parent["relationships"].push_back(std::move(rel));
}
}
@@ -63,7 +63,7 @@ void generator::generate(const package &p, nlohmann::json &parent) const
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["id"] = std::to_string(p.id().value());
j["name"] = p.name();
j["type"] = to_string(config().package_type());
j["display_name"] = p.name();

View File

@@ -41,12 +41,12 @@ common::optional_ref<clanguml::common::model::diagram_element> diagram::get(
}
common::optional_ref<clanguml::common::model::diagram_element> diagram::get(
const clanguml::common::id_t id) const
const eid_t id) const
{
return find<package>(id);
}
std::string diagram::to_alias(const clanguml::common::id_t id) const
std::string diagram::to_alias(const eid_t id) const
{
LOG_DBG("Looking for alias for {}", id);

View File

@@ -26,6 +26,7 @@
namespace clanguml::package_diagram::model {
using clanguml::common::eid_t;
using clanguml::common::opt_ref;
using clanguml::common::model::diagram_element;
using clanguml::common::model::package;
@@ -75,7 +76,7 @@ public:
* @param id Element id.
* @return Optional reference to a diagram element.
*/
opt_ref<diagram_element> get(common::id_t id) const override;
opt_ref<diagram_element> get(eid_t id) const override;
/**
* @brief Find an element in the diagram by name.
@@ -100,7 +101,7 @@ public:
* @param id Id of the element
* @return Optional reference to a diagram element
*/
template <typename ElementT> opt_ref<ElementT> find(common::id_t id) const;
template <typename ElementT> opt_ref<ElementT> find(eid_t id) const;
/**
* @brief Find elements in the diagram by regex pattern.
@@ -148,7 +149,7 @@ public:
* @param id Id of a package in the diagram
* @return PlantUML alias of the element
*/
std::string to_alias(common::id_t id) const;
std::string to_alias(eid_t id) const;
/**
* @brief Return the elements JSON context for inja templates.
@@ -213,8 +214,7 @@ opt_ref<ElementT> diagram::find(const std::string &name) const
return {};
}
template <typename ElementT>
opt_ref<ElementT> diagram::find(common::id_t id) const
template <typename ElementT> opt_ref<ElementT> diagram::find(eid_t id) const
{
for (const auto &element : element_view<ElementT>::view()) {
if (element.get().id() == id) {

View File

@@ -78,7 +78,7 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
p->set_id(common::to_id(*ns));
set_source_location(*ns, *p);
assert(p->id() > 0);
assert(p->id().value() > 0);
if (diagram().should_include(*p) && !diagram().get(p->id())) {
process_comment(*ns, *p);
@@ -282,7 +282,7 @@ void translation_unit_visitor::add_relationships(
auto current_package_id = get_package_id(cls);
if (current_package_id == 0)
if (current_package_id.value() == 0)
// These are relationships to a global namespace, and we don't care
// about those
return;
@@ -290,7 +290,7 @@ void translation_unit_visitor::add_relationships(
auto current_package = diagram().get(current_package_id);
if (current_package) {
std::vector<common::id_t> parent_ids =
std::vector<eid_t> parent_ids =
get_parent_package_ids(current_package_id);
for (const auto &dependency : relationships) {
@@ -313,7 +313,7 @@ void translation_unit_visitor::add_relationships(
}
}
common::id_t translation_unit_visitor::get_package_id(const clang::Decl *cls)
eid_t translation_unit_visitor::get_package_id(const clang::Decl *cls)
{
if (config().package_type() == config::package_type_t::kNamespace) {
const auto *namespace_context =
@@ -677,15 +677,15 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
void translation_unit_visitor::finalize() { }
std::vector<common::id_t> translation_unit_visitor::get_parent_package_ids(
common::id_t id)
std::vector<eid_t> translation_unit_visitor::get_parent_package_ids(eid_t id)
{
std::vector<common::id_t> parent_ids;
std::optional<common::id_t> parent_id = id;
std::vector<eid_t> parent_ids;
std::optional<eid_t> parent_id = id;
while (parent_id.has_value()) {
parent_ids.push_back(parent_id.value());
auto parent = this->diagram().get(parent_id.value());
const auto pid = parent_id.value(); // NOLINT
parent_ids.push_back(pid);
auto parent = this->diagram().get(pid);
if (parent)
parent_id = parent.value().parent_element_id();
else

View File

@@ -33,8 +33,10 @@
namespace clanguml::package_diagram::visitor {
using found_relationships_t = std::vector<
std::pair<clanguml::common::id_t, common::model::relationship_t>>;
using clanguml::common::eid_t;
using found_relationships_t =
std::vector<std::pair<eid_t, common::model::relationship_t>>;
using visitor_specialization_t =
common::visitor::translation_unit_visitor<clanguml::config::package_diagram,
@@ -98,7 +100,7 @@ private:
* @param cls C++ entity declaration
* @return Id of the package containing that declaration
*/
common::id_t get_package_id(const clang::Decl *cls);
eid_t get_package_id(const clang::Decl *cls);
/**
* @brief Process class declaration
@@ -203,6 +205,6 @@ private:
void add_relationships(
clang::Decl *cls, found_relationships_t &relationships);
std::vector<common::id_t> get_parent_package_ids(common::id_t id);
std::vector<eid_t> get_parent_package_ids(eid_t id);
};
} // namespace clanguml::package_diagram::visitor

View File

@@ -53,7 +53,7 @@ void to_json(nlohmann::json &j, const participant &c)
void to_json(nlohmann::json &j, const activity &c)
{
j["participant_id"] = std::to_string(c.from());
j["participant_id"] = std::to_string(c.from().value());
}
} // namespace clanguml::sequence_diagram::model
@@ -115,8 +115,8 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
msg["name"] = message;
msg["type"] = "message";
msg["from"]["activity_id"] = std::to_string(from.value().id());
msg["to"]["activity_id"] = std::to_string(to.value().id());
msg["from"]["activity_id"] = std::to_string(from.value().id().value());
msg["to"]["activity_id"] = std::to_string(to.value().id().value());
if (const auto &cmt = m.comment(); cmt.has_value())
msg["comment"] = cmt.value();
@@ -125,7 +125,7 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
model().get_participant<model::method>(from.value().id()).value();
msg["from"]["participant_id"] =
std::to_string(class_participant.class_id());
std::to_string(class_participant.class_id().value());
}
else if (from.value().type_name() == "function" ||
from.value().type_name() == "function_template") {
@@ -134,15 +134,17 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
model()
.get_participant<model::function>(from.value().id())
.value();
msg["from"]["participant_id"] =
std::to_string(common::to_id(file_participant.file_relative()));
msg["from"]["participant_id"] = std::to_string(
common::to_id(file_participant.file_relative()).value());
}
else {
msg["from"]["participant_id"] = std::to_string(from.value().id());
msg["from"]["participant_id"] =
std::to_string(from.value().id().value());
}
}
else if (from.value().type_name() == "lambda") {
msg["from"]["participant_id"] = std::to_string(from.value().id());
msg["from"]["participant_id"] =
std::to_string(from.value().id().value());
}
if (to.value().type_name() == "method") {
@@ -150,7 +152,7 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
model().get_participant<model::method>(to.value().id()).value();
msg["to"]["participant_id"] =
std::to_string(class_participant.class_id());
std::to_string(class_participant.class_id().value());
}
else if (to.value().type_name() == "function" ||
to.value().type_name() == "function_template") {
@@ -159,15 +161,16 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
model()
.get_participant<model::function>(to.value().id())
.value();
msg["to"]["participant_id"] =
std::to_string(common::to_id(file_participant.file_relative()));
msg["to"]["participant_id"] = std::to_string(
common::to_id(file_participant.file_relative()).value());
}
else {
msg["to"]["participant_id"] = std::to_string(to.value().id());
msg["to"]["participant_id"] =
std::to_string(to.value().id().value());
}
}
else if (to.value().type_name() == "lambda") {
msg["to"]["participant_id"] = std::to_string(to.value().id());
msg["to"]["participant_id"] = std::to_string(to.value().id().value());
}
msg["source_location"] =
@@ -183,7 +186,7 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
}
void generator::generate_activity(
const activity &a, std::vector<common::id_t> &visited) const
const activity &a, std::vector<eid_t> &visited) const
{
// Generate calls from this activity to other activities
for (const auto &m : a.messages()) {
@@ -260,7 +263,7 @@ nlohmann::json &generator::current_block_statement() const
}
void generator::process_call_message(
const model::message &m, std::vector<common::id_t> &visited) const
const model::message &m, std::vector<eid_t> &visited) const
{
visited.push_back(m.from());
@@ -299,7 +302,7 @@ void generator::process_while_message(const message &m) const
nlohmann::json while_block;
while_block["type"] = "loop";
while_block["name"] = "while";
while_block["activity_id"] = std::to_string(m.from());
while_block["activity_id"] = std::to_string(m.from().value());
if (auto text = m.condition_text(); text.has_value())
while_block["condition_text"] = *text;
@@ -320,7 +323,7 @@ void generator::process_for_message(const message &m) const
nlohmann::json for_block;
for_block["type"] = "loop";
for_block["name"] = "for";
for_block["activity_id"] = std::to_string(m.from());
for_block["activity_id"] = std::to_string(m.from().value());
if (auto text = m.condition_text(); text.has_value())
for_block["condition_text"] = *text;
@@ -341,7 +344,7 @@ void generator::process_do_message(const message &m) const
nlohmann::json do_block;
do_block["type"] = "loop";
do_block["name"] = "do";
do_block["activity_id"] = std::to_string(m.from());
do_block["activity_id"] = std::to_string(m.from().value());
if (auto text = m.condition_text(); text.has_value())
do_block["condition_text"] = *text;
@@ -362,7 +365,7 @@ void generator::process_try_message(const message &m) const
nlohmann::json try_block;
try_block["type"] = "break";
try_block["name"] = "try";
try_block["activity_id"] = std::to_string(m.from());
try_block["activity_id"] = std::to_string(m.from().value());
current_block_statement()["messages"].push_back(std::move(try_block));
@@ -404,7 +407,7 @@ void generator::process_switch_message(const message &m) const
nlohmann::json if_block;
if_block["type"] = "alt";
if_block["name"] = "switch";
if_block["activity_id"] = std::to_string(m.from());
if_block["activity_id"] = std::to_string(m.from().value());
current_block_statement()["messages"].push_back(std::move(if_block));
@@ -439,7 +442,7 @@ void generator::process_conditional_message(const message &m) const
nlohmann::json if_block;
if_block["type"] = "alt";
if_block["name"] = "conditional";
if_block["activity_id"] = std::to_string(m.from());
if_block["activity_id"] = std::to_string(m.from().value());
if (auto text = m.condition_text(); text.has_value())
if_block["condition_text"] = *text;
@@ -507,7 +510,7 @@ void generator::process_if_message(const message &m) const
nlohmann::json if_block;
if_block["type"] = "alt";
if_block["name"] = "if";
if_block["activity_id"] = std::to_string(m.from());
if_block["activity_id"] = std::to_string(m.from().value());
if (auto text = m.condition_text(); text.has_value())
if_block["condition_text"] = *text;
@@ -538,10 +541,10 @@ void generator::generate_participant(
generate_participant(parent, p.value().id(), true);
}
common::id_t generator::generate_participant(
nlohmann::json & /*parent*/, common::id_t id, bool force) const
std::optional<eid_t> generator::generate_participant(
nlohmann::json & /*parent*/, eid_t id, bool force) const
{
common::id_t participant_id{0};
std::optional<eid_t> participant_id{};
if (!force) {
for (const auto pid : model().active_participants()) {
@@ -554,27 +557,27 @@ common::id_t generator::generate_participant(
else
participant_id = id;
if (participant_id == 0)
if (!participant_id.has_value())
return participant_id;
if (is_participant_generated(participant_id))
if (is_participant_generated(*participant_id))
return participant_id;
const auto &participant =
model().get_participant<model::participant>(participant_id).value();
model().get_participant<model::participant>(*participant_id).value();
const auto participant_type = participant.type_name();
if (participant_type == "method") {
auto class_participant_id =
model()
.get_participant<model::method>(participant_id)
.get_participant<model::method>(*participant_id)
.value()
.class_id();
LOG_DBG("Generating JSON method participant: {}",
model()
.get_participant<model::method>(participant_id)
.get_participant<model::method>(*participant_id)
.value()
.full_name(false));
@@ -584,7 +587,7 @@ common::id_t generator::generate_participant(
.get_participant<model::participant>(class_participant_id)
.value();
generated_participants_.emplace(participant_id);
generated_participants_.emplace(*participant_id);
generated_participants_.emplace(class_participant_id);
json_["participants"].push_back(class_participant);
@@ -600,10 +603,11 @@ common::id_t generator::generate_participant(
return class_participant_id;
}
if (!is_participant_generated(participant_id)) {
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);
if (p.at("id") ==
std::to_string(class_participant_id.value())) {
generated_participants_.emplace(*participant_id);
p["activities"].push_back(participant);
return class_participant_id;
}
@@ -617,7 +621,7 @@ common::id_t generator::generate_participant(
// single file
// participant_id will become activity_id within a file participant
const auto &function_participant =
model().get_participant<model::function>(participant_id).value();
model().get_participant<model::function>(*participant_id).value();
const auto file_participant_id =
common::to_id(function_participant.file_relative());
@@ -634,11 +638,11 @@ common::id_t generator::generate_participant(
if (is_participant_generated(file_participant_id))
return participant_id;
p["id"] = std::to_string(file_participant_id);
p["id"] = std::to_string(file_participant_id.value());
p["type"] = "file";
p.erase("source_location");
generated_participants_.emplace(participant_id);
generated_participants_.emplace(participant_id.value());
p["activities"].push_back(participant);
json_["participants"].push_back(p);
@@ -648,10 +652,10 @@ common::id_t generator::generate_participant(
return file_participant_id;
}
if (!is_participant_generated(participant_id)) {
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);
if (p.at("id") == std::to_string(file_participant_id.value())) {
generated_participants_.emplace(*participant_id);
p["activities"].push_back(participant);
}
}
@@ -663,12 +667,12 @@ common::id_t generator::generate_participant(
json_["participants"].push_back(participant);
}
generated_participants_.emplace(participant_id);
generated_participants_.emplace(*participant_id);
return participant_id;
}
bool generator::is_participant_generated(common::id_t id) const
bool generator::is_participant_generated(eid_t id) const
{
return std::find(generated_participants_.begin(),
generated_participants_.end(),
@@ -700,17 +704,19 @@ void generator::generate_diagram(nlohmann::json &parent) const
auto from_activity_id = model().get_from_activity_id(from_location);
auto to_activity_id = model().get_to_activity_id(to_location);
if (from_activity_id == 0 || to_activity_id == 0)
if (!from_activity_id || !to_activity_id)
continue;
auto message_chains_unique = model().get_all_from_to_message_chains(
from_activity_id, to_activity_id);
*from_activity_id, *to_activity_id);
nlohmann::json sequence;
sequence["from_to"]["from"]["location"] = from_location.location;
sequence["from_to"]["from"]["id"] = from_activity_id;
sequence["from_to"]["from"]["id"] =
std::to_string(from_activity_id.value().value());
sequence["from_to"]["to"]["location"] = to_location.location;
sequence["from_to"]["to"]["id"] = to_activity_id;
sequence["from_to"]["to"]["id"] =
std::to_string(to_activity_id.value().value());
block_statements_stack_.push_back(std::ref(sequence));
@@ -738,15 +744,15 @@ void generator::generate_diagram(nlohmann::json &parent) const
for (const auto &to_location : config().to()) {
auto to_activity_id = model().get_to_activity_id(to_location);
if (to_activity_id == 0)
if (!to_activity_id.has_value())
continue;
auto message_chains_unique =
model().get_all_from_to_message_chains(0, to_activity_id);
auto message_chains_unique = model().get_all_from_to_message_chains(
eid_t{}, to_activity_id.value());
nlohmann::json sequence;
sequence["to"]["location"] = to_location.location;
sequence["to"]["id"] = to_activity_id;
sequence["to"]["id"] = std::to_string(to_activity_id.value().value());
block_statements_stack_.push_back(std::ref(sequence));
@@ -773,7 +779,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
for (const auto &sf : config().from()) {
if (sf.location_type == location_t::function) {
common::id_t start_from{0};
eid_t start_from{};
std::string start_from_str;
for (const auto &[k, v] : model().sequences()) {
const auto &caller = *model().participants().at(v.from());
@@ -793,7 +799,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
}
// Use this to break out of recurrent loops
std::vector<common::id_t> visited_participants;
std::vector<eid_t> visited_participants;
const auto &from =
model().get_participant<model::function>(start_from);
@@ -812,7 +818,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
nlohmann::json sequence;
sequence["start_from"]["location"] = sf.location;
sequence["start_from"]["id"] = start_from;
sequence["start_from"]["id"] = std::to_string(start_from.value());
block_statements_stack_.push_back(std::ref(sequence));

View File

@@ -32,6 +32,8 @@
namespace clanguml::sequence_diagram::generators::json {
using clanguml::common::eid_t;
std::string render_name(std::string name);
using diagram_config = clanguml::config::sequence_diagram;
@@ -77,8 +79,8 @@ public:
* the set of active participants
* @return Id of the generated participant
*/
common::id_t generate_participant(
nlohmann::json &parent, common::id_t id, bool force = false) const;
std::optional<eid_t> generate_participant(
nlohmann::json &parent, eid_t id, bool force = false) const;
/**
* @brief Generate sequence diagram participant by name
@@ -99,7 +101,7 @@ public:
* for breaking infinite recursion on recursive calls
*/
void generate_activity(const sequence_diagram::model::activity &a,
std::vector<common::id_t> &visited) const;
std::vector<eid_t> &visited) const;
/**
* @brief Get reference to the current block statement.
@@ -120,7 +122,7 @@ private:
* @param id Participant id.
* @return True, if participant has already been generated.
*/
bool is_participant_generated(common::id_t id) const;
bool is_participant_generated(eid_t id) const;
/**
* @brief Process call message
@@ -129,7 +131,7 @@ private:
* @param visited List of already visited participants
*/
void process_call_message(
const model::message &m, std::vector<common::id_t> &visited) const;
const model::message &m, std::vector<eid_t> &visited) const;
/**
* @brief Process `if` statement message
@@ -239,7 +241,7 @@ private:
*/
void process_end_while_message() const;
mutable std::set<common::id_t> generated_participants_;
mutable std::set<eid_t> generated_participants_;
// Needed to add "participants" array in a temporary object accessible from
// all methods of the generator

View File

@@ -192,8 +192,8 @@ void generator::generate_return(const message &m, std::ostream &ostr) const
}
}
void generator::generate_activity(const activity &a, std::ostream &ostr,
std::vector<common::id_t> &visited) const
void generator::generate_activity(
const activity &a, std::ostream &ostr, std::vector<eid_t> &visited) const
{
for (const auto &m : a.messages()) {
if (m.in_static_declaration_context()) {
@@ -352,9 +352,9 @@ void generator::generate_participant(
}
void generator::generate_participant(
std::ostream &ostr, common::id_t id, bool force) const
std::ostream &ostr, eid_t id, bool force) const
{
common::id_t participant_id{0};
eid_t participant_id{};
if (!force) {
for (const auto pid : model().active_participants()) {
@@ -424,8 +424,9 @@ void generator::generate_participant(
std::filesystem::path{file_path}, config().root_directory())
.string());
ostr << indent(1) << "participant " << fmt::format("C_{:022}", file_id)
<< " as " << render_participant_name(participant_name);
ostr << indent(1) << "participant "
<< fmt::format("C_{:022}", file_id.value()) << " as "
<< render_participant_name(participant_name);
ostr << '\n';
generated_participants_.emplace(file_id);
@@ -459,7 +460,7 @@ void generator::generate_participant(
}
}
bool generator::is_participant_generated(common::id_t id) const
bool generator::is_participant_generated(eid_t id) const
{
return std::find(generated_participants_.begin(),
generated_participants_.end(),
@@ -474,7 +475,7 @@ std::string generator::generate_alias(
config().combine_free_functions_into_file_participants()) {
const auto file_id = common::to_id(participant.file());
return fmt::format("C_{:022}", file_id);
return fmt::format("C_{:022}", file_id.value());
}
return participant.alias();
@@ -504,21 +505,21 @@ void generator::generate_diagram(std::ostream &ostr) const
auto from_activity_id = model().get_from_activity_id(from_location);
auto to_activity_id = model().get_to_activity_id(to_location);
if (from_activity_id == 0 || to_activity_id == 0)
if (!from_activity_id || !to_activity_id)
continue;
if (model().participants().count(from_activity_id) == 0)
if (model().participants().count(*from_activity_id) == 0)
continue;
if (model().participants().count(to_activity_id) == 0)
if (model().participants().count(*to_activity_id) == 0)
continue;
auto message_chains_unique = model().get_all_from_to_message_chains(
from_activity_id, to_activity_id);
*from_activity_id, *to_activity_id);
for (const auto &mc : message_chains_unique) {
const auto &from =
model().get_participant<model::function>(from_activity_id);
model().get_participant<model::function>(*from_activity_id);
if (from.value().type_name() == "method" ||
config().combine_free_functions_into_file_participants()) {
@@ -526,7 +527,7 @@ void generator::generate_diagram(std::ostream &ostr) const
ostr << indent(1) << "participant *\n";
star_participant_generated = true;
}
generate_participant(ostr, from_activity_id);
generate_participant(ostr, *from_activity_id);
ostr << indent(1) << "* "
<< common::generators::mermaid::to_mermaid(
message_t::kCall)
@@ -545,11 +546,11 @@ void generator::generate_diagram(std::ostream &ostr) const
for (const auto &to_location : config().to()) {
auto to_activity_id = model().get_to_activity_id(to_location);
if (to_activity_id == 0)
if (!to_activity_id)
continue;
auto message_chains_unique =
model().get_all_from_to_message_chains(0, to_activity_id);
model().get_all_from_to_message_chains(eid_t{}, *to_activity_id);
for (const auto &mc : message_chains_unique) {
const auto from_activity_id = mc.front().from();
@@ -580,7 +581,7 @@ void generator::generate_diagram(std::ostream &ostr) const
for (const auto &sf : config().from()) {
if (sf.location_type == location_t::function) {
common::id_t start_from{0};
eid_t start_from{};
for (const auto &[k, v] : model().sequences()) {
if (model().participants().count(v.from()) == 0)
continue;
@@ -602,7 +603,7 @@ void generator::generate_diagram(std::ostream &ostr) const
}
// Use this to break out of recurrent loops
std::vector<common::id_t> visited_participants;
std::vector<eid_t> visited_participants;
if (model().participants().count(start_from) == 0)
continue;

View File

@@ -35,6 +35,8 @@ namespace sequence_diagram {
namespace generators {
namespace mermaid {
using clanguml::common::eid_t;
using diagram_config = clanguml::config::sequence_diagram;
using diagram_model = clanguml::sequence_diagram::model::diagram;
@@ -95,7 +97,7 @@ public:
* @return Id of the generated participant
*/
void generate_participant(
std::ostream &ostr, common::id_t id, bool force = false) const;
std::ostream &ostr, eid_t id, bool force = false) const;
/**
* @brief Generate sequence diagram participant by name
@@ -117,7 +119,7 @@ public:
* for breaking infinite recursion on recursive calls
*/
void generate_activity(const clanguml::sequence_diagram::model::activity &a,
std::ostream &ostr, std::vector<common::id_t> &visited) const;
std::ostream &ostr, std::vector<eid_t> &visited) const;
private:
/**
@@ -126,7 +128,7 @@ private:
* @param id Participant id.
* @return True, if participant has already been generated.
*/
bool is_participant_generated(common::id_t id) const;
bool is_participant_generated(eid_t id) const;
/**
* @brief Generate MermaidJS alias for participant
@@ -153,7 +155,7 @@ private:
model::function::message_render_mode
select_method_arguments_render_mode() const;
mutable std::set<common::id_t> generated_participants_;
mutable std::set<eid_t> generated_participants_;
mutable std::vector<model::message> already_generated_in_static_context_;
};

View File

@@ -20,6 +20,7 @@
namespace clanguml::sequence_diagram::generators::plantuml {
using clanguml::common::eid_t;
using clanguml::common::model::message_t;
using clanguml::config::location_t;
using clanguml::sequence_diagram::model::activity;
@@ -149,8 +150,8 @@ void generator::generate_return(const message &m, std::ostream &ostr) const
}
}
void generator::generate_activity(const activity &a, std::ostream &ostr,
std::vector<common::id_t> &visited) const
void generator::generate_activity(
const activity &a, std::ostream &ostr, std::vector<eid_t> &visited) const
{
for (const auto &m : a.messages()) {
if (m.in_static_declaration_context()) {
@@ -348,9 +349,9 @@ void generator::generate_participant(
}
void generator::generate_participant(
std::ostream &ostr, common::id_t id, bool force) const
std::ostream &ostr, eid_t id, bool force) const
{
common::id_t participant_id{0};
eid_t participant_id{};
if (!force) {
for (const auto pid : model().active_participants()) {
@@ -429,7 +430,7 @@ void generator::generate_participant(
.string());
ostr << "participant \"" << render_name(participant_name) << "\" as "
<< fmt::format("C_{:022}", file_id);
<< fmt::format("C_{:022}", file_id.value());
ostr << '\n';
@@ -465,7 +466,7 @@ void generator::generate_participant(
}
}
bool generator::is_participant_generated(common::id_t id) const
bool generator::is_participant_generated(eid_t id) const
{
return std::find(generated_participants_.begin(),
generated_participants_.end(),
@@ -480,7 +481,7 @@ std::string generator::generate_alias(
config().combine_free_functions_into_file_participants()) {
const auto file_id = common::to_id(participant.file());
return fmt::format("C_{:022}", file_id);
return fmt::format("C_{:022}", file_id.value());
}
return participant.alias();
@@ -508,17 +509,17 @@ void generator::generate_diagram(std::ostream &ostr) const
auto from_activity_id = model().get_from_activity_id(from_location);
auto to_activity_id = model().get_to_activity_id(to_location);
if (from_activity_id == 0 || to_activity_id == 0)
if (!from_activity_id || !to_activity_id)
continue;
if (model().participants().count(from_activity_id) == 0)
if (model().participants().count(*from_activity_id) == 0)
continue;
if (model().participants().count(to_activity_id) == 0)
if (model().participants().count(*to_activity_id) == 0)
continue;
auto message_chains_unique = model().get_all_from_to_message_chains(
from_activity_id, to_activity_id);
*from_activity_id, *to_activity_id);
bool first_separator_skipped{false};
for (const auto &mc : message_chains_unique) {
@@ -528,11 +529,11 @@ void generator::generate_diagram(std::ostream &ostr) const
ostr << "====\n";
const auto &from =
model().get_participant<model::function>(from_activity_id);
model().get_participant<model::function>(*from_activity_id);
if (from.value().type_name() == "method" ||
config().combine_free_functions_into_file_participants()) {
generate_participant(ostr, from_activity_id);
generate_participant(ostr, *from_activity_id);
ostr << "[->"
<< " " << generate_alias(from.value()) << " : "
<< from.value().message_name(
@@ -549,11 +550,11 @@ void generator::generate_diagram(std::ostream &ostr) const
for (const auto &to_location : config().to()) {
auto to_activity_id = model().get_to_activity_id(to_location);
if (to_activity_id == 0)
if (!to_activity_id)
continue;
auto message_chains_unique =
model().get_all_from_to_message_chains(0, to_activity_id);
model().get_all_from_to_message_chains(eid_t{}, *to_activity_id);
bool first_separator_skipped{false};
for (const auto &mc : message_chains_unique) {
@@ -588,7 +589,7 @@ void generator::generate_diagram(std::ostream &ostr) const
for (const auto &sf : config().from()) {
if (sf.location_type == location_t::function) {
common::id_t start_from{0};
eid_t start_from{};
for (const auto &[k, v] : model().sequences()) {
if (model().participants().count(v.from()) == 0)
continue;
@@ -613,7 +614,7 @@ void generator::generate_diagram(std::ostream &ostr) const
continue;
// Use this to break out of recurrent loops
std::vector<common::id_t> visited_participants;
std::vector<eid_t> visited_participants;
const auto &from =
model().get_participant<model::function>(start_from);

View File

@@ -35,6 +35,8 @@ namespace sequence_diagram {
namespace generators {
namespace plantuml {
using clanguml::common::eid_t;
using diagram_config = clanguml::config::sequence_diagram;
using diagram_model = clanguml::sequence_diagram::model::diagram;
@@ -89,7 +91,7 @@ public:
* @return Id of the generated participant
*/
void generate_participant(
std::ostream &ostr, common::id_t id, bool force = false) const;
std::ostream &ostr, eid_t id, bool force = false) const;
/**
* @brief Generate sequence diagram participant by name
@@ -111,7 +113,7 @@ public:
* for breaking infinite recursion on recursive calls
*/
void generate_activity(const clanguml::sequence_diagram::model::activity &a,
std::ostream &ostr, std::vector<common::id_t> &visited) const;
std::ostream &ostr, std::vector<eid_t> &visited) const;
private:
/**
@@ -120,7 +122,7 @@ private:
* @param id Participant id.
* @return True, if participant has already been generated.
*/
bool is_participant_generated(common::id_t id) const;
bool is_participant_generated(eid_t id) const;
/**
* @brief Generate PlantUML alias for participant
@@ -155,7 +157,7 @@ private:
model::function::message_render_mode
select_method_arguments_render_mode() const;
mutable std::set<common::id_t> generated_participants_;
mutable std::set<eid_t> generated_participants_;
mutable std::vector<model::message> already_generated_in_static_context_;
};

View File

@@ -20,7 +20,7 @@
namespace clanguml::sequence_diagram::model {
activity::activity(common::id_t id)
activity::activity(eid_t id)
: from_{id}
{
}
@@ -31,6 +31,6 @@ std::vector<message> &activity::messages() { return messages_; }
const std::vector<message> &activity::messages() const { return messages_; }
common::id_t activity::from() const { return from_; }
eid_t activity::from() const { return from_; }
} // namespace clanguml::sequence_diagram::model

View File

@@ -35,7 +35,7 @@ public:
*
* @param id Id of the participant parent for the activity
*/
activity(common::id_t id);
activity(eid_t id);
/**
* @brief Add a message call to the activity
@@ -63,10 +63,10 @@ public:
*
* @return Id of activity participant
*/
common::id_t from() const;
eid_t from() const;
private:
common::id_t from_;
eid_t from_;
std::vector<message> messages_;
};

View File

@@ -42,7 +42,7 @@ common::optional_ref<common::model::diagram_element> diagram::get(
}
common::optional_ref<common::model::diagram_element> diagram::get(
const common::id_t id) const
const eid_t id) const
{
if (participants_.find(id) != participants_.end())
return {*participants_.at(id)};
@@ -77,6 +77,8 @@ void diagram::add_participant(std::unique_ptr<participant> p)
{
const auto participant_id = p->id();
assert(participant_id.is_global());
if (participants_.find(participant_id) == participants_.end()) {
LOG_DBG("Adding '{}' participant: {}, {} [{}]", p->type_name(),
p->full_name(false), p->id(),
@@ -88,22 +90,19 @@ void diagram::add_participant(std::unique_ptr<participant> p)
}
}
void diagram::add_active_participant(common::id_t id)
void diagram::add_active_participant(eid_t id)
{
active_participants_.emplace(id);
}
const activity &diagram::get_activity(common::id_t id) const
const activity &diagram::get_activity(eid_t id) const
{
return activities_.at(id);
}
bool diagram::has_activity(common::id_t id) const
{
return activities_.count(id) > 0;
}
bool diagram::has_activity(eid_t id) const { return activities_.count(id) > 0; }
activity &diagram::get_activity(common::id_t id) { return activities_.at(id); }
activity &diagram::get_activity(eid_t id) { return activities_.at(id); }
void diagram::add_message(model::message &&message)
{
@@ -151,30 +150,27 @@ void diagram::add_case_stmt_message(model::message &&m)
}
}
std::map<common::id_t, activity> &diagram::sequences() { return activities_; }
std::map<eid_t, activity> &diagram::sequences() { return activities_; }
const std::map<common::id_t, activity> &diagram::sequences() const
const std::map<eid_t, activity> &diagram::sequences() const
{
return activities_;
}
std::map<common::id_t, std::unique_ptr<participant>> &diagram::participants()
std::map<eid_t, std::unique_ptr<participant>> &diagram::participants()
{
return participants_;
}
const std::map<common::id_t, std::unique_ptr<participant>> &
const std::map<eid_t, std::unique_ptr<participant>> &
diagram::participants() const
{
return participants_;
}
std::set<common::id_t> &diagram::active_participants()
{
return active_participants_;
}
std::set<eid_t> &diagram::active_participants() { return active_participants_; }
const std::set<common::id_t> &diagram::active_participants() const
const std::set<eid_t> &diagram::active_participants() const
{
return active_participants_;
}
@@ -226,10 +222,10 @@ std::vector<std::string> diagram::list_to_values() const
return result;
}
common::id_t diagram::get_to_activity_id(
std::optional<eid_t> diagram::get_to_activity_id(
const config::source_location &to_location) const
{
common::id_t to_activity{0};
std::optional<eid_t> to_activity{};
for (const auto &[k, v] : sequences()) {
for (const auto &m : v.messages()) {
@@ -246,7 +242,7 @@ common::id_t diagram::get_to_activity_id(
}
}
if (to_activity == 0) {
if (!to_activity.has_value()) {
LOG_WARN("Failed to find 'to' participant {} for to "
"condition",
to_location.location);
@@ -255,10 +251,10 @@ common::id_t diagram::get_to_activity_id(
return to_activity;
}
common::id_t diagram::get_from_activity_id(
std::optional<eid_t> diagram::get_from_activity_id(
const config::source_location &from_location) const
{
common::id_t from_activity{0};
std::optional<eid_t> from_activity{};
for (const auto &[k, v] : sequences()) {
const auto &caller = *participants().at(v.from());
@@ -270,7 +266,7 @@ common::id_t diagram::get_from_activity_id(
}
}
if (from_activity == 0) {
if (!from_activity.has_value()) {
LOG_WARN("Failed to find 'from' participant {} for from "
"condition",
from_location.location);
@@ -280,7 +276,7 @@ common::id_t diagram::get_from_activity_id(
}
std::vector<message_chain_t> diagram::get_all_from_to_message_chains(
const common::id_t from_activity, const common::id_t to_activity) const
const eid_t from_activity, const eid_t to_activity) const
{
std::vector<message_chain_t> message_chains_unique{};
@@ -385,7 +381,8 @@ std::vector<message_chain_t> diagram::get_all_from_to_message_chains(
message_chains_unique.end(), mc) != message_chains_unique.end())
continue;
if (from_activity == 0 || (mc.front().from() == from_activity)) {
if (from_activity.value() == 0 ||
(mc.front().from() == from_activity)) {
message_chains_unique.push_back(mc);
}
}
@@ -411,9 +408,9 @@ bool diagram::is_empty() const
void diagram::inline_lambda_operator_calls()
{
std::map<common::id_t, activity> activities;
std::map<common::id_t, std::unique_ptr<participant>> participants;
std::set<common::id_t> active_participants;
std::map<eid_t, activity> activities;
std::map<eid_t, std::unique_ptr<participant>> participants;
std::set<eid_t> active_participants;
for (auto &[id, act] : sequences()) {
model::activity new_activity{id};
@@ -485,8 +482,8 @@ void diagram::inline_lambda_operator_calls()
active_participants_ = std::move(active_participants);
}
bool diagram::inline_lambda_operator_call(const common::id_t id,
model::activity &new_activity, const model::message &m)
bool diagram::inline_lambda_operator_call(
const eid_t id, model::activity &new_activity, const model::message &m)
{
bool message_call_to_lambda{false};
auto maybe_lambda_operator = get_participant<model::method>(m.to());

View File

@@ -67,7 +67,7 @@ public:
* @return Optional reference to a diagram element.
*/
common::optional_ref<common::model::diagram_element> get(
common::id_t id) const override;
eid_t id) const override;
/**
* @brief Get participant by id
@@ -76,7 +76,7 @@ public:
* @return Optional reference to a diagram element.
*/
template <typename T>
common::optional_ref<T> get_participant(common::id_t id) const
common::optional_ref<T> get_participant(eid_t id) const
{
if (participants_.find(id) == participants_.end()) {
return {};
@@ -98,7 +98,7 @@ public:
*
* @param id Id of participant to activate
*/
void add_active_participant(common::id_t id);
void add_active_participant(eid_t id);
/**
* @brief Check if diagram has activity identified by caller id
@@ -106,7 +106,7 @@ public:
* @param id Caller id representing the activity
* @return True, if an activity already exists
*/
bool has_activity(common::id_t id) const;
bool has_activity(eid_t id) const;
/**
* @brief Get reference to current activity of a participant
@@ -114,7 +114,7 @@ public:
* @param id Participant id
* @return
*/
const activity &get_activity(common::id_t id) const;
const activity &get_activity(eid_t id) const;
/**
* @brief Get reference to current activity of a participant
@@ -122,7 +122,7 @@ public:
* @param id Participant id
* @return
*/
activity &get_activity(common::id_t id);
activity &get_activity(eid_t id);
/**
* @brief Add message to current activity
@@ -163,43 +163,42 @@ public:
*
* @return Map of sequences in the diagram
*/
std::map<common::id_t, activity> &sequences();
std::map<eid_t, activity> &sequences();
/**
* @brief Get all sequences in the diagram
*
* @return Map of sequences in the diagram
*/
const std::map<common::id_t, activity> &sequences() const;
const std::map<eid_t, activity> &sequences() const;
/**
* @brief Get map of all participants in the diagram
*
* @return Map of participants in the diagram
*/
std::map<common::id_t, std::unique_ptr<participant>> &participants();
std::map<eid_t, std::unique_ptr<participant>> &participants();
/**
* @brief Get map of all participants in the diagram
*
* @return Map of participants in the diagram
*/
const std::map<common::id_t, std::unique_ptr<participant>> &
participants() const;
const std::map<eid_t, std::unique_ptr<participant>> &participants() const;
/**
* @brief Get all active participants in the diagram
*
* @return Set of all active participant ids
*/
std::set<common::id_t> &active_participants();
std::set<eid_t> &active_participants();
/**
* @brief Get all active participants in the diagram
*
* @return Set of all active participant ids
*/
const std::set<common::id_t> &active_participants() const;
const std::set<eid_t> &active_participants() const;
/**
* @brief Convert element full name to PlantUML alias.
@@ -259,7 +258,7 @@ public:
* @return List of message chains
*/
std::vector<message_chain_t> get_all_from_to_message_chains(
common::id_t from_activity, common::id_t to_activity) const;
eid_t from_activity, eid_t to_activity) const;
/**
* @brief Get id of a 'to' activity
@@ -267,7 +266,7 @@ public:
* @param to_location Target activity
* @return Activity id
*/
common::id_t get_to_activity_id(
std::optional<eid_t> get_to_activity_id(
const config::source_location &to_location) const;
/**
@@ -276,7 +275,7 @@ public:
* @param from_location Source activity
* @return Activity id
*/
common::id_t get_from_activity_id(
std::optional<eid_t> get_from_activity_id(
const config::source_location &from_location) const;
/**
@@ -344,14 +343,14 @@ private:
return block_end_types.count(mt) > 0;
};
bool inline_lambda_operator_call(common::id_t id,
model::activity &new_activity, const model::message &m);
bool inline_lambda_operator_call(
eid_t id, model::activity &new_activity, const model::message &m);
std::map<common::id_t, activity> activities_;
std::map<eid_t, activity> activities_;
std::map<common::id_t, std::unique_ptr<participant>> participants_;
std::map<eid_t, std::unique_ptr<participant>> participants_;
std::set<common::id_t> active_participants_;
std::set<eid_t> active_participants_;
};
} // namespace clanguml::sequence_diagram::model

View File

@@ -20,7 +20,7 @@
namespace clanguml::sequence_diagram::model {
message::message(common::model::message_t type, common::id_t from)
message::message(common::model::message_t type, eid_t from)
: type_{type}
, from_{from}
{
@@ -38,13 +38,13 @@ void message::set_type(common::model::message_t t) { type_ = t; }
common::model::message_t message::type() const { return type_; }
void message::set_from(common::id_t f) { from_ = f; }
void message::set_from(eid_t f) { from_ = f; }
common::id_t message::from() const { return from_; }
eid_t message::from() const { return from_; }
void message::set_to(common::id_t t) { to_ = t; }
void message::set_to(eid_t t) { to_ = t; }
common::id_t message::to() const { return to_; }
eid_t message::to() const { return to_; }
void message::set_message_name(std::string name)
{

View File

@@ -38,7 +38,7 @@ public:
* @param type Message type
* @param from Id of originating sequence
*/
message(common::model::message_t type, common::id_t from);
message(common::model::message_t type, eid_t from);
/**
* @brief Equality operator
@@ -67,28 +67,28 @@ public:
*
* @param f Id of the participant from which message originates
*/
void set_from(common::id_t f);
void set_from(eid_t f);
/**
* @brief Get the id of source of message
*
* @return
*/
common::id_t from() const;
eid_t from() const;
/**
* @brief Set the id of the message target
*
* @param t Id of the message target
*/
void set_to(common::id_t t);
void set_to(eid_t t);
/**
* @brief Get the id of the message target
*
* @return Id of the message target
*/
common::id_t to() const;
eid_t to() const;
/**
* @brief Set the message label
@@ -162,9 +162,9 @@ public:
private:
common::model::message_t type_{common::model::message_t::kNone};
common::id_t from_{};
eid_t from_{};
common::id_t to_{};
eid_t to_{};
common::model::message_scope_t scope_{
common::model::message_scope_t::kNormal};

View File

@@ -178,9 +178,9 @@ std::string method::method_name() const { return method_name_; }
std::string method::alias() const
{
assert(class_id_ >= 0);
assert(class_id_.is_global());
return fmt::format("C_{:022}", class_id_);
return fmt::format("C_{:022}", class_id_.value());
}
bool method::is_constructor() const { return is_constructor_; }
@@ -197,7 +197,7 @@ void method::is_assignment(bool a) { is_assignment_ = a; }
void method::set_method_name(const std::string &name) { method_name_ = name; }
void method::set_class_id(common::id_t id) { class_id_ = id; }
void method::set_class_id(eid_t id) { class_id_ = id; }
void method::set_class_full_name(const std::string &name)
{
@@ -238,7 +238,7 @@ std::string method::message_name(message_render_mode mode) const
fmt::join(parameters(), ","), is_const() ? " const" : "", style);
}
common::id_t method::class_id() const { return class_id_; }
eid_t method::class_id() const { return class_id_; }
std::string method::to_string() const
{

View File

@@ -27,6 +27,7 @@
namespace clanguml::sequence_diagram::model {
using clanguml::common::eid_t;
using clanguml::common::model::template_trait;
/**
@@ -190,9 +191,9 @@ public:
*/
void is_lambda(bool is_lambda);
void set_lambda_operator_id(common::id_t id) { lambda_operator_id_ = id; }
void set_lambda_operator_id(eid_t id) { lambda_operator_id_ = id; }
common::id_t lambda_operator_id() const { return lambda_operator_id_; }
eid_t lambda_operator_id() const { return lambda_operator_id_; }
private:
bool is_struct_{false};
@@ -200,7 +201,7 @@ private:
bool is_template_instantiation_{false};
bool is_alias_{false};
bool is_lambda_{false};
common::id_t lambda_operator_id_{0};
eid_t lambda_operator_id_{};
std::string full_name_;
};
@@ -420,7 +421,7 @@ struct method : public function {
*
* @param id Id of the class to which this method belongs to
*/
void set_class_id(common::id_t id);
void set_class_id(eid_t id);
/**
* @brief Set full qualified name of the class
@@ -450,7 +451,7 @@ struct method : public function {
*
* @return Class id
*/
common::id_t class_id() const;
eid_t class_id() const;
/**
* @brief Create a string representation of the participant
@@ -502,7 +503,7 @@ struct method : public function {
void is_assignment(bool a);
private:
common::id_t class_id_{};
eid_t class_id_{};
std::string method_name_;
std::string class_full_name_;
bool is_constructor_{false};

View File

@@ -24,7 +24,7 @@ call_expression_context::call_expression_context() = default;
void call_expression_context::reset()
{
current_caller_id_ = 0;
current_caller_id_ = eid_t{};
current_class_decl_ = nullptr;
current_class_template_decl_ = nullptr;
current_class_template_specialization_decl_ = nullptr;
@@ -130,35 +130,35 @@ void call_expression_context::update(
current_function_template_decl_ = function_template;
}
std::int64_t call_expression_context::caller_id() const
eid_t call_expression_context::caller_id() const
{
if (lambda_caller_id() != 0)
return lambda_caller_id();
if (lambda_caller_id().has_value())
return *lambda_caller_id(); // NOLINT
return current_caller_id_;
}
std::int64_t call_expression_context::lambda_caller_id() const
std::optional<eid_t> call_expression_context::lambda_caller_id() const
{
if (current_lambda_caller_id_.empty())
return 0;
return {};
return current_lambda_caller_id_.top();
}
void call_expression_context::set_caller_id(std::int64_t id)
void call_expression_context::set_caller_id(eid_t id)
{
LOG_DBG("Setting current caller id to {}", id);
current_caller_id_ = id;
}
void call_expression_context::enter_lambda_expression(std::int64_t id)
void call_expression_context::enter_lambda_expression(eid_t id)
{
LOG_DBG("Setting current lambda caller id to {}", id);
assert(id != 0);
assert(id.value() != 0);
current_lambda_caller_id_.push(id);
current_lambda_caller_id_.emplace(id);
}
void call_expression_context::leave_lambda_expression()
@@ -182,7 +182,7 @@ clang::IfStmt *call_expression_context::current_ifstmt() const
void call_expression_context::enter_ifstmt(clang::IfStmt *stmt)
{
if_stmt_stack_.push(stmt);
if_stmt_stack_.emplace(stmt);
}
void call_expression_context::leave_ifstmt()
@@ -197,7 +197,7 @@ void call_expression_context::enter_elseifstmt(clang::IfStmt *stmt)
{
assert(current_ifstmt() != nullptr);
elseif_stmt_stacks_[current_ifstmt()].push(stmt);
elseif_stmt_stacks_[current_ifstmt()].emplace(stmt);
}
clang::IfStmt *call_expression_context::current_elseifstmt() const
@@ -221,7 +221,7 @@ clang::Stmt *call_expression_context::current_loopstmt() const
void call_expression_context::enter_loopstmt(clang::Stmt *stmt)
{
loop_stmt_stack_.push(stmt);
loop_stmt_stack_.emplace(stmt);
}
void call_expression_context::leave_loopstmt()
@@ -241,12 +241,12 @@ call_expression_context::current_callexpr() const
void call_expression_context::enter_callexpr(clang::CallExpr *expr)
{
call_expr_stack_.push(expr);
call_expr_stack_.emplace(expr);
}
void call_expression_context::enter_callexpr(clang::CXXConstructExpr *expr)
{
call_expr_stack_.push(expr);
call_expr_stack_.emplace(expr);
}
void call_expression_context::leave_callexpr()
@@ -266,7 +266,7 @@ clang::Stmt *call_expression_context::current_trystmt() const
void call_expression_context::enter_trystmt(clang::Stmt *stmt)
{
try_stmt_stack_.push(stmt);
try_stmt_stack_.emplace(stmt);
}
void call_expression_context::leave_trystmt()
@@ -285,7 +285,7 @@ clang::SwitchStmt *call_expression_context::current_switchstmt() const
void call_expression_context::enter_switchstmt(clang::SwitchStmt *stmt)
{
switch_stmt_stack_.push(stmt);
switch_stmt_stack_.emplace(stmt);
}
void call_expression_context::leave_switchstmt()
@@ -306,7 +306,7 @@ call_expression_context::current_conditionaloperator() const
void call_expression_context::enter_conditionaloperator(
clang::ConditionalOperator *stmt)
{
conditional_operator_stack_.push(stmt);
conditional_operator_stack_.emplace(stmt);
}
void call_expression_context::leave_conditionaloperator()

View File

@@ -28,6 +28,8 @@
namespace clanguml::sequence_diagram::visitor {
using clanguml::common::eid_t;
/**
* @brief This class is used to track current context of the call expressions.
*
@@ -116,14 +118,14 @@ struct call_expression_context {
*
* @param id Set current caller id.
*/
void set_caller_id(std::int64_t id);
void set_caller_id(eid_t id);
/**
* @brief Get current caller id
*
* @return Id of the current caller participant
*/
std::int64_t caller_id() const;
eid_t caller_id() const;
/**
* @brief Get the id of the current lambda caller.
@@ -133,14 +135,14 @@ struct call_expression_context {
*
* @return Current lambda caller id, or 0 if current caller is not lambda.
*/
std::int64_t lambda_caller_id() const;
std::optional<eid_t> lambda_caller_id() const;
/**
* @brief Enter a lambda expression
*
* @param id Lambda id
*/
void enter_lambda_expression(std::int64_t id);
void enter_lambda_expression(eid_t id);
/**
* @brief Leave current lambda expression
@@ -315,8 +317,8 @@ struct call_expression_context {
clang::FunctionTemplateDecl *current_function_template_decl_{nullptr};
private:
std::int64_t current_caller_id_{0};
std::stack<std::int64_t> current_lambda_caller_id_;
eid_t current_caller_id_{};
std::stack<eid_t> current_lambda_caller_id_;
std::stack<callexpr_stack_t> call_expr_stack_;

View File

@@ -64,7 +64,7 @@ bool translation_unit_visitor::VisitCXXRecordDecl(
// Skip this class if it's parent template is already in the model
if (declaration->isTemplated() &&
declaration->getDescribedTemplate() != nullptr) {
if (get_unique_id(declaration->getDescribedTemplate()->getID()))
if (get_unique_id(eid_t{declaration->getDescribedTemplate()->getID()}))
return true;
}
@@ -335,7 +335,8 @@ bool translation_unit_visitor::VisitFunctionDecl(
if (declaration->getDescribedTemplate() != nullptr) {
// If the described templated of this function is already in the
// model skip it:
if (get_unique_id(declaration->getDescribedTemplate()->getID()))
if (get_unique_id(
eid_t{declaration->getDescribedTemplate()->getID()}))
return true;
}
}
@@ -474,7 +475,7 @@ bool translation_unit_visitor::VisitLambdaExpr(clang::LambdaExpr *expr)
// method function would be excluded by filters
if (std::holds_alternative<clang::CallExpr *>(
context().current_callexpr()) &&
(context().lambda_caller_id() == 0)) {
(!context().lambda_caller_id().has_value())) {
using clanguml::common::model::message_t;
using clanguml::sequence_diagram::model::message;
@@ -661,7 +662,7 @@ bool translation_unit_visitor::TraverseCompoundStmt(clang::CompoundStmt *stmt)
if (current_elseifstmt->getElse() == stmt) {
const auto current_caller_id = context().caller_id();
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
model::message m{message_t::kElse, current_caller_id};
set_source_location(*stmt, m);
diagram().add_message(std::move(m));
@@ -672,7 +673,7 @@ bool translation_unit_visitor::TraverseCompoundStmt(clang::CompoundStmt *stmt)
if (current_ifstmt->getElse() == stmt) {
const auto current_caller_id = context().caller_id();
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
model::message m{message_t::kElse, current_caller_id};
set_source_location(*stmt, m);
diagram().add_message(std::move(m));
@@ -718,7 +719,7 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
std::any_of(current_elseifstmt->children().begin(),
current_elseifstmt->children().end(), child_stmt_compare);
if ((current_caller_id != 0) && !stmt->isConstexpr()) {
if ((current_caller_id.value() != 0) && !stmt->isConstexpr()) {
if (elseif_block) {
context().enter_elseifstmt(stmt);
@@ -743,7 +744,7 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
RecursiveASTVisitor<translation_unit_visitor>::TraverseIfStmt(stmt);
if ((current_caller_id != 0) && !stmt->isConstexpr()) {
if ((current_caller_id.value() != 0) && !stmt->isConstexpr()) {
if (!elseif_block) {
diagram().end_block_message(
{message_t::kIfEnd, current_caller_id}, message_t::kIf);
@@ -766,7 +767,7 @@ bool translation_unit_visitor::TraverseWhileStmt(clang::WhileStmt *stmt)
if (config().generate_condition_statements())
condition_text = common::get_condition_text(source_manager(), stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().enter_loopstmt(stmt);
message m{message_t::kWhile, current_caller_id};
set_source_location(*stmt, m);
@@ -777,7 +778,7 @@ bool translation_unit_visitor::TraverseWhileStmt(clang::WhileStmt *stmt)
}
RecursiveASTVisitor<translation_unit_visitor>::TraverseWhileStmt(stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
diagram().end_block_message(
{message_t::kWhileEnd, current_caller_id}, message_t::kWhile);
context().leave_loopstmt();
@@ -798,7 +799,7 @@ bool translation_unit_visitor::TraverseDoStmt(clang::DoStmt *stmt)
if (config().generate_condition_statements())
condition_text = common::get_condition_text(source_manager(), stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().enter_loopstmt(stmt);
message m{message_t::kDo, current_caller_id};
set_source_location(*stmt, m);
@@ -810,7 +811,7 @@ bool translation_unit_visitor::TraverseDoStmt(clang::DoStmt *stmt)
RecursiveASTVisitor<translation_unit_visitor>::TraverseDoStmt(stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
diagram().end_block_message(
{message_t::kDoEnd, current_caller_id}, message_t::kDo);
context().leave_loopstmt();
@@ -831,7 +832,7 @@ bool translation_unit_visitor::TraverseForStmt(clang::ForStmt *stmt)
if (config().generate_condition_statements())
condition_text = common::get_condition_text(source_manager(), stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().enter_loopstmt(stmt);
message m{message_t::kFor, current_caller_id};
set_source_location(*stmt, m);
@@ -845,7 +846,7 @@ bool translation_unit_visitor::TraverseForStmt(clang::ForStmt *stmt)
RecursiveASTVisitor<translation_unit_visitor>::TraverseForStmt(stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
diagram().end_block_message(
{message_t::kForEnd, current_caller_id}, message_t::kFor);
context().leave_loopstmt();
@@ -862,7 +863,7 @@ bool translation_unit_visitor::TraverseCXXTryStmt(clang::CXXTryStmt *stmt)
const auto current_caller_id = context().caller_id();
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().enter_trystmt(stmt);
message m{message_t::kTry, current_caller_id};
set_source_location(*stmt, m);
@@ -873,7 +874,7 @@ bool translation_unit_visitor::TraverseCXXTryStmt(clang::CXXTryStmt *stmt)
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXTryStmt(stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
diagram().end_block_message(
{message_t::kTryEnd, current_caller_id}, message_t::kTry);
context().leave_trystmt();
@@ -890,7 +891,8 @@ bool translation_unit_visitor::TraverseCXXCatchStmt(clang::CXXCatchStmt *stmt)
const auto current_caller_id = context().caller_id();
if ((current_caller_id != 0) && (context().current_trystmt() != nullptr)) {
if ((current_caller_id.value() != 0) &&
(context().current_trystmt() != nullptr)) {
std::string caught_type;
if (stmt->getCaughtType().isNull())
caught_type = "...";
@@ -921,7 +923,7 @@ bool translation_unit_visitor::TraverseCXXForRangeStmt(
if (config().generate_condition_statements())
condition_text = common::get_condition_text(source_manager(), stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().enter_loopstmt(stmt);
message m{message_t::kFor, current_caller_id};
set_source_location(*stmt, m);
@@ -934,7 +936,7 @@ bool translation_unit_visitor::TraverseCXXForRangeStmt(
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXForRangeStmt(
stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
diagram().end_block_message(
{message_t::kForEnd, current_caller_id}, message_t::kFor);
context().leave_loopstmt();
@@ -949,7 +951,7 @@ bool translation_unit_visitor::TraverseSwitchStmt(clang::SwitchStmt *stmt)
const auto current_caller_id = context().caller_id();
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().enter_switchstmt(stmt);
model::message m{message_t::kSwitch, current_caller_id};
set_source_location(*stmt, m);
@@ -960,7 +962,7 @@ bool translation_unit_visitor::TraverseSwitchStmt(clang::SwitchStmt *stmt)
RecursiveASTVisitor<translation_unit_visitor>::TraverseSwitchStmt(stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().leave_switchstmt();
diagram().end_block_message(
{message_t::kSwitchEnd, current_caller_id}, message_t::kSwitch);
@@ -975,7 +977,7 @@ bool translation_unit_visitor::TraverseCaseStmt(clang::CaseStmt *stmt)
const auto current_caller_id = context().caller_id();
if ((current_caller_id != 0) &&
if ((current_caller_id.value() != 0) &&
(context().current_switchstmt() != nullptr)) {
model::message m{message_t::kCase, current_caller_id};
m.set_message_name(common::to_string(stmt->getLHS()));
@@ -993,7 +995,7 @@ bool translation_unit_visitor::TraverseDefaultStmt(clang::DefaultStmt *stmt)
const auto current_caller_id = context().caller_id();
if ((current_caller_id != 0) &&
if ((current_caller_id.value() != 0) &&
(context().current_switchstmt() != nullptr)) {
model::message m{message_t::kCase, current_caller_id};
m.set_message_name("default");
@@ -1016,7 +1018,7 @@ bool translation_unit_visitor::TraverseConditionalOperator(
if (config().generate_condition_statements())
condition_text = common::get_condition_text(source_manager(), stmt);
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().enter_conditionaloperator(stmt);
model::message m{message_t::kConditional, current_caller_id};
set_source_location(*stmt, m);
@@ -1032,7 +1034,7 @@ bool translation_unit_visitor::TraverseConditionalOperator(
RecursiveASTVisitor<translation_unit_visitor>::TraverseStmt(
stmt->getTrueExpr());
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
model::message m{message_t::kConditionalElse, current_caller_id};
set_source_location(*stmt, m);
diagram().add_message(std::move(m));
@@ -1041,7 +1043,7 @@ bool translation_unit_visitor::TraverseConditionalOperator(
RecursiveASTVisitor<translation_unit_visitor>::TraverseStmt(
stmt->getFalseExpr());
if (current_caller_id != 0) {
if (current_caller_id.value() != 0) {
context().leave_conditionaloperator();
diagram().end_block_message(
{message_t::kConditionalEnd, current_caller_id},
@@ -1185,7 +1187,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
}
// Add message to diagram
if (m.from() > 0 && m.to() > 0) {
if (m.from().value() > 0 && m.to().value() > 0) {
m.set_comment(stripped_comment);
if (diagram().sequences().find(m.from()) ==
@@ -1269,7 +1271,7 @@ bool translation_unit_visitor::VisitCXXConstructExpr(
if (!process_construct_expression(m, expr))
return true;
if (m.from() > 0 && m.to() > 0) {
if (m.from().value() > 0 && m.to().value() > 0) {
if (diagram().sequences().find(m.from()) ==
diagram().sequences().end()) {
activity a{m.from()};
@@ -1311,10 +1313,10 @@ bool translation_unit_visitor::process_cuda_kernel_call_expression(
auto callee_name = callee_function->getQualifiedNameAsString() + "()";
const auto maybe_id = get_unique_id(callee_function->getID());
const auto maybe_id = get_unique_id(eid_t{callee_function->getID()});
if (!maybe_id.has_value()) {
// This is hopefully not an interesting call...
m.set_to(callee_function->getID());
m.set_to(eid_t{callee_function->getID()});
}
else {
m.set_to(maybe_id.value());
@@ -1349,16 +1351,16 @@ bool translation_unit_visitor::process_operator_call_expression(
auto lambda_name = make_lambda_name(lambda_method->getParent());
m.set_to(lambda_method->getParent()->getID());
m.set_to(eid_t{lambda_method->getParent()->getID()});
}
else {
auto maybe_id =
get_unique_id(operator_call_expr->getCalleeDecl()->getID());
get_unique_id(eid_t{operator_call_expr->getCalleeDecl()->getID()});
if (maybe_id.has_value()) {
m.set_to(maybe_id.value());
}
else {
m.set_to(operator_call_expr->getCalleeDecl()->getID());
m.set_to(eid_t{operator_call_expr->getCalleeDecl()->getID()});
}
}
@@ -1384,19 +1386,19 @@ bool translation_unit_visitor::process_construct_expression(
constructor->getID(),
construct_expr->getBeginLoc().printToString(source_manager()));
auto maybe_id = get_unique_id(constructor->getID());
auto maybe_id = get_unique_id(eid_t{constructor->getID()});
if (maybe_id.has_value()) {
m.set_to(maybe_id.value());
}
else {
m.set_to(constructor->getID());
m.set_to(eid_t{constructor->getID()});
}
m.set_message_name(
fmt::format("{}::{}", constructor_parent->getQualifiedNameAsString(),
constructor_parent->getNameAsString()));
diagram().add_active_participant(constructor->getID());
diagram().add_active_participant(eid_t{constructor->getID()});
return true;
}
@@ -1421,7 +1423,7 @@ bool translation_unit_visitor::process_class_method_call_expression(
if (!should_include(callee_decl) || !should_include(method_decl))
return false;
m.set_to(method_decl->getID());
m.set_to(eid_t{method_decl->getID()});
m.set_message_name(method_decl->getNameAsString());
m.set_return_type(
method_call_expr->getCallReturnType(*context().get_ast_context())
@@ -1430,7 +1432,7 @@ bool translation_unit_visitor::process_class_method_call_expression(
LOG_TRACE("Set callee method id {} for method name {}", m.to(),
method_decl->getQualifiedNameAsString());
diagram().add_active_participant(method_decl->getID());
diagram().add_active_participant(eid_t{method_decl->getID()});
return true;
}
@@ -1507,7 +1509,7 @@ bool translation_unit_visitor::process_class_template_method_call_expression(
dependent_member_callee->getMember().getAsString());
if (const auto maybe_id =
get_unique_id(template_declaration->getID());
get_unique_id(eid_t{template_declaration->getID()});
maybe_id.has_value())
diagram().add_active_participant(maybe_id.value());
}
@@ -1544,10 +1546,10 @@ bool translation_unit_visitor::process_function_call_expression(
auto callee_name = callee_function->getQualifiedNameAsString() + "()";
const auto maybe_id = get_unique_id(callee_function->getID());
const auto maybe_id = get_unique_id(eid_t{callee_function->getID()});
if (!maybe_id.has_value()) {
// This is hopefully not an interesting call...
m.set_to(callee_function->getID());
m.set_to(eid_t{callee_function->getID()});
}
else {
m.set_to(maybe_id.value());
@@ -1567,7 +1569,7 @@ bool translation_unit_visitor::process_lambda_call_expression(
if (lambda_expr == nullptr)
return true;
const auto lambda_class_id = lambda_expr->getLambdaClass()->getID();
const auto lambda_class_id = eid_t{lambda_expr->getLambdaClass()->getID()};
const auto maybe_id = get_unique_id(lambda_class_id);
if (!maybe_id.has_value())
m.set_to(lambda_class_id);
@@ -1592,9 +1594,9 @@ bool translation_unit_visitor::process_unresolved_lookup_call_expression(
const auto *ftd =
clang::dyn_cast_or_null<clang::FunctionTemplateDecl>(decl);
const auto maybe_id = get_unique_id(ftd->getID());
const auto maybe_id = get_unique_id(eid_t{ftd->getID()});
if (!maybe_id.has_value())
m.set_to(ftd->getID());
m.set_to(eid_t{ftd->getID()});
else {
m.set_to(maybe_id.value());
}
@@ -1606,9 +1608,9 @@ bool translation_unit_visitor::process_unresolved_lookup_call_expression(
const auto *fd =
clang::dyn_cast_or_null<clang::FunctionDecl>(decl);
const auto maybe_id = get_unique_id(fd->getID());
const auto maybe_id = get_unique_id(eid_t{fd->getID()});
if (!maybe_id.has_value())
m.set_to(fd->getID());
m.set_to(eid_t{fd->getID()});
else {
m.set_to(maybe_id.value());
}
@@ -1678,24 +1680,24 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls)
// - the parent is a regular C++ class/struct
// - the parent is a class template declaration/specialization
// - the parent is a lambda (i.e. this is a nested lambda expression)
std::optional<common::id_t> id_opt;
std::optional<eid_t> id_opt;
const auto *parent_record_decl =
clang::dyn_cast<clang::RecordDecl>(parent);
assert(parent_record_decl != nullptr);
int64_t local_id = parent_record_decl->getID();
const eid_t ast_id{parent_record_decl->getID()};
// First check if the parent has been added to the diagram as
// regular class
id_opt = get_unique_id(local_id);
id_opt = get_unique_id(ast_id);
// If not, check if the parent template declaration is in the model
if (!id_opt &&
(parent_record_decl->getDescribedTemplate() != nullptr)) {
parent_record_decl->getDescribedTemplate()->getID();
if (parent_record_decl->getDescribedTemplate() != nullptr)
id_opt = get_unique_id(local_id);
id_opt = get_unique_id(ast_id);
}
if (!id_opt)
@@ -1769,21 +1771,21 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls)
return c_ptr;
}
void translation_unit_visitor::set_unique_id(
int64_t local_id, common::id_t global_id)
void translation_unit_visitor::set_unique_id(int64_t local_id, eid_t global_id)
{
LOG_TRACE("Setting local element mapping {} --> {}", local_id, global_id);
local_ast_id_map_[local_id] = global_id;
}
std::optional<common::id_t> translation_unit_visitor::get_unique_id(
int64_t local_id) const
std::optional<eid_t> translation_unit_visitor::get_unique_id(
eid_t local_id) const
{
if (local_ast_id_map_.find(local_id) == local_ast_id_map_.end())
if (local_ast_id_map_.find(local_id.ast_local_value()) ==
local_ast_id_map_.end())
return {};
return local_ast_id_map_.at(local_id);
return local_ast_id_map_.at(local_id.ast_local_value());
}
std::unique_ptr<model::function_template>
@@ -1924,14 +1926,16 @@ std::string translation_unit_visitor::make_lambda_name(
const auto location = cls->getLocation();
const std::string source_location{lambda_source_location(location)};
if (context().lambda_caller_id() != 0) {
const auto maybe_lambda_caller_id = context().lambda_caller_id();
if (maybe_lambda_caller_id.has_value()) {
// Parent is also a lambda (this id points to a lambda operator())
std::string parent_lambda_class_name{"()"};
if (diagram().get_participant<model::method>(
context().lambda_caller_id())) {
auto parent_lambda_class_id = diagram()
maybe_lambda_caller_id.value())) {
auto parent_lambda_class_id =
diagram()
.get_participant<model::method>(
context().lambda_caller_id())
maybe_lambda_caller_id.value())
.value()
.class_id();
@@ -1948,7 +1952,7 @@ std::string translation_unit_visitor::make_lambda_name(
result = fmt::format(
"{}##(lambda {})", parent_lambda_class_name, source_location);
}
else if (context().caller_id() != 0 &&
else if (context().caller_id().value() != 0 &&
get_participant(context().caller_id()).has_value()) {
auto parent_full_name =
get_participant(context().caller_id()).value().full_name_no_ns();
@@ -2037,7 +2041,7 @@ void translation_unit_visitor::ensure_lambda_messages_have_operator_as_target()
auto participant = diagram().get_participant<model::class_>(m.to());
if (participant && participant.value().is_lambda() &&
participant.value().lambda_operator_id() != 0) {
participant.value().lambda_operator_id().value() != 0) {
LOG_DBG("Changing lambda expression target id from {} to {}",
m.to(), participant.value().lambda_operator_id());
@@ -2050,14 +2054,17 @@ void translation_unit_visitor::ensure_lambda_messages_have_operator_as_target()
void translation_unit_visitor::resolve_ids_to_global()
{
std::set<common::id_t> active_participants_unique;
std::set<eid_t> active_participants_unique;
// Change all active participants AST local ids to diagram global ids
for (auto id : diagram().active_participants()) {
if (local_ast_id_map_.find(id) != local_ast_id_map_.end()) {
active_participants_unique.emplace(local_ast_id_map_.at(id));
if (!id.is_global() &&
local_ast_id_map_.find(id.ast_local_value()) !=
local_ast_id_map_.end()) {
active_participants_unique.emplace(
local_ast_id_map_.at(id.ast_local_value()));
}
else {
else if (id.is_global()) {
active_participants_unique.emplace(id);
}
}
@@ -2067,8 +2074,10 @@ void translation_unit_visitor::resolve_ids_to_global()
// Change all message callees AST local ids to diagram global ids
for (auto &[id, activity] : diagram().sequences()) {
for (auto &m : activity.messages()) {
if (local_ast_id_map_.find(m.to()) != local_ast_id_map_.end()) {
m.set_to(local_ast_id_map_.at(m.to()));
if (!m.to().is_global() &&
local_ast_id_map_.find(m.to().ast_local_value()) !=
local_ast_id_map_.end()) {
m.set_to(local_ast_id_map_.at(m.to().ast_local_value()));
}
}
}
@@ -2280,7 +2289,7 @@ bool translation_unit_visitor::should_include(
std::optional<std::string> translation_unit_visitor::get_expression_comment(
const clang::SourceManager &sm, const clang::ASTContext &context,
const int64_t caller_id, const clang::Stmt *stmt)
const eid_t caller_id, const clang::Stmt *stmt)
{
const auto *raw_comment =
clanguml::common::get_expression_raw_comment(sm, context, stmt);
@@ -2288,7 +2297,9 @@ std::optional<std::string> translation_unit_visitor::get_expression_comment(
if (raw_comment == nullptr)
return {};
if (!processed_comments_by_caller_id_.emplace(caller_id, raw_comment)
if (!caller_id.is_global() &&
!processed_comments_by_caller_id_
.emplace(caller_id.ast_local_value(), raw_comment)
.second) {
return {};
}

View File

@@ -166,7 +166,7 @@ public:
{
assert(decl != nullptr);
auto unique_participant_id = get_unique_id(decl->getID());
auto unique_participant_id = get_unique_id(eid_t{decl->getID()});
if (!unique_participant_id.has_value())
return {};
@@ -185,7 +185,7 @@ public:
{
assert(decl != nullptr);
auto unique_participant_id = get_unique_id(decl->getID());
auto unique_participant_id = get_unique_id(eid_t{decl->getID()});
if (!unique_participant_id.has_value())
return {};
@@ -200,7 +200,7 @@ public:
* @return Optional reference to participant diagram element
*/
template <typename T = model::participant>
common::optional_ref<T> get_participant(const common::id_t id)
common::optional_ref<T> get_participant(const eid_t id)
{
if (diagram().participants().find(id) == diagram().participants().end())
return {};
@@ -217,7 +217,7 @@ public:
* @return Optional reference to participant diagram element
*/
template <typename T = model::participant>
common::optional_ref<T> get_participant(common::id_t id) const
common::optional_ref<T> get_participant(eid_t id) const
{
if (diagram().participants().find(id) == diagram().participants().end())
return {};
@@ -235,7 +235,7 @@ public:
* @param local_id Local AST element id
* @param global_id Globa diagram element id
*/
void set_unique_id(int64_t local_id, common::id_t global_id);
void set_unique_id(int64_t local_id, eid_t global_id);
/**
* @brief Retrieve the global `clang-uml` entity id based on the Clang
@@ -243,7 +243,7 @@ public:
* @param local_id AST local element id
* @return Global diagram element id
*/
std::optional<common::id_t> get_unique_id(int64_t local_id) const;
std::optional<eid_t> get_unique_id(eid_t local_id) const;
/**
* @brief Finalize diagram model for this translation unit
@@ -469,7 +469,7 @@ private:
std::optional<std::string> get_expression_comment(
const clang::SourceManager &sm, const clang::ASTContext &context,
int64_t caller_id, const clang::Stmt *stmt);
eid_t caller_id, const clang::Stmt *stmt);
/**
* @brief Initializes model message from comment call directive
@@ -502,15 +502,14 @@ private:
std::map<clang::CXXConstructExpr *, model::message>
construct_expr_message_map_;
std::map<common::id_t,
std::unique_ptr<clanguml::sequence_diagram::model::class_>>
std::map<eid_t, std::unique_ptr<clanguml::sequence_diagram::model::class_>>
forward_declarations_;
/**
* @todo Refactor to @ref ast_id_mapper
*/
std::map</* local id from ->getID() */ int64_t,
/* global ID based on full name */ common::id_t>
/* global ID based on full name */ eid_t>
local_ast_id_map_;
std::map<int64_t /* local anonymous struct id */,

View File

@@ -164,7 +164,7 @@ template <typename T, typename S>
std::unique_ptr<T> unique_pointer_cast(std::unique_ptr<S> &&p) noexcept
{
if (T *const converted = dynamic_cast<T *>(p.get())) {
p.release(); // NOLINT
std::move(p).release(); // NOLINT
return std::unique_ptr<T>{converted};
}

View File

@@ -84,6 +84,7 @@ if(APPLE)
endif(APPLE)
set(TEST_NAMES
test_types
test_util
test_model
test_cases

43
tests/test_types.cc Normal file
View File

@@ -0,0 +1,43 @@
/**
* @file tests/test_types.cc
*
* Copyright (c) 2021-2024 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.
*/
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "common/types.h"
#include "doctest/doctest.h"
TEST_CASE("Test eid_t")
{
using clanguml::common::eid_t;
eid_t empty{};
REQUIRE(empty.is_global());
REQUIRE_EQ(empty.value(), 0);
eid_t local_id{(int64_t)100};
REQUIRE_EQ(local_id.ast_local_value(), 100);
REQUIRE_EQ(local_id.value(), 100);
REQUIRE(!local_id.is_global());
eid_t global_id{(uint64_t)100};
REQUIRE_EQ(global_id.value(), 100);
REQUIRE(global_id.is_global());
REQUIRE(local_id != global_id);
}