Refactored lambda naming in sequence diagrams
This commit is contained in:
@@ -164,6 +164,8 @@ std::string get_source_text(
|
|||||||
return get_source_text_raw(printable_range, sm);
|
return get_source_text_raw(printable_range, sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <> id_t to_id(const std::string &full_name)
|
template <> id_t to_id(const std::string &full_name)
|
||||||
{
|
{
|
||||||
return std::hash<std::string>{}(full_name) >> 3;
|
return std::hash<std::string>{}(full_name) >> 3;
|
||||||
|
|||||||
@@ -36,6 +36,13 @@ generator::generator(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string generator::render_name(std::string name) const
|
||||||
|
{
|
||||||
|
util::replace_all(name, "##", "::");
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
void generator::generate_call(const message &m, std::ostream &ostr) const
|
void generator::generate_call(const message &m, std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
const auto &from = m_model.get_participant<model::participant>(m.from);
|
const auto &from = m_model.get_participant<model::participant>(m.from);
|
||||||
@@ -142,8 +149,8 @@ void generator::generate_participant(std::ostream &ostr, common::id_t id) const
|
|||||||
m_model.get_participant<model::participant>(class_id).value();
|
m_model.get_participant<model::participant>(class_id).value();
|
||||||
|
|
||||||
ostr << "participant \""
|
ostr << "participant \""
|
||||||
<< m_config.using_namespace().relative(
|
<< render_name(m_config.using_namespace().relative(
|
||||||
class_participant.full_name(false))
|
class_participant.full_name(false)))
|
||||||
<< "\" as " << class_participant.alias() << '\n';
|
<< "\" as " << class_participant.alias() << '\n';
|
||||||
|
|
||||||
generated_participants_.emplace(class_id);
|
generated_participants_.emplace(class_id);
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool is_participant_generated(common::id_t id) const;
|
bool is_participant_generated(common::id_t id) const;
|
||||||
|
|
||||||
|
std::string render_name(std::string name) const;
|
||||||
|
|
||||||
mutable std::set<common::id_t> generated_participants_;
|
mutable std::set<common::id_t> generated_participants_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -68,11 +68,22 @@ call_expression_context &translation_unit_visitor::context()
|
|||||||
return call_expression_context_;
|
return call_expression_context_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const call_expression_context &translation_unit_visitor::context() const
|
||||||
|
{
|
||||||
|
return call_expression_context_;
|
||||||
|
}
|
||||||
|
|
||||||
clanguml::sequence_diagram::model::diagram &translation_unit_visitor::diagram()
|
clanguml::sequence_diagram::model::diagram &translation_unit_visitor::diagram()
|
||||||
{
|
{
|
||||||
return diagram_;
|
return diagram_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clanguml::sequence_diagram::model::diagram &
|
||||||
|
translation_unit_visitor::diagram() const
|
||||||
|
{
|
||||||
|
return diagram_;
|
||||||
|
}
|
||||||
|
|
||||||
const clanguml::config::sequence_diagram &
|
const clanguml::config::sequence_diagram &
|
||||||
translation_unit_visitor::config() const
|
translation_unit_visitor::config() const
|
||||||
{
|
{
|
||||||
@@ -920,15 +931,8 @@ translation_unit_visitor::create_class_declaration(clang::CXXRecordDecl *cls)
|
|||||||
else if (cls->isLambda()) {
|
else if (cls->isLambda()) {
|
||||||
c.is_lambda(true);
|
c.is_lambda(true);
|
||||||
if (cls->getParent()) {
|
if (cls->getParent()) {
|
||||||
auto parent_full_name = get_participant(context().caller_id())
|
const auto type_name = make_lambda_name(cls);
|
||||||
.value()
|
|
||||||
.full_name_no_ns();
|
|
||||||
|
|
||||||
const auto location = cls->getLocation();
|
|
||||||
const auto type_name =
|
|
||||||
fmt::format("{}##(lambda {}:{})", parent_full_name,
|
|
||||||
source_manager().getSpellingLineNumber(location),
|
|
||||||
source_manager().getSpellingColumnNumber(location));
|
|
||||||
c.set_name(type_name);
|
c.set_name(type_name);
|
||||||
c.set_namespace(ns);
|
c.set_namespace(ns);
|
||||||
c.set_id(common::to_id(c.full_name(false)));
|
c.set_id(common::to_id(c.full_name(false)));
|
||||||
@@ -1370,17 +1374,8 @@ void translation_unit_visitor::process_template_specialization_argument(
|
|||||||
.full_name(false));
|
.full_name(false));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto parent_full_name = get_participant(context().caller_id())
|
|
||||||
.value()
|
|
||||||
.full_name_no_ns();
|
|
||||||
|
|
||||||
const auto location =
|
|
||||||
arg.getAsType()->getAsCXXRecordDecl()->getLocation();
|
|
||||||
const auto type_name =
|
const auto type_name =
|
||||||
fmt::format("{}##(lambda {}:{})", parent_full_name,
|
make_lambda_name(arg.getAsType()->getAsCXXRecordDecl());
|
||||||
source_manager().getSpellingLineNumber(location),
|
|
||||||
source_manager().getSpellingColumnNumber(location));
|
|
||||||
|
|
||||||
argument.set_name(type_name);
|
argument.set_name(type_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1680,6 +1675,32 @@ bool translation_unit_visitor::simplify_system_template(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string translation_unit_visitor::make_lambda_name(
|
||||||
|
const clang::CXXRecordDecl *cls) const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
const auto location = cls->getLocation();
|
||||||
|
const auto file_line = source_manager().getSpellingLineNumber(location);
|
||||||
|
const auto file_column = source_manager().getSpellingColumnNumber(location);
|
||||||
|
const std::string file_name =
|
||||||
|
util::split(source_manager().getFilename(location).str(), "/").back();
|
||||||
|
|
||||||
|
if (context().caller_id() != 0 &&
|
||||||
|
get_participant(context().caller_id()).has_value()) {
|
||||||
|
auto parent_full_name =
|
||||||
|
get_participant(context().caller_id()).value().full_name_no_ns();
|
||||||
|
|
||||||
|
result = fmt::format("{}##(lambda {}:{}:{})", parent_full_name,
|
||||||
|
file_name, file_line, file_column);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result =
|
||||||
|
fmt::format("(lambda {}:{}:{})", file_name, file_line, file_column);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void translation_unit_visitor::finalize()
|
void translation_unit_visitor::finalize()
|
||||||
{
|
{
|
||||||
for (auto &[id, activity] : diagram().sequences) {
|
for (auto &[id, activity] : diagram().sequences) {
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "call_expression_context.h"
|
||||||
#include "common/visitor/translation_unit_visitor.h"
|
#include "common/visitor/translation_unit_visitor.h"
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "sequence_diagram/model/diagram.h"
|
#include "sequence_diagram/model/diagram.h"
|
||||||
#include "call_expression_context.h"
|
|
||||||
|
|
||||||
#include <clang/AST/Expr.h>
|
#include <clang/AST/Expr.h>
|
||||||
#include <clang/AST/RecursiveASTVisitor.h>
|
#include <clang/AST/RecursiveASTVisitor.h>
|
||||||
@@ -64,10 +64,14 @@ public:
|
|||||||
|
|
||||||
clanguml::sequence_diagram::model::diagram &diagram();
|
clanguml::sequence_diagram::model::diagram &diagram();
|
||||||
|
|
||||||
|
const clanguml::sequence_diagram::model::diagram &diagram() const;
|
||||||
|
|
||||||
const clanguml::config::sequence_diagram &config() const;
|
const clanguml::config::sequence_diagram &config() const;
|
||||||
|
|
||||||
call_expression_context &context();
|
call_expression_context &context();
|
||||||
|
|
||||||
|
const call_expression_context &context() const;
|
||||||
|
|
||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
template <typename T = model::participant>
|
template <typename T = model::participant>
|
||||||
@@ -82,6 +86,18 @@ public:
|
|||||||
return get_participant<T>(unique_participant_id.value());
|
return get_participant<T>(unique_participant_id.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T = model::participant>
|
||||||
|
const common::optional_ref<T> get_participant(const clang::Decl *decl) const
|
||||||
|
{
|
||||||
|
assert(decl != nullptr);
|
||||||
|
|
||||||
|
auto unique_participant_id = get_unique_id(decl->getID());
|
||||||
|
if (!unique_participant_id.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return get_participant<T>(unique_participant_id.value());
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T = model::participant>
|
template <typename T = model::participant>
|
||||||
common::optional_ref<T> get_participant(
|
common::optional_ref<T> get_participant(
|
||||||
const common::model::diagram_element::id_t id)
|
const common::model::diagram_element::id_t id)
|
||||||
@@ -93,6 +109,17 @@ public:
|
|||||||
*(static_cast<T *>(diagram().participants.at(id).get())));
|
*(static_cast<T *>(diagram().participants.at(id).get())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T = model::participant>
|
||||||
|
const common::optional_ref<T> get_participant(
|
||||||
|
const common::model::diagram_element::id_t id) const
|
||||||
|
{
|
||||||
|
if (diagram().participants.find(id) == diagram().participants.end())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return common::optional_ref<T>(
|
||||||
|
*(static_cast<T *>(diagram().participants.at(id).get())));
|
||||||
|
}
|
||||||
|
|
||||||
/// Store the mapping from local clang entity id (obtained using
|
/// Store the mapping from local clang entity id (obtained using
|
||||||
/// getID()) method to clang-uml global id
|
/// getID()) method to clang-uml global id
|
||||||
void set_unique_id(
|
void set_unique_id(
|
||||||
@@ -168,6 +195,8 @@ private:
|
|||||||
bool simplify_system_template(class_diagram::model::template_parameter &ct,
|
bool simplify_system_template(class_diagram::model::template_parameter &ct,
|
||||||
const std::string &full_name);
|
const std::string &full_name);
|
||||||
|
|
||||||
|
std::string make_lambda_name(const clang::CXXRecordDecl *cls) const;
|
||||||
|
|
||||||
bool is_smart_pointer(const clang::TemplateDecl *primary_template) const;
|
bool is_smart_pointer(const clang::TemplateDecl *primary_template) const;
|
||||||
|
|
||||||
bool is_callee_valid_template_specialization(
|
bool is_callee_valid_template_specialization(
|
||||||
|
|||||||
@@ -36,30 +36,35 @@ TEST_CASE("t20012", "[test-case][sequence]")
|
|||||||
|
|
||||||
// Check if all calls exist
|
// Check if all calls exist
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
HasCall(_A("tmain()"), _A("tmain()##(lambda 49:20)"), "operator()"));
|
HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:49:20)"),
|
||||||
REQUIRE_THAT(puml, HasCall(_A("tmain()##(lambda 49:20)"), _A("A"), "a"));
|
"operator()"));
|
||||||
|
REQUIRE_THAT(
|
||||||
|
puml, HasCall(_A("tmain()::(lambda t20012.cc:49:20)"), _A("A"), "a"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aa"));
|
REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aa"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aaa"));
|
REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aaa"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, HasCall(_A("tmain()##(lambda 49:20)"), _A("B"), "b"));
|
REQUIRE_THAT(
|
||||||
|
puml, HasCall(_A("tmain()::(lambda t20012.cc:49:20)"), _A("B"), "b"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bb"));
|
REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bb"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bbb"));
|
REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bbb"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, HasCall(_A("tmain()##(lambda 62:20)"), _A("C"), "c"));
|
REQUIRE_THAT(
|
||||||
|
puml, HasCall(_A("tmain()::(lambda t20012.cc:62:20)"), _A("C"), "c"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "cc"));
|
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "cc"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc"));
|
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc"));
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
HasCall(_A("tmain()##(lambda 62:20)"), _A("tmain()##(lambda 49:20)"),
|
HasCall(_A("tmain()::(lambda t20012.cc:62:20)"),
|
||||||
"operator()"));
|
_A("tmain()::(lambda t20012.cc:49:20)"), "operator()"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc"));
|
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, HasCall(_A("tmain()"), _A("R<R##(lambda 68:9)>"), "r"));
|
|
||||||
REQUIRE_THAT(puml,
|
|
||||||
HasCall(_A("R<R##(lambda 68:9)>"), _A("tmain()##(lambda 68:9)"),
|
|
||||||
"operator()"));
|
|
||||||
REQUIRE_THAT(
|
REQUIRE_THAT(
|
||||||
puml, HasCall(_A("tmain()##(lambda 68:9)"), _A("C"), "c"));
|
puml, HasCall(_A("tmain()"), _A("R<R::(lambda t20012.cc:68:9)>"), "r"));
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
HasCall(_A("R<R::(lambda t20012.cc:68:9)>"),
|
||||||
|
_A("tmain()::(lambda t20012.cc:68:9)"), "operator()"));
|
||||||
|
REQUIRE_THAT(
|
||||||
|
puml, HasCall(_A("tmain()::(lambda t20012.cc:68:9)"), _A("C"), "c"));
|
||||||
|
|
||||||
save_puml(
|
save_puml(
|
||||||
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
|
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
|
||||||
|
|||||||
Reference in New Issue
Block a user