0.5.4
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
clanguml::sequence_diagram::visitor::translation_unit_visitor Class Reference

Sequence diagram translation unit visitor. More...

Detailed Description

Sequence diagram translation unit visitor.

This class implements the clang::RecursiveASTVisitor interface for selected visitors relevant to generating sequence diagrams.

Definition at line 49 of file translation_unit_visitor.h.

#include <translation_unit_visitor.h>

Public Types

using template_builder_t = common::visitor::template_builder< translation_unit_visitor >
 
using config_t = ConfigT
 
using diagram_t = DiagramT
 
- Public Types inherited from clanguml::common::visitor::translation_unit_visitor< ConfigT, DiagramT >
using config_t = ConfigT
 
using diagram_t = DiagramT
 

Public Member Functions

 translation_unit_visitor (clang::SourceManager &sm, clanguml::sequence_diagram::model::diagram &diagram, const clanguml::config::sequence_diagram &config)
 Constructor.
 
 ~translation_unit_visitor () override=default
 
bool shouldVisitTemplateInstantiations ()
 
bool VisitCallExpr (clang::CallExpr *expr)
 
bool TraverseVarDecl (clang::VarDecl *VD)
 
bool TraverseCallExpr (clang::CallExpr *expr)
 
bool TraverseCUDAKernelCallExpr (clang::CUDAKernelCallExpr *expr)
 
bool TraverseCXXMemberCallExpr (clang::CXXMemberCallExpr *expr)
 
bool TraverseCXXOperatorCallExpr (clang::CXXOperatorCallExpr *expr)
 
bool VisitCXXConstructExpr (clang::CXXConstructExpr *expr)
 
bool TraverseCXXConstructExpr (clang::CXXConstructExpr *expr)
 
bool TraverseCXXTemporaryObjectExpr (clang::CXXTemporaryObjectExpr *expr)
 
bool VisitLambdaExpr (clang::LambdaExpr *expr)
 
bool TraverseLambdaExpr (clang::LambdaExpr *expr)
 
bool TraverseCXXMethodDecl (clang::CXXMethodDecl *declaration)
 
bool VisitCXXMethodDecl (clang::CXXMethodDecl *declaration)
 
bool VisitCXXRecordDecl (clang::CXXRecordDecl *declaration)
 
bool VisitClassTemplateDecl (clang::ClassTemplateDecl *declaration)
 
bool VisitClassTemplateSpecializationDecl (clang::ClassTemplateSpecializationDecl *declaration)
 
bool TraverseFunctionDecl (clang::FunctionDecl *declaration)
 
bool VisitFunctionDecl (clang::FunctionDecl *declaration)
 
bool VisitFunctionTemplateDecl (clang::FunctionTemplateDecl *function_declaration)
 
bool TraverseCompoundStmt (clang::CompoundStmt *stmt)
 
bool TraverseIfStmt (clang::IfStmt *stmt)
 
bool TraverseWhileStmt (clang::WhileStmt *stmt)
 
bool TraverseDoStmt (clang::DoStmt *stmt)
 
bool TraverseForStmt (clang::ForStmt *stmt)
 
bool TraverseCXXForRangeStmt (clang::CXXForRangeStmt *stmt)
 
bool TraverseCXXTryStmt (clang::CXXTryStmt *stmt)
 
bool TraverseCXXCatchStmt (clang::CXXCatchStmt *stmt)
 
bool TraverseSwitchStmt (clang::SwitchStmt *stmt)
 
bool TraverseCaseStmt (clang::CaseStmt *stmt)
 
bool TraverseDefaultStmt (clang::DefaultStmt *stmt)
 
bool TraverseConditionalOperator (clang::ConditionalOperator *stmt)
 
call_expression_contextcontext ()
 Get current call expression context reference.
 
const call_expression_contextcontext () const
 Get current call expression context reference.
 
template<typename T = model::participant>
common::optional_ref< T > get_participant (const clang::Decl *decl)
 Get participant by declaration.
 
template<typename T = model::participant>
common::optional_ref< T > get_participant (const clang::Decl *decl) const
 Get participant by declaration.
 
template<typename T = model::participant>
common::optional_ref< T > get_participant (const eid_t id)
 Get participant by global element id.
 
template<typename T = model::participant>
common::optional_ref< T > get_participant (eid_t id) const
 Get participant by global element id.
 
void set_unique_id (int64_t local_id, eid_t global_id)
 Store the mapping from local clang entity id (obtained using getID()) method to clang-uml global id.
 
std::optional< eid_tget_unique_id (eid_t local_id) const
 Retrieve the global clang-uml entity id based on the Clang local id.
 
void finalize ()
 Finalize diagram model for this translation unit.
 
std::unique_ptr< sequence_diagram::model::class_create_element (const clang::NamedDecl *decl) const
 
- Public Member Functions inherited from clanguml::common::visitor::translation_unit_visitor< ConfigT, DiagramT >
 translation_unit_visitor (clang::SourceManager &sm, DiagramT &diagram, const ConfigT &config)
 Constructor.
 
virtual ~translation_unit_visitor ()=default
 
void set_tu_path (const std::string &translation_unit_path)
 
const std::filesystem::path & tu_path () const
 Return relative path to current translation unit.
 
common::visitor::ast_id_mapperid_mapper () const
 Get reference to Clang AST to clang-uml id mapper.
 
clang::SourceManager & source_manager () const
 Get clang::SourceManager.
 
void set_source_location (const clang::Decl &decl, clanguml::common::model::source_location &element)
 Set source location in diagram element.
 
void set_source_location (const clang::Expr &expr, clanguml::common::model::source_location &element)
 Set source location in diagram element.
 
void set_source_location (const clang::Stmt &stmt, clanguml::common::model::source_location &element)
 
void set_qualified_name (const clang::NamedDecl &decl, clanguml::common::model::element &element)
 
void set_source_location (const clang::SourceLocation &location, clanguml::common::model::source_location &element)
 Set source location in diagram element.
 
void set_owning_module (const clang::Decl &decl, clanguml::common::model::element &element)
 
virtual void add_diagram_element (std::unique_ptr< common::model::template_element > element)
 
void process_comment (const clang::NamedDecl &decl, clanguml::common::model::decorated_element &e)
 Process comment directives in comment attached to a declaration.
 
std::string process_comment (const clang::RawComment *comment, clang::DiagnosticsEngine &de, clanguml::common::model::decorated_element &e)
 Process comment directives in raw comment.
 
bool skip_system_header_decl (const clang::NamedDecl *decl) const
 
bool should_include (const clang::NamedDecl *decl) const
 Check if the diagram should include a declaration.
 
DiagramT & diagram ()
 Get diagram model reference.
 
const DiagramT & diagram () const
 Get diagram model reference.
 
const ConfigT & config () const
 Get diagram config instance.
 

Private Member Functions

bool should_include (const clang::TagDecl *decl) const
 Check if the diagram should include a declaration.
 
bool should_include (const clang::LambdaExpr *expr) const
 Check if the diagram should include a lambda expression.
 
bool should_include (const clang::CallExpr *expr) const
 Check if the diagram should include a call expression.
 
bool should_include (const clang::CXXMethodDecl *decl) const
 Check if the diagram should include a declaration.
 
bool should_include (const clang::FunctionDecl *decl) const
 Check if the diagram should include a declaration.
 
bool should_include (const clang::FunctionTemplateDecl *decl) const
 Check if the diagram should include a declaration.
 
bool should_include (const clang::ClassTemplateDecl *decl) const
 Check if the diagram should include a declaration.
 
std::unique_ptr< clanguml::sequence_diagram::model::class_create_class_model (clang::CXXRecordDecl *cls)
 
std::unique_ptr< clanguml::sequence_diagram::model::methodcreate_method_model (clang::CXXMethodDecl *cls)
 
std::unique_ptr< clanguml::sequence_diagram::model::methodcreate_lambda_method_model (clang::CXXMethodDecl *cls)
 
std::unique_ptr< model::function_templatebuild_function_template_instantiation (const clang::FunctionDecl &pDecl)
 
std::unique_ptr< model::functionbuild_function_model (const clang::FunctionDecl &declaration)
 
std::unique_ptr< model::function_templatebuild_function_template (const clang::FunctionTemplateDecl &declaration)
 
std::unique_ptr< model::class_process_class_template_specialization (clang::ClassTemplateSpecializationDecl *cls)
 
std::string simplify_system_template (const std::string &full_name) const
 
std::string make_lambda_name (const clang::CXXRecordDecl *cls) const
 Assuming cls is a lambda, create it's full name.
 
std::string lambda_source_location (const clang::SourceLocation &source_location) const
 Render lambda source location to string.
 
bool is_smart_pointer (const clang::TemplateDecl *primary_template) const
 Check if template is a smart pointer.
 
bool is_callee_valid_template_specialization (const clang::CXXDependentScopeMemberExpr *dependent_member_expr) const
 Check, the callee is a template specialization.
 
bool process_construct_expression (model::message &m, const clang::CXXConstructExpr *construct_expr)
 Handle CXX constructor call.
 
bool process_operator_call_expression (model::message &m, const clang::CXXOperatorCallExpr *operator_call_expr)
 Handle a operator call expression.
 
bool process_cuda_kernel_call_expression (model::message &m, const clang::CUDAKernelCallExpr *cuda_call_expr)
 
bool process_class_method_call_expression (model::message &m, const clang::CXXMemberCallExpr *method_call_expr)
 Handle a class method call expresion.
 
bool process_class_template_method_call_expression (model::message &m, const clang::CallExpr *expr)
 Handle a class template method call expresion.
 
bool process_function_call_expression (model::message &m, const clang::CallExpr *expr)
 Handle a function call expresion.
 
bool process_unresolved_lookup_call_expression (model::message &m, const clang::CallExpr *expr) const
 Handle an unresolved lookup call expresion.
 
bool process_lambda_call_expression (model::message &m, const clang::CallExpr *expr) const
 
void push_message (clang::CallExpr *expr, model::message &&m)
 Register a message model m with a call expression.
 
void push_message (clang::CXXConstructExpr *expr, model::message &&m)
 
void pop_message_to_diagram (clang::CallExpr *expr)
 Move a message model to diagram.
 
void pop_message_to_diagram (clang::CXXConstructExpr *expr)
 
std::optional< std::pair< unsigned int, std::string > > get_expression_comment (const clang::SourceManager &sm, const clang::ASTContext &context, eid_t caller_id, const clang::Stmt *stmt)
 
bool generate_message_from_comment (model::message &m) const
 Initializes model message from comment call directive.
 
template_builder_ttbuilder ()
 Get template builder reference.
 
void resolve_ids_to_global ()
 
void ensure_lambda_messages_have_operator_as_target ()
 

Private Attributes

call_expression_context call_expression_context_
 
std::map< clang::CallExpr *, model::messagecall_expr_message_map_
 
std::map< clang::CXXConstructExpr *, model::messageconstruct_expr_message_map_
 
std::map< eid_t, std::unique_ptr< clanguml::sequence_diagram::model::class_ > > forward_declarations_
 
std::map< int64_t, std::tuple< std::string, common::model::relationship_t, common::model::access_t > > anonymous_struct_relationships_
 
unsigned within_static_variable_declaration_ {0}
 
std::set< const clang::Expr * > already_visited_in_static_declaration_ {}
 
std::set< std::pair< int64_t, const clang::RawComment * > > processed_comments_by_caller_id_
 
template_builder_t template_builder_
 

Additional Inherited Members

- Protected Member Functions inherited from clanguml::common::visitor::translation_unit_visitor< ConfigT, DiagramT >
std::set< const clang::RawComment * > & processed_comments ()
 

Member Typedef Documentation

◆ config_t

using clanguml::common::visitor::translation_unit_visitor< ConfigT, DiagramT >::config_t = ConfigT

Definition at line 56 of file translation_unit_visitor.h.

◆ diagram_t

using clanguml::common::visitor::translation_unit_visitor< ConfigT, DiagramT >::diagram_t = DiagramT

Definition at line 57 of file translation_unit_visitor.h.

◆ template_builder_t

Definition at line 56 of file translation_unit_visitor.h.

Constructor & Destructor Documentation

◆ translation_unit_visitor()

clanguml::sequence_diagram::visitor::translation_unit_visitor::translation_unit_visitor ( clang::SourceManager &  sm,
clanguml::sequence_diagram::model::diagram diagram,
const clanguml::config::sequence_diagram config 
)

Constructor.

Parameters
smCurrent source manager reference
diagramDiagram model
configDiagram configuration

Definition at line 27 of file translation_unit_visitor.cc.

◆ ~translation_unit_visitor()

clanguml::sequence_diagram::visitor::translation_unit_visitor::~translation_unit_visitor ( )
overridevirtualdefault

Member Function Documentation

◆ build_function_model()

std::unique_ptr< model::function > clanguml::sequence_diagram::visitor::translation_unit_visitor::build_function_model ( const clang::FunctionDecl &  declaration)
private

Definition at line 1804 of file translation_unit_visitor.cc.

1806{
1807 auto function_model_ptr =
1808 std::make_unique<sequence_diagram::model::function>(
1809 config().using_namespace());
1810
1811 common::model::namespace_ ns{declaration.getQualifiedNameAsString()};
1812 function_model_ptr->set_name(ns.name());
1813 ns.pop_back();
1814 function_model_ptr->set_namespace(ns);
1815
1816 function_model_ptr->return_type(common::to_string(
1817 declaration.getReturnType(), declaration.getASTContext()));
1818
1819 for (const auto *param : declaration.parameters()) {
1820 function_model_ptr->add_parameter(
1822 param->getType(), declaration.getASTContext(), false)));
1823 }
1824
1825 return function_model_ptr;
1826}

◆ build_function_template()

std::unique_ptr< model::function_template > clanguml::sequence_diagram::visitor::translation_unit_visitor::build_function_template ( const clang::FunctionTemplateDecl &  declaration)
private

Definition at line 1756 of file translation_unit_visitor.cc.

1758{
1759 auto function_template_model_ptr =
1760 std::make_unique<sequence_diagram::model::function_template>(
1761 config().using_namespace());
1762
1763 set_qualified_name(declaration, *function_template_model_ptr);
1764
1766 *function_template_model_ptr, declaration);
1767
1768 function_template_model_ptr->return_type(
1769 common::to_string(declaration.getAsFunction()->getReturnType(),
1770 declaration.getASTContext()));
1771
1772 for (const auto *param : declaration.getTemplatedDecl()->parameters()) {
1773 function_template_model_ptr->add_parameter(
1775 param->getType(), declaration.getASTContext(), false)));
1776 }
1777
1778 return function_template_model_ptr;
1779}

◆ build_function_template_instantiation()

std::unique_ptr< model::function_template > clanguml::sequence_diagram::visitor::translation_unit_visitor::build_function_template_instantiation ( const clang::FunctionDecl &  pDecl)
private

Definition at line 1782 of file translation_unit_visitor.cc.

