Update Doxygen docs for class_diagram namespace
This commit is contained in:
@@ -56,36 +56,110 @@ using clanguml::common::model::relationship_t;
|
||||
|
||||
using namespace clanguml::util;
|
||||
|
||||
/**
|
||||
* @brief Class diagram JSON generator
|
||||
*/
|
||||
class generator : public common_generator<diagram_config, diagram_model> {
|
||||
public:
|
||||
generator(diagram_config &config, diagram_model &model);
|
||||
|
||||
/**
|
||||
* @brief Main generator method.
|
||||
*
|
||||
* This method is called first and coordinates the entire diagram
|
||||
* generation.
|
||||
*
|
||||
* @param ostr Output stream.
|
||||
*/
|
||||
void generate(std::ostream &ostr) const override;
|
||||
|
||||
/**
|
||||
* Render class element into a JSON node.
|
||||
*
|
||||
* @param c class diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate(const class_ &c, nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* Render enum element into a JSON node.
|
||||
*
|
||||
* @param c enum diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate(const enum_ &c, nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* Render concept element into a JSON node.
|
||||
*
|
||||
* @param c concept diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate(const concept_ &c, nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* Render package element into a JSON node.
|
||||
*
|
||||
* @param p package diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate(const package &p, nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* @brief In a nested diagram, generate the top level elements.
|
||||
*
|
||||
* This method iterates over the top level elements. In case the diagram
|
||||
* is nested (i.e. includes packages), for each package it recursively
|
||||
* call generation of elements contained in each package.
|
||||
*
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate_top_level_elements(nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* @brief Generate all relationships in the diagram.
|
||||
*
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate_relationships(nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* @brief Generate all relationships originating at a class element.
|
||||
*
|
||||
* @param c Class diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate_relationships(const class_ &c, nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* @brief Generate all relationships originating at an enum element.
|
||||
*
|
||||
* @param c Enum diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate_relationships(const enum_ &c, nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* @brief Generate all relationships originating at a concept element.
|
||||
*
|
||||
* @param c Concept diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate_relationships(
|
||||
const concept_ &c, nlohmann::json &parent) const;
|
||||
|
||||
/**
|
||||
* @brief Generate all relationships in a package.
|
||||
*
|
||||
* If the diagram is nested, it recursively calls relationship generation
|
||||
* for all subelements.
|
||||
*
|
||||
* @param p Package diagram element
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate_relationships(const package &p, nlohmann::json &parent) const;
|
||||
|
||||
private:
|
||||
std::string render_name(std::string name) const;
|
||||
|
||||
mutable nlohmann::json json_;
|
||||
};
|
||||
|
||||
|
||||
@@ -59,60 +59,208 @@ using clanguml::common::model::relationship_t;
|
||||
|
||||
using namespace clanguml::util;
|
||||
|
||||
/**
|
||||
* @brief Class diagram PlantUML generator
|
||||
*/
|
||||
class generator : public common_generator<diagram_config, diagram_model> {
|
||||
using method_groups_t = std::map<std::string, std::vector<class_method>>;
|
||||
|
||||
public:
|
||||
generator(diagram_config &config, diagram_model &model);
|
||||
|
||||
/**
|
||||
* @brief Main generator method.
|
||||
*
|
||||
* This method is called first and coordinates the entire diagram
|
||||
* generation.
|
||||
*
|
||||
* @param ostr Output stream.
|
||||
*/
|
||||
void generate(std::ostream &ostr) const override;
|
||||
|
||||
/**
|
||||
* @brief In a nested diagram, generate the top level elements.
|
||||
*
|
||||
* This method iterates over the top level elements. In case the diagram
|
||||
* is nested (i.e. includes packages), for each package it recursively
|
||||
* call generation of elements contained in each package.
|
||||
*
|
||||
* @param parent JSON node
|
||||
*/
|
||||
void generate_top_level_elements(std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Generate a hyperlink for a class element.
|
||||
*
|
||||
* @param ostr Output stream
|
||||
* @param e Class element (e.g. a method)
|
||||
*/
|
||||
void generate_link(std::ostream &ostr, const class_element &e) const;
|
||||
|
||||
/**
|
||||
* @brief Generate PlantUML alias for a class element.
|
||||
*
|
||||
* @param c Class element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_alias(const class_ &c, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Generate PlantUML alias for a enum element.
|
||||
*
|
||||
* @param e Enum element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_alias(const enum_ &e, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Generate PlantUML alias for a concept element.
|
||||
*
|
||||
* @param c Concept element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_alias(const concept_ &c, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render class element to PlantUML
|
||||
*
|
||||
* @param c Class element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate(const class_ &c, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render class methods to PlantUML
|
||||
*
|
||||
* @param methods List of class methods
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_methods(
|
||||
const std::vector<class_method> &methods, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render class methods to PlantUML in groups
|
||||
*
|
||||
* @param methods Methods grouped by method type
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_methods(
|
||||
const method_groups_t &methods, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render class method to PlantUML
|
||||
*
|
||||
* @param m Class method
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_method(const class_method &m, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render class member to PlantUML
|
||||
*
|
||||
* @param m Class member
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_member(const class_member &m, std::ostream &ostr) const;
|
||||
|
||||
void generate_top_level_elements(std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render all relationships in the diagram to PlantUML
|
||||
*
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_relationships(std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render all relationships originating from class element.
|
||||
*
|
||||
* @param c Class element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_relationships(const class_ &c, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render a specific relationship to PlantUML.
|
||||
*
|
||||
* @param r Relationship model
|
||||
* @param rendered_relations Set of already rendered relationships, to
|
||||
* ensure that there are no duplicate
|
||||
* relationships
|
||||
*/
|
||||
void generate_relationship(
|
||||
const relationship &r, std::set<std::string> &rendered_relations) const;
|
||||
|
||||
/**
|
||||
* @brief Render enum element to PlantUML
|
||||
*
|
||||
* @param e Enum element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate(const enum_ &e, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render all relationships originating from enum element.
|
||||
*
|
||||
* @param c Enum element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_relationships(const enum_ &c, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render concept element to PlantUML
|
||||
*
|
||||
* @param c Concept element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate(const concept_ &c, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render all relationships originating from concept element.
|
||||
*
|
||||
* @param c Concept element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_relationships(const concept_ &c, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render package element to PlantUML
|
||||
*
|
||||
* @param p Package element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate(const package &p, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Render all relationships originating from package element.
|
||||
*
|
||||
* @param p Package element
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_relationships(const package &p, std::ostream &ostr) const;
|
||||
|
||||
/**
|
||||
* @brief Generate any notes attached specifically to some class element.
|
||||
*
|
||||
* @param ostream Output stream
|
||||
* @param member Class element (member or method)
|
||||
* @param alias PlantUML class alias
|
||||
*/
|
||||
void generate_member_notes(std::ostream &ostream,
|
||||
const class_element &member, const std::string &basicString) const;
|
||||
const class_element &member, const std::string &alias) const;
|
||||
|
||||
/**
|
||||
* @brief Generate elements grouped together in `together` groups.
|
||||
*
|
||||
* @param ostr Output stream
|
||||
*/
|
||||
void generate_groups(std::ostream &ostr) const;
|
||||
|
||||
void generate(std::ostream &ostr) const override;
|
||||
|
||||
/**
|
||||
* @brief Group class methods based on method type.
|
||||
*
|
||||
* @param methods List of class methods.
|
||||
*
|
||||
* @return Map of method groups.
|
||||
*/
|
||||
method_groups_t group_methods(
|
||||
const std::vector<class_method> &methods) const;
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
/**
|
||||
* @brief Base class for class elements (e.g. member or method).
|
||||
*/
|
||||
class class_element : public common::model::decorated_element,
|
||||
public common::model::source_location {
|
||||
public:
|
||||
@@ -34,13 +37,46 @@ public:
|
||||
|
||||
~class_element() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get elements access scope.
|
||||
*
|
||||
* @return Elements access scope.
|
||||
*/
|
||||
common::model::access_t access() const;
|
||||
|
||||
/**
|
||||
* @brief Get elements name.
|
||||
*
|
||||
* @return Elements name.
|
||||
*/
|
||||
std::string name() const;
|
||||
|
||||
/**
|
||||
* @brief Set elements name.
|
||||
*
|
||||
* @param name Elements name.
|
||||
*/
|
||||
void set_name(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Get elements type as string.
|
||||
*
|
||||
* @return Elements type as string.
|
||||
*/
|
||||
std::string type() const;
|
||||
|
||||
/**
|
||||
* @brief Set elements type as string.
|
||||
*
|
||||
* @param type Elements type as string.
|
||||
*/
|
||||
void set_type(const std::string &type);
|
||||
|
||||
/**
|
||||
* @brief Get elements inja context in JSON.
|
||||
*
|
||||
* @return Context in JSON
|
||||
*/
|
||||
virtual inja::json context() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -23,18 +23,38 @@
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
/**
|
||||
* @brief Class member model.
|
||||
*/
|
||||
class class_member : public class_element {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param access Members access scope (e.g. public)
|
||||
* @param name Members name.
|
||||
* @param type Members type as string.
|
||||
*/
|
||||
class_member(common::model::access_t access, const std::string &name,
|
||||
const std::string &type);
|
||||
|
||||
~class_member() override = default;
|
||||
|
||||
/**
|
||||
* @brief Whether the member is static.
|
||||
*
|
||||
* @return True, if the member is static.
|
||||
*/
|
||||
bool is_static() const;
|
||||
|
||||
/**
|
||||
* @brief Set members static status.
|
||||
*
|
||||
* @param is_static True, if the member is static.
|
||||
*/
|
||||
void is_static(bool is_static);
|
||||
|
||||
private:
|
||||
bool is_relationship_{false};
|
||||
bool is_static_{false};
|
||||
};
|
||||
|
||||
|
||||
@@ -29,56 +29,225 @@ namespace clanguml::class_diagram::model {
|
||||
|
||||
using clanguml::common::model::template_trait;
|
||||
|
||||
/**
|
||||
* @brief Class method model.
|
||||
*/
|
||||
class class_method : public class_element, public template_trait {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param access Methods access scope (e.g. public)
|
||||
* @param name Methods name.
|
||||
* @param type Methods return type as string.
|
||||
*/
|
||||
class_method(common::model::access_t access, const std::string &name,
|
||||
const std::string &type);
|
||||
|
||||
~class_method() override = default;
|
||||
|
||||
/**
|
||||
* @brief Whether the method is pure virtual.
|
||||
*
|
||||
* @return True, if the method is pure virtual
|
||||
*/
|
||||
bool is_pure_virtual() const;
|
||||
void is_pure_virtual(bool is_pure_virtual);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is virtual.
|
||||
*
|
||||
* @return True, if the method is virtual
|
||||
*/
|
||||
bool is_virtual() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is virtual.
|
||||
*
|
||||
* @param is_virtual True, if the method is virtual
|
||||
*/
|
||||
void is_virtual(bool is_virtual);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is const.
|
||||
*
|
||||
* @return True, if the method is const
|
||||
*/
|
||||
bool is_const() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is const.
|
||||
*
|
||||
* @param is_const True, if the method is const
|
||||
*/
|
||||
void is_const(bool is_const);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is defaulted.
|
||||
*
|
||||
* @return True, if the method is defaulted
|
||||
*/
|
||||
bool is_defaulted() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is defaulted.
|
||||
*
|
||||
* @param is_defaulted True, if the method is defaulted
|
||||
*/
|
||||
void is_defaulted(bool is_defaulted);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is deleted.
|
||||
*
|
||||
* @return True, if the method is deleted
|
||||
*/
|
||||
bool is_deleted() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is deleted.
|
||||
*
|
||||
* @param is_deleted True, if the method is deleted
|
||||
*/
|
||||
void is_deleted(bool is_deleted);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is static.
|
||||
*
|
||||
* @return True, if the method is static
|
||||
*/
|
||||
bool is_static() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is static.
|
||||
*
|
||||
* @param is_static True, if the method is static
|
||||
*/
|
||||
void is_static(bool is_static);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is constexpr.
|
||||
*
|
||||
* @return True, if the method is constexpr
|
||||
*/
|
||||
bool is_constexpr() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is constexpr.
|
||||
*
|
||||
* @param is_constexpr True, if the method is constexpr
|
||||
*/
|
||||
void is_constexpr(bool is_constexpr);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is consteval.
|
||||
*
|
||||
* @return True, if the method is consteval
|
||||
*/
|
||||
bool is_consteval() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is consteval.
|
||||
*
|
||||
* @param is_consteval True, if the method is consteval
|
||||
*/
|
||||
void is_consteval(bool is_consteval);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is noexcept.
|
||||
*
|
||||
* @return True, if the method is noexcept
|
||||
*/
|
||||
bool is_noexcept() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is noexcept.
|
||||
*
|
||||
* @param is_noexcept True, if the method is noexcept
|
||||
*/
|
||||
void is_noexcept(bool is_noexcept);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is a constructor.
|
||||
*
|
||||
* @return True, if the method is a constructor
|
||||
*/
|
||||
bool is_constructor() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is a constructor.
|
||||
*
|
||||
* @param is_constructor True, if the method is a constructor
|
||||
*/
|
||||
void is_constructor(bool is_constructor);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is a destructor.
|
||||
*
|
||||
* @return True, if the method is a destructor
|
||||
*/
|
||||
bool is_destructor() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is a destructor.
|
||||
*
|
||||
* @param is_destructor True, if the method is a destructor
|
||||
*/
|
||||
void is_destructor(bool is_destructor);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is move assignment.
|
||||
*
|
||||
* @return True, if the method is move assignment
|
||||
*/
|
||||
bool is_move_assignment() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is a move assignment.
|
||||
*
|
||||
* @param is_move_assignment True, if the method is a move assignment
|
||||
*/
|
||||
void is_move_assignment(bool is_move_assignment);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is copy assignment.
|
||||
*
|
||||
* @return True, if the method is copy assignment
|
||||
*/
|
||||
bool is_copy_assignment() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is a copy assignment.
|
||||
*
|
||||
* @param is_copy_assignment True, if the method is a copy assignment
|
||||
*/
|
||||
void is_copy_assignment(bool is_copy_assignment);
|
||||
|
||||
/**
|
||||
* @brief Whether the method is an operator.
|
||||
*
|
||||
* @return True, if the method is an operator
|
||||
*/
|
||||
bool is_operator() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the method is an operator.
|
||||
*
|
||||
* @param is_copy_assignment True, if the method is an operator
|
||||
*/
|
||||
void is_operator(bool is_operator);
|
||||
|
||||
/**
|
||||
* @brief Get the method parameters.
|
||||
*
|
||||
* @return List of methods parameters
|
||||
*/
|
||||
const std::vector<method_parameter> ¶meters() const;
|
||||
|
||||
/**
|
||||
* @brief Add methods parameter.
|
||||
*
|
||||
* @param parameter Method parameter.
|
||||
*/
|
||||
void add_parameter(method_parameter &¶meter);
|
||||
|
||||
private:
|
||||
|
||||
@@ -24,6 +24,10 @@ void class_parent::set_name(const std::string &name) { name_ = name; }
|
||||
|
||||
std::string class_parent::name() const { return name_; }
|
||||
|
||||
void class_parent::set_id(clanguml::common::id_t id) { id_ = id; }
|
||||
|
||||
clanguml::common::id_t class_parent::id() const noexcept { return id_; }
|
||||
|
||||
void class_parent::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; }
|
||||
|
||||
bool class_parent::is_virtual() const { return is_virtual_; }
|
||||
|
||||
@@ -25,25 +25,75 @@
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
/**
|
||||
* @brief Class parent relationship model.
|
||||
*
|
||||
* @todo Consider refactoring this class to a regular relationship.
|
||||
*/
|
||||
class class_parent {
|
||||
public:
|
||||
class_parent() = default;
|
||||
|
||||
class_parent(const std::string &name)
|
||||
{
|
||||
set_name(name);
|
||||
set_id(common::to_id(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the fully qualified name of class parent.
|
||||
*
|
||||
* @param name Fully qualified name of the parent class.
|
||||
*/
|
||||
void set_name(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Get the fully qualified name of class parent.
|
||||
*
|
||||
* @return Fully qualified name of the parent class.
|
||||
*/
|
||||
std::string name() const;
|
||||
|
||||
clanguml::common::id_t id() const noexcept { return id_; }
|
||||
void set_id(clanguml::common::id_t id) { id_ = id; }
|
||||
/**
|
||||
* @brief Set the id of class parent.
|
||||
*
|
||||
* @param id Id of the parent class.
|
||||
*/
|
||||
void set_id(clanguml::common::id_t id);
|
||||
|
||||
/**
|
||||
* @brief Get the id of class parent.
|
||||
*
|
||||
* @return Id of the parent class.
|
||||
*/
|
||||
clanguml::common::id_t id() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Set whether the parent is virtual.
|
||||
*
|
||||
* @param is_virtual True if the parent is virtual
|
||||
*/
|
||||
void is_virtual(bool is_virtual);
|
||||
|
||||
/**
|
||||
* @brief Get whether the parent is virtual.
|
||||
*
|
||||
* @return True, if the parent is virtual
|
||||
*/
|
||||
bool is_virtual() const;
|
||||
|
||||
/**
|
||||
* @brief Set the parents access scope
|
||||
*
|
||||
* @param access Parents access scope
|
||||
*/
|
||||
void set_access(common::model::access_t access);
|
||||
|
||||
/**
|
||||
* @brief Get parents access scope.
|
||||
*
|
||||
* @return Parents access scope.
|
||||
*/
|
||||
common::model::access_t access() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -29,11 +29,9 @@
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
struct requires_expression {
|
||||
common::model::template_parameter parameter;
|
||||
std::vector<std::string> requirements;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Model of C++ concept.
|
||||
*/
|
||||
class concept_ : public common::model::element,
|
||||
public common::model::stylable_element,
|
||||
public common::model::template_trait {
|
||||
@@ -45,6 +43,11 @@ public:
|
||||
concept_ &operator=(const concept_ &) = delete;
|
||||
concept_ &operator=(concept_ &&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Get the elements type name.
|
||||
*
|
||||
* @return 'concept'
|
||||
*/
|
||||
std::string type_name() const override { return "concept"; }
|
||||
|
||||
friend bool operator==(const concept_ &l, const concept_ &r);
|
||||
@@ -53,12 +56,35 @@ public:
|
||||
|
||||
std::string full_name_no_ns() const override;
|
||||
|
||||
/**
|
||||
* @brief Add concept parameter
|
||||
*
|
||||
* Concept class for convenience uses the same method parameter model
|
||||
* as regular methods and functions.
|
||||
*
|
||||
* @param mp Concept parameter
|
||||
*/
|
||||
void add_parameter(const method_parameter &mp);
|
||||
|
||||
/**
|
||||
* @brief Get concepts requires expression parameters
|
||||
*
|
||||
* @return List of concept requires expression parameters
|
||||
*/
|
||||
const std::vector<method_parameter> &requires_parameters() const;
|
||||
|
||||
/**
|
||||
* @brief Add a concept statement
|
||||
*
|
||||
* @param stmt Concept statement
|
||||
*/
|
||||
void add_statement(std::string stmt);
|
||||
|
||||
/**
|
||||
* @brief Get the concepts requires statements
|
||||
*
|
||||
* @return List of concepts requires statements
|
||||
*/
|
||||
const std::vector<std::string> &requires_statements() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -45,6 +45,9 @@ using nested_trait_ns =
|
||||
clanguml::common::model::nested_trait<clanguml::common::model::element,
|
||||
clanguml::common::model::namespace_>;
|
||||
|
||||
/**
|
||||
* @brief Class representing a class diagram.
|
||||
*/
|
||||
class diagram : public common::model::diagram,
|
||||
public element_view<class_>,
|
||||
public element_view<enum_>,
|
||||
@@ -58,36 +61,132 @@ public:
|
||||
diagram &operator=(const diagram &) = delete;
|
||||
diagram &operator=(diagram &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Get the diagram model type - in this case class.
|
||||
*
|
||||
* @return Type of class diagram.
|
||||
*/
|
||||
diagram_t type() const override;
|
||||
|
||||
/**
|
||||
* Inherit the should_include methods from the common diagram model.
|
||||
*/
|
||||
using common::model::diagram::should_include;
|
||||
|
||||
/**
|
||||
* @brief Whether a class_member should be included in the diagram.
|
||||
*
|
||||
* @param m Class member
|
||||
* @return True, if class member should be included in the diagram.
|
||||
*/
|
||||
bool should_include(const class_member &m) const;
|
||||
|
||||
/**
|
||||
* @brief Whether a class_method should be included in the diagram.
|
||||
*
|
||||
* @param m Class method
|
||||
* @return True, if class method should be included in the diagram.
|
||||
*/
|
||||
bool should_include(const class_method &m) const;
|
||||
|
||||
/**
|
||||
* @brief Search for element in the diagram by fully qualified name.
|
||||
*
|
||||
* @param full_name Fully qualified element name.
|
||||
* @return Optional reference to a diagram element.
|
||||
*/
|
||||
opt_ref<diagram_element> get(const std::string &full_name) const override;
|
||||
|
||||
/**
|
||||
* @brief Search for element in the diagram by id.
|
||||
*
|
||||
* @param id Element id.
|
||||
* @return Optional reference to a diagram element.
|
||||
*/
|
||||
opt_ref<diagram_element> get(diagram_element::id_t id) const override;
|
||||
|
||||
/**
|
||||
* @brief Get list of references to classes in the diagram model.
|
||||
*
|
||||
* @return List of references to classes in the diagram model.
|
||||
*/
|
||||
const common::reference_vector<class_> &classes() const;
|
||||
|
||||
/**
|
||||
* @brief Get list of references to enums in the diagram model.
|
||||
*
|
||||
* @return List of references to enums in the diagram model.
|
||||
*/
|
||||
const common::reference_vector<enum_> &enums() const;
|
||||
|
||||
/**
|
||||
* @brief Get list of references to concepts in the diagram model.
|
||||
*
|
||||
* @return List of references to concepts in the diagram model.
|
||||
*/
|
||||
const common::reference_vector<concept_> &concepts() const;
|
||||
|
||||
/**
|
||||
* @brief Check, if diagram contains a specific element.
|
||||
*
|
||||
* @tparam ElementT Type of diagram element (e.g. class_)
|
||||
* @param e Element to check
|
||||
* @return True, if element already exists in the diagram
|
||||
*/
|
||||
template <typename ElementT> bool contains(const ElementT &e);
|
||||
|
||||
/**
|
||||
* @brief Find an element in the diagram by name.
|
||||
*
|
||||
* This method allows for typed search, where the type of searched for
|
||||
* element is determined from template specialization.
|
||||
*
|
||||
* @tparam ElementT Type of element (e.g. class_)
|
||||
* @param name Fully qualified name of the element
|
||||
* @return Optional reference to a diagram element
|
||||
*/
|
||||
template <typename ElementT>
|
||||
opt_ref<ElementT> find(const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Find elements in the diagram by regex pattern.
|
||||
*
|
||||
* This method allows for typed search, where the type of searched for
|
||||
* element is determined from template specialization.
|
||||
*
|
||||
* @tparam ElementT Type of element (e.g. class_)
|
||||
* @param name String or regex pattern
|
||||
* @return List of optional references to matched elements.
|
||||
*/
|
||||
template <typename ElementT>
|
||||
std::vector<opt_ref<ElementT>> find(
|
||||
const clanguml::common::string_or_regex &pattern) const;
|
||||
|
||||
/**
|
||||
* @brief Find an element in the diagram by id.
|
||||
*
|
||||
* This method allows for typed search, where the type of searched for
|
||||
* element is determined from template specialization.
|
||||
*
|
||||
* @tparam ElementT Type of element (e.g. class_)
|
||||
* @param id Id of the element
|
||||
* @return Optional reference to a diagram element
|
||||
*/
|
||||
template <typename ElementT>
|
||||
opt_ref<ElementT> find(diagram_element::id_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Add element to the diagram at a specified nested path.
|
||||
*
|
||||
* Adds an element to a diagram, at a specific package (if any exist).
|
||||
* The package is specified by the `parent_path`, which can be either
|
||||
* a namespace or a directory path.
|
||||
*
|
||||
* @tparam ElementT Type of diagram element.
|
||||
* @param parent_path Path to the parent package of the new diagram element.
|
||||
* @param e Diagram element to be added.
|
||||
* @return True, if the element was added to the diagram.
|
||||
*/
|
||||
template <typename ElementT>
|
||||
bool add(const path &parent_path, std::unique_ptr<ElementT> &&e)
|
||||
{
|
||||
@@ -98,14 +197,41 @@ public:
|
||||
return add_with_filesystem_path(parent_path, std::move(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert element id to PlantUML alias.
|
||||
*
|
||||
* @todo This method does not belong here - refactor to PlantUML specific
|
||||
* code.
|
||||
*
|
||||
* @param id Id of the diagram element.
|
||||
* @return PlantUML alias.
|
||||
*/
|
||||
std::string to_alias(diagram_element::id_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Given an initial set of classes, add all their parents to the
|
||||
* argument.
|
||||
* @param parents In and out parameter with the parent classes.
|
||||
*/
|
||||
void get_parents(clanguml::common::reference_set<class_> &parents) const;
|
||||
|
||||
friend void print_diagram_tree(const diagram &d, int level);
|
||||
|
||||
/**
|
||||
* @brief Check if diagram contains element by id.
|
||||
*
|
||||
* @todo Remove in favour of 'contains'
|
||||
*
|
||||
* @param id Id of the element.
|
||||
* @return True, if diagram contains an element with a specific id.
|
||||
*/
|
||||
bool has_element(diagram_element::id_t id) const override;
|
||||
|
||||
/**
|
||||
* @brief Return the elements JSON context for inja templates.
|
||||
*
|
||||
* @return JSON node with elements context.
|
||||
*/
|
||||
inja::json context() const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
/*
|
||||
* @brief Diagram element representing an enum.
|
||||
*/
|
||||
class enum_ : public common::model::element,
|
||||
public common::model::stylable_element {
|
||||
public:
|
||||
@@ -36,15 +39,29 @@ public:
|
||||
|
||||
std::string type_name() const override { return "enum"; }
|
||||
|
||||
// TODO: Do we need this?
|
||||
friend bool operator==(const enum_ &l, const enum_ &r);
|
||||
|
||||
std::string full_name(bool relative = true) const override;
|
||||
|
||||
/**
|
||||
* @brief Get the enums constants.
|
||||
*
|
||||
* @return Enums constants names list.
|
||||
*/
|
||||
std::vector<std::string> &constants();
|
||||
|
||||
/**
|
||||
* @brief Get the enums constants.
|
||||
*
|
||||
* @return Enums constants names list.
|
||||
*/
|
||||
const std::vector<std::string> &constants() const;
|
||||
|
||||
/**
|
||||
* @brief Get Doxygen link to documentation page for this element.
|
||||
*
|
||||
* @return Doxygen link for this element.
|
||||
*/
|
||||
std::optional<std::string> doxygen_link() const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -25,23 +25,73 @@
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
/**
|
||||
* @brief Model of a method parameter.
|
||||
*/
|
||||
class method_parameter : public common::model::decorated_element {
|
||||
public:
|
||||
method_parameter() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param type Type of the method parameter as string.
|
||||
* @param name Name of the method parameter.
|
||||
* @param default_value Default value of the parameter or empty.
|
||||
*/
|
||||
method_parameter(
|
||||
std::string type, std::string name, std::string default_value = {});
|
||||
|
||||
~method_parameter() override = default;
|
||||
|
||||
/**
|
||||
* @brief Set parameters type.
|
||||
*
|
||||
* @param type Parameters type as string.
|
||||
*/
|
||||
void set_type(const std::string &type);
|
||||
|
||||
/**
|
||||
* @brief Get parameters type.
|
||||
*
|
||||
* @return Parameters type as string.
|
||||
*/
|
||||
std::string type() const;
|
||||
|
||||
/**
|
||||
* @brief Set parameters name.
|
||||
*
|
||||
* @param type Parameters name.
|
||||
*/
|
||||
void set_name(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Get parameters name.
|
||||
*
|
||||
* @return Parameters name.
|
||||
*/
|
||||
std::string name() const;
|
||||
|
||||
/**
|
||||
* @brief Set parameters default value.
|
||||
*
|
||||
* @param type Parameters default value as string.
|
||||
*/
|
||||
void set_default_value(const std::string &value);
|
||||
|
||||
/**
|
||||
* @brief Get parameters name.
|
||||
*
|
||||
* @return Parameters name.
|
||||
*/
|
||||
std::string default_value() const;
|
||||
|
||||
/**
|
||||
* @brief Render the method parameter to a string.
|
||||
*
|
||||
* @param using_namespaces If provided, make all namespaces relative to it.
|
||||
* @return String representation of the parameter.
|
||||
*/
|
||||
std::string to_string(
|
||||
const common::model::namespace_ &using_namespaces) const;
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ std::unique_ptr<class_> template_builder::build(const clang::NamedDecl *cls,
|
||||
|
||||
auto templated_decl_id =
|
||||
template_type.getTemplateName().getAsTemplateDecl()->getID();
|
||||
auto templated_decl_local_id =
|
||||
auto templated_decl_global_id =
|
||||
id_mapper().get_global_id(templated_decl_id).value_or(0);
|
||||
|
||||
if (best_match_id > 0) {
|
||||
@@ -246,12 +246,13 @@ std::unique_ptr<class_> template_builder::build(const clang::NamedDecl *cls,
|
||||
}
|
||||
// If we can't find optimal match for parent template specialization,
|
||||
// just use whatever clang suggests
|
||||
else if (diagram().has_element(templated_decl_local_id)) {
|
||||
else if (diagram().has_element(templated_decl_global_id)) {
|
||||
template_instantiation.add_relationship(
|
||||
{relationship_t::kInstantiation, templated_decl_local_id});
|
||||
{relationship_t::kInstantiation, templated_decl_global_id});
|
||||
template_instantiation.template_specialization_found(true);
|
||||
}
|
||||
else if (diagram().should_include(full_template_specialization_name)) {
|
||||
else if (diagram().should_include(
|
||||
namespace_{full_template_specialization_name})) {
|
||||
LOG_DBG("Skipping instantiation relationship from {} to {}",
|
||||
template_instantiation_ptr->full_name(false), templated_decl_id);
|
||||
}
|
||||
@@ -351,7 +352,7 @@ template_builder::build_from_class_template_specialization(
|
||||
{relationship_t::kInstantiation, templated_decl_local_id});
|
||||
template_instantiation.template_specialization_found(true);
|
||||
}
|
||||
else if (diagram().should_include(qualified_name)) {
|
||||
else if (diagram().should_include(namespace_{qualified_name})) {
|
||||
LOG_DBG("Skipping instantiation relationship from {} to {}",
|
||||
template_instantiation_ptr->full_name(false), templated_decl_id);
|
||||
}
|
||||
@@ -380,7 +381,7 @@ void template_builder::process_template_arguments(
|
||||
// default values, and add them when they are specifically
|
||||
// overridden
|
||||
if (!diagram().should_include(
|
||||
template_decl->getQualifiedNameAsString())) {
|
||||
namespace_{template_decl->getQualifiedNameAsString()})) {
|
||||
const auto *maybe_type_parm_decl =
|
||||
clang::dyn_cast<clang::TemplateTypeParmDecl>(
|
||||
template_decl->getTemplateParameters()->getParam(
|
||||
@@ -1012,7 +1013,8 @@ template_builder::try_as_template_specialization_type(
|
||||
argument.set_type(nested_type_name);
|
||||
|
||||
auto nested_template_instantiation = build(cls, *nested_template_type,
|
||||
diagram().should_include(template_decl->getQualifiedNameAsString())
|
||||
diagram().should_include(
|
||||
namespace_{template_decl->getQualifiedNameAsString()})
|
||||
? std::make_optional(&template_instantiation)
|
||||
: parent);
|
||||
|
||||
@@ -1031,9 +1033,10 @@ template_builder::try_as_template_specialization_type(
|
||||
nested_template_instantiation->full_name(false);
|
||||
|
||||
if (nested_template_instantiation &&
|
||||
diagram().should_include(nested_template_instantiation_full_name)) {
|
||||
diagram().should_include(
|
||||
namespace_{nested_template_instantiation_full_name})) {
|
||||
if (diagram().should_include(
|
||||
template_decl->getQualifiedNameAsString())) {
|
||||
namespace_{template_decl->getQualifiedNameAsString()})) {
|
||||
template_instantiation.add_relationship(
|
||||
{relationship_t::kDependency,
|
||||
nested_template_instantiation->id()});
|
||||
@@ -1045,7 +1048,8 @@ template_builder::try_as_template_specialization_type(
|
||||
}
|
||||
}
|
||||
|
||||
if (diagram().should_include(nested_template_instantiation_full_name)) {
|
||||
if (diagram().should_include(
|
||||
namespace_{nested_template_instantiation_full_name})) {
|
||||
visitor_.set_source_location(
|
||||
*template_decl, *nested_template_instantiation);
|
||||
visitor_.add_class(std::move(nested_template_instantiation));
|
||||
@@ -1155,7 +1159,7 @@ std::optional<template_parameter> template_builder::try_as_record_type(
|
||||
template_instantiation.add_relationship(std::move(r));
|
||||
}
|
||||
|
||||
if (diagram().should_include(tag_argument->full_name(false))) {
|
||||
if (diagram().should_include(tag_argument->get_namespace())) {
|
||||
if (parent.has_value())
|
||||
parent.value()->add_relationship(
|
||||
{relationship_t::kDependency, tag_argument->id()});
|
||||
@@ -1166,7 +1170,7 @@ std::optional<template_parameter> template_builder::try_as_record_type(
|
||||
}
|
||||
else if (const auto *record_type_decl = record_type->getAsRecordDecl();
|
||||
record_type_decl != nullptr) {
|
||||
if (diagram().should_include(type_name)) {
|
||||
if (diagram().should_include(namespace_{type_name})) {
|
||||
// Add dependency relationship to the parent
|
||||
// template
|
||||
template_instantiation.add_relationship(
|
||||
|
||||
@@ -36,35 +36,111 @@ using found_relationships_t =
|
||||
|
||||
class translation_unit_visitor;
|
||||
|
||||
/**
|
||||
* @brief Class responsible for building all kinds of templates from Clang AST.
|
||||
*/
|
||||
class template_builder {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param visitor Reference to class diagram translation_unit_visitor
|
||||
*/
|
||||
template_builder(
|
||||
clanguml::class_diagram::visitor::translation_unit_visitor &visitor);
|
||||
|
||||
/**
|
||||
* @brief Get reference to the current diagram model
|
||||
*
|
||||
* @return Reference to the current diagram model
|
||||
*/
|
||||
class_diagram::model::diagram &diagram();
|
||||
|
||||
/**
|
||||
* @brief Get reference to the current diagram configuration
|
||||
*
|
||||
* @return Reference to the current diagram configuration
|
||||
*/
|
||||
const config::class_diagram &config() const;
|
||||
|
||||
/**
|
||||
* @brief Get diagram relative namespace
|
||||
*
|
||||
* @return Diagram relative namespace
|
||||
*/
|
||||
const namespace_ &using_namespace() const;
|
||||
|
||||
/**
|
||||
* @brief Simplify system templates
|
||||
*
|
||||
* This method tries to simplify all fully qualified template names
|
||||
* in the `full_name` using substitutions from the configuration file
|
||||
* ().
|
||||
*
|
||||
* Typical example is replace every `std::basic_string<char>` with
|
||||
* `std::string`.
|
||||
*
|
||||
* @param ct Template parameter
|
||||
* @param full_name Full template name
|
||||
* @return
|
||||
*/
|
||||
bool simplify_system_template(
|
||||
template_parameter &ct, const std::string &full_name) const;
|
||||
|
||||
/**
|
||||
* @brief Basic template class build method
|
||||
*
|
||||
* @param cls Clang template declaration
|
||||
* @param template_type_decl Template specialization type
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @return Created template class model
|
||||
*/
|
||||
std::unique_ptr<clanguml::class_diagram::model::class_> build(
|
||||
const clang::NamedDecl *cls,
|
||||
const clang::TemplateSpecializationType &template_type_decl,
|
||||
std::optional<clanguml::class_diagram::model::class_ *> parent = {});
|
||||
|
||||
/**
|
||||
* @brief Build template class from class template specialization decl
|
||||
*
|
||||
* @param template_specialization Class template specialization declaration
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @return Created template class model
|
||||
*/
|
||||
std::unique_ptr<clanguml::class_diagram::model::class_>
|
||||
build_from_class_template_specialization(
|
||||
const clang::ClassTemplateSpecializationDecl &template_specialization,
|
||||
std::optional<clanguml::class_diagram::model::class_ *> parent = {});
|
||||
|
||||
/**
|
||||
* @brief Add base classes to the template class, if any.
|
||||
*
|
||||
* This method adds base classes to a template declaration or
|
||||
* specialization, including inferring whether variadic template
|
||||
* parameter bases.
|
||||
*
|
||||
* @param tinst Class template model
|
||||
* @param template_base_params List of base class template parameters
|
||||
* @param arg_index Index of the template argument used for base class
|
||||
* @param variadic_params Whether the parameter is variadic
|
||||
* @param ct Template parameter model
|
||||
* @return True, if any base classes were added
|
||||
*/
|
||||
bool add_base_classes(clanguml::class_diagram::model::class_ &tinst,
|
||||
std::deque<std::tuple<std::string, int, bool>> &template_base_params,
|
||||
int arg_index, bool variadic_params,
|
||||
const clanguml::common::model::template_parameter &ct);
|
||||
|
||||
/**
|
||||
* @brief Process template class parameters and arguments
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_base_params List of base class template parameters
|
||||
* @param template_args List of template arguments
|
||||
* @param template_instantiation Template class model to add template args
|
||||
* @param template_decl Base template declaration
|
||||
*/
|
||||
void process_template_arguments(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls,
|
||||
@@ -73,6 +149,18 @@ public:
|
||||
model::class_ &template_instantiation,
|
||||
const clang::TemplateDecl *template_decl);
|
||||
|
||||
/**
|
||||
* @brief Process template arguments based on their type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_instantiation Template class model to add template args
|
||||
* @param template_decl Base template declaration
|
||||
* @param arg Template argument
|
||||
* @param argument_index Argument index
|
||||
* @param argument Output list of arguments (can be more than one for
|
||||
* variadic parameters)
|
||||
*/
|
||||
void argument_process_dispatch(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, class_ &template_instantiation,
|
||||
@@ -80,18 +168,64 @@ public:
|
||||
const clang::TemplateArgument &arg, size_t argument_index,
|
||||
std::vector<template_parameter> &argument);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::Expression`
|
||||
*
|
||||
* @note The template argument is a pack expansion of a template name that
|
||||
* was provided for a template template parameter.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
template_parameter process_expression_argument(
|
||||
const clang::TemplateArgument &arg);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::Integral`
|
||||
*
|
||||
* @note The template argument is an integral value stored in an
|
||||
* llvm::APSInt that was provided for an integral non-type template
|
||||
* parameter.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
template_parameter process_integral_argument(
|
||||
const clang::TemplateArgument &arg);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::NullPtr`
|
||||
*
|
||||
* @note The template argument is a null pointer or null pointer to member
|
||||
* that was provided for a non-type template parameter.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
template_parameter process_nullptr_argument(
|
||||
const clang::TemplateArgument &arg);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::Null`
|
||||
*
|
||||
* @note Represents an empty template argument, e.g., one that has not
|
||||
* been deduced.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
template_parameter process_null_argument(
|
||||
const clang::TemplateArgument &arg);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::Pack`
|
||||
*
|
||||
* @note The template argument is actually a parameter pack. Arguments are
|
||||
* stored in the Args struct.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
std::vector<template_parameter> process_pack_argument(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, class_ &template_instantiation,
|
||||
@@ -99,85 +233,260 @@ public:
|
||||
const clang::TemplateArgument &arg, size_t argument_index,
|
||||
std::vector<template_parameter> &argument);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::Type`
|
||||
*
|
||||
* @note The template argument is a type.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
template_parameter process_type_argument(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls,
|
||||
const clang::TemplateDecl *base_template_decl, clang::QualType type,
|
||||
model::class_ &template_instantiation, size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::Template`
|
||||
*
|
||||
* @note The template argument is a template name that was provided for a
|
||||
* template template parameter.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
common::model::template_parameter process_template_argument(
|
||||
const clang::TemplateArgument &arg);
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::TemplateExpansion`
|
||||
*
|
||||
* @note The template argument is a pack expansion of a template name that
|
||||
* was provided for a template template parameter.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
common::model::template_parameter process_template_expansion(
|
||||
const clang::TemplateArgument &arg);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as function template
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @param argument_index Argument index
|
||||
* @return Function template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_function_prototype(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation,
|
||||
size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as array
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @param argument_index Argument index
|
||||
* @return Array template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_array(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation,
|
||||
size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as specialization type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @param argument_index Argument index
|
||||
* @return Template specialization template argument if succeeds,
|
||||
* or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_template_specialization_type(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation,
|
||||
size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as template parameter
|
||||
*
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @return Template parameter if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_template_parm_type(
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as lambda
|
||||
*
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @return Lambda template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_lambda(const clang::NamedDecl *cls,
|
||||
const clang::TemplateDecl *template_decl, clang::QualType &type);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as record type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @param argument_index Argument index
|
||||
* @return Record type template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_record_type(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation,
|
||||
size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as enum type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @return Enum type template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_enum_type(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as builtin type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param type Template type
|
||||
* @param template_decl Base template declaration
|
||||
* @return Builtin type template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_builtin_type(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
clang::QualType &type, const clang::TemplateDecl *template_decl);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as member pointer type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @param argument_index Argument index
|
||||
* @return Member pointer type template argument if succeeds,
|
||||
* or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_member_pointer(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation,
|
||||
size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as `decltype()` type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @param argument_index Argument index
|
||||
* @return `decltype()` type template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_decl_type(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation,
|
||||
size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Try to process template type argument as typedef/using type
|
||||
*
|
||||
* @param parent Optional class in which this template is contained
|
||||
* @param cls Template class specialization declaration
|
||||
* @param template_decl Base template declaration
|
||||
* @param type Template type
|
||||
* @param template_instantiation Template class model
|
||||
* @param argument_index Argument index
|
||||
* @return Typedef type template argument if succeeds, or std::nullopt
|
||||
*/
|
||||
std::optional<template_parameter> try_as_typedef_type(
|
||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||
const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl,
|
||||
clang::QualType &type, class_ &template_instantiation,
|
||||
size_t argument_index);
|
||||
|
||||
/**
|
||||
* @brief Remove types context (e.g. const or reference qualifiers)
|
||||
*
|
||||
* This method removes all const and reference/pointer qualifiers from
|
||||
* `type`, adds them to the template parameter model `tp` and returns
|
||||
* a type without context.
|
||||
*
|
||||
* @param type Type to remove context from
|
||||
* @param tp Template model to add context to
|
||||
* @return Type without context
|
||||
*/
|
||||
clang::QualType consume_context(
|
||||
clang::QualType type, template_parameter &tp) const;
|
||||
|
||||
/**
|
||||
* @brief Try to find additional relationships in unexposed parameters
|
||||
*
|
||||
* Sometimes, Clang will report a template parameter as unexposed, which
|
||||
* means all we get a is a string representation of the type, sometimes
|
||||
* with template parameter names replaced with `type-parameter-X-Y`
|
||||
* string.
|
||||
*
|
||||
* This method tries to find any type names, which might be relevant for
|
||||
* the diagram relationships.
|
||||
*
|
||||
* @param ct Template argument model
|
||||
* @param relationships List of discovered relationships
|
||||
* @return True, if any relationships were found
|
||||
*/
|
||||
bool find_relationships_in_unexposed_template_params(
|
||||
const template_parameter &ct,
|
||||
class_diagram::visitor::found_relationships_t &relationships);
|
||||
|
||||
/**
|
||||
* @brief Get reference to Clang AST to clang-uml id mapper
|
||||
*
|
||||
* @return Reference to Clang AST to clang-uml id mapper
|
||||
*/
|
||||
common::visitor::ast_id_mapper &id_mapper();
|
||||
|
||||
/**
|
||||
* @brief Get reference to the current source manager
|
||||
*
|
||||
* @return Reference to the current source manager
|
||||
*/
|
||||
clang::SourceManager &source_manager() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -100,7 +100,7 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
|
||||
if (enm->getNameAsString().empty())
|
||||
return true;
|
||||
|
||||
if (!diagram().should_include(enm->getQualifiedNameAsString()))
|
||||
if (!should_include(enm))
|
||||
return true;
|
||||
|
||||
LOG_DBG("= Visiting enum declaration {} at {}",
|
||||
@@ -169,7 +169,6 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
|
||||
e.constants().push_back(ev->getNameAsString());
|
||||
}
|
||||
|
||||
if (diagram().should_include(qualified_name))
|
||||
add_enum(std::move(e_ptr));
|
||||
|
||||
return true;
|
||||
@@ -178,10 +177,7 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
|
||||
bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
|
||||
clang::ClassTemplateSpecializationDecl *cls)
|
||||
{
|
||||
if (source_manager().isInSystemHeader(cls->getSourceRange().getBegin()))
|
||||
return true;
|
||||
|
||||
if (!diagram().should_include(cls->getQualifiedNameAsString()))
|
||||
if (!should_include(cls))
|
||||
return true;
|
||||
|
||||
LOG_DBG("= Visiting template specialization declaration {} at {} "
|
||||
@@ -241,10 +237,7 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
|
||||
bool translation_unit_visitor::VisitTypeAliasTemplateDecl(
|
||||
clang::TypeAliasTemplateDecl *cls)
|
||||
{
|
||||
if (source_manager().isInSystemHeader(cls->getSourceRange().getBegin()))
|
||||
return true;
|
||||
|
||||
if (!diagram().should_include(cls->getQualifiedNameAsString()))
|
||||
if (!should_include(cls))
|
||||
return true;
|
||||
|
||||
LOG_DBG("= Visiting template type alias declaration {} at {}",
|
||||
@@ -280,10 +273,7 @@ bool translation_unit_visitor::VisitTypeAliasTemplateDecl(
|
||||
bool translation_unit_visitor::VisitClassTemplateDecl(
|
||||
clang::ClassTemplateDecl *cls)
|
||||
{
|
||||
if (source_manager().isInSystemHeader(cls->getSourceRange().getBegin()))
|
||||
return true;
|
||||
|
||||
if (!diagram().should_include(cls->getQualifiedNameAsString()))
|
||||
if (!should_include(cls))
|
||||
return true;
|
||||
|
||||
LOG_DBG("= Visiting class template declaration {} at {}",
|
||||
@@ -339,16 +329,12 @@ bool translation_unit_visitor::VisitClassTemplateDecl(
|
||||
|
||||
bool translation_unit_visitor::VisitRecordDecl(clang::RecordDecl *rec)
|
||||
{
|
||||
// Skip system headers
|
||||
if (source_manager().isInSystemHeader(rec->getSourceRange().getBegin()))
|
||||
return true;
|
||||
|
||||
if (clang::dyn_cast_or_null<clang::CXXRecordDecl>(rec) != nullptr)
|
||||
// This is handled by VisitCXXRecordDecl()
|
||||
return true;
|
||||
|
||||
// It seems we are in a C (not C++) translation unit
|
||||
if (!diagram().should_include(rec->getQualifiedNameAsString()))
|
||||
if (!should_include(rec))
|
||||
return true;
|
||||
|
||||
LOG_DBG("= Visiting record declaration {} at {}",
|
||||
@@ -396,11 +382,7 @@ bool translation_unit_visitor::VisitRecordDecl(clang::RecordDecl *rec)
|
||||
|
||||
bool translation_unit_visitor::TraverseConceptDecl(clang::ConceptDecl *cpt)
|
||||
{
|
||||
// Skip system headers
|
||||
if (source_manager().isInSystemHeader(cpt->getSourceRange().getBegin()))
|
||||
return true;
|
||||
|
||||
if (!diagram().should_include(cpt->getQualifiedNameAsString()))
|
||||
if (!should_include(cpt))
|
||||
return true;
|
||||
|
||||
LOG_DBG("= Visiting concept (isType: {}) declaration {} at {}",
|
||||
@@ -1314,7 +1296,7 @@ void translation_unit_visitor::process_method(
|
||||
*unaliased_type, &c);
|
||||
|
||||
if (diagram().should_include(
|
||||
template_specialization_ptr->full_name(false))) {
|
||||
template_specialization_ptr->get_namespace())) {
|
||||
relationships.emplace_back(template_specialization_ptr->id(),
|
||||
relationship_t::kDependency);
|
||||
|
||||
@@ -1686,7 +1668,7 @@ void translation_unit_visitor::process_function_parameter(
|
||||
templ->getTemplateName().getAsTemplateDecl(), *templ, &c);
|
||||
|
||||
if (diagram().should_include(
|
||||
template_specialization_ptr->full_name(false))) {
|
||||
template_specialization_ptr->get_namespace())) {
|
||||
relationships.emplace_back(template_specialization_ptr->id(),
|
||||
relationship_t::kDependency);
|
||||
|
||||
@@ -1956,7 +1938,7 @@ void translation_unit_visitor::process_field(
|
||||
// it's a std::vector<>, it's nested types might be added
|
||||
bool add_template_instantiation_to_diagram{false};
|
||||
if (diagram().should_include(
|
||||
template_specialization.full_name(false))) {
|
||||
template_specialization.get_namespace())) {
|
||||
|
||||
found_relationships_t::value_type r{
|
||||
template_specialization.id(), relationship_hint};
|
||||
@@ -2034,7 +2016,7 @@ void translation_unit_visitor::process_field(
|
||||
void translation_unit_visitor::add_incomplete_forward_declarations()
|
||||
{
|
||||
for (auto &[id, c] : forward_declarations_) {
|
||||
if (diagram().should_include(c->full_name(false))) {
|
||||
if (diagram().should_include(c->get_namespace())) {
|
||||
add_class(std::move(c));
|
||||
}
|
||||
}
|
||||
@@ -2107,8 +2089,21 @@ void translation_unit_visitor::extract_constrained_template_param_name(
|
||||
|
||||
bool translation_unit_visitor::should_include(const clang::NamedDecl *decl)
|
||||
{
|
||||
return decl != nullptr &&
|
||||
diagram().should_include(decl->getQualifiedNameAsString());
|
||||
if (decl == nullptr)
|
||||
return false;
|
||||
|
||||
if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
|
||||
return false;
|
||||
|
||||
auto should_include_namespace =
|
||||
diagram().should_include(namespace_{decl->getQualifiedNameAsString()});
|
||||
|
||||
const auto decl_file = decl->getLocation().printToString(source_manager());
|
||||
|
||||
const auto should_include_decl_file =
|
||||
diagram().should_include(common::model::source_file{decl_file});
|
||||
|
||||
return should_include_namespace && should_include_decl_file;
|
||||
}
|
||||
|
||||
void translation_unit_visitor::add_processed_template_class(
|
||||
|
||||
@@ -64,10 +64,21 @@ class translation_unit_visitor
|
||||
: public clang::RecursiveASTVisitor<translation_unit_visitor>,
|
||||
public common::visitor::translation_unit_visitor {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param sm Current source manager reference
|
||||
* @param diagram Diagram model
|
||||
* @param config Diagram configuration
|
||||
*/
|
||||
explicit translation_unit_visitor(clang::SourceManager &sm,
|
||||
clanguml::class_diagram::model::diagram &diagram,
|
||||
const clanguml::config::class_diagram &config);
|
||||
|
||||
/**
|
||||
* \defgroup Implementation of ResursiveASTVisitor methods
|
||||
* @{
|
||||
*/
|
||||
bool shouldVisitTemplateInstantiations() const { return false; }
|
||||
|
||||
bool shouldVisitImplicitCode() const { return false; }
|
||||
@@ -89,6 +100,7 @@ public:
|
||||
virtual bool VisitTypeAliasTemplateDecl(clang::TypeAliasTemplateDecl *cls);
|
||||
|
||||
virtual bool TraverseConceptDecl(clang::ConceptDecl *cpt);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Get diagram model reference
|
||||
@@ -97,6 +109,11 @@ public:
|
||||
*/
|
||||
clanguml::class_diagram::model::diagram &diagram() { return diagram_; }
|
||||
|
||||
/**
|
||||
* @brief Get diagram model reference
|
||||
*
|
||||
* @return Reference to diagram model created by the visitor
|
||||
*/
|
||||
const clanguml::class_diagram::model::diagram &diagram() const
|
||||
{
|
||||
return diagram_;
|
||||
@@ -119,112 +136,335 @@ public:
|
||||
*/
|
||||
void finalize();
|
||||
|
||||
/**
|
||||
* @brief Get reference to Clang AST to clang-uml id mapper
|
||||
*
|
||||
* @return Reference to Clang AST to clang-uml id mapper
|
||||
*/
|
||||
common::visitor::ast_id_mapper &id_mapper() const { return id_mapper_; }
|
||||
|
||||
/**
|
||||
* @brief Add class (or template class) to the diagram.
|
||||
*
|
||||
* @param c Class model
|
||||
*/
|
||||
void add_class(std::unique_ptr<class_> &&c);
|
||||
|
||||
/**
|
||||
* @brief Add enum to the diagram.
|
||||
*
|
||||
* @param e Enum model
|
||||
*/
|
||||
void add_enum(std::unique_ptr<enum_> &&e);
|
||||
|
||||
/**
|
||||
* @brief Add concept to the diagram.
|
||||
*
|
||||
* @param c Concept model
|
||||
*/
|
||||
void add_concept(std::unique_ptr<concept_> &&c);
|
||||
|
||||
void ensure_lambda_type_is_relative(std::string ¶meter_type) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Check if the diagram should include a declaration.
|
||||
*
|
||||
* @param decl Clang declaration.
|
||||
* @return True, if the entity should be included in the diagram.
|
||||
*/
|
||||
bool should_include(const clang::NamedDecl *decl);
|
||||
|
||||
/**
|
||||
* @brief Create class element model from class declaration
|
||||
*
|
||||
* @param cls Class declaration
|
||||
* @return Class diagram element model
|
||||
*/
|
||||
std::unique_ptr<clanguml::class_diagram::model::class_>
|
||||
create_class_declaration(clang::CXXRecordDecl *cls);
|
||||
|
||||
/**
|
||||
* @brief Create class element model from record (e.g. struct) declaration
|
||||
*
|
||||
* @param rec Record declaration
|
||||
* @return Class diagram element model
|
||||
*/
|
||||
std::unique_ptr<clanguml::class_diagram::model::class_>
|
||||
create_record_declaration(clang::RecordDecl *rec);
|
||||
|
||||
/**
|
||||
* @brief Create concept element model from concept declaration
|
||||
* @param cpt Concept declaration
|
||||
* @return Concept diagram element model
|
||||
*/
|
||||
std::unique_ptr<clanguml::class_diagram::model::concept_>
|
||||
create_concept_declaration(clang::ConceptDecl *cpt);
|
||||
|
||||
/**
|
||||
* @brief Process class declaration
|
||||
*
|
||||
* @param cls Class declaration
|
||||
* @param c Class diagram element return from `create_class_declaration`
|
||||
*/
|
||||
void process_class_declaration(const clang::CXXRecordDecl &cls,
|
||||
clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process class declaration bases (parents), if any
|
||||
*
|
||||
* @param cls Class declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_class_bases(const clang::CXXRecordDecl *cls,
|
||||
clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process class children elements (members and methods)
|
||||
*
|
||||
* @param cls Class declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_class_children(const clang::CXXRecordDecl *cls,
|
||||
clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process class or record data members
|
||||
* @param cls Class declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_record_members(const clang::RecordDecl *cls, class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process class template specialization/instantiation
|
||||
*
|
||||
* @param cls Class template specialization declaration
|
||||
* @return Class diagram element model
|
||||
*/
|
||||
std::unique_ptr<clanguml::class_diagram::model::class_>
|
||||
process_template_specialization(
|
||||
clang::ClassTemplateSpecializationDecl *cls);
|
||||
|
||||
/**
|
||||
* @brief Process template specialiaztion children (members and methods)
|
||||
* @param cls Class template specialization declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_template_specialization_children(
|
||||
const clang::ClassTemplateSpecializationDecl *cls, class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process template parameters
|
||||
*
|
||||
* @param template_declaration Template declaration
|
||||
* @param t `template_trait` instance to which the parameters should be
|
||||
* added
|
||||
* @param templated_element Optional templated diagram element (e.g. class_)
|
||||
* @return Ignored
|
||||
*/
|
||||
bool process_template_parameters(
|
||||
const clang::TemplateDecl &template_declaration,
|
||||
clanguml::common::model::template_trait &t,
|
||||
common::optional_ref<common::model::element> templated_element = {});
|
||||
|
||||
/**
|
||||
* @brief Process class method
|
||||
*
|
||||
* @param mf Method declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_method(const clang::CXXMethodDecl &mf,
|
||||
clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process class method properties
|
||||
* @param mf Method declaration
|
||||
* @param c Class diagram element model
|
||||
* @param method_name Method name
|
||||
* @param method Method model
|
||||
*/
|
||||
void process_method_properties(const clang::CXXMethodDecl &mf,
|
||||
const class_ &c, const std::string &method_name,
|
||||
class_method &method) const;
|
||||
|
||||
/**
|
||||
* @brief Process class template method
|
||||
*
|
||||
* @param mf Method declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_template_method(const clang::FunctionTemplateDecl &mf,
|
||||
clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process class static data member
|
||||
*
|
||||
* @param field_declaration Static data member declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_static_field(const clang::VarDecl &field_declaration,
|
||||
clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process class data member
|
||||
*
|
||||
* @param field_declaration Data member declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_field(const clang::FieldDecl &field_declaration,
|
||||
clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Process function/method parameter
|
||||
*
|
||||
* @param param Parameter declaration
|
||||
* @param method Class method model
|
||||
* @param c Class diagram element model
|
||||
* @param template_parameter_names Ignored
|
||||
*/
|
||||
void process_function_parameter(const clang::ParmVarDecl ¶m,
|
||||
clanguml::class_diagram::model::class_method &method,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
const std::set<std::string> &template_parameter_names = {});
|
||||
|
||||
/**
|
||||
* @brief Process class friend
|
||||
*
|
||||
* @param f Friend declaration
|
||||
* @param c Class diagram element model
|
||||
*/
|
||||
void process_friend(
|
||||
const clang::FriendDecl &f, clanguml::class_diagram::model::class_ &c);
|
||||
|
||||
/**
|
||||
* @brief Find relationships in a specific type
|
||||
*
|
||||
* @param type Type to search for relationships
|
||||
* @param relationship_hint Default relationship type to infer from this
|
||||
* type
|
||||
* @return True, if any relationships were found
|
||||
*/
|
||||
bool find_relationships(const clang::QualType &type,
|
||||
found_relationships_t & /*relationships*/,
|
||||
clanguml::common::model::relationship_t relationship_hint);
|
||||
|
||||
/**
|
||||
* @brief Add relationships from relationship list to a class model
|
||||
*
|
||||
* This method takes a list of relationships whose originating element
|
||||
* is class `c` and adds them to it, ignoring any duplicates and skipping
|
||||
* relationships that should be excluded from the diagram.
|
||||
*
|
||||
* @param c Class diagram element model
|
||||
* @param field Class member model
|
||||
* @param relationships List of found relationships
|
||||
* @param break_on_first_aggregation Stop adding relatinoships, after first
|
||||
* aggregation is found
|
||||
*/
|
||||
void add_relationships(clanguml::class_diagram::model::class_ &c,
|
||||
const clanguml::class_diagram::model::class_member &field,
|
||||
const found_relationships_t &relationships,
|
||||
bool break_on_first_aggregation = false);
|
||||
|
||||
/**
|
||||
* @brief Process record parent element (e.g. for nested classes)
|
||||
*
|
||||
* This method handles nested classes or structs.
|
||||
*
|
||||
* @param cls Record declaration
|
||||
* @param c Class diagram element model
|
||||
* @param ns Package in the diagram to which the class `c` should belong
|
||||
*/
|
||||
void process_record_parent(
|
||||
clang::RecordDecl *cls, class_ &c, const namespace_ &ns);
|
||||
|
||||
/**
|
||||
* @brief Find relationships in function parameter
|
||||
*
|
||||
* @param c Class diagram element model
|
||||
* @param atsp `auto` type
|
||||
*/
|
||||
void process_function_parameter_find_relationships_in_autotype(
|
||||
model::class_ &c, const clang::AutoType *atsp);
|
||||
|
||||
/**
|
||||
* @brief Find relationships in concept constraint expression
|
||||
*
|
||||
* @param c Diagram element model (concept)
|
||||
* @param expr Concept constraint expression
|
||||
*/
|
||||
void find_relationships_in_constraint_expression(
|
||||
clanguml::common::model::element &c, const clang::Expr *expr);
|
||||
|
||||
/**
|
||||
* @brief Register incomplete forward declaration to be updated later
|
||||
*/
|
||||
void add_incomplete_forward_declarations();
|
||||
|
||||
/**
|
||||
* @brief Replace any AST local ids in diagram elements with global ones
|
||||
*
|
||||
* Not all elements global ids can be set in relationships during
|
||||
* traversal of the AST. In such cases, a local id (obtained from `getID()`)
|
||||
* and at after the traversal is complete, the id is replaced with the
|
||||
* global diagram id.
|
||||
*/
|
||||
void resolve_local_to_global_ids();
|
||||
|
||||
/**
|
||||
* @brief Process concept constraint requirements
|
||||
*
|
||||
* @param cpt Concept declaration
|
||||
* @param expr Requires expression
|
||||
* @param concept_model Concept diagram element model
|
||||
*/
|
||||
void process_constraint_requirements(const clang::ConceptDecl *cpt,
|
||||
const clang::Expr *expr, model::concept_ &concept_model) const;
|
||||
|
||||
/**
|
||||
* @brief Find concept specializations relationships
|
||||
*
|
||||
* @param c Concept element model
|
||||
* @param concept_specialization Concept specialization expression
|
||||
*/
|
||||
void process_concept_specialization_relationships(common::model::element &c,
|
||||
const clang::ConceptSpecializationExpr *concept_specialization);
|
||||
|
||||
/**
|
||||
* @brief Extract template contraint parameter name from raw source code
|
||||
*
|
||||
* @param concept_specialization Concept specialization expression
|
||||
* @param cpt Concept declaration
|
||||
* @param constrained_template_params Found constraint template param names
|
||||
* @param argument_index Argument index
|
||||
* @param type_name Type parameter name - used if extraction fails
|
||||
*/
|
||||
void extract_constrained_template_param_name(
|
||||
const clang::ConceptSpecializationExpr *concept_specialization,
|
||||
const clang::ConceptDecl *cpt,
|
||||
std::vector<std::string> &constrained_template_params,
|
||||
size_t argument_index, std::string &type_name) const;
|
||||
|
||||
/// Store the mapping from local clang entity id (obtained using
|
||||
/// getID()) method to clang-uml global id
|
||||
void set_ast_local_id(
|
||||
int64_t local_id, common::model::diagram_element::id_t global_id);
|
||||
|
||||
/**
|
||||
* @brief Register already processed template class name
|
||||
*
|
||||
* @param qualified_name Fully qualified template class name
|
||||
*/
|
||||
void add_processed_template_class(std::string qualified_name);
|
||||
|
||||
/**
|
||||
* @brief Check if template class has already been processed
|
||||
*
|
||||
* @param qualified_name Fully qualified template class name
|
||||
* @return True, if template class has already been processed
|
||||
*/
|
||||
bool has_processed_template_class(const std::string &qualified_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get template builder reference
|
||||
*
|
||||
* @return Reference to 'template_builder' instance
|
||||
*/
|
||||
template_builder &tbuilder() { return template_builder_; }
|
||||
|
||||
// Reference to the output diagram model
|
||||
@@ -246,13 +486,13 @@ private:
|
||||
common::model::access_t>>
|
||||
anonymous_struct_relationships_;
|
||||
|
||||
// When visiting CXX records we need to know if they have already been
|
||||
// process in VisitClassTemplateDecl or VisitClassTemplateSpecializationDecl
|
||||
// If yes, then we need to skip it
|
||||
// TODO: There must be a better way to do this...
|
||||
/**
|
||||
* When visiting CXX records we need to know if they have already been
|
||||
* process in VisitClassTemplateDecl or
|
||||
* VisitClassTemplateSpecializationDecl. If yes, then we need to skip it
|
||||
*
|
||||
* @todo There must be a better way to do this...
|
||||
*/
|
||||
std::set<std::string> processed_template_qualified_names_;
|
||||
void process_method_properties(const clang::CXXMethodDecl &mf,
|
||||
const class_ &c, const std::string &method_name,
|
||||
class_method &method) const;
|
||||
};
|
||||
} // namespace clanguml::class_diagram::visitor
|
||||
|
||||
@@ -137,6 +137,8 @@ public:
|
||||
bool should_include(relationship r) const;
|
||||
bool should_include(relationship_t r) const;
|
||||
bool should_include(access_t s) const;
|
||||
// Disallow std::string overload
|
||||
bool should_include(const std::string &s) const = delete;
|
||||
|
||||
virtual bool has_element(const diagram_element::id_t /*id*/) const
|
||||
{
|
||||
|
||||
@@ -553,8 +553,9 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
|
||||
clang::cast<clang::NamespaceDecl>(namespace_context);
|
||||
|
||||
if (namespace_declaration != nullptr &&
|
||||
diagram().should_include(common::get_qualified_name(
|
||||
*namespace_declaration))) {
|
||||
diagram().should_include(
|
||||
namespace_{common::get_qualified_name(
|
||||
*namespace_declaration)})) {
|
||||
const auto target_id = get_package_id(cxxrecord_decl);
|
||||
relationships.emplace_back(
|
||||
target_id, relationship_hint);
|
||||
@@ -563,8 +564,9 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (diagram().should_include(common::get_qualified_name(
|
||||
*type->getAsCXXRecordDecl()))) {
|
||||
if (diagram().should_include(
|
||||
namespace_{common::get_qualified_name(
|
||||
*type->getAsCXXRecordDecl())})) {
|
||||
const auto target_id =
|
||||
get_package_id(type->getAsCXXRecordDecl());
|
||||
relationships.emplace_back(target_id, relationship_hint);
|
||||
@@ -578,7 +580,7 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
|
||||
// need to consider namespaces here
|
||||
if (config().package_type() == config::package_type_t::kDirectory) {
|
||||
if (diagram().should_include(
|
||||
common::get_qualified_name(*record_decl))) {
|
||||
namespace_{common::get_qualified_name(*record_decl)})) {
|
||||
const auto target_id = get_package_id(record_decl);
|
||||
relationships.emplace_back(target_id, relationship_hint);
|
||||
result = true;
|
||||
|
||||
@@ -1222,18 +1222,15 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls)
|
||||
config().using_namespace())};
|
||||
auto &c = *c_ptr;
|
||||
|
||||
// TODO: refactor to method get_qualified_name()
|
||||
auto qualified_name =
|
||||
cls->getQualifiedNameAsString(); // common::get_qualified_name(*cls);
|
||||
auto qualified_name = cls->getQualifiedNameAsString();
|
||||
|
||||
if (!cls->isLambda())
|
||||
if (!diagram().should_include(qualified_name))
|
||||
if (!should_include(cls))
|
||||
return {};
|
||||
|
||||
auto ns = common::get_tag_namespace(*cls);
|
||||
|
||||
if (cls->isLambda() &&
|
||||
!diagram().should_include(ns.to_string() + "::lambda"))
|
||||
if (cls->isLambda() && !diagram().should_include(ns | "lambda"))
|
||||
return {};
|
||||
|
||||
const auto *parent = cls->getParent();
|
||||
@@ -2202,7 +2199,8 @@ bool translation_unit_visitor::should_include(const clang::TagDecl *decl) const
|
||||
|
||||
const auto decl_file = decl->getLocation().printToString(source_manager());
|
||||
|
||||
return diagram().should_include(decl->getQualifiedNameAsString()) &&
|
||||
return diagram().should_include(
|
||||
namespace_{decl->getQualifiedNameAsString()}) &&
|
||||
diagram().should_include(common::model::source_file{decl_file});
|
||||
}
|
||||
|
||||
@@ -2255,7 +2253,8 @@ bool translation_unit_visitor::should_include(
|
||||
{
|
||||
const auto decl_file = decl->getLocation().printToString(source_manager());
|
||||
|
||||
return diagram().should_include(decl->getQualifiedNameAsString()) &&
|
||||
return diagram().should_include(
|
||||
namespace_{decl->getQualifiedNameAsString()}) &&
|
||||
diagram().should_include(common::model::source_file{decl_file});
|
||||
}
|
||||
|
||||
@@ -2273,7 +2272,8 @@ bool translation_unit_visitor::should_include(
|
||||
|
||||
const auto decl_file = decl->getLocation().printToString(source_manager());
|
||||
|
||||
return diagram().should_include(decl->getQualifiedNameAsString()) &&
|
||||
return diagram().should_include(
|
||||
namespace_{decl->getQualifiedNameAsString()}) &&
|
||||
diagram().should_include(common::model::source_file{decl_file});
|
||||
}
|
||||
} // namespace clanguml::sequence_diagram::visitor
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
namespace clanguml::sequence_diagram::visitor {
|
||||
|
||||
using common::model::namespace_;
|
||||
using common::model::template_parameter;
|
||||
|
||||
std::string to_string(const clang::FunctionTemplateDecl *decl);
|
||||
|
||||
@@ -31,7 +31,6 @@ TEST_CASE("t00003", "[test-case][class]")
|
||||
auto model = generate_class_diagram(*db, diagram);
|
||||
|
||||
REQUIRE(model->name() == "t00003_class");
|
||||
REQUIRE(model->should_include(std::string("clanguml::t00003::A")));
|
||||
|
||||
{
|
||||
auto puml = generate_class_puml(diagram, *model);
|
||||
|
||||
Reference in New Issue
Block a user