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

View File

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

View File

@@ -488,7 +488,7 @@ void generator::generate_relationships(
plantuml_common::to_plantuml(r, config())); plantuml_common::to_plantuml(r, config()));
std::stringstream relstr; std::stringstream relstr;
clanguml::common::id_t destination{0}; eid_t destination{};
try { try {
destination = r.destination(); destination = r.destination();
@@ -583,7 +583,7 @@ void generator::generate_relationships(
LOG_DBG("== Processing relationship {}", to_string(r.type())); LOG_DBG("== Processing relationship {}", to_string(r.type()));
std::stringstream relstr; std::stringstream relstr;
clanguml::common::id_t destination{0}; eid_t destination{};
try { try {
destination = r.destination(); destination = r.destination();
@@ -664,7 +664,7 @@ void generator::generate_relationships(const enum_ &e, std::ostream &ostr) const
if (!model().should_include(r.type())) if (!model().should_include(r.type()))
continue; continue;
clanguml::common::id_t destination{0}; eid_t destination{};
std::stringstream relstr; std::stringstream relstr;
try { try {
destination = r.destination(); 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::class_method;
using clanguml::class_diagram::model::concept_; using clanguml::class_diagram::model::concept_;
using clanguml::class_diagram::model::enum_; using clanguml::class_diagram::model::enum_;
using clanguml::common::eid_t;
using clanguml::common::model::access_t; using clanguml::common::model::access_t;
using clanguml::common::model::package; using clanguml::common::model::package;
using clanguml::common::model::relationship; 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_> const std::reference_wrapper<clanguml::class_diagram::model::class_>
&key) const &key) const
{ {
using clanguml::common::id_t; return std::hash<uint64_t>{}(key.get().id().value());
return std::hash<id_t>{}(key.get().id());
} }
}; };
} // namespace std } // 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_; } 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; } void class_parent::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; }

View File

@@ -25,6 +25,8 @@
namespace clanguml::class_diagram::model { namespace clanguml::class_diagram::model {
using clanguml::common::eid_t;
/** /**
* @brief Class parent relationship model. * @brief Class parent relationship model.
* *
@@ -59,14 +61,14 @@ public:
* *
* @param id Id of the parent class. * @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. * @brief Get the id of class parent.
* *
* @return Id of the parent class. * @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. * @brief Set whether the parent is virtual.
@@ -97,7 +99,7 @@ public:
common::model::access_t access() const; common::model::access_t access() const;
private: private:
clanguml::common::id_t id_{}; eid_t id_{};
std::string name_; std::string name_;
bool is_virtual_{false}; bool is_virtual_{false};
common::model::access_t access_{common::model::access_t::kPublic}; 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( 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; 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(), const auto has_class = std::any_of(classes().begin(), classes().end(),
[id](const auto &c) { return c.get().id() == id; }); [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; }); [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); LOG_DBG("Looking for alias for {}", id);
@@ -224,12 +224,12 @@ inja::json diagram::context() const
void diagram::remove_redundant_dependencies() void diagram::remove_redundant_dependencies()
{ {
using common::id_t; using common::eid_t;
using common::model::relationship; using common::model::relationship;
using common::model::relationship_t; using common::model::relationship_t;
for (auto &c : element_view<class_>::view()) { 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()) { for (auto &r : c.get().relationships()) {
if (r.type() != relationship_t::kDependency) if (r.type() != relationship_t::kDependency)

View File

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

View File

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

View File

@@ -22,7 +22,6 @@
#include "class_diagram/generators/plantuml/class_diagram_generator.h" #include "class_diagram/generators/plantuml/class_diagram_generator.h"
#include "cli/cli_handler.h" #include "cli/cli_handler.h"
#include "common/compilation_database.h" #include "common/compilation_database.h"
#include "common/generators/generators.h"
#include "common/model/diagram_filter.h" #include "common/model/diagram_filter.h"
#include "config/config.h" #include "config/config.h"
#include "include_diagram/generators/json/include_diagram_generator.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) 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())}, {"name", common::generators::json::render_name(c.name())},
{"namespace", c.get_namespace().to_string()}, {"type", c.type_name()}, {"namespace", c.get_namespace().to_string()}, {"type", c.type_name()},
{"display_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) void to_json(nlohmann::json &j, const relationship &c)
{ {
j["type"] = to_string(c.type()); 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()) if (!c.multiplicity_source().empty())
j["multiplicity_source"] = c.multiplicity_source(); j["multiplicity_source"] = c.multiplicity_source();
if (!c.multiplicity_destination().empty()) if (!c.multiplicity_destination().empty())

View File

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

View File

@@ -26,25 +26,26 @@ namespace clanguml::common::model {
diagram_element::diagram_element() = default; 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_; 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; parent_element_id_ = id;
} }
std::string diagram_element::alias() const 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) void diagram_element::add_relationship(relationship &&cr)

View File

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

View File

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

View File

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

View File

@@ -21,6 +21,8 @@
namespace clanguml::common::model { namespace clanguml::common::model {
using clanguml::common::eid_t;
/** /**
* Provides type based views over elements in a diagram. * Provides type based views over elements in a diagram.
* *
@@ -58,7 +60,7 @@ public:
* *
* @return * @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_) { for (const auto &e : elements_) {
if (e.get().id() == id) { 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 std::reference_wrapper<clanguml::common::model::package> &key)
const 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 } // namespace std

View File

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

View File

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

View File

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

View File

@@ -20,6 +20,75 @@
namespace clanguml::common { 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 std::string &s) { return s; }
std::string to_string(const string_or_regex &sr) { return sr.to_string(); } std::string to_string(const string_or_regex &sr) { return sr.to_string(); }

View File

@@ -29,13 +29,62 @@
namespace clanguml::common { 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. * Type of output diagram format generator.
*/ */
enum class generator_type_t { 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 */ json, /*!< Diagrams will be generated in JSON format */
mermaid /*!< Diagrams will be generated in MermaidJS 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> { }; struct path_or_regex : public or_regex<std::filesystem::path> { };
} // namespace clanguml::common } // 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 { 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); 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 {};
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 } // namespace clanguml::common::visitor

View File

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

View File

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

View File

@@ -42,8 +42,8 @@
namespace clanguml::common::visitor { namespace clanguml::common::visitor {
using found_relationships_t = std::vector< using found_relationships_t =
std::pair<clanguml::common::id_t, common::model::relationship_t>>; std::vector<std::pair<eid_t, common::model::relationship_t>>;
/** /**
* @brief Diagram translation unit visitor base class * @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()); }, [this](const auto &r) { return model().should_include(r.type()); },
[&f, &parent](const auto &r) { [&f, &parent](const auto &r) {
nlohmann::json rel = 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)); 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 void generator::generate(const source_file &f, nlohmann::json &parent) const
{ {
nlohmann::json j; nlohmann::json j;
j["id"] = std::to_string(f.id()); j["id"] = std::to_string(f.id().value());
j["name"] = f.name(); j["name"] = f.name();
auto display_name = f.full_name(false); auto display_name = f.full_name(false);
#if defined(_MSC_VER) #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( 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); return find<source_file>(id);
} }
@@ -51,7 +51,7 @@ void diagram::add_file(std::unique_ptr<common::model::source_file> &&f)
auto &ff = *f; auto &ff = *f;
assert(!ff.name().empty()); assert(!ff.name().empty());
assert(ff.id() != 0); assert(ff.id().value() != 0);
element_view<source_file>::add(ff); element_view<source_file>::add(ff);

View File

@@ -28,6 +28,7 @@
namespace clanguml::include_diagram::model { namespace clanguml::include_diagram::model {
using clanguml::common::eid_t;
using clanguml::common::opt_ref; using clanguml::common::opt_ref;
using clanguml::common::model::diagram_element; using clanguml::common::model::diagram_element;
using clanguml::common::model::source_file; using clanguml::common::model::source_file;
@@ -68,7 +69,7 @@ public:
* @param id Element id. * @param id Element id.
* @return Optional reference to a diagram element. * @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. * @brief Add include diagram element, an include file.
@@ -100,7 +101,7 @@ public:
* @param id Id of the element * @param id Id of the element
* @return Optional reference to a diagram 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. * @brief Convert element id to PlantUML alias.
@@ -158,8 +159,7 @@ opt_ref<ElementT> diagram::find(const std::string &name) const
return {}; return {};
} }
template <typename ElementT> template <typename ElementT> opt_ref<ElementT> diagram::find(eid_t id) const
opt_ref<ElementT> diagram::find(common::id_t id) const
{ {
for (const auto &element : element_view<ElementT>::view()) { for (const auto &element : element_view<ElementT>::view()) {
if (element.get().id() == id) { 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( void translation_unit_visitor::include_visitor::process_internal_header(
const std::filesystem::path &include_path, bool is_system, 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 // Make the path relative with respect to relative_to config option
auto relative_include_path = 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( void translation_unit_visitor::include_visitor::process_external_system_header(
const std::filesystem::path &include_path, const std::filesystem::path &include_path, const eid_t current_file_id)
const common::id_t current_file_id)
{ {
const auto file_name = include_path.filename(); const auto file_name = include_path.filename();
const auto file_name_str = file_name.string(); 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( translation_unit_visitor::include_visitor::process_source_file(
const std::filesystem::path &file) const std::filesystem::path &file)
{ {

View File

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

View File

@@ -44,7 +44,7 @@ void generator::generate_relationships(
dynamic_cast<const package &>(*destination_package))) dynamic_cast<const package &>(*destination_package)))
continue; continue;
rel["source"] = std::to_string(p.id()); rel["source"] = std::to_string(p.id().value());
parent["relationships"].push_back(std::move(rel)); 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(); const auto &uns = config().using_namespace();
if (!uns.starts_with({p.full_name(false)})) { if (!uns.starts_with({p.full_name(false)})) {
nlohmann::json j; nlohmann::json j;
j["id"] = std::to_string(p.id()); j["id"] = std::to_string(p.id().value());
j["name"] = p.name(); j["name"] = p.name();
j["type"] = to_string(config().package_type()); j["type"] = to_string(config().package_type());
j["display_name"] = p.name(); 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( 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); 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); LOG_DBG("Looking for alias for {}", id);

View File

@@ -26,6 +26,7 @@
namespace clanguml::package_diagram::model { namespace clanguml::package_diagram::model {
using clanguml::common::eid_t;
using clanguml::common::opt_ref; using clanguml::common::opt_ref;
using clanguml::common::model::diagram_element; using clanguml::common::model::diagram_element;
using clanguml::common::model::package; using clanguml::common::model::package;
@@ -75,7 +76,7 @@ public:
* @param id Element id. * @param id Element id.
* @return Optional reference to a diagram element. * @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. * @brief Find an element in the diagram by name.
@@ -100,7 +101,7 @@ public:
* @param id Id of the element * @param id Id of the element
* @return Optional reference to a diagram 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. * @brief Find elements in the diagram by regex pattern.
@@ -148,7 +149,7 @@ public:
* @param id Id of a package in the diagram * @param id Id of a package in the diagram
* @return PlantUML alias of the element * @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. * @brief Return the elements JSON context for inja templates.
@@ -213,8 +214,7 @@ opt_ref<ElementT> diagram::find(const std::string &name) const
return {}; return {};
} }
template <typename ElementT> template <typename ElementT> opt_ref<ElementT> diagram::find(eid_t id) const
opt_ref<ElementT> diagram::find(common::id_t id) const
{ {
for (const auto &element : element_view<ElementT>::view()) { for (const auto &element : element_view<ElementT>::view()) {
if (element.get().id() == id) { 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)); p->set_id(common::to_id(*ns));
set_source_location(*ns, *p); set_source_location(*ns, *p);
assert(p->id() > 0); assert(p->id().value() > 0);
if (diagram().should_include(*p) && !diagram().get(p->id())) { if (diagram().should_include(*p) && !diagram().get(p->id())) {
process_comment(*ns, *p); process_comment(*ns, *p);
@@ -282,7 +282,7 @@ void translation_unit_visitor::add_relationships(
auto current_package_id = get_package_id(cls); 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 // These are relationships to a global namespace, and we don't care
// about those // about those
return; return;
@@ -290,7 +290,7 @@ void translation_unit_visitor::add_relationships(
auto current_package = diagram().get(current_package_id); auto current_package = diagram().get(current_package_id);
if (current_package) { if (current_package) {
std::vector<common::id_t> parent_ids = std::vector<eid_t> parent_ids =
get_parent_package_ids(current_package_id); get_parent_package_ids(current_package_id);
for (const auto &dependency : relationships) { 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) { if (config().package_type() == config::package_type_t::kNamespace) {
const auto *namespace_context = const auto *namespace_context =
@@ -677,15 +677,15 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
void translation_unit_visitor::finalize() { } void translation_unit_visitor::finalize() { }
std::vector<common::id_t> translation_unit_visitor::get_parent_package_ids( std::vector<eid_t> translation_unit_visitor::get_parent_package_ids(eid_t id)
common::id_t id)
{ {
std::vector<common::id_t> parent_ids; std::vector<eid_t> parent_ids;
std::optional<common::id_t> parent_id = id; std::optional<eid_t> parent_id = id;
while (parent_id.has_value()) { while (parent_id.has_value()) {
parent_ids.push_back(parent_id.value()); const auto pid = parent_id.value(); // NOLINT
auto parent = this->diagram().get(parent_id.value()); parent_ids.push_back(pid);
auto parent = this->diagram().get(pid);
if (parent) if (parent)
parent_id = parent.value().parent_element_id(); parent_id = parent.value().parent_element_id();
else else

View File

@@ -33,8 +33,10 @@
namespace clanguml::package_diagram::visitor { namespace clanguml::package_diagram::visitor {
using found_relationships_t = std::vector< using clanguml::common::eid_t;
std::pair<clanguml::common::id_t, common::model::relationship_t>>;
using found_relationships_t =
std::vector<std::pair<eid_t, common::model::relationship_t>>;
using visitor_specialization_t = using visitor_specialization_t =
common::visitor::translation_unit_visitor<clanguml::config::package_diagram, common::visitor::translation_unit_visitor<clanguml::config::package_diagram,
@@ -98,7 +100,7 @@ private:
* @param cls C++ entity declaration * @param cls C++ entity declaration
* @return Id of the package containing that 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 * @brief Process class declaration
@@ -203,6 +205,6 @@ private:
void add_relationships( void add_relationships(
clang::Decl *cls, found_relationships_t &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 } // 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) 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 } // namespace clanguml::sequence_diagram::model
@@ -115,8 +115,8 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
msg["name"] = message; msg["name"] = message;
msg["type"] = "message"; msg["type"] = "message";
msg["from"]["activity_id"] = std::to_string(from.value().id()); msg["from"]["activity_id"] = std::to_string(from.value().id().value());
msg["to"]["activity_id"] = std::to_string(to.value().id()); msg["to"]["activity_id"] = std::to_string(to.value().id().value());
if (const auto &cmt = m.comment(); cmt.has_value()) if (const auto &cmt = m.comment(); cmt.has_value())
msg["comment"] = cmt.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(); model().get_participant<model::method>(from.value().id()).value();
msg["from"]["participant_id"] = 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" || else if (from.value().type_name() == "function" ||
from.value().type_name() == "function_template") { from.value().type_name() == "function_template") {
@@ -134,15 +134,17 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
model() model()
.get_participant<model::function>(from.value().id()) .get_participant<model::function>(from.value().id())
.value(); .value();
msg["from"]["participant_id"] = msg["from"]["participant_id"] = std::to_string(
std::to_string(common::to_id(file_participant.file_relative())); common::to_id(file_participant.file_relative()).value());
} }
else { 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") { 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") { 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(); model().get_participant<model::method>(to.value().id()).value();
msg["to"]["participant_id"] = 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" || else if (to.value().type_name() == "function" ||
to.value().type_name() == "function_template") { to.value().type_name() == "function_template") {
@@ -159,15 +161,16 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
model() model()
.get_participant<model::function>(to.value().id()) .get_participant<model::function>(to.value().id())
.value(); .value();
msg["to"]["participant_id"] = msg["to"]["participant_id"] = std::to_string(
std::to_string(common::to_id(file_participant.file_relative())); common::to_id(file_participant.file_relative()).value());
} }
else { 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") { 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"] = msg["source_location"] =
@@ -183,7 +186,7 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const
} }
void generator::generate_activity( 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 // Generate calls from this activity to other activities
for (const auto &m : a.messages()) { for (const auto &m : a.messages()) {
@@ -260,7 +263,7 @@ nlohmann::json &generator::current_block_statement() const
} }
void generator::process_call_message( 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()); visited.push_back(m.from());
@@ -299,7 +302,7 @@ void generator::process_while_message(const message &m) const
nlohmann::json while_block; nlohmann::json while_block;
while_block["type"] = "loop"; while_block["type"] = "loop";
while_block["name"] = "while"; 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()) if (auto text = m.condition_text(); text.has_value())
while_block["condition_text"] = *text; while_block["condition_text"] = *text;
@@ -320,7 +323,7 @@ void generator::process_for_message(const message &m) const
nlohmann::json for_block; nlohmann::json for_block;
for_block["type"] = "loop"; for_block["type"] = "loop";
for_block["name"] = "for"; 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()) if (auto text = m.condition_text(); text.has_value())
for_block["condition_text"] = *text; for_block["condition_text"] = *text;
@@ -341,7 +344,7 @@ void generator::process_do_message(const message &m) const
nlohmann::json do_block; nlohmann::json do_block;
do_block["type"] = "loop"; do_block["type"] = "loop";
do_block["name"] = "do"; 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()) if (auto text = m.condition_text(); text.has_value())
do_block["condition_text"] = *text; do_block["condition_text"] = *text;
@@ -362,7 +365,7 @@ void generator::process_try_message(const message &m) const
nlohmann::json try_block; nlohmann::json try_block;
try_block["type"] = "break"; try_block["type"] = "break";
try_block["name"] = "try"; 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)); 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; nlohmann::json if_block;
if_block["type"] = "alt"; if_block["type"] = "alt";
if_block["name"] = "switch"; 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)); 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; nlohmann::json if_block;
if_block["type"] = "alt"; if_block["type"] = "alt";
if_block["name"] = "conditional"; 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 (auto text = m.condition_text(); text.has_value())
if_block["condition_text"] = *text; if_block["condition_text"] = *text;
@@ -507,7 +510,7 @@ void generator::process_if_message(const message &m) const
nlohmann::json if_block; nlohmann::json if_block;
if_block["type"] = "alt"; if_block["type"] = "alt";
if_block["name"] = "if"; 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 (auto text = m.condition_text(); text.has_value())
if_block["condition_text"] = *text; if_block["condition_text"] = *text;
@@ -538,10 +541,10 @@ void generator::generate_participant(
generate_participant(parent, p.value().id(), true); generate_participant(parent, p.value().id(), true);
} }
common::id_t generator::generate_participant( std::optional<eid_t> generator::generate_participant(
nlohmann::json & /*parent*/, common::id_t id, bool force) const nlohmann::json & /*parent*/, eid_t id, bool force) const
{ {
common::id_t participant_id{0}; std::optional<eid_t> participant_id{};
if (!force) { if (!force) {
for (const auto pid : model().active_participants()) { for (const auto pid : model().active_participants()) {
@@ -554,27 +557,27 @@ common::id_t generator::generate_participant(
else else
participant_id = id; participant_id = id;
if (participant_id == 0) if (!participant_id.has_value())
return participant_id; return participant_id;
if (is_participant_generated(participant_id)) if (is_participant_generated(*participant_id))
return participant_id; return participant_id;
const auto &participant = 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(); const auto participant_type = participant.type_name();
if (participant_type == "method") { if (participant_type == "method") {
auto class_participant_id = auto class_participant_id =
model() model()
.get_participant<model::method>(participant_id) .get_participant<model::method>(*participant_id)
.value() .value()
.class_id(); .class_id();
LOG_DBG("Generating JSON method participant: {}", LOG_DBG("Generating JSON method participant: {}",
model() model()
.get_participant<model::method>(participant_id) .get_participant<model::method>(*participant_id)
.value() .value()
.full_name(false)); .full_name(false));
@@ -584,7 +587,7 @@ common::id_t generator::generate_participant(
.get_participant<model::participant>(class_participant_id) .get_participant<model::participant>(class_participant_id)
.value(); .value();
generated_participants_.emplace(participant_id); generated_participants_.emplace(*participant_id);
generated_participants_.emplace(class_participant_id); generated_participants_.emplace(class_participant_id);
json_["participants"].push_back(class_participant); json_["participants"].push_back(class_participant);
@@ -600,10 +603,11 @@ common::id_t generator::generate_participant(
return class_participant_id; return class_participant_id;
} }
if (!is_participant_generated(participant_id)) { if (!is_participant_generated(*participant_id)) {
for (auto &p : json_["participants"]) { for (auto &p : json_["participants"]) {
if (p.at("id") == std::to_string(class_participant_id)) { if (p.at("id") ==
generated_participants_.emplace(participant_id); std::to_string(class_participant_id.value())) {
generated_participants_.emplace(*participant_id);
p["activities"].push_back(participant); p["activities"].push_back(participant);
return class_participant_id; return class_participant_id;
} }
@@ -617,7 +621,7 @@ common::id_t generator::generate_participant(
// single file // single file
// participant_id will become activity_id within a file participant // participant_id will become activity_id within a file participant
const auto &function_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 = const auto file_participant_id =
common::to_id(function_participant.file_relative()); common::to_id(function_participant.file_relative());
@@ -634,11 +638,11 @@ common::id_t generator::generate_participant(
if (is_participant_generated(file_participant_id)) if (is_participant_generated(file_participant_id))
return 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["type"] = "file";
p.erase("source_location"); p.erase("source_location");
generated_participants_.emplace(participant_id); generated_participants_.emplace(participant_id.value());
p["activities"].push_back(participant); p["activities"].push_back(participant);
json_["participants"].push_back(p); json_["participants"].push_back(p);
@@ -648,10 +652,10 @@ common::id_t generator::generate_participant(
return file_participant_id; return file_participant_id;
} }
if (!is_participant_generated(participant_id)) { if (!is_participant_generated(*participant_id)) {
for (auto &p : json_["participants"]) { for (auto &p : json_["participants"]) {
if (p.at("id") == std::to_string(file_participant_id)) { if (p.at("id") == std::to_string(file_participant_id.value())) {
generated_participants_.emplace(participant_id); generated_participants_.emplace(*participant_id);
p["activities"].push_back(participant); p["activities"].push_back(participant);
} }
} }
@@ -663,12 +667,12 @@ common::id_t generator::generate_participant(
json_["participants"].push_back(participant); json_["participants"].push_back(participant);
} }
generated_participants_.emplace(participant_id); generated_participants_.emplace(*participant_id);
return 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(), return std::find(generated_participants_.begin(),
generated_participants_.end(), 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 from_activity_id = model().get_from_activity_id(from_location);
auto to_activity_id = model().get_to_activity_id(to_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; continue;
auto message_chains_unique = model().get_all_from_to_message_chains( 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; nlohmann::json sequence;
sequence["from_to"]["from"]["location"] = from_location.location; 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"]["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)); 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()) { for (const auto &to_location : config().to()) {
auto to_activity_id = model().get_to_activity_id(to_location); auto to_activity_id = model().get_to_activity_id(to_location);
if (to_activity_id == 0) if (!to_activity_id.has_value())
continue; continue;
auto message_chains_unique = auto message_chains_unique = model().get_all_from_to_message_chains(
model().get_all_from_to_message_chains(0, to_activity_id); eid_t{}, to_activity_id.value());
nlohmann::json sequence; nlohmann::json sequence;
sequence["to"]["location"] = to_location.location; 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)); 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()) { for (const auto &sf : config().from()) {
if (sf.location_type == location_t::function) { if (sf.location_type == location_t::function) {
common::id_t start_from{0}; eid_t start_from{};
std::string start_from_str; std::string start_from_str;
for (const auto &[k, v] : model().sequences()) { for (const auto &[k, v] : model().sequences()) {
const auto &caller = *model().participants().at(v.from()); 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 // Use this to break out of recurrent loops
std::vector<common::id_t> visited_participants; std::vector<eid_t> visited_participants;
const auto &from = const auto &from =
model().get_participant<model::function>(start_from); model().get_participant<model::function>(start_from);
@@ -812,7 +818,7 @@ void generator::generate_diagram(nlohmann::json &parent) const
nlohmann::json sequence; nlohmann::json sequence;
sequence["start_from"]["location"] = sf.location; 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)); block_statements_stack_.push_back(std::ref(sequence));

View File

@@ -32,6 +32,8 @@
namespace clanguml::sequence_diagram::generators::json { namespace clanguml::sequence_diagram::generators::json {
using clanguml::common::eid_t;
std::string render_name(std::string name); std::string render_name(std::string name);
using diagram_config = clanguml::config::sequence_diagram; using diagram_config = clanguml::config::sequence_diagram;
@@ -77,8 +79,8 @@ public:
* the set of active participants * the set of active participants
* @return Id of the generated participant * @return Id of the generated participant
*/ */
common::id_t generate_participant( std::optional<eid_t> generate_participant(
nlohmann::json &parent, common::id_t id, bool force = false) const; nlohmann::json &parent, eid_t id, bool force = false) const;
/** /**
* @brief Generate sequence diagram participant by name * @brief Generate sequence diagram participant by name
@@ -99,7 +101,7 @@ public:
* for breaking infinite recursion on recursive calls * for breaking infinite recursion on recursive calls
*/ */
void generate_activity(const sequence_diagram::model::activity &a, 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. * @brief Get reference to the current block statement.
@@ -120,7 +122,7 @@ private:
* @param id Participant id. * @param id Participant id.
* @return True, if participant has already been generated. * @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 * @brief Process call message
@@ -129,7 +131,7 @@ private:
* @param visited List of already visited participants * @param visited List of already visited participants
*/ */
void process_call_message( 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 * @brief Process `if` statement message
@@ -239,7 +241,7 @@ private:
*/ */
void process_end_while_message() const; 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 // Needed to add "participants" array in a temporary object accessible from
// all methods of the generator // 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, void generator::generate_activity(
std::vector<common::id_t> &visited) const const activity &a, std::ostream &ostr, std::vector<eid_t> &visited) const
{ {
for (const auto &m : a.messages()) { for (const auto &m : a.messages()) {
if (m.in_static_declaration_context()) { if (m.in_static_declaration_context()) {
@@ -352,9 +352,9 @@ void generator::generate_participant(
} }
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) { if (!force) {
for (const auto pid : model().active_participants()) { for (const auto pid : model().active_participants()) {
@@ -424,8 +424,9 @@ void generator::generate_participant(
std::filesystem::path{file_path}, config().root_directory()) std::filesystem::path{file_path}, config().root_directory())
.string()); .string());
ostr << indent(1) << "participant " << fmt::format("C_{:022}", file_id) ostr << indent(1) << "participant "
<< " as " << render_participant_name(participant_name); << fmt::format("C_{:022}", file_id.value()) << " as "
<< render_participant_name(participant_name);
ostr << '\n'; ostr << '\n';
generated_participants_.emplace(file_id); 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(), return std::find(generated_participants_.begin(),
generated_participants_.end(), generated_participants_.end(),
@@ -474,7 +475,7 @@ std::string generator::generate_alias(
config().combine_free_functions_into_file_participants()) { config().combine_free_functions_into_file_participants()) {
const auto file_id = common::to_id(participant.file()); 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(); 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 from_activity_id = model().get_from_activity_id(from_location);
auto to_activity_id = model().get_to_activity_id(to_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; continue;
if (model().participants().count(from_activity_id) == 0) if (model().participants().count(*from_activity_id) == 0)
continue; continue;
if (model().participants().count(to_activity_id) == 0) if (model().participants().count(*to_activity_id) == 0)
continue; continue;
auto message_chains_unique = model().get_all_from_to_message_chains( 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) { for (const auto &mc : message_chains_unique) {
const auto &from = 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" || if (from.value().type_name() == "method" ||
config().combine_free_functions_into_file_participants()) { config().combine_free_functions_into_file_participants()) {
@@ -526,7 +527,7 @@ void generator::generate_diagram(std::ostream &ostr) const
ostr << indent(1) << "participant *\n"; ostr << indent(1) << "participant *\n";
star_participant_generated = true; star_participant_generated = true;
} }
generate_participant(ostr, from_activity_id); generate_participant(ostr, *from_activity_id);
ostr << indent(1) << "* " ostr << indent(1) << "* "
<< common::generators::mermaid::to_mermaid( << common::generators::mermaid::to_mermaid(
message_t::kCall) message_t::kCall)
@@ -545,11 +546,11 @@ void generator::generate_diagram(std::ostream &ostr) const
for (const auto &to_location : config().to()) { for (const auto &to_location : config().to()) {
auto to_activity_id = model().get_to_activity_id(to_location); auto to_activity_id = model().get_to_activity_id(to_location);
if (to_activity_id == 0) if (!to_activity_id)
continue; continue;
auto message_chains_unique = 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) { for (const auto &mc : message_chains_unique) {
const auto from_activity_id = mc.front().from(); 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()) { for (const auto &sf : config().from()) {
if (sf.location_type == location_t::function) { if (sf.location_type == location_t::function) {
common::id_t start_from{0}; eid_t start_from{};
for (const auto &[k, v] : model().sequences()) { for (const auto &[k, v] : model().sequences()) {
if (model().participants().count(v.from()) == 0) if (model().participants().count(v.from()) == 0)
continue; continue;
@@ -602,7 +603,7 @@ void generator::generate_diagram(std::ostream &ostr) const
} }
// Use this to break out of recurrent loops // 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) if (model().participants().count(start_from) == 0)
continue; continue;

View File

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

View File

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

View File

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

View File

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

View File

@@ -35,7 +35,7 @@ public:
* *
* @param id Id of the participant parent for the activity * @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 * @brief Add a message call to the activity
@@ -63,10 +63,10 @@ public:
* *
* @return Id of activity participant * @return Id of activity participant
*/ */
common::id_t from() const; eid_t from() const;
private: private:
common::id_t from_; eid_t from_;
std::vector<message> messages_; 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( 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()) if (participants_.find(id) != participants_.end())
return {*participants_.at(id)}; return {*participants_.at(id)};
@@ -77,6 +77,8 @@ void diagram::add_participant(std::unique_ptr<participant> p)
{ {
const auto participant_id = p->id(); const auto participant_id = p->id();
assert(participant_id.is_global());
if (participants_.find(participant_id) == participants_.end()) { if (participants_.find(participant_id) == participants_.end()) {
LOG_DBG("Adding '{}' participant: {}, {} [{}]", p->type_name(), LOG_DBG("Adding '{}' participant: {}, {} [{}]", p->type_name(),
p->full_name(false), p->id(), 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); 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); return activities_.at(id);
} }
bool diagram::has_activity(common::id_t id) const bool diagram::has_activity(eid_t id) const { return activities_.count(id) > 0; }
{
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) 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_; 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_; return participants_;
} }
const std::map<common::id_t, std::unique_ptr<participant>> & const std::map<eid_t, std::unique_ptr<participant>> &
diagram::participants() const diagram::participants() const
{ {
return participants_; return participants_;
} }
std::set<common::id_t> &diagram::active_participants() std::set<eid_t> &diagram::active_participants() { return 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_; return active_participants_;
} }
@@ -226,10 +222,10 @@ std::vector<std::string> diagram::list_to_values() const
return result; 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 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 &[k, v] : sequences()) {
for (const auto &m : v.messages()) { 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 " LOG_WARN("Failed to find 'to' participant {} for to "
"condition", "condition",
to_location.location); to_location.location);
@@ -255,10 +251,10 @@ common::id_t diagram::get_to_activity_id(
return to_activity; 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 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()) { for (const auto &[k, v] : sequences()) {
const auto &caller = *participants().at(v.from()); 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 " LOG_WARN("Failed to find 'from' participant {} for from "
"condition", "condition",
from_location.location); 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( 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{}; 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()) message_chains_unique.end(), mc) != message_chains_unique.end())
continue; 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); message_chains_unique.push_back(mc);
} }
} }
@@ -411,9 +408,9 @@ bool diagram::is_empty() const
void diagram::inline_lambda_operator_calls() void diagram::inline_lambda_operator_calls()
{ {
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;
for (auto &[id, act] : sequences()) { for (auto &[id, act] : sequences()) {
model::activity new_activity{id}; model::activity new_activity{id};
@@ -485,8 +482,8 @@ void diagram::inline_lambda_operator_calls()
active_participants_ = std::move(active_participants); active_participants_ = std::move(active_participants);
} }
bool diagram::inline_lambda_operator_call(const common::id_t id, bool diagram::inline_lambda_operator_call(
model::activity &new_activity, const model::message &m) const eid_t id, model::activity &new_activity, const model::message &m)
{ {
bool message_call_to_lambda{false}; bool message_call_to_lambda{false};
auto maybe_lambda_operator = get_participant<model::method>(m.to()); auto maybe_lambda_operator = get_participant<model::method>(m.to());

View File

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

View File

@@ -20,7 +20,7 @@
namespace clanguml::sequence_diagram::model { 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} : type_{type}
, from_{from} , 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_; } 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) void message::set_message_name(std::string name)
{ {

View File

@@ -38,7 +38,7 @@ public:
* @param type Message type * @param type Message type
* @param from Id of originating sequence * @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 * @brief Equality operator
@@ -67,28 +67,28 @@ public:
* *
* @param f Id of the participant from which message originates * @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 * @brief Get the id of source of message
* *
* @return * @return
*/ */
common::id_t from() const; eid_t from() const;
/** /**
* @brief Set the id of the message target * @brief Set the id of the message target
* *
* @param t 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 * @brief Get the id of the message target
* *
* @return 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 * @brief Set the message label
@@ -162,9 +162,9 @@ public:
private: private:
common::model::message_t type_{common::model::message_t::kNone}; 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 scope_{
common::model::message_scope_t::kNormal}; 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 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_; } 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_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) 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); 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 std::string method::to_string() const
{ {

View File

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

View File

@@ -24,7 +24,7 @@ call_expression_context::call_expression_context() = default;
void call_expression_context::reset() void call_expression_context::reset()
{ {
current_caller_id_ = 0; current_caller_id_ = eid_t{};
current_class_decl_ = nullptr; current_class_decl_ = nullptr;
current_class_template_decl_ = nullptr; current_class_template_decl_ = nullptr;
current_class_template_specialization_decl_ = nullptr; current_class_template_specialization_decl_ = nullptr;
@@ -130,35 +130,35 @@ void call_expression_context::update(
current_function_template_decl_ = function_template; 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) if (lambda_caller_id().has_value())
return lambda_caller_id(); return *lambda_caller_id(); // NOLINT
return current_caller_id_; 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()) if (current_lambda_caller_id_.empty())
return 0; return {};
return current_lambda_caller_id_.top(); 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); LOG_DBG("Setting current caller id to {}", id);
current_caller_id_ = 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); 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() 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) 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() void call_expression_context::leave_ifstmt()
@@ -197,7 +197,7 @@ void call_expression_context::enter_elseifstmt(clang::IfStmt *stmt)
{ {
assert(current_ifstmt() != nullptr); 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 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) 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() 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) 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) 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() 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) 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() 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) 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() void call_expression_context::leave_switchstmt()
@@ -306,7 +306,7 @@ call_expression_context::current_conditionaloperator() const
void call_expression_context::enter_conditionaloperator( void call_expression_context::enter_conditionaloperator(
clang::ConditionalOperator *stmt) clang::ConditionalOperator *stmt)
{ {
conditional_operator_stack_.push(stmt); conditional_operator_stack_.emplace(stmt);
} }
void call_expression_context::leave_conditionaloperator() void call_expression_context::leave_conditionaloperator()

View File

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

View File

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

View File

@@ -84,6 +84,7 @@ if(APPLE)
endif(APPLE) endif(APPLE)
set(TEST_NAMES set(TEST_NAMES
test_types
test_util test_util
test_model test_model
test_cases 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);
}