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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <> id_t to_id(const std::string &full_name)
|
||||
{
|
||||
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
|
||||
{
|
||||
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();
|
||||
|
||||
ostr << "participant \""
|
||||
<< m_config.using_namespace().relative(
|
||||
class_participant.full_name(false))
|
||||
<< render_name(m_config.using_namespace().relative(
|
||||
class_participant.full_name(false)))
|
||||
<< "\" as " << class_participant.alias() << '\n';
|
||||
|
||||
generated_participants_.emplace(class_id);
|
||||
|
||||
@@ -63,6 +63,8 @@ public:
|
||||
private:
|
||||
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_;
|
||||
};
|
||||
|
||||
|
||||
@@ -68,11 +68,22 @@ call_expression_context &translation_unit_visitor::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()
|
||||
{
|
||||
return diagram_;
|
||||
}
|
||||
|
||||
const clanguml::sequence_diagram::model::diagram &
|
||||
translation_unit_visitor::diagram() const
|
||||
{
|
||||
return diagram_;
|
||||
}
|
||||
|
||||
const clanguml::config::sequence_diagram &
|
||||
translation_unit_visitor::config() const
|
||||
{
|
||||
@@ -920,15 +931,8 @@ translation_unit_visitor::create_class_declaration(clang::CXXRecordDecl *cls)
|
||||
else if (cls->isLambda()) {
|
||||
c.is_lambda(true);
|
||||
if (cls->getParent()) {
|
||||
auto parent_full_name = get_participant(context().caller_id())
|
||||
.value()
|
||||
.full_name_no_ns();
|
||||
const auto type_name = make_lambda_name(cls);
|
||||
|
||||
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_namespace(ns);
|
||||
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));
|
||||
}
|
||||
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 =
|
||||
fmt::format("{}##(lambda {}:{})", parent_full_name,
|
||||
source_manager().getSpellingLineNumber(location),
|
||||
source_manager().getSpellingColumnNumber(location));
|
||||
|
||||
make_lambda_name(arg.getAsType()->getAsCXXRecordDecl());
|
||||
argument.set_name(type_name);
|
||||
}
|
||||
}
|
||||
@@ -1680,6 +1675,32 @@ bool translation_unit_visitor::simplify_system_template(
|
||||
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()
|
||||
{
|
||||
for (auto &[id, activity] : diagram().sequences) {
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "call_expression_context.h"
|
||||
#include "common/visitor/translation_unit_visitor.h"
|
||||
#include "config/config.h"
|
||||
#include "sequence_diagram/model/diagram.h"
|
||||
#include "call_expression_context.h"
|
||||
|
||||
#include <clang/AST/Expr.h>
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
@@ -64,10 +64,14 @@ public:
|
||||
|
||||
clanguml::sequence_diagram::model::diagram &diagram();
|
||||
|
||||
const clanguml::sequence_diagram::model::diagram &diagram() const;
|
||||
|
||||
const clanguml::config::sequence_diagram &config() const;
|
||||
|
||||
call_expression_context &context();
|
||||
|
||||
const call_expression_context &context() const;
|
||||
|
||||
void finalize();
|
||||
|
||||
template <typename T = model::participant>
|
||||
@@ -82,6 +86,18 @@ public:
|
||||
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>
|
||||
common::optional_ref<T> get_participant(
|
||||
const common::model::diagram_element::id_t id)
|
||||
@@ -93,6 +109,17 @@ public:
|
||||
*(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
|
||||
/// getID()) method to clang-uml global id
|
||||
void set_unique_id(
|
||||
@@ -168,6 +195,8 @@ private:
|
||||
bool simplify_system_template(class_diagram::model::template_parameter &ct,
|
||||
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_callee_valid_template_specialization(
|
||||
|
||||
@@ -36,30 +36,35 @@ TEST_CASE("t20012", "[test-case][sequence]")
|
||||
|
||||
// Check if all calls exist
|
||||
REQUIRE_THAT(puml,
|
||||
HasCall(_A("tmain()"), _A("tmain()##(lambda 49:20)"), "operator()"));
|
||||
REQUIRE_THAT(puml, HasCall(_A("tmain()##(lambda 49:20)"), _A("A"), "a"));
|
||||
HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:49:20)"),
|
||||
"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"), "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"), "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"), "ccc"));
|
||||
REQUIRE_THAT(puml,
|
||||
HasCall(_A("tmain()##(lambda 62:20)"), _A("tmain()##(lambda 49:20)"),
|
||||
"operator()"));
|
||||
HasCall(_A("tmain()::(lambda t20012.cc:62:20)"),
|
||||
_A("tmain()::(lambda t20012.cc:49:20)"), "operator()"));
|
||||
|
||||
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(
|
||||
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(
|
||||
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
|
||||
|
||||
Reference in New Issue
Block a user