1784{
1785 auto template_instantiation_ptr =
1786 std::make_unique<model::function_template>(config().using_namespace());
1787 auto &template_instantiation = *template_instantiation_ptr;
1788
1789 set_qualified_name(decl, template_instantiation);
1790
1791 tbuilder().build(template_instantiation, &decl, decl.getPrimaryTemplate(),
1792 decl.getTemplateSpecializationArgs()->asArray(),
1793 common::to_string(&decl));
1794
1795 // Handle function parameters
1796 for (const auto *param : decl.parameters()) {
1797 template_instantiation_ptr->add_parameter(
1798 common::to_string(param->getType(), decl.getASTContext()));
1799 }
1800
1801 return template_instantiation_ptr;
1802}

◆ context() [1/2]

call_expression_context & clanguml::sequence_diagram::visitor::translation_unit_visitor::context ( )

Get current call expression context reference.

Returns
Reference to the current call expression context

Definition at line 48 of file translation_unit_visitor.cc.

49{
51}

◆ context() [2/2]

const call_expression_context & clanguml::sequence_diagram::visitor::translation_unit_visitor::context ( ) const

Get current call expression context reference.

Returns
Reference to the current call expression context

Definition at line 53 of file translation_unit_visitor.cc.

54{
56}

◆ create_class_model()

std::unique_ptr< clanguml::sequence_diagram::model::class_ > clanguml::sequence_diagram::visitor::translation_unit_visitor::create_class_model ( clang::CXXRecordDecl *  cls)
private

Definition at line 1621 of file translation_unit_visitor.cc.

1622{
1623 assert(cls != nullptr);
1624
1625 auto c_ptr{std::make_unique<clanguml::sequence_diagram::model::class_>(
1626 config().using_namespace())};
1627 auto &c = *c_ptr;
1628
1629 auto qualified_name = cls->getQualifiedNameAsString();
1630
1631 if (!cls->isLambda())
1632 if (!should_include(cls))
1633 return {};
1634
1635 auto ns = common::get_tag_namespace(*cls);
1636
1637 if (cls->isLambda() && !diagram().should_include(ns | "lambda"))
1638 return {};
1639
1640 const auto *parent = cls->getParent();
1641
1642 if ((parent != nullptr) && parent->isRecord()) {
1643 // Here we have 3 options, either:
1644 // - the parent is a regular C++ class/struct
1645 // - the parent is a class template declaration/specialization
1646 // - the parent is a lambda (i.e. this is a nested lambda expression)
1647 std::optional<eid_t> id_opt;
1648 const auto *parent_record_decl =
1649 clang::dyn_cast<clang::RecordDecl>(parent);
1650
1651 assert(parent_record_decl != nullptr);
1652
1653 const eid_t ast_id{parent_record_decl->getID()};
1654
1655 // First check if the parent has been added to the diagram as
1656 // regular class
1657 id_opt = get_unique_id(ast_id);
1658
1659 // If not, check if the parent template declaration is in the model
1660 if (!id_opt &&
1661 (parent_record_decl->getDescribedTemplate() != nullptr)) {
1662 parent_record_decl->getDescribedTemplate()->getID();
1663 if (parent_record_decl->getDescribedTemplate() != nullptr)
1664 id_opt = get_unique_id(ast_id);
1665 }
1666
1667 if (!id_opt)
1668 return {};
1669
1670 auto parent_class =
1671 diagram()
1673 *id_opt);
1674
1675 if (!parent_class) {
1676 return {};
1677 }
1678
1679 c.set_namespace(ns);
1680 if (cls->getNameAsString().empty()) {
1681 // Nested structs can be anonymous
1682 if (anonymous_struct_relationships_.count(cls->getID()) > 0) {
1683 const auto &[label, hint, access] =
1684 anonymous_struct_relationships_[cls->getID()];
1685
1686 c.set_name(parent_class.value().name() +
1687 "::" + fmt::format("({})", label));
1688
1689 parent_class.value().add_relationship(
1690 {hint, common::to_id(c.full_name(false)), access, label});
1691 }
1692 else
1693 c.set_name(parent_class.value().name() + "::" +
1694 fmt::format(
1695 "(anonymous_{})", std::to_string(cls->getID())));
1696 }
1697 else {
1698 c.set_name(
1699 parent_class.value().name() + "::" + cls->getNameAsString());
1700 }
1701
1702 c.set_id(common::to_id(c.full_name(false)));
1703
1704 c.nested(true);
1705 }
1706 else if (cls->isLambda()) {
1707 c.is_lambda(true);
1708 if (cls->getParent() != nullptr) {
1709 const auto type_name = make_lambda_name(cls);
1710
1711 c.set_name(type_name);
1712 c.set_namespace(ns);
1713 c.set_id(common::to_id(c.full_name(false)));
1714 }
1715 else {
1716 LOG_WARN("Cannot find parent declaration for lambda {}",
1717 cls->getQualifiedNameAsString());
1718 return {};
1719 }
1720 }
1721 else {
1722 c.set_name(common::get_tag_name(*cls));
1723 c.set_namespace(ns);
1724 c.set_id(common::to_id(c.full_name(false)));
1725 }
1726
1727 c.is_struct(cls->isStruct());
1728
1729 process_comment(*cls, c);
1730 set_source_location(*cls, c);
1731
1732 if (c.skip())
1733 return {};
1734
1735 c.set_style(c.style_spec());
1736
1737 return c_ptr;
1738}

◆ create_element()

std::unique_ptr< sequence_diagram::model::class_ > clanguml::sequence_diagram::visitor::translation_unit_visitor::create_element ( const clang::NamedDecl *  decl) const

Definition at line 36 of file translation_unit_visitor.cc.

38{
39 return std::make_unique<sequence_diagram::model::class_>(
40 config().using_namespace());
41}

◆ create_lambda_method_model()

std::unique_ptr< clanguml::sequence_diagram::model::method > clanguml::sequence_diagram::visitor::translation_unit_visitor::create_lambda_method_model ( clang::CXXMethodDecl *  cls)
private

Definition at line 2049 of file translation_unit_visitor.cc.

2051{
2052 auto method_model_ptr = std::make_unique<sequence_diagram::model::method>(
2053 config().using_namespace());
2054
2055 common::model::namespace_ ns{declaration->getQualifiedNameAsString()};
2056 auto method_name = ns.name();
2057 method_model_ptr->set_method_name(method_name);
2058 ns.pop_back();
2059 method_model_ptr->set_name(ns.name());
2060 ns.pop_back();
2061 method_model_ptr->set_namespace(ns);
2062
2063 method_model_ptr->is_defaulted(declaration->isDefaulted());
2064 method_model_ptr->is_assignment(declaration->isCopyAssignmentOperator() ||
2065 declaration->isMoveAssignmentOperator());
2066 method_model_ptr->is_const(declaration->isConst());
2067 method_model_ptr->is_static(declaration->isStatic());
2068 method_model_ptr->is_operator(declaration->isOverloadedOperator());
2069 method_model_ptr->is_constructor(
2070 clang::dyn_cast<clang::CXXConstructorDecl>(declaration) != nullptr);
2071
2072 method_model_ptr->is_void(declaration->getReturnType()->isVoidType());
2073
2074 method_model_ptr->return_type(common::to_string(
2075 declaration->getReturnType(), declaration->getASTContext()));
2076
2077 for (const auto *param : declaration->parameters()) {
2078 auto parameter_type =
2079 common::to_string(param->getType(), param->getASTContext());
2081 parameter_type = simplify_system_template(parameter_type);
2082 method_model_ptr->add_parameter(config().using_namespace().relative(
2083 simplify_system_template(parameter_type)));
2084 }
2085
2086 return method_model_ptr;
2087}

◆ create_method_model()

std::unique_ptr< clanguml::sequence_diagram::model::method > clanguml::sequence_diagram::visitor::translation_unit_visitor::create_method_model ( clang::CXXMethodDecl *  cls)
private

Definition at line 2090 of file translation_unit_visitor.cc.

2091{
2092 auto method_model_ptr = std::make_unique<sequence_diagram::model::method>(
2093 config().using_namespace());
2094
2095 common::model::namespace_ ns{declaration->getQualifiedNameAsString()};
2096 auto method_name = ns.name();
2097 method_model_ptr->set_method_name(method_name);
2098 ns.pop_back();
2099 method_model_ptr->set_name(ns.name());
2100 ns.pop_back();
2101 method_model_ptr->set_namespace(ns);
2102
2103 method_model_ptr->is_defaulted(declaration->isDefaulted());
2104 method_model_ptr->is_assignment(declaration->isCopyAssignmentOperator() ||
2105 declaration->isMoveAssignmentOperator());
2106 method_model_ptr->is_const(declaration->isConst());
2107 method_model_ptr->is_static(declaration->isStatic());
2108 method_model_ptr->is_operator(declaration->isOverloadedOperator());
2109 method_model_ptr->is_constructor(
2110 clang::dyn_cast<clang::CXXConstructorDecl>(declaration) != nullptr);
2111
2112 clang::Decl *parent_decl = declaration->getParent();
2113
2114 if (context().current_class_template_decl_ != nullptr)
2115 parent_decl = context().current_class_template_decl_;
2116
2117 LOG_DBG("Getting method's class with local id {}", parent_decl->getID());
2118
2119 const auto maybe_method_class = get_participant<model::class_>(parent_decl);
2120
2121 if (!maybe_method_class) {
2122 LOG_DBG("Cannot find parent class_ for method {} in class {}",
2123 declaration->getQualifiedNameAsString(),
2124 declaration->getParent()->getQualifiedNameAsString());
2125 return {};
2126 }
2127
2128 const auto &method_class = maybe_method_class.value();
2129
2130 method_model_ptr->is_void(declaration->getReturnType()->isVoidType());
2131
2132 method_model_ptr->set_class_id(method_class.id());
2133 method_model_ptr->set_class_full_name(method_class.full_name(false));
2134 method_model_ptr->set_name(get_participant(method_model_ptr->class_id())
2135 .value()
2136 .full_name_no_ns() +
2137 "::" + declaration->getNameAsString());
2138
2139 method_model_ptr->return_type(common::to_string(
2140 declaration->getReturnType(), declaration->getASTContext()));
2141
2142 for (const auto *param : declaration->parameters()) {
2143 auto parameter_type =
2144 common::to_string(param->getType(), param->getASTContext());
2146 parameter_type = simplify_system_template(parameter_type);
2147 method_model_ptr->add_parameter(config().using_namespace().relative(
2148 simplify_system_template(parameter_type)));
2149 }
2150
2151 return method_model_ptr;
2152}

◆ ensure_lambda_messages_have_operator_as_target()

void clanguml::sequence_diagram::visitor::translation_unit_visitor::ensure_lambda_messages_have_operator_as_target ( )
private

Definition at line 2001 of file translation_unit_visitor.cc.

2002{
2003 for (auto &[id, activity] : diagram().sequences()) {
2004 for (auto &m : activity.messages()) {
2005 auto participant = diagram().get_participant<model::class_>(m.to());
2006
2007 if (participant && participant.value().is_lambda() &&
2008 participant.value().lambda_operator_id().value() != 0) {
2009 LOG_DBG("Changing lambda expression target id from {} to {}",
2010 m.to(), participant.value().lambda_operator_id());
2011
2012 m.set_to(participant.value().lambda_operator_id());
2013 m.set_message_name("operator()");
2014 }
2015 }
2016 }
2017}

◆ finalize()

void clanguml::sequence_diagram::visitor::translation_unit_visitor::finalize ( )

Finalize diagram model for this translation unit.

Definition at line 1987 of file translation_unit_visitor.cc.

1988{
1990
1991 // Change all messages with target set to an id of a lambda expression to
1992 // to the ID of their operator() - this is necessary, as some calls to
1993 // lambda expressions are visited before the actual lambda expressions
1994 // are visited...
1996
1997 if (config().inline_lambda_messages())
1998 diagram().inline_lambda_operator_calls();
1999}

◆ generate_message_from_comment()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::generate_message_from_comment ( model::message m) const
private

Initializes model message from comment call directive.

Parameters
mMessage instance
Returns
True, if the comment associated with the call expression contained a call directive and it was parsed correctly.

Definition at line 1223 of file translation_unit_visitor.cc.

1225{
1226 auto generated_message_from_comment{false};
1227 for (const auto &decorator : m.decorators()) {
1228 auto call_decorator =
1229 std::dynamic_pointer_cast<decorators::call>(decorator);
1230 if (call_decorator &&
1231 call_decorator->applies_to_diagram(config().name)) {
1232 m.set_to(common::to_id(call_decorator->callee));
1233 generated_message_from_comment = true;
1234 break;
1235 }
1236 }
1237 return generated_message_from_comment;
1238}

◆ get_expression_comment()

std::optional< std::pair< unsigned int, std::string > > clanguml::sequence_diagram::visitor::translation_unit_visitor::get_expression_comment ( const clang::SourceManager &  sm,
const clang::ASTContext &  context,
eid_t  caller_id,
const clang::Stmt *  stmt 
)
private

Definition at line 2241 of file translation_unit_visitor.cc.

2244{
2245 const auto *raw_comment =
2247
2248 if (raw_comment == nullptr)
2249 return {};
2250
2251 if (!caller_id.is_global() &&
2253 .emplace(caller_id.ast_local_value(), raw_comment)
2254 .second) {
2255 return {};
2256 }
2257
2258 const auto &[decorators, stripped_comment] = decorators::parse(
2259 raw_comment->getFormattedText(sm, sm.getDiagnostics()));
2260
2261 if (stripped_comment.empty())
2262 return {};
2263
2264 return {{raw_comment->getBeginLoc().getHashValue(), stripped_comment}};
2265}

◆ get_participant() [1/4]

template<typename T = model::participant>
common::optional_ref< T > clanguml::sequence_diagram::visitor::translation_unit_visitor::get_participant ( const clang::Decl *  decl)
inline

Get participant by declaration.

Template Parameters
TParticipant type
Parameters
declClang entity declaration
Returns
Optional reference to participant diagram element

Definition at line 165 of file translation_unit_visitor.h.

166 {
167 assert(decl != nullptr);
168
169 auto unique_participant_id = get_unique_id(eid_t{decl->getID()});
170 if (!unique_participant_id.has_value())
171 return {};
172
173 return get_participant<T>(unique_participant_id.value());
174 }

◆ get_participant() [2/4]

template<typename T = model::participant>
common::optional_ref< T > clanguml::sequence_diagram::visitor::translation_unit_visitor::get_participant ( const clang::Decl *  decl) const
inline

Get participant by declaration.

Template Parameters
TParticipant type
Parameters
declClang entity declaration
Returns
Optional reference to participant diagram element

Definition at line 184 of file translation_unit_visitor.h.

185 {
186 assert(decl != nullptr);
187
188 auto unique_participant_id = get_unique_id(eid_t{decl->getID()});
189 if (!unique_participant_id.has_value())
190 return {};
191
192 return get_participant<T>(unique_participant_id.value());
193 }

◆ get_participant() [3/4]

template<typename T = model::participant>
common::optional_ref< T > clanguml::sequence_diagram::visitor::translation_unit_visitor::get_participant ( const eid_t  id)
inline

Get participant by global element id.

Template Parameters
TParticipant type
Parameters
idGlobal element id
Returns
Optional reference to participant diagram element

Definition at line 203 of file translation_unit_visitor.h.

204 {
205 if (diagram().participants().find(id) == diagram().participants().end())
206 return {};
207
208 return common::optional_ref<T>(
209 *(static_cast<T *>(diagram().participants().at(id).get())));
210 }

◆ get_participant() [4/4]

template<typename T = model::participant>
common::optional_ref< T > clanguml::sequence_diagram::visitor::translation_unit_visitor::get_participant ( eid_t  id) const
inline

Get participant by global element id.

Template Parameters
TParticipant type
Parameters
idGlobal element id
Returns
Optional reference to participant diagram element

Definition at line 220 of file translation_unit_visitor.h.

221 {
222 if (diagram().participants().find(id) == diagram().participants().end())
223 return {};
224
225 return common::optional_ref<T>(
226 *(static_cast<T *>(diagram().participants().at(id).get())));
227 }

◆ get_unique_id()

std::optional< eid_t > clanguml::sequence_diagram::visitor::translation_unit_visitor::get_unique_id ( eid_t  local_id) const

Retrieve the global clang-uml entity id based on the Clang local id.

Parameters
local_idAST local element id
Returns
Global diagram element id

Definition at line 1749 of file translation_unit_visitor.cc.

1751{
1752 return id_mapper().get_global_id(local_id);
1753}

◆ is_callee_valid_template_specialization()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::is_callee_valid_template_specialization ( const clang::CXXDependentScopeMemberExpr *  dependent_member_expr) const
private

Check, the callee is a template specialization.

Parameters
dependent_member_exprDependent member expression
Returns
True, if the callee is a template specialization

Definition at line 1592 of file translation_unit_visitor.cc.

1594{
1595 if (dependent_member_expr == nullptr)
1596 return false;
1597
1598 if (dependent_member_expr->getBaseType().isNull())
1599 return false;
1600
1601 const auto *tst = dependent_member_expr->getBaseType()
1602 ->getAs<clang::TemplateSpecializationType>();
1603
1604 if (tst == nullptr)
1605 return false;
1606
1607 return !(tst->isPointerType());
1608}

◆ is_smart_pointer()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::is_smart_pointer ( const clang::TemplateDecl *  primary_template) const
private

Check if template is a smart pointer.

Parameters
primary_templateTemplate declaration
Returns
True, if template declaration is a smart pointer

Definition at line 1610 of file translation_unit_visitor.cc.

1612{
1613 return primary_template->getQualifiedNameAsString().find(
1614 "std::unique_ptr") == 0 ||
1615 primary_template->getQualifiedNameAsString().find("std::shared_ptr") ==
1616 0 ||
1617 primary_template->getQualifiedNameAsString().find("std::weak_ptr") == 0;
1618}

◆ lambda_source_location()

std::string clanguml::sequence_diagram::visitor::translation_unit_visitor::lambda_source_location ( const clang::SourceLocation &  source_location) const
private

Render lambda source location to string.

Returns exact source code location of the lambda expression in the form <filepath>:<line>:<column>.

The filepath is relative to the relative_to config option.

Parameters
source_locationClang SourceLocation instance associated with lambda expression
Returns
String representation of the location

Definition at line 1871 of file translation_unit_visitor.cc.

1873{
1874 const auto file_line =
1875 source_manager().getSpellingLineNumber(source_location);
1876 const auto file_column =
1877 source_manager().getSpellingColumnNumber(source_location);
1878 const std::string file_name =
1879 config()
1880 .make_path_relative(
1881 source_manager().getFilename(source_location).str())
1882 .string();
1883 return fmt::format("{}:{}:{}", file_name, file_line, file_column);
1884}

◆ make_lambda_name()

std::string clanguml::sequence_diagram::visitor::translation_unit_visitor::make_lambda_name ( const clang::CXXRecordDecl *  cls) const
private

Assuming cls is a lambda, create it's full name.

Note
Currently, lambda names are generated using their source code location including file path, line and column to ensure unique names.
Parameters
clsLambda declaration
Returns
Full lambda unique name

Definition at line 1886 of file translation_unit_visitor.cc.

1888{
1889 std::string result;
1890 const auto location = cls->getLocation();
1891 const std::string source_location{lambda_source_location(location)};
1892
1893 const auto maybe_lambda_caller_id = context().lambda_caller_id();
1894 if (maybe_lambda_caller_id.has_value()) {
1895 // Parent is also a lambda (this id points to a lambda operator())
1896 std::string parent_lambda_class_name{"()"};
1897 if (diagram().get_participant<model::method>(
1898 maybe_lambda_caller_id.value())) {
1899 auto parent_lambda_class_id =
1900 diagram()
1901 .get_participant<model::method>(
1902 maybe_lambda_caller_id.value())
1903 .value()
1904 .class_id();
1905
1906 if (diagram().get_participant<model::class_>(
1907 parent_lambda_class_id)) {
1908 parent_lambda_class_name =
1909 diagram()
1910 .get_participant<model::class_>(parent_lambda_class_id)
1911 .value()
1912 .full_name(false);
1913 }
1914 }
1915
1916 result = fmt::format(
1917 "{}##(lambda {})", parent_lambda_class_name, source_location);
1918 }
1919 else if (context().caller_id().value() != 0 &&
1920 get_participant(context().caller_id()).has_value()) {
1921 auto parent_full_name =
1922 get_participant(context().caller_id()).value().full_name_no_ns();
1923
1924 result =
1925 fmt::format("{}##(lambda {})", parent_full_name, source_location);
1926 }
1927 else {
1928 result = fmt::format("(lambda {})", source_location);
1929 }
1930
1931 return result;
1932}

◆ pop_message_to_diagram() [1/2]

void clanguml::sequence_diagram::visitor::translation_unit_visitor::pop_message_to_diagram ( clang::CallExpr *  expr)
private

Move a message model to diagram.

Parameters
exprCall expression

Definition at line 1946 of file translation_unit_visitor.cc.

1947{
1948 assert(expr != nullptr);
1949
1950 // Skip if no message was generated from this expr
1951 if (call_expr_message_map_.find(expr) == call_expr_message_map_.end()) {
1952 return;
1953 }
1954
1955 auto msg = std::move(call_expr_message_map_.at(expr));
1956
1957 auto caller_id = msg.from();
1958
1959 if (caller_id == 0)
1960 return;
1961
1962 if (diagram().has_activity(caller_id))
1963 diagram().get_activity(caller_id).add_message(std::move(msg));
1964
1965 call_expr_message_map_.erase(expr);
1966}

◆ pop_message_to_diagram() [2/2]

void clanguml::sequence_diagram::visitor::translation_unit_visitor::pop_message_to_diagram ( clang::CXXConstructExpr *  expr)
private

Definition at line 1968 of file translation_unit_visitor.cc.

1970{
1971 assert(expr != nullptr);
1972
1973 // Skip if no message was generated from this expr
1974 if (construct_expr_message_map_.find(expr) ==
1976 return;
1977 }
1978
1979 auto msg = std::move(construct_expr_message_map_.at(expr));
1980
1981 auto caller_id = msg.from();
1982 diagram().get_activity(caller_id).add_message(std::move(msg));
1983
1984 construct_expr_message_map_.erase(expr);
1985}

◆ process_class_method_call_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_class_method_call_expression ( model::message m,
const clang::CXXMemberCallExpr *  method_call_expr 
)
private

Handle a class method call expresion.

Parameters
mMessage model
method_call_exprOperator call expression
Returns
True, if m contains now a valid call expression model

Definition at line 1398 of file translation_unit_visitor.cc.

1400{
1401 // Get callee declaration as methods parent
1402 const auto *method_decl = method_call_expr->getMethodDecl();
1403
1404 if (method_decl == nullptr)
1405 return false;
1406
1407 std::string method_name = method_decl->getQualifiedNameAsString();
1408
1409 const auto *callee_decl =
1410 method_decl != nullptr ? method_decl->getParent() : nullptr;
1411
1412 if (callee_decl == nullptr)
1413 return false;
1414
1415 if (!should_include(callee_decl) || !should_include(method_decl))
1416 return false;
1417
1418 m.set_to(eid_t{method_decl->getID()});
1419 m.set_message_name(method_decl->getNameAsString());
1420 m.set_return_type(
1421 method_call_expr->getCallReturnType(*context().get_ast_context())
1422 .getAsString());
1423
1424 LOG_TRACE("Set callee method id {} for method name {}", m.to(),
1425 method_decl->getQualifiedNameAsString());
1426
1427 diagram().add_active_participant(eid_t{method_decl->getID()});
1428
1429 return true;
1430}

◆ process_class_template_method_call_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_class_template_method_call_expression ( model::message m,
const clang::CallExpr *  expr 
)
private

Handle a class template method call expresion.

Parameters
mMessage model
exprClass template method call expression
Returns
True, if m contains now a valid call expression model

Definition at line 1432 of file translation_unit_visitor.cc.

1434{
1435 const auto *dependent_member_callee =
1436 clang::dyn_cast_or_null<clang::CXXDependentScopeMemberExpr>(
1437 expr->getCallee());
1438
1439 if (dependent_member_callee == nullptr)
1440 return false;
1441
1442 if (is_callee_valid_template_specialization(dependent_member_callee)) {
1443 if (const auto *tst = dependent_member_callee->getBaseType()
1444 ->getAs<clang::TemplateSpecializationType>();
1445 tst != nullptr) {
1446 const auto *template_declaration =
1447 tst->getTemplateName().getAsTemplateDecl();
1448
1449 std::string callee_method_full_name;
1450
1451 // First check if the primary template is already in the
1452 // participants map
1453 if (get_participant(template_declaration).has_value()) {
1454 callee_method_full_name = get_participant(template_declaration)
1455 .value()
1456 .full_name(false) +
1457 "::" + dependent_member_callee->getMember().getAsString();
1458
1459 for (const auto &[id, p] : diagram().participants()) {
1460 const auto p_full_name = p->full_name(false);
1461
1462 if (p_full_name.find(callee_method_full_name + "(") == 0) {
1463 // TODO: This selects the first matching template method
1464 // without considering arguments!!!
1465 m.set_to(id);
1466 break;
1467 }
1468 }
1469 }
1470 // Otherwise check if it is a smart pointer
1471 else if (is_smart_pointer(template_declaration)) {
1472 const auto *argument_template =
1473 template_declaration->getTemplateParameters()
1474 ->asArray()
1475 .front();
1476
1477 if (get_participant(argument_template).has_value()) {
1478 callee_method_full_name = get_participant(argument_template)
1479 .value()
1480 .full_name(false) +
1481 "::" +
1482 dependent_member_callee->getMember().getAsString();
1483
1484 for (const auto &[id, p] : diagram().participants()) {
1485 const auto p_full_name = p->full_name(false);
1486 if (p_full_name.find(callee_method_full_name + "(") ==
1487 0) {
1488 // TODO: This selects the first matching template
1489 // method without considering arguments!!!
1490 m.set_to(id);
1491 break;
1492 }
1493 }
1494 }
1495 else
1496 return false;
1497 }
1498
1499 m.set_message_name(
1500 dependent_member_callee->getMember().getAsString());
1501
1502 if (const auto maybe_id =
1503 get_unique_id(eid_t{template_declaration->getID()});
1504 maybe_id.has_value())
1505 diagram().add_active_participant(maybe_id.value());
1506 }
1507 }
1508 else {
1509 LOG_DBG("Skipping call due to unresolvable "
1510 "CXXDependentScopeMemberExpr at {}",
1511 expr->getBeginLoc().printToString(source_manager()));
1512 }
1513
1514 return true;
1515}

◆ process_class_template_specialization()

std::unique_ptr< model::class_ > clanguml::sequence_diagram::visitor::translation_unit_visitor::process_class_template_specialization ( clang::ClassTemplateSpecializationDecl *  cls)
private

Definition at line 1829 of file translation_unit_visitor.cc.

1831{
1832 auto c_ptr{std::make_unique<model::class_>(config().using_namespace())};
1833
1835
1836 auto &template_instantiation = *c_ptr;
1837
1838 // TODO: refactor to method get_qualified_name()
1839 auto qualified_name = cls->getQualifiedNameAsString();
1840 util::replace_all(qualified_name, "(anonymous namespace)", "");
1841 util::replace_all(qualified_name, "::::", "::");
1842
1843 common::model::namespace_ ns{qualified_name};
1844 ns.pop_back();
1845 template_instantiation.set_name(cls->getNameAsString());
1846 template_instantiation.set_namespace(ns);
1847
1848 template_instantiation.is_struct(cls->isStruct());
1849
1850 process_comment(*cls, template_instantiation);
1851 set_source_location(*cls, template_instantiation);
1852 set_owning_module(*cls, template_instantiation);
1853
1854 if (template_instantiation.skip())
1855 return {};
1856
1857 template_instantiation.set_id(
1858 common::to_id(template_instantiation.full_name(false)));
1859
1860 set_unique_id(cls->getID(), template_instantiation.id());
1861
1862 return c_ptr;
1863}

◆ process_construct_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_construct_expression ( model::message m,
const clang::CXXConstructExpr *  construct_expr 
)
private

Handle CXX constructor call.

Parameters
mMessage model
construct_exprCXX Construct expression
Returns
True, if m contains a valid constructor call

Definition at line 1372 of file translation_unit_visitor.cc.

1374{
1375 const auto *constructor = construct_expr->getConstructor();
1376 if (constructor == nullptr)
1377 return false;
1378
1379 const auto *constructor_parent = constructor->getParent();
1380 if (constructor_parent == nullptr)
1381 return false;
1382
1383 LOG_DBG("Constructor '{}' call expression to {} at {}",
1384 construct_expr->getConstructor()->getNameAsString(),
1385 constructor->getID(),
1386 construct_expr->getBeginLoc().printToString(source_manager()));
1387
1388 m.set_to(id_mapper().resolve_or(eid_t{constructor->getID()}));
1389 m.set_message_name(
1390 fmt::format("{}::{}", constructor_parent->getQualifiedNameAsString(),
1391 constructor_parent->getNameAsString()));
1392
1393 diagram().add_active_participant(eid_t{constructor->getID()});
1394
1395 return true;
1396}

◆ process_cuda_kernel_call_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_cuda_kernel_call_expression ( model::message m,
const clang::CUDAKernelCallExpr *  cuda_call_expr 
)
private

Definition at line 1305 of file translation_unit_visitor.cc.

1307{
1308 const auto *callee_decl = expr->getCalleeDecl();
1309
1310 if (callee_decl == nullptr)
1311 return false;
1312
1313 const auto *callee_function = callee_decl->getAsFunction();
1314
1315 if (callee_function == nullptr)
1316 return false;
1317
1318 if (!should_include(callee_function))
1319 return false;
1320
1321 // Skip free functions declared in files outside of included paths
1322 if (config().combine_free_functions_into_file_participants() &&
1323 !diagram().should_include(common::model::source_file{m.file()}))
1324 return false;
1325
1326 auto callee_name = callee_function->getQualifiedNameAsString() + "()";
1327
1328 m.set_to(id_mapper().resolve_or(eid_t{callee_function->getID()}));
1329 m.set_message_name(callee_name.substr(0, callee_name.size() - 2));
1330
1331 return true;
1332}

◆ process_function_call_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_function_call_expression ( model::message m,
const clang::CallExpr *  expr 
)
private

Handle a function call expresion.

Parameters
mMessage model
exprFunction call expression
Returns
True, if m contains now a valid call expression model

Definition at line 1517 of file translation_unit_visitor.cc.

1519{
1520 const auto *callee_decl = expr->getCalleeDecl();
1521
1522 if (callee_decl == nullptr)
1523 return false;
1524
1525 const auto *callee_function = callee_decl->getAsFunction();
1526
1527 if (callee_function == nullptr)
1528 return false;
1529
1530 if (!should_include(callee_function))
1531 return false;
1532
1533 // Skip free functions declared in files outside of included paths
1534 if (config().combine_free_functions_into_file_participants() &&
1535 !diagram().should_include(common::model::source_file{m.file()}))
1536 return false;
1537
1538 auto callee_name = callee_function->getQualifiedNameAsString() + "()";
1539
1540 m.set_to(id_mapper().resolve_or(eid_t{callee_function->getID()}));
1541 m.set_message_name(callee_name.substr(0, callee_name.size() - 2));
1542
1543 return true;
1544}

◆ process_lambda_call_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_lambda_call_expression ( model::message m,
const clang::CallExpr *  expr 
) const
private

Definition at line 1546 of file translation_unit_visitor.cc.

1548{
1549 const auto *lambda_expr =
1550 clang::dyn_cast_or_null<clang::LambdaExpr>(expr->getCallee());
1551
1552 if (lambda_expr == nullptr)
1553 return true;
1554
1555 const auto lambda_class_id = eid_t{lambda_expr->getLambdaClass()->getID()};
1556 m.set_to(id_mapper().resolve_or(eid_t{lambda_class_id}));
1557
1558 return true;
1559}

◆ process_operator_call_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_operator_call_expression ( model::message m,
const clang::CXXOperatorCallExpr *  operator_call_expr 
)
private

Handle a operator call expression.

Parameters
mMessage model
operator_call_exprOperator call expression
Returns
True, if m contains now a valid call expression model

Definition at line 1334 of file translation_unit_visitor.cc.

1336{
1337 if (operator_call_expr->getCalleeDecl() == nullptr)
1338 return false;
1339
1340 LOG_DBG("Operator '{}' call expression to {} at {}",
1341 getOperatorSpelling(operator_call_expr->getOperator()),
1342 operator_call_expr->getCalleeDecl()->getID(),
1343 operator_call_expr->getBeginLoc().printToString(source_manager()));
1344
1345 // Handle the case if the callee is a lambda
1346 if (const auto *lambda_method = clang::dyn_cast<clang::CXXMethodDecl>(
1347 operator_call_expr->getCalleeDecl());
1348 lambda_method != nullptr && lambda_method->getParent()->isLambda()) {
1349
1350 LOG_DBG("Operator callee is a lambda: {}",
1351 common::to_string(lambda_method));
1352
1353 const auto source_location{
1354 lambda_source_location(lambda_method->getParent()->getLocation())};
1355
1356 auto lambda_name = make_lambda_name(lambda_method->getParent());
1357
1358 m.set_to(eid_t{lambda_method->getParent()->getID()});
1359 }
1360 else {
1361 const auto operator_ast_id =
1362 operator_call_expr->getCalleeDecl()->getID();
1363 m.set_to(id_mapper().resolve_or(eid_t{operator_ast_id}));
1364 }
1365
1366 m.set_message_name(fmt::format(
1367 "operator{}", getOperatorSpelling(operator_call_expr->getOperator())));
1368
1369 return true;
1370}

◆ process_unresolved_lookup_call_expression()

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::process_unresolved_lookup_call_expression ( model::message m,
const clang::CallExpr *  expr 
) const
private

Handle an unresolved lookup call expresion.

Unresolved lookup expression is a reference to a name which Clang was not able to look up during parsing but could not resolve to a specific declaration.

Parameters
mMessage model
exprCall expression
Returns
True, if m contains now a valid call expression model

Definition at line 1561 of file translation_unit_visitor.cc.

1563{
1564 // This is probably a template
1565 const auto *unresolved_expr =
1566 clang::dyn_cast_or_null<clang::UnresolvedLookupExpr>(expr->getCallee());
1567
1568 if (unresolved_expr != nullptr) {
1569 for (const auto *decl : unresolved_expr->decls()) {
1570 if (clang::dyn_cast_or_null<clang::FunctionTemplateDecl>(decl) !=
1571 nullptr) {
1572 const auto *ftd =
1573 clang::dyn_cast_or_null<clang::FunctionTemplateDecl>(decl);
1574 m.set_to(id_mapper().resolve_or(eid_t{ftd->getID()}));
1575 break;
1576 }
1577
1578 if (clang::dyn_cast_or_null<clang::FunctionDecl>(decl) != nullptr) {
1579 const auto *fd =
1580 clang::dyn_cast_or_null<clang::FunctionDecl>(decl);
1581 m.set_to(id_mapper().resolve_or(eid_t{fd->getID()}));
1582 break;
1583 }
1584
1585 LOG_DBG("Unknown unresolved lookup expression");
1586 }
1587 }
1588
1589 return true;
1590}

◆ push_message() [1/2]

void clanguml::sequence_diagram::visitor::translation_unit_visitor::push_message ( clang::CallExpr *  expr,
model::message &&  m 
)
private

Register a message model m with a call expression.

This is used to know whether a model for a specific call expression has already been created, but not yet added to the diagram.

Parameters
exprCall expresion
mMessage model

Definition at line 1934 of file translation_unit_visitor.cc.

1936{
1937 call_expr_message_map_.emplace(expr, std::move(m));
1938}

◆ push_message() [2/2]

void clanguml::sequence_diagram::visitor::translation_unit_visitor::push_message ( clang::CXXConstructExpr *  expr,
model::message &&  m 
)
private

Definition at line 1940 of file translation_unit_visitor.cc.

1942{
1943 construct_expr_message_map_.emplace(expr, std::move(m));
1944}

◆ resolve_ids_to_global()

void clanguml::sequence_diagram::visitor::translation_unit_visitor::resolve_ids_to_global ( )
private

Definition at line 2019 of file translation_unit_visitor.cc.

2020{
2021 std::set<eid_t> active_participants_unique;
2022
2023 // Change all active participants AST local ids to diagram global ids
2024 for (auto id : diagram().active_participants()) {
2025 if (const auto unique_id = get_unique_id(id);
2026 !id.is_global() && unique_id.has_value()) {
2027 active_participants_unique.emplace(unique_id.value());
2028 }
2029 else if (id.is_global()) {
2030 active_participants_unique.emplace(id);
2031 }
2032 }
2033
2034 diagram().active_participants() = std::move(active_participants_unique);
2035
2036 // Change all message callees AST local ids to diagram global ids
2037 for (auto &[id, activity] : diagram().sequences()) {
2038 for (auto &m : activity.messages()) {
2039 if (const auto unique_id = get_unique_id(m.to());
2040 !m.to().is_global() && unique_id.has_value()) {
2041 m.set_to(unique_id.value());
2042 assert(m.to().is_global());
2043 }
2044 }
2045 }
2046}

◆ set_unique_id()

void clanguml::sequence_diagram::visitor::translation_unit_visitor::set_unique_id ( int64_t  local_id,
eid_t  global_id 
)

Store the mapping from local clang entity id (obtained using getID()) method to clang-uml global id.

Todo:
Refactor to ast_id_mapper
Parameters
local_idLocal AST element id
global_idGloba diagram element id

Definition at line 1740 of file translation_unit_visitor.cc.

1741{
1742 LOG_TRACE("Setting local element mapping {} --> {}", local_id, global_id);
1743
1744 assert(global_id.is_global());
1745
1746 id_mapper().add(local_id, global_id);
1747}

◆ should_include() [1/7]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::should_include ( const clang::CallExpr *  expr) const
private

Check if the diagram should include a call expression.

Parameters
exprCall expression.
Returns
True, if the expression should be included in the diagram.

Definition at line 2167 of file translation_unit_visitor.cc.

2168{
2169 if (context().caller_id() == 0)
2170 return false;
2171
2172 // Skip casts, moves and such
2173 if (expr->isCallToStdMove())
2174 return false;
2175
2176 if (expr->isImplicitCXXThis())
2177 return false;
2178
2179 if (clang::dyn_cast_or_null<clang::ImplicitCastExpr>(expr) != nullptr)
2180 return false;
2181
2182 if (!context().valid())
2183 return false;
2184
2185 const auto expr_file = expr->getBeginLoc().printToString(source_manager());
2186
2187 if (!diagram().should_include(common::model::source_file{expr_file}))
2188 return false;
2189
2190 const auto *callee_decl = expr->getCalleeDecl();
2191
2192 if (callee_decl != nullptr) {
2193 const auto *callee_function = callee_decl->getAsFunction();
2194
2195 if ((callee_function == nullptr) || !should_include(callee_function)) {
2196 LOG_DBG("Skipping call expression at {}",
2197 expr->getBeginLoc().printToString(source_manager()));
2198 return false;
2199 }
2200
2201 return should_include(callee_function);
2202 }
2203
2204 return true;
2205}

◆ should_include() [2/7]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::should_include ( const clang::ClassTemplateDecl *  decl) const
private

Check if the diagram should include a declaration.

Parameters
declClang declaration.
Returns
True, if the entity should be included in the diagram.

Definition at line 2234 of file translation_unit_visitor.cc.

2236{
2238}

◆ should_include() [3/7]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::should_include ( const clang::CXXMethodDecl *  decl) const
private

Check if the diagram should include a declaration.

Parameters
declClang declaration.
Returns
True, if the entity should be included in the diagram.

Definition at line 2207 of file translation_unit_visitor.cc.

2209{
2210 if (!should_include(decl->getParent()))
2211 return false;
2212
2213 if (!diagram().should_include(
2214 common::access_specifier_to_access_t(decl->getAccess())))
2215 return false;
2216
2217 LOG_DBG("Including method {}", decl->getQualifiedNameAsString());
2218
2219 return true;
2220}

◆ should_include() [4/7]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::should_include ( const clang::FunctionDecl *  decl) const
private

Check if the diagram should include a declaration.

Parameters
declClang declaration.
Returns
True, if the entity should be included in the diagram.

Definition at line 2222 of file translation_unit_visitor.cc.

2224{
2226}

◆ should_include() [5/7]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::should_include ( const clang::FunctionTemplateDecl *  decl) const
private

Check if the diagram should include a declaration.

Parameters
declClang declaration.
Returns
True, if the entity should be included in the diagram.

Definition at line 2228 of file translation_unit_visitor.cc.

2230{
2231 return visitor_specialization_t::should_include(decl->getAsFunction());
2232}

◆ should_include() [6/7]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::should_include ( const clang::LambdaExpr *  expr) const
private

Check if the diagram should include a lambda expression.

Parameters
exprLambda expression.
Returns
True, if the expression should be included in the diagram.

Definition at line 2160 of file translation_unit_visitor.cc.

2162{
2163 const auto expr_file = expr->getBeginLoc().printToString(source_manager());
2164 return diagram().should_include(common::model::source_file{expr_file});
2165}

◆ should_include() [7/7]

bool clanguml::sequence_diagram::visitor::translation_unit_visitor::should_include ( const clang::TagDecl *  decl) const
private

Check if the diagram should include a declaration.

Parameters
declClang declaration.
Returns
True, if the entity should be included in the diagram.

Definition at line 2154 of file translation_unit_visitor.cc.

2155{
2157 dynamic_cast<const clang::NamedDecl *>(decl));
2158}

◆ simplify_system_template()

std::string clanguml::sequence_diagram::visitor::translation_unit_visitor::simplify_system_template ( const std::string &  full_name) const
private

Definition at line 1865 of file translation_unit_visitor.cc.

1867{
1868 return config().simplify_template_type(full_name);
1869}

◆ tbuilder()

template_builder_t & clanguml::sequence_diagram::visitor::translation_unit_visitor::tbuilder ( )
inlineprivate

Get template builder reference.

Returns
Reference to 'template_builder' instance

Definition at line 488 of file translation_unit_visitor.h.

488{ return template_builder_; }

Member Data Documentation

◆ already_visited_in_static_declaration_

std::set<const clang::Expr *> clanguml::sequence_diagram::visitor::translation_unit_visitor::already_visited_in_static_declaration_ {}
mutableprivate

Definition at line 515 of file translation_unit_visitor.h.

◆ anonymous_struct_relationships_

std::map<int64_t , std::tuple<std::string , common::model::relationship_t, common::model::access_t> > clanguml::sequence_diagram::visitor::translation_unit_visitor::anonymous_struct_relationships_
private

Definition at line 511 of file translation_unit_visitor.h.

◆ call_expr_message_map_

std::map<clang::CallExpr *, model::message> clanguml::sequence_diagram::visitor::translation_unit_visitor::call_expr_message_map_
private

This is used to generate messages in proper order in case of nested call expressions (e.g. a(b(c(), d())), as they need to be added to the diagram sequence after the visitor leaves the call expression AST node

Definition at line 501 of file translation_unit_visitor.h.

◆ call_expression_context_

call_expression_context clanguml::sequence_diagram::visitor::translation_unit_visitor::call_expression_context_
private

Definition at line 494 of file translation_unit_visitor.h.

◆ construct_expr_message_map_

std::map<clang::CXXConstructExpr *, model::message> clanguml::sequence_diagram::visitor::translation_unit_visitor::construct_expr_message_map_
private

Definition at line 503 of file translation_unit_visitor.h.

◆ forward_declarations_

std::map<eid_t, std::unique_ptr<clanguml::sequence_diagram::model::class_> > clanguml::sequence_diagram::visitor::translation_unit_visitor::forward_declarations_
private

Definition at line 506 of file translation_unit_visitor.h.

◆ processed_comments_by_caller_id_

std::set<std::pair<int64_t, const clang::RawComment *> > clanguml::sequence_diagram::visitor::translation_unit_visitor::processed_comments_by_caller_id_
mutableprivate

Definition at line 518 of file translation_unit_visitor.h.

◆ template_builder_

template_builder_t clanguml::sequence_diagram::visitor::translation_unit_visitor::template_builder_
private

Definition at line 520 of file translation_unit_visitor.h.

◆ within_static_variable_declaration_

unsigned clanguml::sequence_diagram::visitor::translation_unit_visitor::within_static_variable_declaration_ {0}
mutableprivate

Definition at line 513 of file translation_unit_visitor.h.


The documentation for this class was generated from the following files: