Added initial Doxygen config

This commit is contained in:
Bartek Kryza
2023-06-18 01:18:14 +02:00
parent 031235bf49
commit da2cb63ab3
51 changed files with 4330 additions and 158 deletions

View File

@@ -34,26 +34,95 @@ namespace clanguml::common::model {
using comment_t = inja::json;
/**
* @brief Base class for decorated diagram elements
*
* Decorators in `clang-uml` mean that custom `@uml{}` directives can be
* applied to them in the code comments.
*
* @embed{decorated_element_hierarchy_class.svg}
*
* @see clanguml::decorators::decorator
*
*/
class decorated_element {
public:
/**
* Whether this element should be skipped from the diagram.
*
* @return
*/
bool skip() const;
/**
* Whether this relationship should be skipped from the diagram.
*
* @return
*/
bool skip_relationship() const;
/**
* If this element is a member or a method, get relationship decorator
* if any.
*
* @code
* /// @uml{aggregation[0..1:1..5]}
* std::vector<C> ccc;
* @endcode
*
* @return Relationship specified as a decorator on class member.
*/
std::pair<relationship_t, std::string> get_relationship() const;
/**
* Get stype specification for this element, if any.
*
* @code
* /// @uml{style[#back:lightgreen|yellow;header:blue/red]}
* class A { };
* @endcode
*
* @return
*/
std::string style_spec() const;
/**
* Get all decorators for this element.
*
* @return List of decorator pointers.
*/
const std::vector<std::shared_ptr<decorators::decorator>> &
decorators() const;
/**
* Add decorators to the element.
*
* @param decorators List of decorator pointers.
*/
void add_decorators(
const std::vector<std::shared_ptr<decorators::decorator>> &decorators);
/**
* Append decorators from another element.
*
* @param de Source element to copy decorators from.
*/
void append(const decorated_element &de);
/**
* Get entire comment model for this element.
*
* @return Comment model.
*/
std::optional<comment_t> comment() const;
/**
* Set comment model for this element.
*
* Comment model is currently a JSON object.
*
* @param c Comment model.
*/
void set_comment(const comment_t &c);
private:

View File

@@ -31,22 +31,49 @@ class diagram_filter;
class element;
class relationship;
/**
* @brief Base class for all diagram models
*
* @embed{diagram_hierarchy_class.svg}
*/
class diagram {
public:
diagram();
virtual ~diagram();
/**
* @brief Return type of the diagram.
*
* @return Type of diagram
*/
virtual diagram_t type() const = 0;
/**
* Return optional reference to a diagram_element by name.
*
* @param full_name Fully qualified name of a diagram element.
* @return Optional reference to a diagram element.
*/
virtual opt_ref<clanguml::common::model::diagram_element> get(
const std::string &full_name) const = 0;
/**
* Return optional reference to a diagram_element by id.
*
* @param id Id of a diagram element.
* @return Optional reference to a diagram element.
*/
virtual common::optional_ref<clanguml::common::model::diagram_element> get(
diagram_element::id_t id) const = 0;
/// \brief Find element in diagram which can have full name or be
/// relative to ns
/**
* Return optional reference to a diagram_element by name and namespace.
*
* @param name Name of the diagram element (e.g. a class name)
* @param ns Namespace of the element.
* @return Optional reference to a diagram element.
*/
virtual common::optional_ref<clanguml::common::model::diagram_element>
get_with_namespace(const std::string &name, const namespace_ &ns) const;
@@ -55,13 +82,52 @@ public:
diagram &operator=(const diagram &) = delete;
diagram &operator=(diagram && /*unused*/) noexcept;
/**
* Set diagram name.
*
* @param name Name of the diagram.
*/
void set_name(const std::string &name);
/**
* Return the name of the diagram.
*
* @return Name of the diagram.
*/
std::string name() const;
/**
* Set diagram filter for this diagram.
*
* @param filter diagram_filter instance
*
* @see clanguml::common::model::diagram_filter
*/
void set_filter(std::unique_ptr<diagram_filter> filter);
/**
* Get diagram filter
*
* @return Reference to the diagrams element filter
*/
const diagram_filter &filter() const { return *filter_; }
/**
* @brief Set diagram in a complete state.
*
* This must be called after the diagram's 'translation_unit_visitor' has
* completed for all translation units, in order to apply filters which can
* only work after the diagram is complete.
*
* @param complete Status of diagram visitor completion.
*/
void set_complete(bool complete);
/**
* Whether the diagram is complete.
*
* @return Diagram completion status.
*/
bool complete() const;
// TODO: refactor to a template method
@@ -80,6 +146,11 @@ public:
virtual bool should_include(
const namespace_ &ns, const std::string &name) const;
/**
* Return diagrams JSON context for inja templates.
*
* @return JSON context.
*/
virtual inja::json context() const = 0;
private:

View File

@@ -31,6 +31,12 @@
namespace clanguml::common::model {
/**
* @brief Base class for standalone diagram elements.
*
* This is a base cass of any standalone elements such as classes, structs,
* concepts, packages and so on participants and so on.
*/
class diagram_element : public decorated_element, public source_location {
public:
using id_t = int64_t;
@@ -39,26 +45,91 @@ public:
virtual ~diagram_element() = default;
/**
* @brief Returns diagram element id.
*
* Each element in the diagram is uniquely identified by id. The id
* is currently calculated from the full string representation of the
* element, in order to be uniquely identifiable among multiple translation
* units.
*
* @return Elements id.
*/
id_t id() const;
/**
* Set elements id.
*
* @param id Elements id.
*/
void set_id(id_t id);
/**
* @brief Return elements' diagram alias.
*
* @todo This is a PlantUML specific method - it shouldn't be here.
*
* @return PlantUML's diagram element alias.
*/
virtual std::string alias() const;
/**
* Set diagram elements name.
*
* @param name Elements name.
*/
void set_name(const std::string &name) { name_ = name; }
/**
* Return diagram's name.
*
* @return Diagram's name.
*/
std::string name() const { return name_; }
/**
* Return the type name of the diagram.
*
* @return Diagrams type name.
*/
virtual std::string type_name() const { return "__undefined__"; };
/**
* @brief Return the elements fully qualified name.
*
* This method should be implemented in each subclass, and ensure that
* for instance it includes fully qualified namespace, template params, etc.
*
* @return Full elements name.
*/
virtual std::string full_name(bool /*relative*/) const { return name(); }
/**
* Return all relationships outgoing from this element.
*
* @return List of relationships.
*/
std::vector<relationship> &relationships();
/**
* Return all relationships outgoing from this element.
*
* @return List of relationships.
*/
const std::vector<relationship> &relationships() const;
/**
* Add relationships, whose source is this element.
*
* @param cr Relationship to another diagram element.
*/
void add_relationship(relationship &&cr);
/**
* Add element to the diagram.
*
* @param e Diagram element.
*/
void append(const decorated_element &e);
friend bool operator==(const diagram_element &l, const diagram_element &r);
@@ -66,14 +137,39 @@ public:
friend std::ostream &operator<<(
std::ostream &out, const diagram_element &rhs);
/**
* Return elements inja JSON context.
*
* @return Element context.
*/
virtual inja::json context() const;
/**
* Whether this element is nested in another element.
*
* @return
*/
bool is_nested() const;
/**
* Set element's nested status.
*
* @param nested
*/
void nested(bool nested);
/**
* Returns the diagrams completion status.
*
* @return Whether the diagram is complete.
*/
bool complete() const;
/**
* Set the diagrams completion status.
*
* @param completed
*/
void complete(bool completed);
private:

View File

@@ -36,7 +36,15 @@
namespace clanguml::common::model {
enum filter_t { kInclusive, kExclusive };
/**
* Diagram filters can be add in 2 modes:
* - inclusive - the elements that match are included in the diagram
* - exclusive - the elements that match are excluded from the diagram
*/
enum class filter_t {
kInclusive, /*!< Filter is inclusive */
kExclusive /*!< Filter is exclusve */
};
namespace detail {
template <typename ElementT, typename DiagramT>
@@ -56,6 +64,16 @@ clanguml::common::id_t destination_comparator(
const common::model::source_file &f);
} // namespace detail
/**
* @brief Base class for any diagram filter.
*
* This class acts as a visitor for diagram elements. It provides a set of
* common methods which can be overriden by specific filters. If a filter
* does not implement a specific method, it is ignored through the 3 value
* logic implemented in @see clanguml::common::model::tvl
*
* @embed{filter_visitor_hierarchy_class.svg}
*/
class filter_visitor {
public:
filter_visitor(filter_t type);
@@ -111,6 +129,10 @@ private:
std::vector<std::unique_ptr<filter_visitor>> filters_;
};
/**
* Match namespace or diagram element to a set of specified namespaces or
* regex patterns.
*/
struct namespace_filter : public filter_visitor {
namespace_filter(
filter_t type, std::vector<common::namespace_or_regex> namespaces);
@@ -125,6 +147,9 @@ private:
std::vector<common::namespace_or_regex> namespaces_;
};
/**
* Match element's name to a set of names or regex patterns.
*/
struct element_filter : public filter_visitor {
element_filter(
filter_t type, std::vector<common::string_or_regex> elements);
@@ -137,6 +162,9 @@ private:
std::vector<common::string_or_regex> elements_;
};
/**
* Match diagram elements based on elements type (e.g. class).
*/
struct element_type_filter : public filter_visitor {
element_type_filter(filter_t type, std::vector<std::string> element_types);
@@ -148,6 +176,9 @@ private:
std::vector<std::string> element_types_;
};
/**
* Match class methods based on their category (e.g. operator).
*/
struct method_type_filter : public filter_visitor {
method_type_filter(
filter_t type, std::vector<config::method_type> method_types);
@@ -161,6 +192,10 @@ private:
std::vector<config::method_type> method_types_;
};
/**
* Match element based on whether it is a subclass of a set of base classes,
* or one of them.
*/
struct subclass_filter : public filter_visitor {
subclass_filter(filter_t type, std::vector<common::string_or_regex> roots);
@@ -172,6 +207,10 @@ private:
std::vector<common::string_or_regex> roots_;
};
/**
* Match element based on whether it is a parent of a set of children, or one
* of them.
*/
struct parents_filter : public filter_visitor {
parents_filter(filter_t type, std::vector<common::string_or_regex> roots);
@@ -183,6 +222,20 @@ private:
std::vector<common::string_or_regex> children_;
};
/**
* @brief Common template for filters involving traversing relationship graph.
*
* This class template provides a common implementation of a diagram
* relationship graph traversal. It is used for filters, which need to check
* for instance, whether an element is in some kind of relationship with other
* element.
*
* @tparam DiagramT Diagram type
* @tparam ElementT Element type
* @tparam ConfigEntryT Type of configuration option used to specify initial
* elements for traversal
* @tparam MatchOverrideT Type of the matched element
*/
template <typename DiagramT, typename ElementT,
typename ConfigEntryT = std::string,
typename MatchOverrideT = common::model::element>
@@ -337,6 +390,9 @@ private:
bool forward_;
};
/**
* Match relationship types.
*/
struct relationship_filter : public filter_visitor {
relationship_filter(
filter_t type, std::vector<relationship_t> relationships);
@@ -350,6 +406,9 @@ private:
std::vector<relationship_t> relationships_;
};
/**
* Match class members and methods based on access (public, protected, private).
*/
struct access_filter : public filter_visitor {
access_filter(filter_t type, std::vector<access_t> access);
@@ -361,6 +420,10 @@ private:
std::vector<access_t> access_;
};
/**
* Match diagram elements which are in direct relationship to any of the
* elements specified in context.
*/
struct context_filter : public filter_visitor {
context_filter(filter_t type, std::vector<common::string_or_regex> context);
@@ -372,6 +435,10 @@ private:
std::vector<common::string_or_regex> context_;
};
/**
* Match elements based on their source location, whether it matches to
* a specified file paths.
*/
struct paths_filter : public filter_visitor {
paths_filter(filter_t type, const std::filesystem::path &root,
const std::vector<std::string> &p);
@@ -389,6 +456,9 @@ private:
std::filesystem::path root_;
};
/**
* Match class method based on specified method categories.
*/
struct class_method_filter : public filter_visitor {
class_method_filter(filter_t type, std::unique_ptr<access_filter> af,
std::unique_ptr<method_type_filter> mtf);
@@ -403,6 +473,9 @@ private:
std::unique_ptr<method_type_filter> method_type_filter_;
};
/**
* Match class members.
*/
struct class_member_filter : public filter_visitor {
class_member_filter(filter_t type, std::unique_ptr<access_filter> af);
@@ -415,16 +488,49 @@ private:
std::unique_ptr<access_filter> access_filter_;
};
/**
* @brief Composite of all diagrams filters.
*
* Instances of this class contain all filters specified in configuration file
* for a given diagram.
*
* @embed{diagram_filter_context_class.svg}
*
* @see clanguml::common::model::filter_visitor
*/
class diagram_filter {
public:
diagram_filter(const common::model::diagram &d, const config::diagram &c);
/**
* Add inclusive filter.
*
* @param fv Filter visitor.
*/
void add_inclusive_filter(std::unique_ptr<filter_visitor> fv);
/** Add exclusive filter.
*
* @param fv Filter visitor.
*/
void add_exclusive_filter(std::unique_ptr<filter_visitor> fv);
/**
* `should_include` overload for namespace and name.
*
* @param ns Namespace
* @param name Name
* @return Match result.
*/
bool should_include(const namespace_ &ns, const std::string &name) const;
/**
* Generic `should_include` overload for various diagram elements.
*
* @tparam T Type to to match - must match one of filter_visitor's match(T)
* @param e Value of type T to match
* @return Match result.
*/
template <typename T> bool should_include(const T &e) const
{
auto exc = tvl::any_of(exclusive_.begin(), exclusive_.end(),
@@ -440,11 +546,22 @@ public:
}
private:
/**
* @brief Initialize filters.
*
* Some filters require initialization.
*
* @param c Diagram config.
*/
void init_filters(const config::diagram &c);
/*! List of inclusive filters */
std::vector<std::unique_ptr<filter_visitor>> inclusive_;
/*! List of exclusive filters */
std::vector<std::unique_ptr<filter_visitor>> exclusive_;
/*! Reference to the diagram model */
const common::model::diagram &diagram_;
};

View File

@@ -32,36 +32,83 @@
namespace clanguml::common::model {
/**
* @brief Base class for any element qualified by namespace.
*/
class element : public diagram_element {
public:
element(namespace_ using_namespace);
~element() override = default;
/**
* Return the elements fully qualified name, but without template
* arguments or function params.
*
* @return Fully qualified element name.
*/
std::string name_and_ns() const
{
auto ns = ns_ | name();
return ns.to_string();
}
/**
* Set elements namespace.
*
* @param ns Namespace.
*/
void set_namespace(const namespace_ &ns) { ns_ = ns; }
/**
* Return elements namespace.
*
* @return Namespace.
*/
namespace_ get_namespace() const { return ns_; }
/**
* Return elements relative namespace.
*
* @return Namespace.
*/
namespace_ get_relative_namespace() const
{
return ns_.relative_to(using_namespace_);
}
/**
* Return elements namespace as path.
*
* Namespace is a nested path in diagrams where packages are generated
* from namespaces.
*
* @return Namespace.
*/
const namespace_ &path() const { return ns_; }
/**
* Return elements full name.
*
* @return Fully qualified elements name.
*/
std::string full_name(bool /*relative*/) const override
{
return name_and_ns();
}
/**
* Return elements full name but without namespace.
*
* @return Elements full name without namespace.
*/
virtual std::string full_name_no_ns() const { return name(); }
/**
* Return the relative namespace from config.
*
* @return Namespace.
*/
const namespace_ &using_namespace() const;
friend bool operator==(const element &l, const element &r);

View File

@@ -25,6 +25,18 @@
#include <vector>
namespace clanguml::common::model {
/**
* @brief Base class for elements nested in the diagram.
*
* This class provides a common trait for diagram elements which can contain
* other nested elements, e.g. packages.
*
* @embed{nested_trait_hierarchy_class.svg}
*
* @tparam T Type of element
* @tparam Path Type of nested path (e.g. namespace or directory path)
*/
template <typename T, typename Path> class nested_trait {
public:
nested_trait() = default;
@@ -37,6 +49,13 @@ public:
virtual ~nested_trait() = default;
/**
* Add element at the current nested level.
*
* @tparam V Type of element
* @param p Element
* @return True, if element was added.
*/
template <typename V = T>
[[nodiscard]] bool add_element(std::unique_ptr<V> p)
{
@@ -53,6 +72,14 @@ public:
return true;
}
/**
* Add element at a nested path.
*
* @tparam V Type of element
* @param path Nested path (e.g. list of namespaces)
* @param p Element
* @return True, if element was added.
*/
template <typename V = T>
bool add_element(const Path &path, std::unique_ptr<V> p)
{
@@ -77,6 +104,13 @@ public:
"No parent element found for " + path.to_string());
}
/**
* Get element at path, if exists.
*
* @tparam V Element type.
* @param path Path to the element.
* @return Optional reference to the element.
*/
template <typename V = T> auto get_element(const Path &path) const
{
if (path.is_empty() || !has_element(path[0])) {
@@ -100,18 +134,13 @@ public:
return optional_ref<V>{};
}
template <typename V = T> auto get_element_parent(const T &element) const
{
auto path = element.path();
auto parent = get_element(path);
if (parent.has_value())
return optional_ref<V>{
std::ref<V>(dynamic_cast<V &>(parent.value()))};
return optional_ref<V>{};
}
/**
* Get element by name at the current nested level.
*
* @tparam V Type of element.
* @param name Name of the element (cannot contain namespace or path)
* @return Optional reference to the element.
*/
template <typename V = T> auto get_element(const std::string &name) const
{
assert(!util::contains(name, "::"));
@@ -130,6 +159,13 @@ public:
return optional_ref<V>{};
}
/**
* Returns true of this nested level contains an element with specified
* name.
*
* @param name Name of the element.
* @return True if element exists.
*/
bool has_element(const std::string &name) const
{
return std::find_if(elements_.cbegin(), elements_.cend(),
@@ -137,6 +173,12 @@ public:
elements_.end();
}
/**
* Return result of functor f applied to all_of elements.
* @tparam F Functor type
* @param f Functor value
* @return True, if functor return true for elements, including nested ones.
*/
template <typename F> bool all_of(F &&f) const
{
return std::all_of(
@@ -151,6 +193,11 @@ public:
});
}
/**
* Check if nested element is empty.
*
* @return True if this nested element is empty.
*/
bool is_empty() const
{
return elements_.empty() ||
@@ -170,6 +217,13 @@ public:
auto begin() const { return elements_.begin(); }
auto end() const { return elements_.end(); }
/**
* Print the nested trait in the form of a tree.
*
* This method is used for debugging only.
*
* @param level Tree level
*/
void print_tree(const int level)
{
const auto &d = *this;

View File

@@ -32,6 +32,11 @@
namespace clanguml::common::model {
/**
* @brief Diagram element representing namespace or directory package
*
* @embed{package_hierarchy_class.svg}
*/
class package : public element,
public stylable_element,
public nested_trait<element, path> {
@@ -47,10 +52,25 @@ public:
std::string full_name(bool relative) const override;
/**
* Returns whether the namespace is deprecated.
*
* @return True, if namespace is deprecated.
*/
bool is_deprecated() const;
/**
* Set namespace deprecation status.
*
* @param deprecated True, if namespace is deprecated
*/
void set_deprecated(bool deprecated);
/**
* Add subpackage.
*
* @param p Package.
*/
void add_package(std::unique_ptr<common::model::package> &&p);
private:

View File

@@ -22,6 +22,9 @@
namespace clanguml::common::model {
/**
* @brief Base class of all diagram elements that have source location.
*/
class source_location {
public:
source_location() = default;
@@ -32,31 +35,96 @@ public:
{
}
/**
* Return absolute source file path.
*
* @return Absolute file path.
*/
const std::string &file() const { return file_; }
/**
* Set absolute file path.
*
* @param file Absolute file path.
*/
void set_file(const std::string &file) { file_ = file; }
/**
* Return source file path relative to `relative_to` config option.
*
* @return Relative file path.
*/
const std::string &file_relative() const { return file_relative_; }
/**
* Set relative file path.
*
* @param file Relative file path.
*/
void set_file_relative(const std::string &file) { file_relative_ = file; }
/**
* Get the translation unit, from which this source location was visited.
*
* @return Path to the translation unit.
*/
const std::string &translation_unit() const { return translation_unit_; }
/**
* Set the path to translation unit, from which this source location was
* visited.
*
* @param translation_unit Path to the translation unit.
*/
void set_translation_unit(const std::string &translation_unit)
{
translation_unit_ = translation_unit;
}
/**
* Get the source location line number.
*
* @return Line number.
*/
unsigned int line() const { return line_; }
/**
* Set the source location line number.
*
* @param line Line number.
*/
void set_line(const unsigned line) { line_ = line; }
/**
* Get the source location column number.
*
* @return Column number.
*/
unsigned int column() const { return column_; }
/**
* Set the source location column number.
*
* @param line Column number.
*/
void set_column(const unsigned column) { column_ = column; }
/**
* Get the source location id.
*
* The location id is equivalent to Clang's SourceLocation::getHashValue()
*
* @return Location id.
*/
unsigned int location_id() const { return hash_; }
/**
* Set the source location id.
*
* The location id is equivalent to Clang's SourceLocation::getHashValue()
*
* @param h Location id.
*/
void set_location_id(unsigned int h) { hash_ = h; }
private: