Refactored sequence diagram visitor

This commit is contained in:
Bartek Kryza
2022-11-27 19:15:31 +01:00
parent da5a4f8c5d
commit f1af5460e3
2 changed files with 77 additions and 74 deletions

View File

@@ -58,6 +58,16 @@ translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm,
{ {
} }
bool translation_unit_visitor::shouldVisitTemplateInstantiations()
{
return true;
}
call_expression_context &translation_unit_visitor::context()
{
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_;
@@ -78,14 +88,10 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
if (!diagram().should_include(cls->getQualifiedNameAsString())) if (!diagram().should_include(cls->getQualifiedNameAsString()))
return true; return true;
if (!diagram().should_include(cls->getQualifiedNameAsString())) {
return true;
}
if (cls->isTemplated() && cls->getDescribedTemplate()) { if (cls->isTemplated() && cls->getDescribedTemplate()) {
// 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 (get_ast_local_id(cls->getDescribedTemplate()->getID())) if (get_unique_id(cls->getDescribedTemplate()->getID()))
return true; return true;
} }
@@ -100,11 +106,11 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
if (!c_ptr) if (!c_ptr)
return true; return true;
call_expression_context_.reset(); context().reset();
const auto cls_id = c_ptr->id(); const auto cls_id = c_ptr->id();
set_ast_local_id(cls->getID(), cls_id); set_unique_id(cls->getID(), cls_id);
auto &class_model = auto &class_model =
diagram() diagram()
@@ -124,16 +130,16 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
forward_declarations_.erase(id); forward_declarations_.erase(id);
} }
if (diagram_.should_include(class_model)) { if (diagram().should_include(class_model)) {
LOG_DBG("Adding class {} with id {}", class_model.full_name(false), LOG_DBG("Adding class {} with id {}", class_model.full_name(false),
class_model.id()); class_model.id());
assert(class_model.id() == cls_id); assert(class_model.id() == cls_id);
call_expression_context_.set_caller_id(cls_id); context().set_caller_id(cls_id);
call_expression_context_.update(cls); context().update(cls);
diagram_.add_participant(std::move(c_ptr)); diagram().add_participant(std::move(c_ptr));
} }
else { else {
LOG_DBG("Skipping class {} with id {}", class_model.full_name(), LOG_DBG("Skipping class {} with id {}", class_model.full_name(),
@@ -170,7 +176,7 @@ bool translation_unit_visitor::VisitClassTemplateDecl(
c_ptr->set_id(id); c_ptr->set_id(id);
set_ast_local_id(cls->getID(), id); set_unique_id(cls->getID(), id);
if (!cls->getTemplatedDecl()->isCompleteDefinition()) { if (!cls->getTemplatedDecl()->isCompleteDefinition()) {
forward_declarations_.emplace(id, std::move(c_ptr)); forward_declarations_.emplace(id, std::move(c_ptr));
@@ -180,13 +186,13 @@ bool translation_unit_visitor::VisitClassTemplateDecl(
forward_declarations_.erase(id); forward_declarations_.erase(id);
} }
if (diagram_.should_include(*c_ptr)) { if (diagram().should_include(*c_ptr)) {
LOG_DBG("Adding class template {} with id {}", cls_full_name, id); LOG_DBG("Adding class template {} with id {}", cls_full_name, id);
call_expression_context_.set_caller_id(id); context().set_caller_id(id);
call_expression_context_.update(cls); context().update(cls);
diagram_.add_participant(std::move(c_ptr)); diagram().add_participant(std::move(c_ptr));
} }
return true; return true;
@@ -201,7 +207,7 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
if (!diagram().should_include(cls->getQualifiedNameAsString())) if (!diagram().should_include(cls->getQualifiedNameAsString()))
return true; return true;
LOG_DBG("##### Visiting template specialization declaration {} at {}", LOG_DBG("Visiting template specialization declaration {} at {}",
cls->getQualifiedNameAsString(), cls->getQualifiedNameAsString(),
cls->getLocation().printToString(source_manager())); cls->getLocation().printToString(source_manager()));
@@ -219,7 +225,7 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
template_specialization_ptr->set_id(id); template_specialization_ptr->set_id(id);
set_ast_local_id(cls->getID(), id); set_unique_id(cls->getID(), id);
if (!cls->isCompleteDefinition()) { if (!cls->isCompleteDefinition()) {
forward_declarations_.emplace( forward_declarations_.emplace(
@@ -230,14 +236,14 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
forward_declarations_.erase(id); forward_declarations_.erase(id);
} }
if (diagram_.should_include(*template_specialization_ptr)) { if (diagram().should_include(*template_specialization_ptr)) {
LOG_DBG("Adding class template specialization {} with id {}", LOG_DBG("Adding class template specialization {} with id {}",
cls_full_name, id); cls_full_name, id);
call_expression_context_.set_caller_id(id); context().set_caller_id(id);
call_expression_context_.update(cls); context().update(cls);
diagram_.add_participant(std::move(template_specialization_ptr)); diagram().add_participant(std::move(template_specialization_ptr));
} }
return true; return true;
@@ -245,17 +251,16 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
bool translation_unit_visitor::VisitCXXMethodDecl(clang::CXXMethodDecl *m) bool translation_unit_visitor::VisitCXXMethodDecl(clang::CXXMethodDecl *m)
{ {
if (call_expression_context_.current_class_decl_ == nullptr && if (context().current_class_decl_ == nullptr &&
call_expression_context_.current_class_template_decl_ == nullptr && context().current_class_template_decl_ == nullptr &&
call_expression_context_.current_class_template_specialization_decl_ == context().current_class_template_specialization_decl_ == nullptr)
nullptr)
return true; return true;
LOG_DBG("= Processing method {} in class {} [{}]", LOG_DBG("= Processing method {} in class {} [{}]",
m->getQualifiedNameAsString(), m->getQualifiedNameAsString(),
m->getParent()->getQualifiedNameAsString(), (void *)m->getParent()); m->getParent()->getQualifiedNameAsString(), (void *)m->getParent());
call_expression_context_.update(m); context().update(m);
auto m_ptr = std::make_unique<sequence_diagram::model::method>( auto m_ptr = std::make_unique<sequence_diagram::model::method>(
config().using_namespace()); config().using_namespace());
@@ -269,17 +274,15 @@ bool translation_unit_visitor::VisitCXXMethodDecl(clang::CXXMethodDecl *m)
clang::Decl *parent_decl = m->getParent(); clang::Decl *parent_decl = m->getParent();
if (call_expression_context_.current_class_template_decl_) if (context().current_class_template_decl_)
parent_decl = call_expression_context_.current_class_template_decl_; parent_decl = context().current_class_template_decl_;
call_expression_context_.dump();
LOG_DBG("Getting method's class with local id {}", parent_decl->getID()); LOG_DBG("Getting method's class with local id {}", parent_decl->getID());
const auto &method_class = const auto &method_class =
diagram() diagram()
.get_participant<model::class_>( .get_participant<model::class_>(
get_ast_local_id(parent_decl->getID()).value()) get_unique_id(parent_decl->getID()).value())
.value(); .value();
m_ptr->set_class_id(method_class.id()); m_ptr->set_class_id(method_class.id());
@@ -296,11 +299,11 @@ bool translation_unit_visitor::VisitCXXMethodDecl(clang::CXXMethodDecl *m)
diagram().participants.at(m_ptr->class_id())->full_name(false) + diagram().participants.at(m_ptr->class_id())->full_name(false) +
"::" + m->getNameAsString()); "::" + m->getNameAsString());
call_expression_context_.update(m); context().update(m);
call_expression_context_.set_caller_id(m_ptr->id()); context().set_caller_id(m_ptr->id());
set_ast_local_id(m->getID(), m_ptr->id()); set_unique_id(m->getID(), m_ptr->id());
diagram().add_participant(std::move(m_ptr)); diagram().add_participant(std::move(m_ptr));
@@ -324,7 +327,7 @@ bool translation_unit_visitor::VisitFunctionDecl(clang::FunctionDecl *f)
if (f->getDescribedTemplate()) { if (f->getDescribedTemplate()) {
// 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_ast_local_id(f->getDescribedTemplate()->getID())) if (get_unique_id(f->getDescribedTemplate()->getID()))
return true; return true;
} }
} }
@@ -334,11 +337,11 @@ bool translation_unit_visitor::VisitFunctionDecl(clang::FunctionDecl *f)
f_ptr->set_id(common::to_id(f_ptr->full_name(false))); f_ptr->set_id(common::to_id(f_ptr->full_name(false)));
call_expression_context_.update(f); context().update(f);
call_expression_context_.set_caller_id(f_ptr->id()); context().set_caller_id(f_ptr->id());
set_ast_local_id(f->getID(), f_ptr->id()); set_unique_id(f->getID(), f_ptr->id());
// TODO: Handle overloaded functions with different arguments // TODO: Handle overloaded functions with different arguments
diagram().add_participant(std::move(f_ptr)); diagram().add_participant(std::move(f_ptr));
@@ -353,11 +356,11 @@ bool translation_unit_visitor::VisitFunctionDecl(clang::FunctionDecl *f)
f_ptr->set_namespace(ns); f_ptr->set_namespace(ns);
f_ptr->set_id(common::to_id(function_name)); f_ptr->set_id(common::to_id(function_name));
call_expression_context_.update(f); context().update(f);
call_expression_context_.set_caller_id(f_ptr->id()); context().set_caller_id(f_ptr->id());
set_ast_local_id(f->getID(), f_ptr->id()); set_unique_id(f->getID(), f_ptr->id());
// TODO: Handle overloaded functions with different arguments // TODO: Handle overloaded functions with different arguments
diagram().add_participant(std::move(f_ptr)); diagram().add_participant(std::move(f_ptr));
@@ -389,10 +392,10 @@ bool translation_unit_visitor::VisitFunctionTemplateDecl(
f_ptr->set_id(common::to_id(f_ptr->full_name(false))); f_ptr->set_id(common::to_id(f_ptr->full_name(false)));
call_expression_context_.update(function_template); context().update(function_template);
call_expression_context_.set_caller_id(f_ptr->id()); context().set_caller_id(f_ptr->id());
set_ast_local_id(function_template->getID(), f_ptr->id()); set_unique_id(function_template->getID(), f_ptr->id());
// TODO: Handle overloaded functions with different arguments // TODO: Handle overloaded functions with different arguments
diagram().add_participant(std::move(f_ptr)); diagram().add_participant(std::move(f_ptr));
@@ -417,15 +420,14 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
if (clang::dyn_cast_or_null<clang::ImplicitCastExpr>(expr)) if (clang::dyn_cast_or_null<clang::ImplicitCastExpr>(expr))
return true; return true;
if (!call_expression_context_.valid()) if (!context().valid())
return true; return true;
message m; message m;
m.type = message_t::kCall; m.type = message_t::kCall;
m.from = call_expression_context_.caller_id(); m.from = context().caller_id();
const auto &current_ast_context = const auto &current_ast_context = *context().get_ast_context();
*call_expression_context_.get_ast_context();
LOG_DBG("Visiting call expression at {}", LOG_DBG("Visiting call expression at {}",
expr->getBeginLoc().printToString(source_manager())); expr->getBeginLoc().printToString(source_manager()));
@@ -463,8 +465,8 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
const auto &participant = const auto &participant =
diagram() diagram()
.get_participant<model::class_>(get_ast_local_id( .get_participant<model::class_>(
callee_template_specialization->getID()) get_unique_id(callee_template_specialization->getID())
.value()) .value())
.value(); .value();
@@ -476,7 +478,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
const auto &parent_template_participant = const auto &parent_template_participant =
diagram() diagram()
.get_participant<model::class_>( .get_participant<model::class_>(
get_ast_local_id(parent_template->getID()).value()) get_unique_id(parent_template->getID()).value())
.value(); .value();
const auto parent_method_name = const auto parent_method_name =
@@ -508,7 +510,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
m_ptr->set_name(method_decl->getNameAsString()); m_ptr->set_name(method_decl->getNameAsString());
m_ptr->set_class_id(participant.id()); m_ptr->set_class_id(participant.id());
m_ptr->set_class_full_name(participant.full_name(false)); m_ptr->set_class_full_name(participant.full_name(false));
set_ast_local_id(method_decl->getID(), m_ptr->id()); set_unique_id(method_decl->getID(), m_ptr->id());
diagram().add_active_participant(m_ptr->id()); diagram().add_active_participant(m_ptr->id());
diagram().add_participant(std::move(m_ptr)); diagram().add_participant(std::move(m_ptr));
} }
@@ -516,7 +518,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
else { else {
const auto &specialization_participant = const auto &specialization_participant =
diagram() diagram()
.get_participant<model::class_>(get_ast_local_id( .get_participant<model::class_>(get_unique_id(
callee_template_specialization->getID()) callee_template_specialization->getID())
.value()) .value())
.value(); .value();
@@ -541,9 +543,9 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
LOG_DBG("Set callee method id {} for method name {}", m.to, LOG_DBG("Set callee method id {} for method name {}", m.to,
method_decl->getQualifiedNameAsString()); method_decl->getQualifiedNameAsString());
if (get_ast_local_id(callee_decl->getID())) if (get_unique_id(callee_decl->getID()))
diagram().add_active_participant( diagram().add_active_participant(
get_ast_local_id(callee_decl->getID()).value()); get_unique_id(callee_decl->getID()).value());
} }
// //
// Call to a function // Call to a function
@@ -578,7 +580,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
auto callee_method_full_name = auto callee_method_full_name =
diagram() diagram()
.participants .participants
.at(get_ast_local_id(primary_template->getID()) .at(get_unique_id(primary_template->getID())
.value()) .value())
->full_name(false) + ->full_name(false) +
"::" + "::" +
@@ -591,10 +593,9 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
dependent_member_callee->getMember().getAsString(); dependent_member_callee->getMember().getAsString();
m.return_type = ""; m.return_type = "";
if (get_ast_local_id(primary_template->getID())) if (get_unique_id(primary_template->getID()))
diagram().add_active_participant( diagram().add_active_participant(
get_ast_local_id(primary_template->getID()) get_unique_id(primary_template->getID()).value());
.value());
} }
} }
// //
@@ -615,7 +616,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
auto *ftd = clang::dyn_cast_or_null< auto *ftd = clang::dyn_cast_or_null<
clang::FunctionTemplateDecl>(decl); clang::FunctionTemplateDecl>(decl);
m.to = get_ast_local_id(ftd->getID()).value(); m.to = get_unique_id(ftd->getID()).value();
auto message_name = auto message_name =
diagram() diagram()
.get_participant<model::function_template>( .get_participant<model::function_template>(
@@ -646,12 +647,12 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
std::unique_ptr<model::function_template> f_ptr; std::unique_ptr<model::function_template> f_ptr;
if (!get_ast_local_id(callee_function->getID()).has_value()) { if (!get_unique_id(callee_function->getID()).has_value()) {
// This is hopefully not an interesting call... // This is hopefully not an interesting call...
return true; return true;
} }
else { else {
m.to = get_ast_local_id(callee_function->getID()).value(); m.to = get_unique_id(callee_function->getID()).value();
} }
auto message_name = callee_name; auto message_name = callee_name;
@@ -701,7 +702,7 @@ translation_unit_visitor::create_class_declaration(clang::CXXRecordDecl *cls)
assert(cls != nullptr); assert(cls != nullptr);
auto c_ptr{std::make_unique<clanguml::sequence_diagram::model::class_>( auto c_ptr{std::make_unique<clanguml::sequence_diagram::model::class_>(
config_.using_namespace())}; config().using_namespace())};
auto &c = *c_ptr; auto &c = *c_ptr;
// TODO: refactor to method get_qualified_name() // TODO: refactor to method get_qualified_name()
@@ -725,7 +726,7 @@ translation_unit_visitor::create_class_declaration(clang::CXXRecordDecl *cls)
// First check if the parent has been added to the diagram as regular // First check if the parent has been added to the diagram as regular
// class // class
id_opt = get_ast_local_id(local_id); id_opt = get_unique_id(local_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) {
@@ -734,7 +735,7 @@ translation_unit_visitor::create_class_declaration(clang::CXXRecordDecl *cls)
->getID(); ->getID();
if (static_cast<const clang::RecordDecl *>(parent) if (static_cast<const clang::RecordDecl *>(parent)
->getDescribedTemplate()) ->getDescribedTemplate())
id_opt = get_ast_local_id(local_id); id_opt = get_unique_id(local_id);
} }
assert(id_opt); assert(id_opt);
@@ -853,7 +854,7 @@ bool translation_unit_visitor::process_template_parameters(
return false; return false;
} }
void translation_unit_visitor::set_ast_local_id( void translation_unit_visitor::set_unique_id(
int64_t local_id, common::model::diagram_element::id_t global_id) int64_t local_id, common::model::diagram_element::id_t global_id)
{ {
LOG_DBG("== Setting local element mapping {} --> {}", local_id, global_id); LOG_DBG("== Setting local element mapping {} --> {}", local_id, global_id);
@@ -862,7 +863,7 @@ void translation_unit_visitor::set_ast_local_id(
} }
std::optional<common::model::diagram_element::id_t> std::optional<common::model::diagram_element::id_t>
translation_unit_visitor::get_ast_local_id(int64_t local_id) const translation_unit_visitor::get_unique_id(int64_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) == local_ast_id_map_.end())
return {}; return {};
@@ -1121,7 +1122,7 @@ translation_unit_visitor::process_template_specialization(
template_instantiation.set_id( template_instantiation.set_id(
common::to_id(template_instantiation.full_name(false))); common::to_id(template_instantiation.full_name(false)));
set_ast_local_id(cls->getID(), template_instantiation.id()); set_unique_id(cls->getID(), template_instantiation.id());
return c_ptr; return c_ptr;
} }
@@ -1450,7 +1451,7 @@ translation_unit_visitor::build_template_instantiation(
auto templated_decl_id = auto templated_decl_id =
template_type.getTemplateName().getAsTemplateDecl()->getID(); template_type.getTemplateName().getAsTemplateDecl()->getID();
// auto templated_decl_local_id = // auto templated_decl_local_id =
// get_ast_local_id(templated_decl_id).value_or(0); // get_unique_id(templated_decl_id).value_or(0);
if (best_match_id > 0) { if (best_match_id > 0) {
destination = best_match_full_name; destination = best_match_full_name;

View File

@@ -176,7 +176,7 @@ public:
clanguml::sequence_diagram::model::diagram &diagram, clanguml::sequence_diagram::model::diagram &diagram,
const clanguml::config::sequence_diagram &config); const clanguml::config::sequence_diagram &config);
bool shouldVisitTemplateInstantiations() { return true; } bool shouldVisitTemplateInstantiations();
virtual bool VisitCallExpr(clang::CallExpr *expr); virtual bool VisitCallExpr(clang::CallExpr *expr);
@@ -198,15 +198,17 @@ public:
const clanguml::config::sequence_diagram &config() const; const clanguml::config::sequence_diagram &config() const;
call_expression_context &context();
void finalize() { } void finalize() { }
/// 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_ast_local_id( void set_unique_id(
int64_t local_id, common::model::diagram_element::id_t global_id); int64_t local_id, common::model::diagram_element::id_t global_id);
/// Retrieve the global clang-uml entity id based on the clang local id /// Retrieve the global clang-uml entity id based on the clang local id
std::optional<common::model::diagram_element::id_t> get_ast_local_id( std::optional<common::model::diagram_element::id_t> get_unique_id(
int64_t local_id) const; int64_t local_id) const;
private: private: