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

@@ -1,32 +1,63 @@
compilation_database_dir: debug
output_directory: docs/diagrams
comment_parser: clang
generate_links:
link: https://github.com/bkryza/clang-uml/blob/{{ git.commit }}/{{ element.source.path }}#L{{ element.source.line }}
tooltip: "{% if existsIn(element, \"comment\") and existsIn(element.comment, \"brief\") %}{{ abbrv(trim(replace(element.comment.brief.0, \"\\n+\", \" \")), 256) }}{% else %}{{ element.name }}{% endif %}"
diagrams:
main_package:
include!: uml/main_package_diagram.yml
# Class diagrams
config_class:
include!: uml/config_class_diagram.yml
include!: uml/class/config_class.yml
config_context_class:
include!: uml/class/config_context_class.yml
compilation_database_context_class:
include!: uml/class/compilation_database_context_class.yml
inheritable_diagram_options_context_class:
include!: uml/class/inheritable_diagram_options_context_class.yml
diagram_config_hierarchy_class:
include!: uml/class/diagram_config_hierarchy_class.yml
diagram_hierarchy_class:
include!: uml/class/diagram_hierarchy_class.yml
decorated_element_hierarchy_class:
include!: uml/class/decorated_element_hierarchy_class.yml
filter_visitor_hierarchy_class:
include!: uml/class/filter_visitor_hierarchy_class.yml
diagram_filter_context_class:
include!: uml/class/diagram_filter_context_class.yml
nested_trait_hierarchy_class:
include!: uml/class/nested_trait_hierarchy_class.yml
package_hierarchy_class:
include!: uml/class/package_hierarchy_class.yml
decorators_class:
include!: uml/decorators_class_diagram.yml
include!: uml/class/decorators_class.yml
common_model_class:
include!: uml/common_model_class_diagram.yml
include!: uml/class/common_model_class.yml
class_model_class:
include!: uml/class_model_class_diagram.yml
include!: uml/class/class_model_class.yml
diagram_element_hierarchy_class:
include!: uml/diagram_element_hierarchy_diagram.yml
include!: uml/class/diagram_element_hierarchy_class.yml
sequence_model_class:
include!: uml/sequence_model_class_diagram.yml
main_sequence:
include!: uml/main_sequence_diagram.yml
sequence_diagram_visitor_sequence:
include!: uml/sequence_diagram_visitor_sequence_diagram.yml
class_diagram_generator_sequence:
include!: uml/class_diagram_generator_sequence_diagram.yml
template_builder_sequence:
include!: uml/template_builder_sequence_diagram.yml
include!: uml/class/sequence_model_class.yml
package_model_class:
include!: uml/package_model_class_diagram.yml
include!: uml/class/package_model_class.yml
# Sequence diargams
main_sequence:
include!: uml/sequence/main_sequence.yml
load_config_sequence:
include!: uml/sequence/load_config_sequence.yml
cli_handle_options_sequence:
include!: uml/sequence/cli_handle_options_sequence.yml
diagram_generate_generic_sequence:
include!: uml/sequence/diagram_generate_generic_sequence.yml
sequence_diagram_visitor_sequence:
include!: uml/sequence/sequence_diagram_visitor_sequence.yml
class_diagram_generator_sequence:
include!: uml/sequence/class_diagram_generator_sequence.yml
template_builder_sequence:
include!: uml/sequence/template_builder_sequence.yml
# Package diagrams
main_package:
include!: uml/package/main_package.yml
# Include diagrams
include_graph:
include!: uml/include_diagram.yml
include!: uml/include/include.yml

1
.gitignore vendored
View File

@@ -22,6 +22,7 @@ bin/
/debug_tidy
/.cache
docs/diagrams
docs/doxygen
coverage*.info

2667
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,20 @@
@mainpage clang-uml
# Documentation
`clang-uml` is an automatic C++ to UML class, sequence, package and include diagram generator, driven by
YAML configuration files. The main idea behind the
project is to easily maintain up-to-date diagrams within a code-base or document
legacy code. The configuration file or files for `clang-uml` define the
types and contents of each generated diagram.
The diagrams can be generated in [PlantUML](https://plantuml.com) and JSON formats.
`clang-uml` currently supports C++ up to version 17 with partial support for C++ 20.
To see what `clang-uml` can do, checkout the diagrams generated for unit
test cases [here](./test_cases.md) or examples in
[clang-uml-examples](https://github.com/bkryza/clang-uml-examples) repository.
* [Quick start](./quick_start.md)
* [Installation](./installation.md)
* Generating diagrams
@@ -18,3 +33,6 @@
* [Doxygen integration](./doxygen_integration.md)
* [Test cases documentation](./test_cases.md)
* [Troubleshooting](./troubleshooting.md)
* Development
* [Architecture](./architecture.md)
* [Contributing](../CONTRIBUTING.md)

View File

@@ -2,18 +2,18 @@
<!-- toc -->
* [`namespaces` _[string or regex]_](#namespaces-_string-or-regex_)
* [`elements` _[string or regex]_](#elements-_string-or-regex_)
* [`element_types`](#element_types)
* [`paths` _[string or glob]_](#paths-_string-or-glob_)
* [`context` _[string or regex]_](#context-_string-or-regex_)
* [`relationships`](#relationships)
* [`subclasses` _[string or regex]_](#subclasses-_string-or-regex_)
* [`parents` _[string or regex]_](#parents-_string-or-regex_)
* [`specializations` _[string or regex]_](#specializations-_string-or-regex_)
* [`access`](#access)
* [`method_types`](#method_types)
* [`dependants` and `dependencies` _[string or regex]_](#dependants-and-dependencies-_string-or-regex_)
* [namespaces](#namespaces)
* [elements](#elements)
* [element_types](#element_types)
* [paths](#paths)
* [context](#context)
* [relationships](#relationships)
* [subclasses](#subclasses)
* [parents](#parents)
* [specializations](#specializations)
* [access](#access)
* [method_types](#method_types)
* [dependants and dependencies](#dependants-and-dependencies)
<!-- tocstop -->
@@ -56,28 +56,28 @@ exclude:
The following table specifies the values allowed in each filter:
| Filter name | Possible values | Example values |
|-------------------|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `namespaces` | Qualified name or regex | - `ns1::ns2::ClassA` <br/>- `r: '.*detail.*'` |
| `elements` | Qualified name or regex | - `ns1::ns2::ClassA` <br/>- `r: '.*detail.*'` |
| `element_types` | Types of diagram elements | - `class`<br/>- `enum`<br/>- `concept` |
| `paths` | File or dir path or glob pattern | - `src/dir1`<br/>- `src/dir2/a.cpp`<br/>- `src/dir3/*.cpp` |
| `context` | Qualified name or regex | - `ns1::ns2::ClassA`<br/>- `r: 'ns1::ns2::ClassA.+'` |
| `relationships` | Type of relationship | - `inheritance`<br/>- `composition`<br/>- `aggregation`<br/>- `ownership`<br/>- `association`<br/>- `instantiation`<br/>- `friendship`<br/>- `dependency` |
| `subclasses` | Qualified name or regex | - `ns1::ns2::ClassA`<br/>- `r: 'ns1::ns2::ClassA.+'` |
| `parents` | Qualified name or regex | - `ns1::ns2::ClassA`<br/>- `r: 'ns1::ns2::ClassA.+'` |
| `specializations` | Qualified name or regex | - `ns1::ns2::ClassA`<br/>- `r: 'ns1::ns2::ClassA.+'` |
| `access` | Method or member access scope | - `public`<br/>- `protected`<br/>- `private` |
| `method_types` | Type of class method | - `constructor`<br/>- `destructor`<br/>- `assignment`<br/>- `operator`<br/>- `defaulted`<br/>- `deleted`<br/>- `static` |
| `dependants` | Qualified name or regex | - `ns1::ns2::ClassA`<br/>- `r: 'ns1::ns2::ClassA.+'` |
| `dependencies` | Qualified name or regex | - `ns1::ns2::ClassA`<br/>- `r: 'ns1::ns2::ClassA.+'` |
|-------------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------|
| `namespaces` | Qualified name or regex | `ns1::ns2::ClassA`, `r: '.*detail.*'` |
| `elements` | Qualified name or regex | `ns1::ns2::ClassA`,`r: '.*detail.*'` |
| `element_types` | Types of diagram elements | `class`, `enum`, `concept` |
| `paths` | File or dir path or glob pattern | `src/dir1`, `src/dir2/a.cpp`, `src/dir3/*.cpp` |
| `context` | Qualified name or regex | `ns1::ns2::ClassA`, `r: 'ns1::ns2::ClassA.+'` |
| `relationships` | Type of relationship | `inheritance`, `composition`, `aggregation`, `ownership`, `association`, `instantiation`, `friendship`, `dependency` |
| `subclasses` | Qualified name or regex | `ns1::ns2::ClassA`, `r: 'ns1::ns2::ClassA.+'` |
| `parents` | Qualified name or regex | `ns1::ns2::ClassA`, `r: 'ns1::ns2::ClassA.+'` |
| `specializations` | Qualified name or regex | `ns1::ns2::ClassA`, `r: 'ns1::ns2::ClassA.+'` |
| `access` | Method or member access scope | `public`, `protected`, `private` |
| `method_types` | Type of class method | `constructor`, `destructor`, `assignment`, `operator`, `defaulted`, `deleted`, `static` |
| `dependants` | Qualified name or regex | `ns1::ns2::ClassA`, `r: 'ns1::ns2::ClassA.+'` |
| `dependencies` | Qualified name or regex | `ns1::ns2::ClassA`, `r: 'ns1::ns2::ClassA.+'` |
The following filters are available.
## `namespaces` _[string or regex]_
## namespaces
Allows to include or exclude entities from specific namespaces.
## `elements` _[string or regex]_
## elements
Allows to directly include or exclude specific entities from the diagrams, for instance to exclude a specific class
from an included namespace:
@@ -91,7 +91,7 @@ from an included namespace:
- ns1::ns2::MyClass
```
## `element_types`
## element_types
Allows to include or exclude elements of specific type from the diagram, for instance
to remove all enums from a diagram add the following:
@@ -102,7 +102,7 @@ to remove all enums from a diagram add the following:
- enum
```
## `paths` _[string or glob]_
## paths
This filter allows to include or exclude from the diagram elements declared
in specific files.
@@ -122,7 +122,7 @@ diagrams:
Currently, this filter does not allow any globbing or wildcards, however
paths to directories can be specified.
## `context` _[string or regex]_
## context
This filter allows to limit the diagram elements only to classes which are in direct relationship (of any kind) with
the specified class:
@@ -134,7 +134,7 @@ the specified class:
```
## `relationships`
## relationships
This filter allows to include or exclude specific types of relationships from the diagram, for instance to only
include inheritance and template specialization/instantiation relationships add the following to the diagram:
@@ -156,19 +156,19 @@ The following relationships can be used in this filter:
* friendship
* dependency
## `subclasses` _[string or regex]_
## subclasses
This filter allows to include or exclude all subclasses of a given class in the diagram.
## `parents` _[string or regex]_
## parents
This filter allows to include or exclude all parents (base classes) of a given class in the diagram.
## `specializations` _[string or regex]_
## specializations
This filter allows to include or exclude specializations and instantiations of a specific template from the diagram.
## `access`
## access
This filter allows to include or exclude class methods and members based on their access scope, allowed values ar:
@@ -176,7 +176,7 @@ This filter allows to include or exclude class methods and members based on thei
* `protected`
* `private`
## `method_types`
## method_types
This filter allows to include or exclude various method types from the class diagram, allowed values ar:
* constructor
@@ -190,7 +190,7 @@ This filter allows to include or exclude various method types from the class dia
This filter is independent of the `access` filter, which controls which methods
are included based on access scope (e.g. `public`).
## `dependants` and `dependencies` _[string or regex]_
## dependants and dependencies
These filters allow to specify that only dependants or dependencies of a given class should be included in the diagram.
This can be useful for analyzing what classes in your project depend on some other class, which could have impact for

View File

@@ -1,4 +1,4 @@
/**
/*
* src/options/cli_handler.h
*
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
@@ -25,9 +25,21 @@
#include <optional>
namespace clanguml::cli {
/**
* This enum represents possible exit states of the command line parser.
*/
enum class cli_flow_t {
kExit, /*!< The application should exit (e.g. `-h`) */
kError, /*!< The options or configuration file were invalid */
kContinue /*!< Continue with processing diagrams */
};
enum class cli_flow_t { kExit, kError, kContinue };
/**
* @brief Command line options handler
*
* This class is responsible for handling the command line options
* and executing required actions.
*/
class cli_handler {
public:
cli_handler(std::ostream &ostr = std::cout,
@@ -37,45 +49,55 @@ public:
/**
* Main CLI handling method.
*
* @embed{cli_handle_options_sequence.svg}
*
* @param argc
* @param argv
* @return
* @return Command line handler state
*/
cli_flow_t handle_options(int argc, const char **argv);
/**
* Print the program version and basic information
*
* @return Command line handler state
*/
cli_flow_t print_version();
/**
* Print list of diagrams available in the configuration file
*
* @return Command line handler state
*/
cli_flow_t print_diagrams_list();
/**
* Print list of available diagram templates, including their names
* and types.
*
* @return Command line handler state
*/
cli_flow_t print_diagram_templates();
/**
* Print definition of a specific diagram template.
*
* @param template_name
* @return
* @param template_name Name of the diagram template
* @return Command line handler state
*/
cli_flow_t print_diagram_template(const std::string &template_name);
/**
* Print effective config after loading and setting default values.
*
* @return Command line handler state
*/
cli_flow_t print_config();
/**
* Generate sample configuration file and exit.
*
* @return 0 on success or error code
* @return Command line handler state
*/
cli_flow_t create_config_file();
@@ -85,7 +107,7 @@ public:
* @param type Type of the sample diagram to add
* @param config_file_path Path to the config file
* @param name Name of the new diagram
* @return 0 on success or error code
* @return Command line handler state
*/
cli_flow_t add_config_diagram(clanguml::common::model::diagram_t type,
const std::string &config_file_path, const std::string &name);
@@ -96,7 +118,7 @@ public:
* @param config_file_path
* @param template_name
* @param template_variables
* @return
* @return Command line handler state
*/
cli_flow_t add_config_diagram_from_template(
const std::string &config_file_path, const std::string &template_name,
@@ -144,14 +166,39 @@ public:
clanguml::config::config config;
private:
/**
* This method parses the command line options using CLI11 library.
*
* @param argc
* @param argv
* @return Command line handler state
*/
cli_flow_t parse(int argc, const char **argv);
/**
* Handle command line options before parsing the configuration file
*
* @return Command line handler state
*/
cli_flow_t handle_pre_config_options();
/**
* Load configuration file from file or stdin
*
* @return Command line handler state
*/
cli_flow_t load_config();
/**
* Handle command line options before parsing the configuration file
*
* @return Command line handler state
*/
cli_flow_t handle_post_config_options();
/**
* Setup spdlog library depending on provided command line options
*/
void setup_logging();
std::ostream &ostr_;

View File

@@ -35,16 +35,18 @@ class NamespaceDecl;
namespace clanguml::common {
/**
* @brief Convert @link clang::AccessSpecifier to @link model::access_t
* @brief Convert `clang::AccessSpecifier` to @see clanguml::model::access_t
*
* @param access_specifier Clang member access specifier
* @return Enum value of @link model::access_t
* @return Enum value of @see clanguml::model::access_t
*/
model::access_t access_specifier_to_access_t(
clang::AccessSpecifier access_specifier);
/**
* @brief Generate full qualified name for @link clang::TagDecl instance
* @brief Generate full qualified name for
* [clang::TagDecl](https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html)
* instance
*
* @param declaration Input declaration
* @return String representation including any templates, parameters and
@@ -52,6 +54,16 @@ model::access_t access_specifier_to_access_t(
*/
std::string get_tag_name(const clang::TagDecl &declaration);
/**
* @brief Get qualified name of some Clang declaration
*
* This template is convenient for getting qualified name of various types of
* clang declarations.
*
* @tparam T Type of Clang's declaration, e.g. `clang::TagDecl`
* @param declaration Reference to a clang declaration
* @return Fully qualified name
*/
template <typename T> std::string get_qualified_name(const T &declaration)
{
auto qualified_name = declaration.getQualifiedNameAsString();
@@ -70,8 +82,20 @@ template <typename T> std::string get_qualified_name(const T &declaration)
return qualified_name;
}
/**
* Get namespace of a specific `clang::TagDecl`
*
* @param declaration Reference to clang::TagDecl
* @return Namespace instance
*/
model::namespace_ get_tag_namespace(const clang::TagDecl &declaration);
/**
* Get namespace of a specific `clang::TemplateDecl`
*
* @param declaration Reference to clang::TemplateDecl
* @return Namespace instance
*/
model::namespace_ get_template_namespace(
const clang::TemplateDecl &declaration);
@@ -94,12 +118,35 @@ std::string to_string(const clang::TypeConstraint *tc);
std::string to_string(const clang::TemplateName &templ);
/**
* @brief Get raw text of specific source range
*
* @param range Source range
* @param sm Source manager reference
* @return Raw source text
*/
std::string get_source_text_raw(
clang::SourceRange range, const clang::SourceManager &sm);
/**
* @brief Get printable range of text of specific source range
*
* @param range Source range
* @param sm Source manager reference
* @return Printable source text
*/
std::string get_source_text(
clang::SourceRange range, const clang::SourceManager &sm);
/**
* @brief Extract template depth and index
*
* This function extracts template depth and index values from Clang's
* `type-parameter-` names.
*
* @param type_parameter Clang's type parameter string
* @return (depth, index, qualifier)
*/
std::tuple<unsigned int, unsigned int, std::string>
extract_template_parameter_index(const std::string &type_parameter);
@@ -115,17 +162,14 @@ extract_template_parameter_index(const std::string &type_parameter);
*/
bool is_subexpr_of(const clang::Stmt *parent_stmt, const clang::Stmt *sub_stmt);
/**
* @brief Forward template for convertions to ID from various entities
/** @defgroup to_id Forward template for convertions to ID from various entities
*
* These methods provide the main mechanism for generating globally unique
* identifiers for all elements in the diagrams. The identifiers must be unique
* between different translation units in order for element relationships to
* be properly rendered in diagrams.
*
* @tparam T Type of entity for which ID should be computed
* @param declaration Element (e.g. declaration) for which the ID is needed
* @return Unique ID
* @{
*/
template <typename T> id_t to_id(const T &declaration);
@@ -148,10 +192,25 @@ template <> id_t to_id(const clang::EnumType &type);
template <> id_t to_id(const clang::TemplateSpecializationType &type);
template <> id_t to_id(const std::filesystem::path &type);
/** @} */ // end of to_id
/**
* @brief Split qualified name to namespace and name
*
* @param full_name Fully qualified element name
* @return (namespace, name)
*/
std::pair<common::model::namespace_, std::string> split_ns(
const std::string &full_name);
/**
* @brief Parse unexposed (available as string) template params
*
* @param params String parameters as provided by Clang
* @param ns_resolve Namespace resolver function
* @param depth Current depth in the template specification
* @return Parsed template parameter
*/
std::vector<common::model::template_parameter> parse_unexposed_template_params(
const std::string &params,
const std::function<std::string(const std::string &)> &ns_resolve,
@@ -191,6 +250,17 @@ bool is_type_token(const std::string &t);
clang::QualType dereference(clang::QualType type);
/**
* @brief Extract type context and return raw type
*
* This function removes the context for a type, for example for:
* `std::string const&`
* it will return
* `(std::string, [const&])`
*
* @param type Type to process
* @return (type, [qualifiers])
*/
std::pair<clang::QualType, std::deque<common::model::context>>
consume_type_context(clang::QualType type);

View File

@@ -38,6 +38,16 @@ class compilation_database_error : public std::runtime_error {
using std::runtime_error::runtime_error;
};
/**
* @brief Custom compilation database class
*
* This class provides custom specialization of Clang's
* [CompilationDatabase](https://clang.llvm.org/doxygen/classclang_1_1tooling_1_1CompilationDatabase.html),
* which provides the possibility of adjusting the compilation flags after
* they have been loaded from the `compile_commands.json` file.
*
* @embed{compilation_database_context_class.svg}
*/
class compilation_database : public clang::tooling::CompilationDatabase {
public:
compilation_database(
@@ -46,19 +56,52 @@ public:
~compilation_database() override = default;
/**
* Loads the compilation database from directory specified on command
* line or in the configuration file.
*
* @param cfg Reference to config instance
* @return Instance of compilation_database.
*/
static std::unique_ptr<compilation_database> auto_detect_from_directory(
const clanguml::config::config &cfg);
/**
* Retrieves and adjusts compilation commands from the database, for
* a given translation unit.
*
* @return List of adjusted compile commands.
*/
std::vector<clang::tooling::CompileCommand> getCompileCommands(
clang::StringRef FilePath) const override;
/**
* Returns all files in the database.
*
* @return List of all files in compilation database.
*/
std::vector<std::string> getAllFiles() const override;
/**
* Retrieves and adjusts all compilation commands from the database.
*
* @return List of adjusted compile commands.
*/
std::vector<clang::tooling::CompileCommand>
getAllCompileCommands() const override;
/**
* Returns reference to clanguml's config instance.
*
* @return Reference to config instance.
*/
const clanguml::config::config &config() const;
/**
* Returns reference to CompilationDatabase as was loaded from file.
*
* @return Reference to CompilationDatabase.
*/
const clang::tooling::CompilationDatabase &base() const;
std::string guess_language_from_filename(const std::string &filename) const;
@@ -67,11 +110,17 @@ private:
void adjust_compilation_database(
std::vector<clang::tooling::CompileCommand> &commands) const;
// Actual instance of the compilation database is stored in here
// The inheritance is just to keep the interface
/*!
* Pointer to the Clang's original compilation database.
*
* Actual instance of the compilation database is stored in here.
* The inheritance is just to keep the interface.
*/
std::unique_ptr<clang::tooling::CompilationDatabase> base_;
// Reference to the clang-uml config
/*!
* Reference to the instance of clanguml config.
*/
const clanguml::config::config &config_;
};

View File

@@ -184,14 +184,13 @@ void generate_diagrams(const std::vector<std::string> &diagram_names,
continue;
}
futs.emplace_back(generator_executor.add(
[&od, &generators, &name = name, &diagram = diagram, &indicator,
db = std::ref(*db), translation_units = valid_translation_units,
auto generator = [&od, &generators, &name = name, &diagram = diagram,
&indicator, db = std::ref(*db),
translation_units = valid_translation_units,
verbose]() mutable {
try {
if (indicator)
indicator->add_progress_bar(name,
translation_units.size(),
indicator->add_progress_bar(name, translation_units.size(),
diagram_type_to_color(diagram->type()));
generate_diagram(od, name, diagram, db, translation_units,
@@ -209,7 +208,9 @@ void generate_diagrams(const std::vector<std::string> &diagram_names,
LOG_ERROR(e.what());
}
}));
};
futs.emplace_back(generator_executor.add(std::move(generator)));
}
for (auto &fut : futs) {

View File

@@ -49,8 +49,13 @@
namespace clanguml::common::generators {
// template trait for selecting diagram model type based on diagram config
// type
/** @defgroup diagram_model_t Diagram model selector
*
* Template traits for selecting diagram model type based on diagram config
* type
*
* @{
*/
template <typename DiagramConfig> struct diagram_model_t;
template <> struct diagram_model_t<clanguml::config::class_diagram> {
using type = clanguml::class_diagram::model::diagram;
@@ -64,9 +69,15 @@ template <> struct diagram_model_t<clanguml::config::package_diagram> {
template <> struct diagram_model_t<clanguml::config::include_diagram> {
using type = clanguml::include_diagram::model::diagram;
};
/** @} */
// template trait for selecting diagram visitor type based on diagram config
// type
/** @defgroup diagram_visitor_t Diagram model selector
*
* Template traits for selecting diagram visitor type based on diagram config
* type
*
* @{
*/
template <typename DiagramConfig> struct diagram_visitor_t;
template <> struct diagram_visitor_t<clanguml::config::class_diagram> {
using type = clanguml::class_diagram::visitor::translation_unit_visitor;
@@ -80,16 +91,29 @@ template <> struct diagram_visitor_t<clanguml::config::package_diagram> {
template <> struct diagram_visitor_t<clanguml::config::include_diagram> {
using type = clanguml::include_diagram::visitor::translation_unit_visitor;
};
/** @} */
// template trait for selecting diagram generator type based on diagram config
// type
/** @defgroup diagram_generator_tag Diagram model tags
*
* Tags to determine the generator output file extension
*
* @{
*/
struct plantuml_generator_tag {
inline static const std::string extension = "puml";
};
struct json_generator_tag {
inline static const std::string extension = "json";
};
/** @} */
/** @defgroup diagram_generator_t Diagram generator selector
*
* Tags to determine the generator type based on diagram config type
* and output format
*
* @{
*/
template <typename DiagramConfig, typename GeneratorType>
struct diagram_generator_t;
template <>
@@ -132,14 +156,40 @@ struct diagram_generator_t<clanguml::config::include_diagram,
json_generator_tag> {
using type = clanguml::include_diagram::generators::json::generator;
};
/** @} */
template <typename DiagramConfig> struct diagram_visitor_t;
/**
* @brief Assign translation units to diagrams
*
* This function assigns for each diagram to be generated the list of
* translation units based on it's `glob` pattern if any.
*
* If `diagram_names` is empty, this function processes all diagrams in
* `config`.
*
* @param diagram_names List of diagram names, applies to all if empty
* @param config Reference to config instance
* @param compilation_database_files List of files found in compilation database
* @param translation_units_map Resulting translation units map is stored here
*/
void find_translation_units_for_diagrams(
const std::vector<std::string> &diagram_names,
clanguml::config::config &config,
const std::vector<std::string> &compilation_database_files,
std::map<std::string, std::vector<std::string>> &translation_units_map);
/**
* @brief Specialization of
* [clang::ASTConsumer](https://clang.llvm.org/doxygen/classclang_1_1ASTConsumer.html)
*
* This class provides overriden HandleTranslationUnit() method, which
* calls a translation_unit_visitor for a specific diagram type on
* each translation unit assigned to the diagram.
*
* @tparam DiagramModel Type of diagram_model
* @tparam DiagramConfig Type of diagram_config
* @tparam TranslationUnitVisitor Type of translation_unit_visitor
*/
template <typename DiagramModel, typename DiagramConfig,
typename TranslationUnitVisitor>
class diagram_ast_consumer : public clang::ASTConsumer {
@@ -161,6 +211,17 @@ public:
}
};
/**
* @brief Specialization of
* [clang::ASTFrontendAction](https://clang.llvm.org/doxygen/classclang_1_1ASTFrontendAction.html)
*
* This class overrides the BeginSourceFileAction() and CreateASTConsumer()
* methods to create and setup an appropriate diagram_ast_consumer instance.
*
* @tparam DiagramModel Type of diagram_model
* @tparam DiagramConfig Type of diagram_config
* @tparam TranslationUnitVisitor Type of translation_unit_visitor
*/
template <typename DiagramModel, typename DiagramConfig,
typename DiagramVisitor>
class diagram_fronted_action : public clang::ASTFrontendAction {
@@ -193,6 +254,8 @@ protected:
{
LOG_DBG("Visiting source file: {}", getCurrentFile().str());
// Update progress indicators, if enabled, on each translation
// unit
if (progress_)
progress_();
@@ -216,6 +279,17 @@ private:
std::function<void()> progress_;
};
/**
* @brief Specialization of
* [clang::ASTFrontendAction](https://clang.llvm.org/doxygen/classclang_1_1tooling_1_1FrontendActionFactory.html)
*
* This class overrides the create() method in order to create an instance
* of diagram_frontend_action of appropriate type.
*
* @tparam DiagramModel Type of diagram_model
* @tparam DiagramConfig Type of diagram_config
* @tparam TranslationUnitVisitor Type of translation_unit_visitor
*/
template <typename DiagramModel, typename DiagramConfig,
typename DiagramVisitor>
class diagram_action_visitor_factory
@@ -241,6 +315,19 @@ private:
std::function<void()> progress_;
};
/**
* @brief Specialization of
* [clang::ASTFrontendAction](https://clang.llvm.org/doxygen/classclang_1_1tooling_1_1FrontendActionFactory.html)
*
* This is the entry point function to initiate AST frontend action for a
* specific diagram.
*
* @embed{diagram_generate_generic_sequence.svg}
*
* @tparam DiagramModel Type of diagram_model
* @tparam DiagramConfig Type of diagram_config
* @tparam TranslationUnitVisitor Type of translation_unit_visitor
*/
template <typename DiagramModel, typename DiagramConfig,
typename DiagramVisitor>
std::unique_ptr<DiagramModel> generate(const common::compilation_database &db,
@@ -275,6 +362,17 @@ std::unique_ptr<DiagramModel> generate(const common::compilation_database &db,
return diagram;
}
/**
* @brief Generate a single diagram
*
* @param od Output directory path
* @param name Name of the diagram
* @param diagram Effective diagram configuration
* @param db Reference to compilation database
* @param translation_units List of translation units for the diagram
* @param generators List of generator types to be used for the diagram
* @param verbose Log level
*/
void generate_diagram(const std::string &od, const std::string &name,
std::shared_ptr<clanguml::config::diagram> diagram,
const common::compilation_database &db,
@@ -282,6 +380,19 @@ void generate_diagram(const std::string &od, const std::string &name,
const std::vector<clanguml::common::generator_type_t> &generators,
bool verbose);
/**
* @brief Generate diagrams
*
* @param diagram_names List of diagram names to generate
* @param config Reference to config instance
* @param od Path to output directory
* @param db Reference to compilation database
* @param verbose Log level
* @param thread_count Number of diagrams to be generated in parallel
* @param progress Whether progress indicators should be displayed
* @param generators List of generator types to use for each diagram
* @param translation_units_map Map of translation units for each file
*/
void generate_diagrams(const std::vector<std::string> &diagram_names,
clanguml::config::config &config, const std::string &od,
const common::compilation_database_ptr &db, int verbose,
@@ -290,6 +401,12 @@ void generate_diagrams(const std::vector<std::string> &diagram_names,
const std::map<std::string, std::vector<std::string>>
&translation_units_map);
/**
* @brief Return indicators progress bar color for diagram type
*
* @param diagram_type Diagram type
* @return Progress bar color
*/
indicators::Color diagram_type_to_color(model::diagram_t diagram_type);
} // namespace clanguml::common::generators

View File

@@ -334,7 +334,7 @@ void generator<C, D>::generate_plantuml_directives(
// Render the directive with template engine first
std::string directive{env().render(std::string_view{d}, context())};
// Now search for alias @A() directives in the text
// Now search for alias `@A()` directives in the text
// (this is deprecated)
std::tuple<std::string, size_t, size_t> alias_match;
while (util::find_element_alias(directive, alias_match)) {

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:

View File

@@ -31,10 +31,32 @@ namespace clanguml::common {
using id_t = int64_t;
enum class generator_type_t { plantuml, json };
/**
* Type of output diagram format generator.
*/
enum class generator_type_t {
plantuml, /*!< Diagrams will be gnerated in PlantUML format */
json /*!< Diagrams will be generated in JSON format */
};
std::string to_string(const std::string &s);
/**
* @brief Simple optional reference type.
*
* This class template provides a convenient way around the std::optional
* limitation of not allowing references. This is useful for storing
* references to diagram elements in various `views`, and writing methods
* which return can return an empty value if the diagram does not contain
* something.
*
* This is not an owning type - it will not accept an rvalue - the actual
* value must be stored somewhere else as lvalue or some kind of smart pointer.
*
* @note Probably unsafe - do not use at home.
*
* @tparam T Type of reference
*/
template <typename T> class optional_ref {
public:
using optional_type = T;
@@ -159,6 +181,13 @@ using reference_set = std::unordered_set<std::reference_wrapper<T>>;
* @brief Wrapper around std::regex, which contains original pattern
*/
struct regex {
/**
* @brief Constructor
*
* @param r Parsed regular expression
* @param p Raw regular expression pattern used for regenerating config and
* debugging
*/
regex(std::regex r, std::string p)
: regexp{std::move(r)}
, pattern{std::move(p)}
@@ -170,18 +199,36 @@ struct regex {
return std::regex_match(v, regexp);
}
std::regex regexp;
std::string pattern;
std::regex regexp; /*!< Parsed regular expression */
std::string pattern; /*!< Original regular expression pattern */
};
/**
* @brief Convenience class for configuration options with regex support
*
* This template class provides a convenient way of handling configuraiton
* options, which can be either some basic type like std::string or regex.
*
* @tparam T Type of alternative to regex (e.g. std::string)
*/
template <typename T> struct or_regex {
or_regex() = default;
/**
* @brief Constructor from alternative type
*/
or_regex(T v)
: value_{std::move(v)}
{
}
/**
* @brief Constructor from regex
*
* @param r Parsed regular expression
* @param p Raw regular expression pattern used for regenerating config and
* debugging
*/
or_regex(std::regex r, std::string p)
: value_{regex{std::move(r), std::move(p)}}
{

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,10 @@
namespace clanguml {
namespace config {
/**
* @brief Return YAML with predefined diagram templates
* @return YAML definition of predefined diagram templates
*/
const std::string &get_predefined_diagram_templates();
} // namespace config

View File

@@ -24,9 +24,28 @@ namespace clanguml {
namespace config {
template <typename T> void append_value(T &l, const T &r) { l = r; }
/**
* Possible option inheritance methods from top level to diagram level.
*/
enum class option_inherit_mode {
kOverride, /*!< Override entire options */
kAppend /*!< Append to list options */
};
enum class option_inherit_mode { kOverride, kAppend };
/**
* @brief Generic configuration option type
*
* This class template represents a single configuration option, which can
* be either a simple type such as bool or std::string or can be a list
* or dictionary.
*
* If the option is constructed only from default value, it's `is_declared`
* member is false, so we can deduce whether user provided the option or not.
*
* For each option type, there has to be defined a YAML decoder and emitter.
*
* @tparam T The type of the configuration option
*/
template <typename T> struct option {
option(std::string name_,
option_inherit_mode im = option_inherit_mode::kOverride)
@@ -44,6 +63,11 @@ template <typename T> struct option {
{
}
/**
* @brief Set the option value
*
* @param v Option value
*/
void set(const T &v)
{
value = v;
@@ -51,6 +75,13 @@ template <typename T> struct option {
has_value = true;
}
/**
* @brief Override option value
*
* This method overrides the option depending on it's inheritance type.
*
* @param o New option value
*/
void override(const option<T> &o)
{
if (o.is_declared && inheritance_mode == option_inherit_mode::kAppend) {
@@ -73,10 +104,22 @@ template <typename T> struct option {
operator bool() const { return has_value; }
/*! Option name, it is also the YAML key in the configuration file */
std::string name;
/*! Option value */
T value;
/*! Whether or not the value was provided by the user or default */
bool is_declared{false};
/*!
* Whether the option has value, if the option has no default value
* and wasn't provided in the config this is set to `false`.
*/
bool has_value{false};
/*! The inheritance mode for this option */
option_inherit_mode inheritance_mode;
};
} // namespace config

View File

@@ -1809,6 +1809,10 @@ void translation_unit_visitor::process_template_specialization_argument(
// Otherwise just set the name for the template argument to
// whatever clang says
if (template_params.size() > argument_index &&
template_params[argument_index].type())
argument.set_type(type_name);
else
argument.set_name(type_name);
}
else

View File

@@ -0,0 +1,11 @@
type: class
include_relations_also_as_members: true
generate_packages: false
glob:
- src/common/compilation_database.cc
include:
namespaces:
- clanguml
- clang::tooling
context:
- clanguml::common::compilation_database

View File

@@ -0,0 +1,14 @@
type: class
include_relations_also_as_members: true
glob:
- src/config/config.cc
include:
namespaces:
- clanguml::config
context:
- clanguml::config::config
using_namespace:
- clanguml::config
plantuml:
before:
- 'title clanguml::config::config context diagram'

View File

@@ -0,0 +1,20 @@
type: class
include_relations_also_as_members: true
generate_packages: true
glob:
- src/common/model/*.cc
- src/class_diagram/model/*.cc
- src/sequence_diagram/model/*.cc
- src/include_diagram/model/*.cc
- src/package_diagram/model/*.cc
include:
namespaces:
- clanguml
subclasses:
- clanguml::common::model::decorated_element
relationships:
- inheritance
exclude:
access: [public, protected, private]
using_namespace:
- clanguml

View File

@@ -0,0 +1,19 @@
type: class
include_relations_also_as_members: true
generate_packages: true
glob:
- src/config/config.cc
include:
namespaces:
- clanguml
subclasses:
- clanguml::config::diagram
parents:
- clanguml::config::diagram
exclude:
access: [public, protected, private]
using_namespace:
- clanguml
plantuml:
before:
- 'title clanguml::config::diagram class hierarchy'

View File

@@ -0,0 +1,16 @@
type: class
include_relations_also_as_members: true
generate_packages: true
glob:
- src/common/model/diagram_filter.cc
- src/common/model/diagram.cc
include:
namespaces:
- clanguml
context:
- clanguml::common::model::diagram_filter
exclude:
elements:
- clanguml::common::model::path
using_namespace:
- clanguml

View File

@@ -0,0 +1,21 @@
type: class
include_relations_also_as_members: true
generate_packages: true
generate_method_arguments: none
glob:
- src/common/model/diagram.cc
- src/class_diagram/model/diagram.cc
- src/sequence_diagram/model/diagram.cc
- src/include_diagram/model/diagram.cc
- src/package_diagram/model/diagram.cc
include:
namespaces:
- clanguml
subclasses:
- clanguml::common::model::diagram
relationships:
- inheritance
exclude:
access: [public, protected, private]
using_namespace:
- clanguml

View File

@@ -0,0 +1,17 @@
type: class
include_relations_also_as_members: true
generate_packages: true
glob:
- src/common/model/diagram_filter.cc
include:
namespaces:
- clanguml
subclasses:
- clanguml::common::model::filter_visitor
exclude:
access: [public, protected, private]
using_namespace:
- clanguml
plantuml:
before:
- left to right direction

View File

@@ -0,0 +1,15 @@
type: class
include_relations_also_as_members: true
glob:
- src/config/config.cc
include:
namespaces:
- clanguml::config
context:
- clanguml::config::inheritable_diagram_options
using_namespace:
- clanguml::config
plantuml:
before:
- title clanguml::config::config context diagram
- left to right direction

View File

@@ -0,0 +1,13 @@
type: class
include_relations_also_as_members: true
glob:
- src/common/model/*.cc
include:
namespaces:
- clanguml
subclasses:
- r: ".*nested_trait.*"
exclude:
access: [private, protected, public]
using_namespace:
- clanguml

View File

@@ -0,0 +1,13 @@
type: class
include_relations_also_as_members: true
glob:
- src/common/model/package.cc
include:
namespaces:
- clanguml
parents:
- clanguml::common::model::package
exclude:
access: [private, protected, public]
using_namespace:
- clanguml

View File

@@ -0,0 +1,20 @@
type: sequence
combine_free_functions_into_file_participants: true
generate_method_arguments: none
glob:
- src/cli/cli_handler.cc
- src/config/config.cc
- src/config/yaml_decoders.cc
include:
namespaces:
- clanguml
- YAML
exclude:
elements:
- r: "clanguml::config::option.*"
paths:
- src/util/util.h
using_namespace:
- clanguml
start_from:
- function: "clanguml::cli::cli_handler::handle_options(int,const char **)"

View File

@@ -0,0 +1,19 @@
type: sequence
combine_free_functions_into_file_participants: true
generate_method_arguments: none
glob:
- src/common/generators/generators.cc
using_namespace:
- clanguml
include:
namespaces:
- clang
- clanguml::common::generators
exclude:
namespaces:
- clanguml::model::tvl
- clanguml::decorators
paths:
- src/common/model/source_location.h
start_from:
- function: "clanguml::common::generators::generate_diagram(const std::string &,const std::string &,std::shared_ptr<clanguml::config::diagram>,const common::compilation_database &,const std::vector<std::string> &,const std::vector<clanguml::common::generator_type_t> &,bool,std::function<void ()> &&)"

View File

@@ -0,0 +1,19 @@
type: sequence
combine_free_functions_into_file_participants: true
generate_method_arguments: none
glob:
- src/config/config.cc
- src/config/yaml_decoders.cc
include:
namespaces:
- clanguml
- YAML
exclude:
elements:
- r: "clanguml::config::option.*"
paths:
- src/util/util.h
using_namespace:
- clanguml
start_from:
- function: "clanguml::config::load(const std::string &,std::optional<bool>,std::optional<bool>)"