Merge pull request #163 from bkryza/add-doxygen-config
Add doxygen config
This commit is contained in:
85
.clang-uml
85
.clang-uml
@@ -1,32 +1,79 @@
|
||||
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 }}
|
||||
link: "{% if existsIn(element, \"doxygen_link\") %}{{ element.doxygen_link }}{% endif %}"
|
||||
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
|
||||
architecture_visitors_class:
|
||||
include!: uml/class/architecture_visitors_class.yml
|
||||
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
|
||||
stylable_element_hierarchy_class:
|
||||
include!: uml/class/stylable_element_hierarchy_class.yml
|
||||
source_location_hierarchy_class:
|
||||
include!: uml/class/source_location_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
|
||||
source_file_hierarchy_class:
|
||||
include!: uml/class/source_file_hierarchy_class.yml
|
||||
template_trait_hierarchy_class:
|
||||
include!: uml/class/template_trait_hierarchy_class.yml
|
||||
comment_visitor_hierarchy_class:
|
||||
include!: uml/class/comment_visitor_hierarchy_class.yml
|
||||
decorators_class:
|
||||
include!: uml/decorators_class_diagram.yml
|
||||
include!: uml/class/decorators_class.yml
|
||||
relationship_context_class:
|
||||
include!: uml/class/relationship_context_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 diagrams
|
||||
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
|
||||
architecture_package:
|
||||
include!: uml/package/architecture_package.yml
|
||||
# Include diagrams
|
||||
include_graph:
|
||||
include!: uml/include_diagram.yml
|
||||
include!: uml/include/include.yml
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -22,6 +22,11 @@ bin/
|
||||
/debug_tidy
|
||||
/.cache
|
||||
docs/diagrams
|
||||
docs/doxygen/html
|
||||
docs/doxygen/xml
|
||||
docs/doxygen/latex
|
||||
docs/contributing.md
|
||||
docs/changelog.md
|
||||
|
||||
coverage*.info
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Contributing to `clang-uml`
|
||||
# Contributing to clang-uml
|
||||
|
||||
Thanks for taking interest in `clang-uml`!
|
||||
|
||||
> Please, make sure you're ok with [Code of conduct](./CODE_OF_CONDUCT.md) and [LICENSE](./LICENSE.md)
|
||||
> Please, make sure you're ok with
|
||||
> [Code of conduct](./CODE_OF_CONDUCT.md)
|
||||
> and [LICENSE](./LICENSE.md)
|
||||
|
||||
|
||||
## If you found a bug
|
||||
@@ -18,12 +20,12 @@ Thanks for taking interest in `clang-uml`!
|
||||
the C++ code which triggers the issue, and in `tests/t00050/test_case.h` write the test checks.
|
||||
The test case must be also added manually to `tests/test_cases.cc`:
|
||||
```cpp
|
||||
...
|
||||
// ...
|
||||
#include "t00047/test_case.h"
|
||||
#include "t00048/test_case.h"
|
||||
#include "t00049/test_case.h"
|
||||
#include "t00050/test_case.h"
|
||||
...
|
||||
#include "t00050/test_case.h" // <<<
|
||||
// ...
|
||||
```
|
||||
|
||||
Finally, create an issue with a link to your branch with the new test case.
|
||||
@@ -82,8 +84,8 @@ Thanks for taking interest in `clang-uml`!
|
||||
the feature to ensure we're on the same page as to its purpose and possible implementation
|
||||
* Next, implement the feature, please try to adapt to the overall code style:
|
||||
* 80-character line width
|
||||
* snakes over camels
|
||||
* use `make format` before submitting PR to ensure consistent formatting
|
||||
* snakes not camels
|
||||
* use `make format` before submitting PR to ensure consistent formatting (requires Docker)
|
||||
* use `make tidy` to check if your code doesn't introduce any `clang-tidy` warnings
|
||||
* Add test case (or multiple test cases), which cover the new feature
|
||||
* Finally, create a pull request!
|
||||
|
||||
9
Makefile
9
Makefile
@@ -138,6 +138,15 @@ iwyu_fixes: debug
|
||||
docs:
|
||||
make -C docs toc
|
||||
|
||||
.PHONY: doxygen
|
||||
doxygen: docs
|
||||
cp CONTRIBUTING.md docs/contributing.md
|
||||
cp CHANGELOG.md docs/changelog.md
|
||||
cp docs/diagrams/*.svg docs/doxygen/html/
|
||||
mkdir -p docs/doxygen/html/test_cases
|
||||
cp docs/test_cases/*.svg docs/doxygen/html/test_cases/
|
||||
../doxygen/_build/bin/doxygen
|
||||
|
||||
.PHONY: fedora/%
|
||||
fedora/%:
|
||||
mkdir -p packaging/_BUILD/fedora/$*
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
[](https://codecov.io/gh/bkryza/clang-uml)
|
||||
[](https://github.com/bkryza/clang-uml/releases)
|
||||
[](https://github.com/bkryza/clang-uml/releases)
|
||||
[](https://clang-uml.github.io)
|
||||
|
||||
`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
|
||||
@@ -16,7 +17,7 @@ The diagrams can be generated in [PlantUML](https://plantuml.com) and JSON forma
|
||||
|
||||
`clang-uml` currently supports C++ up to version 17 with partial support for C++ 20.
|
||||
|
||||
Full documentation can be found [here](./docs/README.md).
|
||||
Full documentation can be found at [clang-uml.github.io](https://clang-uml.github.io).
|
||||
|
||||
To see what `clang-uml` can do, checkout the diagrams generated for unit
|
||||
test cases [here](./docs/test_cases.md) or examples in
|
||||
@@ -55,7 +56,7 @@ Main features supported so far include:
|
||||
* **Include graph diagram generation**
|
||||
* Show include graph for selected files - [_example_](docs/test_cases/t40001.md)
|
||||
|
||||
More comprehensive documentation can be found [here](./docs/README.md).
|
||||
More comprehensive documentation can be at [clang-uml.github.io](https://clang-uml.github.io).
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -441,6 +442,8 @@ This project relies on the following great tools:
|
||||
* [backward-cpp](https://github.com/bombela/backward-cpp) - stack trace pretty printer for C++
|
||||
* [yaml-cpp](https://github.com/jbeder/yaml-cpp) - YAML parser library for C++
|
||||
* [spdlog](https://github.com/gabime/spdlog) - Fast C++ logging library
|
||||
* [Doxygen](https://www.doxygen.nl/) - C++ documentation generator
|
||||
* [Doxygen Awesome](https://jothepro.github.io/doxygen-awesome-css) - Doxygen CSS style
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ UPDATE_TOC := markdown-toc --bullets "*" -i
|
||||
|
||||
.PHONY: toc
|
||||
toc:
|
||||
$(UPDATE_TOC) architecture.md
|
||||
$(UPDATE_TOC) class_diagrams.md
|
||||
$(UPDATE_TOC) comment_decorators.md
|
||||
$(UPDATE_TOC) common_options.md
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
@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.
|
||||
|
||||
Example sequence diagram generated using `clang-uml` from [this code](https://github.com/bkryza/clang-uml/blob/master/tests/t20029/t20029.cc):
|
||||

|
||||
|
||||
`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.
|
||||
|
||||
These pages provide both user and developer documentation.
|
||||
|
||||
* [Quick start](./quick_start.md)
|
||||
* [Installation](./installation.md)
|
||||
* Generating diagrams
|
||||
* **Generating diagrams**
|
||||
* [Common options](./common_options.md)
|
||||
* [Generator types](./generator_types.md)
|
||||
* [Class diagrams](./class_diagrams.md)
|
||||
@@ -18,3 +38,8 @@
|
||||
* [Doxygen integration](./doxygen_integration.md)
|
||||
* [Test cases documentation](./test_cases.md)
|
||||
* [Troubleshooting](./troubleshooting.md)
|
||||
* [Changelog](./changelog.md)
|
||||
* [License](./license.md)
|
||||
* **Development**
|
||||
* [Architecture](./architecture.md)
|
||||
* [Contributing](./contributing.md)
|
||||
|
||||
202
docs/architecture.md
Normal file
202
docs/architecture.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Architecture
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Configuration model](#configuration-model)
|
||||
* [Diagram model](#diagram-model)
|
||||
* [Common model](#common-model)
|
||||
* [Diagram filters](#diagram-filters)
|
||||
* [Translation unit visitors](#translation-unit-visitors)
|
||||
* [Diagram generators](#diagram-generators)
|
||||
* [Command line handler](#command-line-handler)
|
||||
* [Tests](#tests)
|
||||
* [Unit tests](#unit-tests)
|
||||
* [Test cases](#test-cases)
|
||||
* [Real code tests](#real-code-tests)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
This section presents general architecture and components of `clang-uml`.
|
||||
|
||||
> All diagrams below are generated by `clang-uml` and updated automatically.
|
||||
|
||||
## Overview
|
||||
|
||||
`clang-uml` is written in C++17 and
|
||||
uses [Clang LibTooling API](https://releases.llvm.org/16.0.0/tools/clang/docs/LibTooling.html)
|
||||
to traverse
|
||||
the AST (Abstract Syntax Tree) of the source code and extract any information
|
||||
relevant for a specified diagram.
|
||||
|
||||
The code is divided into several packages (namespaces), the main of them are:
|
||||
|
||||
- [`clanguml::config`](./namespaceclanguml_1_1config.html) - configuration
|
||||
handling
|
||||
- [`clanguml::common`](./namespaceclanguml_1_1common.html) - common interfaces
|
||||
- [`clanguml::class_diagram`](./namespaceclanguml_1_1class__diagram.html) -
|
||||
specializations for class diagrams
|
||||
- [`clanguml::sequence_diagram`](./namespaceclanguml_1_1sequence__diagram.html) -
|
||||
specializations for sequence diagrams
|
||||
- [`clanguml::include_diagram`](./namespaceclanguml_1_1include__diagram.html) -
|
||||
specializations for include diagrams
|
||||
- [`clanguml::package_diagram`](./namespaceclanguml_1_1package__diagram.html) -
|
||||
specializations for package diagrams
|
||||
|
||||

|
||||
|
||||
## Configuration model
|
||||
|
||||
The configuration model consists of classes representing the configuration
|
||||
specified in the YAML configuration files.
|
||||
|
||||
Depending on the option, it can either:
|
||||
|
||||
- be specified only at the top level of the configuration file
|
||||
- only in the specific diagram configuration
|
||||
- either of the above
|
||||
|
||||
The first group of options are stored in
|
||||
the [`config::config`](structclanguml_1_1config_1_1config.html) class.
|
||||
|
||||
The second group is stored in a specific diagram config subclass, e.g.
|
||||
[`config::sequence_diagram`](structclanguml_1_1config_1_1sequence__diagram.html)
|
||||
|
||||
The options in the last group are modeled in the
|
||||
[`config::inheritable_diagram_options`](./structclanguml_1_1config_1_1inheritable__diagram__options.html).
|
||||
|
||||

|
||||
|
||||
The YAML configuration file is parsed
|
||||
using [yaml-cpp](https://github.com/jbeder/yaml-cpp) library:
|
||||
|
||||

|
||||
|
||||
For each possible option type, there must an implementation of a
|
||||
YAML decoder - e.g.
|
||||
[`YAML::convert<filter>`](./structYAML_1_1convert_3_01filter_01_4.html)
|
||||
(for converting YAML nodes to configuration model classes)
|
||||
and a YAML emitter - e.g.
|
||||
[`operator<<`](./group__yaml__emitters.html#ga4c8bc075684b08daa379aef609bb6297)
|
||||
(for generating YAML from configuration model classes).
|
||||
|
||||
## Diagram model
|
||||
|
||||
The diagram model namespace is divided into the [`common`](#common-model) model
|
||||
namespace and 1 namespace for each supported diagram type.
|
||||
|
||||

|
||||
|
||||
### Common model
|
||||
|
||||
The [common diagram model namespace](./namespaceclanguml_1_1common_1_1model.html),
|
||||
provides a set of classes representing typical UML and C++ concepts such as
|
||||
diagram elements, packages, templates, and others which are shared by more than
|
||||
1 diagram type.
|
||||
|
||||

|
||||
|
||||
The diagram elements are composed into a hierarchy spanning all major
|
||||
namespaces,
|
||||
depending on whether the element is specific for a single diagram type (
|
||||
e.g. [`participant`](./structclanguml_1_1sequence__diagram_1_1model_1_1participant.html)),
|
||||
or whether it's common for several diagram types (
|
||||
e.g. [`package`](./classclanguml_1_1common_1_1model_1_1package.html)).
|
||||
|
||||
### Diagram filters
|
||||
|
||||
In order to ease the generation of diagrams, `clang-uml` has a (very) simple
|
||||
intermediate UML model, which covers only the features necessary for
|
||||
generation of the supported diagram types. The model can be extended if
|
||||
necessary to add new features.
|
||||
|
||||

|
||||
|
||||
## Translation unit visitors
|
||||
|
||||
The first stage in the diagram generation involves traversing the AST of
|
||||
each translation unit from the `compile_commands.json` compilation database,
|
||||
which matched at least one pattern specified in the `glob` pattern of the
|
||||
configuration file.
|
||||
|
||||
Each visitor is implemented in a subclass of
|
||||
[`translation_unit_visitor`](./classclanguml_1_1common_1_1visitor_1_1translation__unit__visitor.html),
|
||||
and must also implement relevant methods from Clang's
|
||||
[RecursiveASTVisitor](https://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html).
|
||||
|
||||

|
||||
|
||||
The output of the `translation_unit_visitor` for each diagram type is an
|
||||
intermediate diagram model, which is then passed to the relevant diagram
|
||||
generator.
|
||||
|
||||
## Diagram generators
|
||||
|
||||
Diagram generators convert the `clang-uml`'s internal UML model into actual
|
||||
diagram in one of the supported formats:
|
||||
|
||||
- PlantUML
|
||||
- JSON
|
||||
|
||||
Each diagram generator extends a common interface appropriate for the
|
||||
selected output format, i.e.:
|
||||
|
||||
- [PlantUML](classclanguml_1_1common_1_1generators_1_1plantuml_1_1generator.html)
|
||||
- [JSON](classclanguml_1_1common_1_1generators_1_1json_1_1generator.html)
|
||||
|
||||
and renders the output to a file. For each diagram type there is a separate
|
||||
generator for each supported output format.
|
||||
|
||||
## Command line handler
|
||||
|
||||
The [cli_handler](classclanguml_1_1cli_1_1cli__handler.html) is a command line
|
||||
handler class is a wrapper around [CLI11](https://github.com/CLIUtils/CLI11),
|
||||
and implements handlers for various actions, validates command line parameters
|
||||
and reports errors.
|
||||
|
||||
## Tests
|
||||
|
||||
### Unit tests
|
||||
|
||||
Basic set of units tests are stored in
|
||||
[tests/test_*.cc](https://github.com/bkryza/clang-uml/tree/master/tests)
|
||||
test files. The unit tests do not aim to cover the entire codebase, only
|
||||
specific algorithms or methods, which should behave as expected and if their
|
||||
errors can be difficult to diagnose when running the test cases on C++ code.
|
||||
|
||||
### Test cases
|
||||
|
||||
These tests are the main tests of `clang-uml`. Each test case tests one or
|
||||
more feature of a specific diagram type. Each of them has a separated directory
|
||||
in the `tests` directory and its own `.clang-uml` with diagram configuration
|
||||
as well as a `test_case.h` file which contains the tests assertions.
|
||||
|
||||
Any other sources in that directory are compiled and then used to generate the
|
||||
diagrams, whose contents should be then verified within `test_case.h`
|
||||
for correctness. All the sources should be wrapped within a namespace:
|
||||
`clanguml::`
|
||||
|
||||
These test directories are numbered in consecutive numbers using the following
|
||||
convention:
|
||||
- Start with a letter `t`
|
||||
- The first digit of the number is the diagram type:
|
||||
- `0` - class diagram
|
||||
- `2` - sequence diagram
|
||||
- `3` - package diagram
|
||||
- `4` - include diagram
|
||||
- `9` - other test cases
|
||||
- The rest of the name is the consecutive number of the test case
|
||||
|
||||
Each test case is also referenced in
|
||||
[test_cases.yaml](https://github.com/bkryza/clang-uml/blob/master/tests/test_cases.yaml)
|
||||
where it has assigned a title. That file is used to generate the [test cases
|
||||
documentation page](./md_docs_2test__cases.html).
|
||||
|
||||
### Real code tests
|
||||
|
||||
Each release is tested on a set of open-source C++ projects, to be sure that
|
||||
at least the new version does not crash or introduce some obvious regressions.
|
||||
|
||||
The tests are stored in a separate
|
||||
repository: [clang-uml-examples](https://github.com/bkryza/clang-uml-examples).
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
* [`note`](#note)
|
||||
* [`skip` and `skiprelationship`](#skip-and-skiprelationship)
|
||||
* [`composition`, `association` and `aggregation`](#composition-association-and-aggregation)
|
||||
* [`style`](#style)
|
||||
* ['note'](#note)
|
||||
* ['skip' and 'skiprelationship'](#skip-and-skiprelationship)
|
||||
* ['composition', 'association' and 'aggregation'](#composition-association-and-aggregation)
|
||||
* ['style'](#style)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -27,7 +27,7 @@ The optional `:<diagram_name>` suffix will apply this decorator only to a specif
|
||||
|
||||
Currently, the following decorators are supported.
|
||||
|
||||
## `note`
|
||||
## 'note'
|
||||
|
||||
This decorator allows to specify directly in the code comments that should be included in the generated diagrams.
|
||||
|
||||
@@ -91,7 +91,7 @@ generates the following class diagram:
|
||||
|
||||

|
||||
|
||||
## `skip` and `skiprelationship`
|
||||
## 'skip' and 'skiprelationship'
|
||||
This decorator allows to skip the specific classes or methods from the diagrams, for instance the following code:
|
||||
```cpp
|
||||
|
||||
@@ -145,7 +145,7 @@ generates the following diagram:
|
||||
|
||||

|
||||
|
||||
## `composition`, `association` and `aggregation`
|
||||
## 'composition', 'association' and 'aggregation'
|
||||
|
||||
These decorators allow to specify explicitly the type of relationship within a class diagram that should be
|
||||
generated for a given class member. For instance the following code:
|
||||
@@ -190,7 +190,7 @@ generates the following diagram:
|
||||

|
||||
|
||||
|
||||
## `style`
|
||||
## 'style'
|
||||
This decorator allows to specify in the code specific styles for diagram elements, for instance:
|
||||
|
||||
```cpp
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
* [PlantUML custom directives](#plantuml-custom-directives)
|
||||
* [Adding debug information in the generated diagrams](#adding-debug-information-in-the-generated-diagrams)
|
||||
* [Resolving include path and compiler flags issues](#resolving-include-path-and-compiler-flags-issues)
|
||||
* [Use `--query-driver` command line option](#use---query-driver-command-line-option)
|
||||
* [Use '--query-driver' command line option](#use---query-driver-command-line-option)
|
||||
* [Manually add and remove compile flags from the compilation database](#manually-add-and-remove-compile-flags-from-the-compilation-database)
|
||||
* [Using `CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES`](#using-cmake_cxx_implicit_include_directories)
|
||||
* [Using 'CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES'](#using-cmake_cxx_implicit_include_directories)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -18,14 +18,17 @@ By default, `clang-uml` will look for file `.clang-uml` in the projects director
|
||||
from it. The file must be specified in YAML and it's overall structure is as follows:
|
||||
|
||||
```yaml
|
||||
<common options for all diagrams>
|
||||
# common options for all diagrams
|
||||
...
|
||||
diagrams:
|
||||
<first diagram name>:
|
||||
type: [class|sequence|package|include]
|
||||
<diagram specific options>
|
||||
<second diagram name>:
|
||||
type: [class|sequence|package|include]
|
||||
<diagram specific options>
|
||||
first_diagram_name:
|
||||
type: class|sequence|package|include
|
||||
# diagram specific options
|
||||
...
|
||||
second_diagram_name:
|
||||
type: class|sequence|package|include
|
||||
# diagram specific options
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
@@ -116,7 +119,7 @@ These errors can be overcome, by ensuring that the Clang parser has the correct
|
||||
include paths to analyse your code base on the given platform. `clang-uml`
|
||||
provides several mechanisms to resolve this issue:
|
||||
|
||||
### Use `--query-driver` command line option
|
||||
### Use '--query-driver' command line option
|
||||
|
||||
> This option is not available on Windows.
|
||||
|
||||
@@ -133,7 +136,7 @@ system, when generating diagrams for an embedded project and providing
|
||||
`arm-none-eabi-gcc` as driver:
|
||||
|
||||
```bash
|
||||
$ clang-uml --query-driver arm-none-eabi-gcc
|
||||
clang-uml --query-driver arm-none-eabi-gcc
|
||||
```
|
||||
|
||||
the following options are appended to each command line after `argv[0]` of the
|
||||
@@ -148,7 +151,7 @@ already as `argv[0]` in your `compile_commands.json`, you can simply invoke
|
||||
`clang-uml` as:
|
||||
|
||||
```bash
|
||||
$ clang-uml --query-driver .
|
||||
clang-uml --query-driver .
|
||||
```
|
||||
|
||||
however please make sure that the `compile_commands.json` contain a command,
|
||||
@@ -173,11 +176,11 @@ remove_compile_flags:
|
||||
These options can be also passed on the command line, for instance:
|
||||
|
||||
```bash
|
||||
$ clang-uml --add-compile-flag -I/opt/my_toolchain/include \
|
||||
--remove-compile-flag -I/usr/include ...
|
||||
clang-uml --add-compile-flag -I/opt/my_toolchain/include \
|
||||
--remove-compile-flag -I/usr/include ...
|
||||
```
|
||||
|
||||
### Using `CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES`
|
||||
### Using 'CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES'
|
||||
Yet another option, for CMake based projects, is to use the following CMake option:
|
||||
|
||||
```cmake
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -55,29 +55,29 @@ 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.+'` |
|
||||
| Filter name | Possible values | Example values |
|
||||
|-------------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------|
|
||||
| `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
|
||||
|
||||
@@ -88,7 +88,7 @@ clang-uml --show-template parents_hierarchy_tmpl
|
||||
users configuration file defines another template with a name which already
|
||||
exists as built-in template it will override the predefined templates.
|
||||
|
||||
Currently the following templates are built-in:
|
||||
Currently, the following templates are built-in:
|
||||
* `parents_hierarchy_tmpl` - generate inheritance hierarchy diagram including
|
||||
parents of a specified class
|
||||
* `subclass_hierarchy_tmpl` - generate inheritance hierarchy diagram including
|
||||
|
||||
28
docs/doxygen/footer.html
Normal file
28
docs/doxygen/footer.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<!-- HTML footer for doxygen 1.9.1-->
|
||||
<!-- start footer part -->
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
<ul>
|
||||
$navpath
|
||||
<li class="footer">
|
||||
$generatedby
|
||||
<a href="https://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer">
|
||||
<small>
|
||||
<span class="copyright">  Copyright © 2022-present <a href="https://github.com/bkryza">Bartek Kryza</a>
|
||||
</span>
|
||||
$generatedby 
|
||||
<a href="https://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
</body>
|
||||
</html>
|
||||
7
docs/doxygen/github.min.css
vendored
Normal file
7
docs/doxygen/github.min.css
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/*!
|
||||
Theme: Github
|
||||
Author: Defman21
|
||||
License: ~ MIT (or more permissive) [via base16-schemes-source]
|
||||
Maintainer: @highlightjs/core-team
|
||||
Version: 2021.09.0
|
||||
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#333;background:#fff}.hljs ::selection,.hljs::selection{background-color:#c8c8fa;color:#333}.hljs-comment{color:#969896}.hljs-tag{color:#e8e8e8}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#333}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ed6a43}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#0086b3}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#795da3}.hljs-strong{font-weight:700;color:#795da3}.hljs-addition,.hljs-built_in,.hljs-code,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp,.hljs-string,.hljs-title.class_.inherited__{color:#183691}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#795da3}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#a71d5d}.hljs-emphasis{color:#a71d5d;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#333}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
|
||||
111
docs/doxygen/header.html
Normal file
111
docs/doxygen/header.html
Normal file
@@ -0,0 +1,111 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
|
||||
<!-- BEGIN opengraph metadata -->
|
||||
<meta property="og:title" content="clang-uml" />
|
||||
<meta property="og:image" content="$relpath^clang-uml-logo.svg" />
|
||||
<meta property="og:description" content="C++ to UML diagram generator based on Clang." />
|
||||
<meta property="og:url" content="https://clang-uml.github.io/" />
|
||||
<!-- END opengraph metadata -->
|
||||
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="icon" type="image/svg+xml" href="logo.drawio.svg"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
<!--<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>-->
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-fragment-copy-button.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-paragraph-link.js"></script>
|
||||
<!--<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>-->
|
||||
<!--<script type="text/javascript" src="$relpath^doxygen-awesome-tabs.js"></script>-->
|
||||
<!--<script type="text/javascript" src="$relpath^toggle-alternative-theme.js"></script>-->
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeFragmentCopyButton.init()
|
||||
// DoxygenAwesomeDarkModeToggle.init()
|
||||
DoxygenAwesomeParagraphLink.init()
|
||||
// DoxygenAwesomeInteractiveToc.init()
|
||||
// DoxygenAwesomeTabs.init()
|
||||
</script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="$relpath^github.min.css">
|
||||
<script src="$relpath^highlight.min.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
hljs.configure({useBR: false});
|
||||
$(".fragment").each(function(i,node) {
|
||||
var $node = $(node);
|
||||
// Only apply highlight.js to non-cpp code blocks
|
||||
if (!$node.hasClass("language-cpp")) {
|
||||
$node.html("<pre><code class='" +
|
||||
$node.attr("class") + "'>" +
|
||||
$node.text() + "</code></pre>");
|
||||
hljs.highlightElement(node);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- https://tholman.com/github-corners/ -->
|
||||
<!--<a href="https://github.com/bkryza/clang-uml" class="github-corner" title="View source on GitHub" target="_blank">-->
|
||||
<!-- <svg viewBox="0 0 250 250" width="70" height="70" style="position: absolute; top: 0; border: 0; right: 0; z-index: 99;" aria-hidden="true">-->
|
||||
<!-- <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>-->
|
||||
|
||||
<div id="top" style="background-color: gainsboro"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo">
|
||||
<a href="$relpath^index.html">
|
||||
<img alt="Main page" src="$relpath^$projectlogo"/>
|
||||
</a>
|
||||
</td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN PROJECT_NAME-->
|
||||
<td id="projectalign" style="padding-left: 0.5em;">
|
||||
<div id="projectname">
|
||||
<span id="projectnumber">$projectnumber</span>
|
||||
</div>
|
||||
<div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||
</td>
|
||||
<!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME-->
|
||||
<!--BEGIN PROJECT_BRIEF-->
|
||||
<!-- <td style="padding-left: 0.5em;">-->
|
||||
<!-- <div id="projectbrief">$projectbrief</div>-->
|
||||
<!-- </td>-->
|
||||
<td>
|
||||
<div>
|
||||
<a href="https://github.com/bkryza/clang-uml">
|
||||
<img alt="GitHub" src="$relpath^github-mark.svg"/>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
<!--END PROJECT_BRIEF-->
|
||||
<!--END !PROJECT_NAME-->
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<td>$searchbox</td>
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
<!-- end header part -->
|
||||
2575
docs/doxygen/highlight.js
Normal file
2575
docs/doxygen/highlight.js
Normal file
File diff suppressed because it is too large
Load Diff
611
docs/doxygen/highlight.min.js
vendored
Normal file
611
docs/doxygen/highlight.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
234
docs/doxygen/layout-clang-uml.xml
Normal file
234
docs/doxygen/layout-clang-uml.xml
Normal file
@@ -0,0 +1,234 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.9.7 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<!-- <tab type="mainpage" visible="yes" title=""/>-->
|
||||
<!-- <tab type="pages" visible="yes" title="" intro=""/>-->
|
||||
<!-- <tab type="modules" visible="yes" title="" intro=""/>-->
|
||||
<tab type="user" url="./md_docs_2installation.html" title="Installation"/>
|
||||
<tab type="user" url="./md_docs_2test__cases.html" title="Test cases"/>
|
||||
<tab type="user" visible="yes" url="./index.html" title="Doxygen">
|
||||
<tab type="namespaces" visible="yes" title="">
|
||||
<tab type="namespacelist" visible="yes" title="" intro=""/>
|
||||
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="classes" visible="yes" title="">
|
||||
<tab type="classlist" visible="yes" title="" intro=""/>
|
||||
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||
<tab type="hierarchy" visible="yes" title="" intro=""/>
|
||||
<tab type="classmembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="structs" visible="yes" title="">
|
||||
<tab type="structlist" visible="yes" title="" intro=""/>
|
||||
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||
</tab>
|
||||
<tab type="files" visible="yes" title="">
|
||||
<tab type="filelist" visible="yes" title="" intro=""/>
|
||||
<tab type="globals" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
</tab>
|
||||
<tab type="user" url="https://github.com/bkryza/clang-uml-examples" title="Examples"/>
|
||||
<tab type="user" url="https://github.com/bkryza/clang-uml" title="GitHub"/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<includes visible="$SHOW_HEADERFILE"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<interfaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<concepts visible="yes" title=""/>
|
||||
<structs visible="yes" title=""/>
|
||||
<exceptions visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a concept page -->
|
||||
<concept>
|
||||
<briefdescription visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<includes visible="$SHOW_HEADERFILE"/>
|
||||
<definition visible="yes" title=""/>
|
||||
<detaileddescription title=""/>
|
||||
<authorsection visible="yes"/>
|
||||
</concept>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="yes"/>
|
||||
<!-- <detaileddescription title=""/>-->
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdecl>
|
||||
<interfaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<structs visible="yes" title=""/>
|
||||
<exceptions visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<concepts visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<concepts visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<!-- <detaileddescription title=""/>-->
|
||||
</directory>
|
||||
</doxygenlayout>
|
||||
7
docs/doxygen/solarized-light.min.css
vendored
Normal file
7
docs/doxygen/solarized-light.min.css
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/*!
|
||||
Theme: Solarized Light
|
||||
Author: Ethan Schoonover (modified by aramisgithub)
|
||||
License: ~ MIT (or more permissive) [via base16-schemes-source]
|
||||
Maintainer: @highlightjs/core-team
|
||||
Version: 2021.09.0
|
||||
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#586e75;background:#fdf6e3}.hljs ::selection,.hljs::selection{background-color:#93a1a1;color:#586e75}.hljs-comment{color:#839496}.hljs-tag{color:#657b83}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#586e75}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#dc322f}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#cb4b16}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#b58900}.hljs-strong{font-weight:700;color:#b58900}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#859900}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#2aa198}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#268bd2}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#6c71c4}.hljs-emphasis{color:#6c71c4;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#d33682}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
|
||||
@@ -6,10 +6,12 @@
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
`clang-uml` diagrams can be easily added to the Doxygen documentation using the image tag, however
|
||||
[Doxygen](https://www.doxygen.nl/index.html) does not support the `clang-uml` specific commands.
|
||||
`clang-uml` diagrams can be easily added to the Doxygen documentation using the
|
||||
`image` tag, however [Doxygen](https://www.doxygen.nl/index.html) does not
|
||||
support the `clang-uml` specific [commands](./comment_decorators.md), which
|
||||
will appear in the documentation unprocessed.
|
||||
|
||||
`clang-uml` decorators can be omitted completely in Doxygen, by adding the
|
||||
The best solution to this is to tell Doxygen to ignore them, by adding the
|
||||
following lines to the Doxygen config file:
|
||||
|
||||
```
|
||||
@@ -17,4 +19,44 @@ ALIASES += uml=""
|
||||
ALIASES += uml{1}=""
|
||||
ALIASES += uml{2}=""
|
||||
ALIASES += uml{3}=""
|
||||
```
|
||||
```
|
||||
|
||||
Furthermore, Doxygen adds images to HTML documentation as `<img src=""/>`,
|
||||
which disables interactive links in SVG diagrams. One way to go around it
|
||||
is to use a special command for these images, for instance:
|
||||
|
||||
```
|
||||
ALIASES += embed{1}="\htmlonly <embed src=\"\1\"/> \endhtmlonly"
|
||||
```
|
||||
|
||||
and then use the following in the source code comments:
|
||||
|
||||
```cpp
|
||||
/**
|
||||
* @brief Base class for all diagram models
|
||||
*
|
||||
* @embed{diagram_hierarchy_class.svg}
|
||||
*/
|
||||
class diagram {
|
||||
public:
|
||||
// ...
|
||||
```
|
||||
|
||||
This directive in the configuration file will add the SVG diagrams using
|
||||
`<embed>` HTML tag, and enable the links in the diagram on most browsers.
|
||||
|
||||
Finally, to have `clang-uml` generate links from diagram elements such as classes
|
||||
or packages to Doxygen pages, it is only necessary to add the following
|
||||
configuration file option:
|
||||
|
||||
```yaml
|
||||
generate_links:
|
||||
link: "{% if existsIn(element, \"doxygen_link\") %}{{ element.doxygen_link }}{% endif %}"
|
||||
tooltip: "{% if existsIn(element, \"comment\") and existsIn(element.comment, \"brief\") %}{{ abbrv(trim(replace(element.comment.brief.0, \"\\n+\", \" \")), 256) }}{% else %}{{ element.name }}{% endif %}"
|
||||
```
|
||||
|
||||
This option will tell `clang-uml` to generate a link to a local Doxygen
|
||||
documentation page, provided that it is possible to generate it. Currently,
|
||||
this only works for diagram elements, it will not work for instance
|
||||
for individual methods.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1
docs/img/github-mark.svg
Normal file
1
docs/img/github-mark.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>
|
||||
|
After Width: | Height: | Size: 963 B |
@@ -2,7 +2,7 @@
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
* [Tracking system headers directly included by projects files](#tracking-system-headers-directly-included-by-projects-files)
|
||||
* [Tracking system headers directly included by project sources](#tracking-system-headers-directly-included-by-project-sources)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -46,7 +46,7 @@ The following table presents the PlantUML arrows representing relationships in t
|
||||
| Include (local) |  |
|
||||
| Include (system) |  |
|
||||
|
||||
## Tracking system headers directly included by projects files
|
||||
## Tracking system headers directly included by project sources
|
||||
|
||||
In case you would like to include the information about what system headers your projects file include simply add
|
||||
the following option to the diagram:
|
||||
|
||||
@@ -30,12 +30,16 @@ sudo apt install clang-uml
|
||||
|
||||
```bash
|
||||
# Fedora 36
|
||||
wget https://github.com/bkryza/clang-uml/releases/download/0.3.1/clang-uml-0.3.1-1.fc36.x86_64.rpm
|
||||
sudo dnf install ./clang-uml-0.3.1-1.fc36.x86_64.rpm
|
||||
wget https://github.com/bkryza/clang-uml/releases/download/0.3.7/clang-uml-0.3.7-1.fc36.x86_64.rpm
|
||||
sudo dnf install ./clang-uml-0.3.7-1.fc36.x86_64.rpm
|
||||
|
||||
# Fedora 37
|
||||
wget https://github.com/bkryza/clang-uml/releases/download/0.3.1/clang-uml-0.3.1-1.fc37.x86_64.rpm
|
||||
sudo dnf install ./clang-uml-0.3.1-1.fc37.x86_64.rpm
|
||||
wget https://github.com/bkryza/clang-uml/releases/download/0.3.7/clang-uml-0.3.7-1.fc37.x86_64.rpm
|
||||
sudo dnf install ./clang-uml-0.3.7-1.fc37.x86_64.rpm
|
||||
|
||||
# Fedora 38
|
||||
wget https://github.com/bkryza/clang-uml/releases/download/0.3.7/clang-uml-0.3.7-1.fc38.x86_64.rpm
|
||||
sudo dnf install ./clang-uml-0.3.7-1.fc38.x86_64.rpm
|
||||
```
|
||||
|
||||
#### Conda
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<!-- toc -->
|
||||
|
||||
* [Accessing comment content](#accessing-comment-content)
|
||||
* [`plain` comment parser](#plain-comment-parser)
|
||||
* [`clang` comment parser](#clang-comment-parser)
|
||||
* ['plain' comment parser](#plain-comment-parser)
|
||||
* ['clang' comment parser](#clang-comment-parser)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -102,12 +102,12 @@ Currently there are 2 available comment parsers:
|
||||
|
||||
They can be selected using `comment_parser` config option.
|
||||
|
||||
#### `plain` comment parser
|
||||
#### 'plain' comment parser
|
||||
This parser provides only 2 options to the Jinja context:
|
||||
* `comment.raw` - raw comment text, including comment markers such as `///` or `/**`
|
||||
* `comment.formatted` - formatted entire comment
|
||||
|
||||
#### `clang` comment parser
|
||||
#### 'clang' comment parser
|
||||
This parser uses Clang comment parsing API to extract commands from the command:
|
||||
* `comment.raw` - raw comment text, including comment markers such as `///` or `/**`
|
||||
* `comment.formatted` - formatted entire comment
|
||||
|
||||
15
docs/license.md
Normal file
15
docs/license.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## LICENSE
|
||||
|
||||
Copyright 2021-present Bartek Kryza <bkryza@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -31,7 +31,7 @@ diagrams:
|
||||
```
|
||||
|
||||
For instance the following C++ code:
|
||||
```
|
||||
```cpp
|
||||
namespace A::AA {
|
||||
namespace A1 {
|
||||
struct CA {
|
||||
@@ -152,7 +152,7 @@ template <typename T> std::map<T, std::shared_ptr<A::AA::A13::CM>> cm()
|
||||
}
|
||||
```
|
||||
|
||||
generates the following diagram:
|
||||
results the following diagram:
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ To add an initial class diagram to your project, follow these steps:
|
||||
|
||||
1. Enter your projects top level directory and run:
|
||||
```bash
|
||||
$ clang-uml --init
|
||||
clang-uml --init
|
||||
```
|
||||
2. Edit the generated `.clang-uml` file and set the following:
|
||||
```yaml
|
||||
@@ -39,21 +39,21 @@ To add an initial class diagram to your project, follow these steps:
|
||||
```
|
||||
3. Run `clang-uml` in the projects top directory:
|
||||
```bash
|
||||
$ clang-uml
|
||||
clang-uml
|
||||
# or to see generation progress for each diagram run
|
||||
$ clang-uml --progress
|
||||
clang-uml --progress
|
||||
```
|
||||
4. Generate SVG images from the PlantUML diagrams:
|
||||
```bash
|
||||
$ plantuml -tsvg puml/*.puml
|
||||
plantuml -tsvg puml/*.puml
|
||||
```
|
||||
5. Add another diagram:
|
||||
```bash
|
||||
$ clang-uml --add-sequence-diagram another_diagram
|
||||
clang-uml --add-sequence-diagram another_diagram
|
||||
```
|
||||
6. Now list the diagrams defined in the config:
|
||||
```bash
|
||||
$ clang-uml -l
|
||||
clang-uml -l
|
||||
The following diagrams are defined in the config file:
|
||||
- another_diagram [sequence]
|
||||
- some_class_diagram [class]
|
||||
|
||||
@@ -89,9 +89,11 @@ Then you just need to copy and paste the signature exactly and rerun `clang-uml`
|
||||
By default, `clang-uml` will generate a new participant for each call to a free function (not method), which can lead
|
||||
to a very large number of participants in the diagram. If it's an issue, an option can be provided in the diagram
|
||||
definition:
|
||||
|
||||
```yaml
|
||||
combine_free_functions_into_file_participants: true
|
||||
```
|
||||
|
||||
which will aggregate free functions per source file where they were declared thus minimizing the
|
||||
diagram size. An example of such diagram is presented below:
|
||||
|
||||
@@ -109,6 +111,7 @@ following rules:
|
||||
Another issue is the naming of lambda participants. Currently, each lambda is rendered in the diagram as a separate
|
||||
class whose name is composed of the lambda location in the code (the only unique way of identifying lambdas I was able
|
||||
to find). For example the following code:
|
||||
|
||||
```cpp
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
# Test cases index
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
* [Class diagrams](#class-diagrams)
|
||||
* [Sequence diagrams](#sequence-diagrams)
|
||||
* [Package diagrams](#package-diagrams)
|
||||
* [Include diagrams](#include-diagrams)
|
||||
* [Other diagrams](#other-diagrams)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Class diagrams
|
||||
* [t00002](./test_cases/t00002.md) - Basic class inheritance
|
||||
* [t00003](./test_cases/t00003.md) - Class fields and methods
|
||||
@@ -112,5 +123,5 @@
|
||||
* [t40001](./test_cases/t40001.md) - Basic include graph diagram test case
|
||||
* [t40002](./test_cases/t40002.md) - Cyclic include graph diagram test case
|
||||
* [t40003](./test_cases/t40003.md) - Dependants and dependencies include diagram filter test
|
||||
## Configuration diagrams
|
||||
## Other diagrams
|
||||
* [t90000](./test_cases/t90000.md) - Basic config test
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
<!-- toc -->
|
||||
|
||||
* [General issues](#general-issues)
|
||||
* [`clang-uml` crashed when generating diagram](#clang-uml-crashed-when-generating-diagram)
|
||||
* [clang-uml crashes when generating diagram](#clang-uml-crashes-when-generating-diagram)
|
||||
* [Diagram generation is very slow](#diagram-generation-is-very-slow)
|
||||
* [Diagram generated with PlantUML is cropped](#diagram-generated-with-plantuml-is-cropped)
|
||||
* [`clang` produces several warnings during diagram generation](#clang-produces-several-warnings-during-diagram-generation)
|
||||
* [Clang produces several warnings during diagram generation](#clang-produces-several-warnings-during-diagram-generation)
|
||||
* [Cannot generate diagrams from header-only projects](#cannot-generate-diagrams-from-header-only-projects)
|
||||
* [YAML anchors and aliases are not fully supported](#yaml-anchors-and-aliases-are-not-fully-supported)
|
||||
* [Class diagrams](#class-diagrams)
|
||||
* ["fatal error: 'stddef.h' file not found"](#fatal-error-stddefh-file-not-found)
|
||||
* [Cannot generate classes for `std` namespace](#cannot-generate-classes-for-std-namespace)
|
||||
* [How can I generate class diagram of my entire project](#how-can-i-generate-class-diagram-of-my-entire-project)
|
||||
* [Cannot generate classes for 'std' namespace](#cannot-generate-classes-for-std-namespace)
|
||||
* [Sequence diagrams](#sequence-diagrams)
|
||||
* [Generated diagram is empty](#generated-diagram-is-empty)
|
||||
* [Generated diagram contains several empty control blocks or calls which should not be there](#generated-diagram-contains-several-empty-control-blocks-or-calls-which-should-not-be-there)
|
||||
@@ -20,14 +21,15 @@
|
||||
|
||||
## General issues
|
||||
|
||||
### `clang-uml` crashed when generating diagram
|
||||
### clang-uml crashes when generating diagram
|
||||
|
||||
If `clang-uml` crashes with a segmentation fault, it is possible to trace the
|
||||
exact stack trace of the fault using the following steps:
|
||||
|
||||
First, build `clang-uml` from source in debug mode, e.g.:
|
||||
|
||||
```bash
|
||||
$ make debug
|
||||
make debug
|
||||
```
|
||||
|
||||
Then run `clang-uml`, preferably with `-vvv` for verbose log output. If your
|
||||
@@ -35,7 +37,7 @@ Then run `clang-uml`, preferably with `-vvv` for verbose log output. If your
|
||||
a single diagram to make it easier to trace the root cause of the crash, e.g.:
|
||||
|
||||
```bash
|
||||
$ debug/src/clang-uml -vvv -n my_diagram
|
||||
debug/src/clang-uml -vvv -n my_diagram
|
||||
```
|
||||
|
||||
After `clang-uml` crashes again, detailed backtrace (generated using
|
||||
@@ -47,11 +49,13 @@ paste the stack trace and few last logs from the console.
|
||||
|
||||
### Diagram generation is very slow
|
||||
|
||||
`clang-uml` uses Clang's [RecursiveASTVisitor](https://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html), to
|
||||
`clang-uml` uses
|
||||
Clang's [RecursiveASTVisitor](https://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html),
|
||||
to
|
||||
traverse the source code. By default, this visitor is invoked on every
|
||||
translation unit (i.e. each entry in your `compile_commands.json`), including
|
||||
all of their header dependencies recursively. This means, that for large code
|
||||
bases with hundreds or thousands of translation units, traversing all of them
|
||||
bases with hundreds or thousands of translation units, traversing all of them
|
||||
will be slow (think `clang-tidy` slow...).
|
||||
|
||||
Fortunately, in most practical cases it is not necessary to traverse the entire
|
||||
@@ -60,7 +64,8 @@ a single diagram usually can be found in just a few translation units, or even
|
||||
a single one.
|
||||
|
||||
This is where the `glob` configuration parameter comes in. It can be used to
|
||||
limit the number of translation units to visit for a given diagram, for instance:
|
||||
limit the number of translation units to visit for a given diagram, for
|
||||
instance:
|
||||
|
||||
```yaml
|
||||
diagrams:
|
||||
@@ -95,11 +100,11 @@ format and then convert
|
||||
to PNG, e.g.:
|
||||
|
||||
```bash
|
||||
$ plantuml -tsvg mydiagram.puml
|
||||
$ convert +antialias mydiagram.svg mydiagram.png
|
||||
plantuml -tsvg mydiagram.puml
|
||||
convert +antialias mydiagram.svg mydiagram.png
|
||||
```
|
||||
|
||||
### `clang` produces several warnings during diagram generation
|
||||
### Clang produces several warnings during diagram generation
|
||||
|
||||
During the generation of the diagram `clang` may report a lot of warnings, which
|
||||
do not occur during the compilation with other compiler (e.g. GCC). This can be
|
||||
@@ -122,8 +127,8 @@ add_compile_flags:
|
||||
Alternatively, the same can be passed through the `clang-uml` command line, e.g.
|
||||
|
||||
```bash
|
||||
$ clang-uml --add-compile-flag -Wno-implicit-const-int-float-conversion \
|
||||
--add-compile-flag -Wno-shadow ...
|
||||
clang-uml --add-compile-flag -Wno-implicit-const-int-float-conversion \
|
||||
--add-compile-flag -Wno-shadow ...
|
||||
```
|
||||
|
||||
Please note that if your `compile_commands.json` already contains - for instance
|
||||
@@ -174,7 +179,7 @@ output_directory: output
|
||||
|
||||
.sequence_diagram_anchor: &sequence_diagram_anchor
|
||||
type: sequence
|
||||
glob: []
|
||||
glob: [ ]
|
||||
start_from:
|
||||
- function: 'main(int,const char**)'
|
||||
|
||||
@@ -182,7 +187,7 @@ diagrams:
|
||||
main_sequence_diagram: *sequence_diagram_anchor # This will work
|
||||
foo_sequence_diagram:
|
||||
<<: *sequence_diagram_anchor # This will not work
|
||||
glob: [src/foo.cc]
|
||||
glob: [ src/foo.cc ]
|
||||
start_from:
|
||||
- function: 'foo(int,float)'
|
||||
```
|
||||
@@ -196,10 +201,11 @@ yq 'explode(.)' .clang-uml | clang-uml --config -
|
||||
```
|
||||
|
||||
## Class diagrams
|
||||
|
||||
### "fatal error: 'stddef.h' file not found"
|
||||
|
||||
This error means that Clang cannot find some standard headers in include
|
||||
paths specified in the `compile_commands.json`. This typically happens on macOS
|
||||
paths specified in the `compile_commands.json`. This typically happens on macOS
|
||||
and sometimes on Linux, when the code was compiled with different Clang version
|
||||
than `clang-uml` itself.
|
||||
|
||||
@@ -212,13 +218,13 @@ set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTOR
|
||||
|
||||
Another option is to provide an option (on command line or in configuration
|
||||
file) called `query_driver` (inspired by the [clangd](https://clangd.llvm.org/)
|
||||
language server - although much less flexible), which will invoke the
|
||||
language server - although much less flexible), which will invoke the
|
||||
provider compiler command and query it for its default system paths, which then
|
||||
will be added to each compile command in the database. This is especially useful
|
||||
on macOS as well as for embedded toolchains, example usage:
|
||||
|
||||
```bash
|
||||
$ clang-uml --query-driver arm-none-eabi-g++
|
||||
clang-uml --query-driver arm-none-eabi-g++
|
||||
```
|
||||
|
||||
Another option is to make sure that the Clang is installed on the system (even
|
||||
@@ -248,12 +254,42 @@ remove_compile_flags:
|
||||
These options can be also passed on the command line, for instance:
|
||||
|
||||
```bash
|
||||
$ clang-uml --add-compile-flag -I/opt/my_toolchain/include \
|
||||
--remove-compile-flag -I/usr/include ...
|
||||
clang-uml --add-compile-flag -I/opt/my_toolchain/include \
|
||||
--remove-compile-flag -I/usr/include ...
|
||||
```
|
||||
|
||||
### Cannot generate classes for `std` namespace
|
||||
Currently, system headers are skipped automatically by `clang-uml`, due to
|
||||
Also see
|
||||
[here](./md_docs_2common__options.html#resolving-include-path-and-compiler-flags-issues).
|
||||
|
||||
### How can I generate class diagram of my entire project
|
||||
|
||||
I want to generate a diagram containing all classes and relationships in my
|
||||
project - I don't care how big it is going to be.
|
||||
|
||||
Of course this is possible, the best way to do this is to specify
|
||||
that `clang-uml`
|
||||
should only include elements defined in files contained in project sources,
|
||||
e.g.:
|
||||
|
||||
```yaml
|
||||
diagrams:
|
||||
all_classes:
|
||||
type: class
|
||||
include:
|
||||
paths: [ include, src ]
|
||||
```
|
||||
|
||||
As the diagram will be huge for even medium-sized projects, it will likely not
|
||||
be readable. However, this option can be useful for cases when we want to get
|
||||
a complete JSON model of the codebase using the JSON generator:
|
||||
|
||||
```bash
|
||||
clang-uml -g json -n all_classes --progress
|
||||
```
|
||||
|
||||
### Cannot generate classes for 'std' namespace
|
||||
|
||||
Currently, system headers are skipped automatically by `clang-uml`, due to
|
||||
too many errors they produce when generating diagrams, especially when trying
|
||||
to process `GCC`'s or `MSVC`'s system headers by `Clang` - not yet sure why
|
||||
that is the case.
|
||||
@@ -278,6 +314,7 @@ exclude:
|
||||
Hopefully this will be eventually resolved.
|
||||
|
||||
## Sequence diagrams
|
||||
|
||||
### Generated diagram is empty
|
||||
|
||||
In order to generate sequence diagram the `start_from` configuration option must
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/generators/json/class_diagram_generator.cc
|
||||
* @file rc/class_diagram/generators/json/class_diagram_generator.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/generators/json/class_diagram_generator.h
|
||||
* @file src/class_diagram/generators/json/class_diagram_generator.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/generators/plantuml/class_diagram_generator.cc
|
||||
* @file src/class_diagram/generators/plantuml/class_diagram_generator.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -813,10 +813,9 @@ void generator::generate(const package &p, std::ostream &ostr) const
|
||||
// using_namespace
|
||||
if (!uns.starts_with({p.full_name(false)})) {
|
||||
ostr << "}" << '\n';
|
||||
generate_notes(ostr, p);
|
||||
}
|
||||
}
|
||||
|
||||
generate_notes(ostr, p);
|
||||
}
|
||||
|
||||
void generator::generate_relationships(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/generators/plantuml/class_diagram_generator.h
|
||||
* @file src/class_diagram/generators/plantuml/class_diagram_generator.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class.cc
|
||||
* @file src/class_diagram/model/class.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -37,6 +37,10 @@ bool class_::is_template() const { return is_template_; }
|
||||
|
||||
void class_::is_template(bool is_template) { is_template_ = is_template; }
|
||||
|
||||
bool class_::is_union() const { return is_union_; }
|
||||
|
||||
void class_::is_union(bool is_union) { is_union_ = is_union; }
|
||||
|
||||
void class_::add_member(class_member &&member)
|
||||
{
|
||||
members_.emplace_back(std::move(member));
|
||||
@@ -121,4 +125,25 @@ int class_::calculate_template_specialization_match(const class_ &other) const
|
||||
|
||||
return template_trait::calculate_template_specialization_match(other);
|
||||
}
|
||||
|
||||
void class_::template_specialization_found(bool found)
|
||||
{
|
||||
template_specialization_found_ = found;
|
||||
}
|
||||
|
||||
bool class_::template_specialization_found() const
|
||||
{
|
||||
return template_specialization_found_;
|
||||
}
|
||||
|
||||
std::optional<std::string> class_::doxygen_link() const
|
||||
{
|
||||
const auto *type = is_struct() ? "struct" : "class";
|
||||
|
||||
auto name = name_and_ns();
|
||||
util::replace_all(name, "_", "__");
|
||||
util::replace_all(name, "::", "_1_1");
|
||||
util::replace_all(name, "##", "_1_1"); // nested classes
|
||||
return fmt::format("{}{}.html", type, name);
|
||||
}
|
||||
} // namespace clanguml::class_diagram::model
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class.h
|
||||
* @file src/class_diagram/model/class.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -32,6 +32,9 @@
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
/**
|
||||
* @brief Diagram element representing a class or class template.
|
||||
*/
|
||||
class class_ : public common::model::element,
|
||||
public common::model::stylable_element,
|
||||
public template_trait {
|
||||
@@ -43,44 +46,165 @@ public:
|
||||
class_ &operator=(const class_ &) = delete;
|
||||
class_ &operator=(class_ &&) = delete;
|
||||
|
||||
std::string type_name() const override { return "class"; }
|
||||
|
||||
bool is_struct() const;
|
||||
void is_struct(bool is_struct);
|
||||
|
||||
bool is_template() const;
|
||||
void is_template(bool is_template);
|
||||
|
||||
bool is_union() const { return is_union_; }
|
||||
void is_union(bool u) { is_union_ = u; }
|
||||
|
||||
void add_member(class_member &&member);
|
||||
void add_method(class_method &&method);
|
||||
void add_parent(class_parent &&parent);
|
||||
|
||||
const std::vector<class_member> &members() const;
|
||||
const std::vector<class_method> &methods() const;
|
||||
const std::vector<class_parent> &parents() const;
|
||||
|
||||
friend bool operator==(const class_ &l, const class_ &r);
|
||||
|
||||
/**
|
||||
* Get the type name of the diagram element.
|
||||
*
|
||||
* @return Type name of the diagram element.
|
||||
*/
|
||||
std::string type_name() const override { return "class"; }
|
||||
|
||||
/**
|
||||
* Whether or not the class was declared in the code as 'struct'.
|
||||
*
|
||||
* @return True, if the class was declared as 'struct'
|
||||
*/
|
||||
bool is_struct() const;
|
||||
|
||||
/**
|
||||
* Set, whether the class was declared as 'struct'.
|
||||
*
|
||||
* @param is_struct True, if the class was declared as 'struct'
|
||||
*/
|
||||
void is_struct(bool is_struct);
|
||||
|
||||
/**
|
||||
* Whether or not the class is a template.
|
||||
*
|
||||
* @return True, if the class is a template.
|
||||
*/
|
||||
bool is_template() const;
|
||||
|
||||
/**
|
||||
* Set, whether the class is a template.
|
||||
*
|
||||
* @param is_struct True, if the class is a template.
|
||||
*/
|
||||
void is_template(bool is_template);
|
||||
|
||||
/**
|
||||
* Whether or not the class is a union.
|
||||
*
|
||||
* @return True, if the class is a union.
|
||||
*/
|
||||
bool is_union() const;
|
||||
|
||||
/**
|
||||
* Set, whether the class is a union.
|
||||
*
|
||||
* @param u True, if the class is a union.
|
||||
*/
|
||||
void is_union(bool is_union);
|
||||
|
||||
/**
|
||||
* Add a data member to the class.
|
||||
*
|
||||
* @param member Class data member.
|
||||
*/
|
||||
void add_member(class_member &&member);
|
||||
|
||||
/**
|
||||
* Add a method to the class.
|
||||
*
|
||||
* @param method Class method.
|
||||
*/
|
||||
void add_method(class_method &&method);
|
||||
|
||||
/**
|
||||
* Add class parent (inheritance relationship).
|
||||
*
|
||||
* @todo Maybe it would be good to refactor this into a regular
|
||||
* relationship. We could drop the 'class_parent' class completely...
|
||||
*
|
||||
* @param parent Class parent.
|
||||
*/
|
||||
void add_parent(class_parent &&parent);
|
||||
|
||||
/**
|
||||
* Get reference to class member list.
|
||||
*
|
||||
* @return Reference to class members.
|
||||
*/
|
||||
const std::vector<class_member> &members() const;
|
||||
|
||||
/**
|
||||
* Get reference to class method list.
|
||||
*
|
||||
* @return Reference to class methods.
|
||||
*/
|
||||
const std::vector<class_method> &methods() const;
|
||||
|
||||
/**
|
||||
* Get reference to class parent list.
|
||||
*
|
||||
* @return Reference to class parents.
|
||||
*/
|
||||
const std::vector<class_parent> &parents() const;
|
||||
|
||||
/**
|
||||
* @brief Get class full name.
|
||||
*
|
||||
* This method renders the entire class name including all template
|
||||
* parameters and/or arguments.
|
||||
*
|
||||
* @param relative Whether the class name should be relative to
|
||||
* using_namespace
|
||||
* @return Full class name.
|
||||
*/
|
||||
std::string full_name(bool relative = true) const override;
|
||||
|
||||
/**
|
||||
* @brief Get unqualified class ful name.
|
||||
*
|
||||
* This method returns the class full name but without any namespace
|
||||
* qualifier.
|
||||
*
|
||||
* @return Full class name without namespace.
|
||||
*/
|
||||
std::string full_name_no_ns() const override;
|
||||
|
||||
/**
|
||||
* Whether the class is abstract.
|
||||
*
|
||||
* @return True, if at least one method is abstract (=0).
|
||||
*/
|
||||
bool is_abstract() const;
|
||||
|
||||
/**
|
||||
* @brief Calculate template specialization match with other class.
|
||||
*
|
||||
* This method is a wrapper over
|
||||
* @ref template_trait::calculate_template_specialization_match()
|
||||
*
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
int calculate_template_specialization_match(const class_ &other) const;
|
||||
|
||||
void template_specialization_found(bool found)
|
||||
{
|
||||
template_specialization_found_ = found;
|
||||
}
|
||||
/**
|
||||
* Whether, a template specialization has already been found for this class.
|
||||
* @return True, if a template specialization has already been found.
|
||||
*/
|
||||
bool template_specialization_found() const;
|
||||
|
||||
bool template_specialization_found() const
|
||||
{
|
||||
return template_specialization_found_;
|
||||
}
|
||||
/**
|
||||
* Set, whether a template specialization has already been found for this
|
||||
* class.
|
||||
*
|
||||
* @param found True, if a template specialization has already been found.
|
||||
*/
|
||||
void template_specialization_found(bool found);
|
||||
|
||||
/**
|
||||
* @brief Generate Doxygen style HTML link for the class.
|
||||
*
|
||||
* This method generates a link, which can be used in SVG diagrams to
|
||||
* create links from classes to Doxygen documentation pages.
|
||||
*
|
||||
* @return Doxygen-style HTML link for the class.
|
||||
*/
|
||||
std::optional<std::string> doxygen_link() const override;
|
||||
|
||||
private:
|
||||
bool is_struct_{false};
|
||||
@@ -90,7 +214,6 @@ private:
|
||||
std::vector<class_method> methods_;
|
||||
std::vector<class_parent> bases_;
|
||||
std::string base_template_full_name_;
|
||||
|
||||
std::string full_name_;
|
||||
|
||||
bool template_specialization_found_{false};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_element.cc
|
||||
* @file src/class_diagram/model/class_element.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_element.h
|
||||
* @file src/class_diagram/model/class_element.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -26,21 +26,57 @@
|
||||
|
||||
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:
|
||||
class_element(
|
||||
common::model::access_t scope, std::string name, std::string type);
|
||||
|
||||
virtual ~class_element() = default;
|
||||
~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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_member.cc
|
||||
* @file src/class_diagram/model/class_member.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_member.h
|
||||
* @file src/class_diagram/model/class_member.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_method.cc
|
||||
* @file src/class_diagram/model/class_method.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_method.h
|
||||
* @file src/class_diagram/model/class_method.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_parent.cc
|
||||
* @file src/class_diagram/model/class_parent.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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_; }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_parent.h
|
||||
* @file src/class_diagram/model/class_parent.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/concept.cc
|
||||
* @file src/class_diagram/model/concept.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -70,9 +70,9 @@ std::string concept_::full_name(bool relative) const
|
||||
return res;
|
||||
}
|
||||
|
||||
void concept_::add_parameter(method_parameter mp)
|
||||
void concept_::add_parameter(const method_parameter &mp)
|
||||
{
|
||||
requires_parameters_.emplace_back(std::move(mp));
|
||||
requires_parameters_.emplace_back(mp);
|
||||
}
|
||||
|
||||
const std::vector<method_parameter> &concept_::requires_parameters() const
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/concept.h
|
||||
* @file src/class_diagram/model/concept.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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;
|
||||
|
||||
void add_parameter(method_parameter mp);
|
||||
/**
|
||||
* @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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/diagram.cc
|
||||
* @file src/class_diagram/model/diagram.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -198,6 +198,11 @@ inja::json diagram::context() const
|
||||
elements.emplace_back(e.get().context());
|
||||
}
|
||||
|
||||
// Add enums
|
||||
for (const auto &c : concepts()) {
|
||||
elements.emplace_back(c.get().context());
|
||||
}
|
||||
|
||||
ctx["elements"] = elements;
|
||||
|
||||
return ctx;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/diagram.h
|
||||
* @file src/class_diagram/model/diagram.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/enum.cc
|
||||
* @file src/class_diagram/model/enum.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -54,4 +54,11 @@ std::vector<std::string> &enum_::constants() { return constants_; }
|
||||
|
||||
const std::vector<std::string> &enum_::constants() const { return constants_; }
|
||||
|
||||
std::optional<std::string> enum_::doxygen_link() const
|
||||
{
|
||||
auto name = name_and_ns();
|
||||
util::replace_all(name, "_", "__");
|
||||
util::replace_all(name, "::", "_1_1");
|
||||
return fmt::format("enum{}.html", name);
|
||||
}
|
||||
} // namespace clanguml::class_diagram::model
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/enum.h
|
||||
* @file src/class_diagram/model/enum.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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,31 @@ 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:
|
||||
std::vector<std::string> constants_;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/method_parameter.cc
|
||||
* @file src/class_diagram/model/method_parameter.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/method_parameter.h
|
||||
* @file src/class_diagram/model/method_parameter.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -25,21 +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;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/visitor/template_builder.cc
|
||||
* @file src/class_diagram/visitor/template_builder.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/visitor/template_builder.h
|
||||
* @file src/class_diagram/visitor/template_builder.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/visitor/translation_unit_visitor.cc
|
||||
* @file src/class_diagram/visitor/translation_unit_visitor.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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,8 +169,7 @@ 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));
|
||||
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(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/visitor/translation_unit_visitor.h
|
||||
* @file src/class_diagram/visitor/translation_unit_visitor.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -57,17 +57,28 @@ using clanguml::common::model::template_trait;
|
||||
/**
|
||||
* @brief Class diagram translation unit visitor
|
||||
*
|
||||
* This class implements the @link clang::RecursiveASTVisitor interface
|
||||
* This class implements the `clang::RecursiveASTVisitor` interface
|
||||
* for selected visitors relevant to generating class diagrams.
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/options/cli_handler.cc
|
||||
* @file src/options/cli_handler.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/options/cli_handler.h
|
||||
* @file 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_;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/visitor/clang_utils.cc
|
||||
* @file src/common/clang_utils.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/clang_utils.h
|
||||
* @file src/common/clang_utils.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -35,23 +35,35 @@ 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
|
||||
* attribtues
|
||||
* attribtues
|
||||
*/
|
||||
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 ¶ms,
|
||||
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);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/compilation_database.cc
|
||||
* @file src/common/compilation_database.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "compilation_database.h"
|
||||
|
||||
#include "util/error.h"
|
||||
#include "util/query_driver_output_extractor.h"
|
||||
|
||||
namespace clanguml::common {
|
||||
@@ -31,7 +31,7 @@ compilation_database::auto_detect_from_directory(
|
||||
cfg.compilation_database_dir(), error_message);
|
||||
|
||||
if (!error_message.empty())
|
||||
throw compilation_database_error(error_message);
|
||||
throw error::compilation_database_error(error_message);
|
||||
|
||||
return std::make_unique<compilation_database>(std::move(res), cfg);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/compilation_database.h
|
||||
* @file src/common/compilation_database.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "common/model/template_parameter.h"
|
||||
#include "config/config.h"
|
||||
#include "types.h"
|
||||
#include "util/error.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
@@ -34,10 +35,16 @@
|
||||
|
||||
namespace clanguml::common {
|
||||
|
||||
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 +53,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 +107,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_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/generators.cc
|
||||
* @file src/common/generators/generators.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -184,32 +184,33 @@ 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,
|
||||
verbose]() mutable {
|
||||
try {
|
||||
if (indicator)
|
||||
indicator->add_progress_bar(name,
|
||||
translation_units.size(),
|
||||
diagram_type_to_color(diagram->type()));
|
||||
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(),
|
||||
diagram_type_to_color(diagram->type()));
|
||||
|
||||
generate_diagram(od, name, diagram, db, translation_units,
|
||||
generators, verbose != 0, [&indicator, &name]() {
|
||||
if (indicator)
|
||||
indicator->increment(name);
|
||||
});
|
||||
generate_diagram(od, name, diagram, db, translation_units,
|
||||
generators, verbose != 0, [&indicator, &name]() {
|
||||
if (indicator)
|
||||
indicator->increment(name);
|
||||
});
|
||||
|
||||
if (indicator)
|
||||
indicator->complete(name);
|
||||
}
|
||||
catch (std::runtime_error &e) {
|
||||
if (indicator)
|
||||
indicator->fail(name);
|
||||
if (indicator)
|
||||
indicator->complete(name);
|
||||
}
|
||||
catch (std::runtime_error &e) {
|
||||
if (indicator)
|
||||
indicator->fail(name);
|
||||
|
||||
LOG_ERROR(e.what());
|
||||
}
|
||||
}));
|
||||
LOG_ERROR(e.what());
|
||||
}
|
||||
};
|
||||
|
||||
futs.emplace_back(generator_executor.add(std::move(generator)));
|
||||
}
|
||||
|
||||
for (auto &fut : futs) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/generators.h
|
||||
* @file src/common/generators/generators.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/json/generator.cc
|
||||
* @file src/common/generators/json/generator.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/json/generator.h
|
||||
* @file src/common/generators/json/generator.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/nested_element_stack.h
|
||||
* @file src/common/generators/nested_element_stack.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -38,6 +38,9 @@ public:
|
||||
current_level_groups_.push_back({});
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to next level in the element stack
|
||||
*/
|
||||
void enter()
|
||||
{
|
||||
if (!is_flat_)
|
||||
@@ -46,6 +49,9 @@ public:
|
||||
current_level_groups_.push_back({});
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to previous level in the element stack
|
||||
*/
|
||||
void leave()
|
||||
{
|
||||
if (!is_flat_)
|
||||
@@ -54,16 +60,30 @@ public:
|
||||
current_level_groups_.pop_back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add element pointer to a specified group at the current level
|
||||
*/
|
||||
void group_together(const std::string &group_name, T *e)
|
||||
{
|
||||
current_level_groups_[current_level_][group_name].push_back(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map of element groups at the current level.
|
||||
*
|
||||
* @return Reference to element groups.
|
||||
*/
|
||||
const std::map<std::string, std::vector<T *>> &get_current_groups()
|
||||
{
|
||||
return current_level_groups_.at(current_level_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get element group by name - the group must exist at the current level.
|
||||
*
|
||||
* @param group_name Element group name
|
||||
* @return
|
||||
*/
|
||||
const std::vector<T *> &get_group(const std::string &group_name)
|
||||
{
|
||||
return get_current_groups().at(group_name);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/plantuml/generator.h
|
||||
* @file src/common/generators/plantuml/generator.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/plantuml/generator.h
|
||||
* @file src/common/generators/plantuml/generator.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/progress_indicator.cc
|
||||
* @file src/common/generators/progress_indicator.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/generators/progress_indicator.h
|
||||
* @file src/common/generators/progress_indicator.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
namespace clanguml::common::generators {
|
||||
|
||||
/**
|
||||
* @brief Container for diagram generation progress indicators
|
||||
*/
|
||||
class progress_indicator {
|
||||
public:
|
||||
struct progress_state {
|
||||
@@ -42,15 +45,40 @@ public:
|
||||
|
||||
progress_indicator();
|
||||
|
||||
/**
|
||||
* Add a new progress bar to the indicator set
|
||||
*
|
||||
* @param name Name (prefix) of the progress bar
|
||||
* @param max Total number of steps in the progress bar
|
||||
* @param color Color of the progress bar
|
||||
*/
|
||||
void add_progress_bar(
|
||||
const std::string &name, size_t max, indicators::Color color);
|
||||
|
||||
/**
|
||||
* Increment specified progress bar.
|
||||
*
|
||||
* @param name Name of the progress bar
|
||||
*/
|
||||
void increment(const std::string &name);
|
||||
|
||||
/**
|
||||
* Stop all the progress bars.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Set specified progress bar as complete.
|
||||
*
|
||||
* @param name Name of the progress bar
|
||||
*/
|
||||
void complete(const std::string &name);
|
||||
|
||||
/**
|
||||
* Set progress bar as failed.
|
||||
*
|
||||
* @param name Name of the progress bar
|
||||
*/
|
||||
void fail(const std::string &name);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/decorated_element.cc
|
||||
* @file src/common/model/decorated_element.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -90,4 +90,10 @@ void decorated_element::append(const decorated_element &de)
|
||||
std::optional<comment_t> decorated_element::comment() const { return comment_; }
|
||||
|
||||
void decorated_element::set_comment(const comment_t &c) { comment_ = c; }
|
||||
|
||||
std::optional<std::string> decorated_element::doxygen_link() const
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace clanguml::common::model
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/class_diagram/model/decorated_element.h
|
||||
* @file src/common/model/decorated_element.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -34,28 +34,106 @@ 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:
|
||||
virtual ~decorated_element() = default;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Return Doxygen HTML documentation link for the element.
|
||||
*
|
||||
* @return Element context.
|
||||
*/
|
||||
virtual std::optional<std::string> doxygen_link() const;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<decorators::decorator>> decorators_;
|
||||
std::optional<comment_t> comment_;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/diagram.cc
|
||||
* @file src/common/model/diagram.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -68,12 +68,12 @@ bool diagram::should_include(const element &e) const
|
||||
filter_->should_include(dynamic_cast<const source_location &>(e));
|
||||
}
|
||||
|
||||
bool diagram::should_include(const std::string &name) const
|
||||
bool diagram::should_include(const namespace_ &ns) const
|
||||
{
|
||||
if (filter_.get() == nullptr)
|
||||
return true;
|
||||
|
||||
return filter_->should_include(name);
|
||||
return filter_->should_include(ns);
|
||||
}
|
||||
|
||||
bool diagram::should_include(const relationship_t r) const
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/diagram.h
|
||||
* @file src/common/model/diagram.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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,22 +82,63 @@ 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
|
||||
bool should_include(const element &e) const;
|
||||
bool should_include(const std::string &e) const;
|
||||
bool should_include(const namespace_ &ns) const;
|
||||
bool should_include(const source_file &path) const;
|
||||
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
|
||||
{
|
||||
@@ -80,6 +148,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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/diagram_element.cc
|
||||
* @file src/common/model/diagram_element.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -73,8 +73,12 @@ inja::json diagram_element::context() const
|
||||
{
|
||||
inja::json ctx;
|
||||
ctx["name"] = name();
|
||||
ctx["type"] = type_name();
|
||||
ctx["alias"] = alias();
|
||||
ctx["full_name"] = full_name(false);
|
||||
auto maybe_doxygen_link = doxygen_link();
|
||||
if (maybe_doxygen_link)
|
||||
ctx["doxygen_link"] = maybe_doxygen_link.value();
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -31,34 +31,105 @@
|
||||
|
||||
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;
|
||||
|
||||
diagram_element();
|
||||
|
||||
virtual ~diagram_element() = default;
|
||||
~diagram_element() override = 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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/diagram_filter.cc
|
||||
* @file src/common/model/diagram_filter.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -186,60 +186,100 @@ tvl::value_t namespace_filter::match(
|
||||
if (ns.is_empty())
|
||||
return {};
|
||||
|
||||
return tvl::any_of(
|
||||
namespaces_.begin(), namespaces_.end(), [&ns](const auto &nsit) {
|
||||
return tvl::any_of(namespaces_.begin(), namespaces_.end(),
|
||||
[&ns, is_inclusive = is_inclusive()](const auto &nsit) {
|
||||
if (std::holds_alternative<namespace_>(nsit.value())) {
|
||||
const auto &ns_pattern = std::get<namespace_>(nsit.value());
|
||||
return ns.starts_with(ns_pattern) || ns == ns_pattern;
|
||||
if (is_inclusive)
|
||||
return ns.starts_with(ns_pattern) ||
|
||||
ns_pattern.starts_with(ns);
|
||||
|
||||
return ns.starts_with(ns_pattern);
|
||||
}
|
||||
|
||||
const auto ®ex = std::get<common::regex>(nsit.value());
|
||||
return regex == ns.to_string();
|
||||
return regex %= ns.to_string();
|
||||
});
|
||||
}
|
||||
|
||||
tvl::value_t namespace_filter::match(
|
||||
const diagram & /*d*/, const element &e) const
|
||||
tvl::value_t namespace_filter::match(const diagram &d, const element &e) const
|
||||
{
|
||||
if (dynamic_cast<const package *>(&e) != nullptr) {
|
||||
return tvl::any_of(namespaces_.begin(), namespaces_.end(),
|
||||
if (d.type() != diagram_t::kPackage &&
|
||||
dynamic_cast<const package *>(&e) != nullptr) {
|
||||
auto result = tvl::any_of(namespaces_.begin(), namespaces_.end(),
|
||||
[&e, is_inclusive = is_inclusive()](const auto &nsit) {
|
||||
if (std::holds_alternative<namespace_>(nsit.value())) {
|
||||
const auto &ns_pattern = std::get<namespace_>(nsit.value());
|
||||
|
||||
auto element_full_name_starts_with_namespace =
|
||||
(e.get_namespace() | e.name()).starts_with(ns_pattern);
|
||||
namespace_{e.name_and_ns()}.starts_with(ns_pattern);
|
||||
|
||||
auto element_full_name_equals_pattern =
|
||||
(e.get_namespace() | e.name()) == ns_pattern;
|
||||
namespace_{e.name_and_ns()} == ns_pattern;
|
||||
|
||||
auto namespace_starts_with_element_qualified_name =
|
||||
ns_pattern.starts_with(e.get_namespace());
|
||||
auto pattern_starts_with_element_full_name =
|
||||
ns_pattern.starts_with(namespace_{e.name_and_ns()});
|
||||
|
||||
auto result = element_full_name_starts_with_namespace ||
|
||||
element_full_name_equals_pattern;
|
||||
|
||||
if (is_inclusive)
|
||||
result = result ||
|
||||
namespace_starts_with_element_qualified_name;
|
||||
result =
|
||||
result || pattern_starts_with_element_full_name;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return std::get<common::regex>(nsit.value()) ==
|
||||
return std::get<common::regex>(nsit.value()) %=
|
||||
e.full_name(false);
|
||||
});
|
||||
|
||||
if (tvl::is_false(result))
|
||||
LOG_DBG("Element {} rejected by namespace_filter 1",
|
||||
e.full_name(false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return tvl::any_of(
|
||||
if (d.type() == diagram_t::kPackage) {
|
||||
auto result = tvl::any_of(namespaces_.begin(), namespaces_.end(),
|
||||
[&e, is_inclusive = is_inclusive()](const auto &nsit) {
|
||||
if (std::holds_alternative<namespace_>(nsit.value())) {
|
||||
auto e_ns = namespace_{e.full_name(false)};
|
||||
auto nsit_ns = std::get<namespace_>(nsit.value());
|
||||
|
||||
if (is_inclusive)
|
||||
return e_ns.starts_with(nsit_ns) ||
|
||||
nsit_ns.starts_with(e_ns) || e_ns == nsit_ns;
|
||||
|
||||
return e_ns.starts_with(nsit_ns) || e_ns == nsit_ns;
|
||||
}
|
||||
|
||||
return std::get<common::regex>(nsit.value()) %=
|
||||
e.full_name(false);
|
||||
});
|
||||
|
||||
if (tvl::is_false(result))
|
||||
LOG_DBG("Element {} rejected by namespace_filter (package diagram)",
|
||||
e.full_name(false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto result = tvl::any_of(
|
||||
namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) {
|
||||
if (std::holds_alternative<namespace_>(nsit.value())) {
|
||||
return e.get_namespace().starts_with(
|
||||
std::get<namespace_>(nsit.value()));
|
||||
}
|
||||
|
||||
return std::get<common::regex>(nsit.value()) == e.full_name(false);
|
||||
return std::get<common::regex>(nsit.value()) %= e.full_name(false);
|
||||
});
|
||||
|
||||
if (tvl::is_false(result))
|
||||
LOG_DBG("Element {} rejected by namespace_filter", e.full_name(false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
element_filter::element_filter(
|
||||
@@ -249,9 +289,12 @@ element_filter::element_filter(
|
||||
{
|
||||
}
|
||||
|
||||
tvl::value_t element_filter::match(
|
||||
const diagram & /*d*/, const element &e) const
|
||||
tvl::value_t element_filter::match(const diagram &d, const element &e) const
|
||||
{
|
||||
// Do not apply element filter to packages in class diagrams
|
||||
if (d.type() == diagram_t::kClass && e.type_name() == "package")
|
||||
return std::nullopt;
|
||||
|
||||
return tvl::any_of(
|
||||
elements_.begin(), elements_.end(), [&e](const auto &el) {
|
||||
return ((el == e.full_name(false)) ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/diagram_filter.h
|
||||
* @file src/common/model/diagram_filter.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/element.cc
|
||||
* @file src/common/model/element.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -34,11 +34,7 @@ const namespace_ &element::using_namespace() const { return using_namespace_; }
|
||||
|
||||
inja::json element::context() const
|
||||
{
|
||||
inja::json ctx;
|
||||
ctx["name"] = name();
|
||||
ctx["type"] = type_name();
|
||||
ctx["alias"] = alias();
|
||||
ctx["full_name"] = full_name(false);
|
||||
inja::json ctx = diagram_element::context();
|
||||
ctx["namespace"] = get_namespace().to_string();
|
||||
if (const auto maybe_comment = comment(); maybe_comment.has_value()) {
|
||||
ctx["comment"] = maybe_comment.value();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/element.h
|
||||
* @file src/common/model/element.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/element_view.h
|
||||
* @file src/common/model/element_view.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/enums.cc
|
||||
* @file src/common/model/enums.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/enums.h
|
||||
* @file src/common/model/enums.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/namespace.cc
|
||||
* @file src/common/model/namespace.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/namespace.h
|
||||
* @file src/common/model/namespace.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/nested_trait.h
|
||||
* @file src/common/model/nested_trait.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/package.cc
|
||||
* @file src/common/model/package.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -40,4 +40,11 @@ bool package::is_deprecated() const { return is_deprecated_; }
|
||||
|
||||
void package::set_deprecated(bool deprecated) { is_deprecated_ = deprecated; }
|
||||
|
||||
std::optional<std::string> package::doxygen_link() const
|
||||
{
|
||||
auto name = full_name(false);
|
||||
util::replace_all(name, "_", "__");
|
||||
util::replace_all(name, "::", "_1_1");
|
||||
return fmt::format("namespace{}.html", name);
|
||||
}
|
||||
} // namespace clanguml::common::model
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/package.h
|
||||
* @file src/common/model/package.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -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,11 +52,29 @@ 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);
|
||||
|
||||
void add_package(std::unique_ptr<common::model::package> &&p);
|
||||
/**
|
||||
* @brief Generate Doxygen style HTML link for the class.
|
||||
*
|
||||
* This method generates a link, which can be used in SVG diagrams to
|
||||
* create links from classes to Doxygen documentation pages.
|
||||
*
|
||||
* @return Doxygen-style HTML link for the class.
|
||||
*/
|
||||
std::optional<std::string> doxygen_link() const override;
|
||||
|
||||
private:
|
||||
bool is_deprecated_{false};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/path.h
|
||||
* @file src/common/model/path.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -25,10 +25,30 @@
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
enum class path_type { kNamespace, kFilesystem };
|
||||
/**
|
||||
* @brief Type of diagram path
|
||||
*
|
||||
* Paths in diagrams represent the nest structure within a diagram, e.g.
|
||||
* a nested set of namespaces or nested set of directories.
|
||||
*/
|
||||
enum class path_type {
|
||||
kNamespace, /*!< Namespace path */
|
||||
kFilesystem /*!< Filesystem path */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Diagram path
|
||||
*
|
||||
* This class stores a diagram path, such as a namespace or directory
|
||||
* structure.
|
||||
*/
|
||||
class path {
|
||||
|
||||
/**
|
||||
* Returns the path separator based on the path type.
|
||||
*
|
||||
* @return Path separator
|
||||
*/
|
||||
const char *separator() const
|
||||
{
|
||||
switch (path_type_) {
|
||||
@@ -133,15 +153,36 @@ public:
|
||||
return left.to_string() < right.to_string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the path as string.
|
||||
*
|
||||
* @return String representation of the path.
|
||||
*/
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("{}", fmt::join(path_, std::string{separator()}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the path is empty.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
bool is_empty() const { return path_.empty(); }
|
||||
|
||||
/**
|
||||
* Return the number of elements in the path.
|
||||
*
|
||||
* @return Size of path.
|
||||
*/
|
||||
size_t size() const { return path_.size(); }
|
||||
|
||||
/**
|
||||
* Append path to path.
|
||||
*
|
||||
* @param right Path to append at the end.
|
||||
* @return New merged path.
|
||||
*/
|
||||
path operator|(const path &right) const
|
||||
{
|
||||
path res{*this};
|
||||
@@ -149,8 +190,18 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append path to the current path.
|
||||
*
|
||||
* @param right
|
||||
*/
|
||||
void operator|=(const path &right) { append(right); }
|
||||
|
||||
/**
|
||||
* Append path element to path.
|
||||
*
|
||||
* @return New path.
|
||||
*/
|
||||
path operator|(const std::string &right) const
|
||||
{
|
||||
path res{*this};
|
||||
@@ -158,6 +209,11 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append path element to the current path.
|
||||
*
|
||||
* @param right Path element to append.
|
||||
*/
|
||||
void operator|=(const std::string &right) { append(right); }
|
||||
|
||||
std::string &operator[](const unsigned int index) { return path_[index]; }
|
||||
@@ -167,8 +223,18 @@ public:
|
||||
return path_[index];
|
||||
}
|
||||
|
||||
void append(const std::string &ns) { path_.push_back(ns); }
|
||||
/**
|
||||
* Append path element to path.
|
||||
*
|
||||
* @return New path.
|
||||
*/
|
||||
void append(const std::string &name) { path_.push_back(name); }
|
||||
|
||||
/**
|
||||
* Append path to current path.
|
||||
*
|
||||
* @param ns Path to append.
|
||||
*/
|
||||
void append(const path &ns)
|
||||
{
|
||||
for (const auto &n : ns) {
|
||||
@@ -176,6 +242,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop the last element of the path.
|
||||
*/
|
||||
void pop_back()
|
||||
{
|
||||
if (!path_.empty()) {
|
||||
@@ -183,6 +252,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent of the last element in the path.
|
||||
*
|
||||
* @return Path to the parent of the last element, or nullopt.
|
||||
*/
|
||||
std::optional<path> parent() const
|
||||
{
|
||||
if (size() <= 1) {
|
||||
@@ -194,16 +268,34 @@ public:
|
||||
return {std::move(res)};
|
||||
}
|
||||
|
||||
bool starts_with(const path &right) const
|
||||
/**
|
||||
* Returns true if path starts with specified prefix.
|
||||
* @param prefix Path prefix to check.
|
||||
* @return
|
||||
*/
|
||||
bool starts_with(const path &prefix) const
|
||||
{
|
||||
return util::starts_with(path_, right.path_);
|
||||
return util::starts_with(path_, prefix.path_);
|
||||
}
|
||||
|
||||
bool ends_with(const path &right) const
|
||||
/**
|
||||
* Returns true if path ends with suffix
|
||||
* @param suffix Path suffix to check
|
||||
* @return
|
||||
*/
|
||||
bool ends_with(const path &suffix) const
|
||||
{
|
||||
return util::ends_with(path_, right.path_);
|
||||
return util::ends_with(path_, suffix.path_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the common prefix of 2 paths.
|
||||
*
|
||||
* If no common prefix exists between 2 paths, the result is an empty path.
|
||||
*
|
||||
* @param right Path to compare
|
||||
* @return Common path prefix
|
||||
*/
|
||||
path common_path(const path &right) const
|
||||
{
|
||||
path res{};
|
||||
@@ -216,6 +308,14 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the current path relative to the other path, if possible.
|
||||
*
|
||||
* If not, return the original path.
|
||||
*
|
||||
* @param right Parent path
|
||||
* @return Path relative to `right`
|
||||
*/
|
||||
path relative_to(const path &right) const
|
||||
{
|
||||
path res{*this};
|
||||
@@ -226,15 +326,21 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string relative(const std::string &name) const
|
||||
/**
|
||||
* Make path represented as a string relative to the current path.
|
||||
*
|
||||
* @param ns Path to make relative against *this.
|
||||
* @return Relative path.
|
||||
*/
|
||||
std::string relative(const std::string &ns) const
|
||||
{
|
||||
if (is_empty())
|
||||
return name;
|
||||
return ns;
|
||||
|
||||
if (name == to_string())
|
||||
return name;
|
||||
if (ns == to_string())
|
||||
return ns;
|
||||
|
||||
auto res = name;
|
||||
auto res = ns;
|
||||
auto ns_prefix = to_string() + std::string{separator()};
|
||||
|
||||
auto it = res.find(ns_prefix);
|
||||
@@ -246,6 +352,11 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the last element in the path.
|
||||
*
|
||||
* @return Name of the last element in the path.
|
||||
*/
|
||||
std::string name() const
|
||||
{
|
||||
assert(size() > 0);
|
||||
@@ -265,6 +376,11 @@ public:
|
||||
path::container_type::const_iterator begin() const { return path_.begin(); }
|
||||
path::container_type::const_iterator end() const { return path_.end(); }
|
||||
|
||||
/**
|
||||
* Get path type.
|
||||
*
|
||||
* @return Path type.
|
||||
*/
|
||||
path_type type() const { return path_type_; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/relationship.cc
|
||||
* @file src/common/model/relationship.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/relationship.h
|
||||
* @file src/common/model/relationship.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -25,33 +25,119 @@
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
/**
|
||||
* @brief Class representing any relationship other than inheritance
|
||||
*
|
||||
* This class represents all kinds of relationships between diagram elements,
|
||||
* except for inheritance which are handled in a special way
|
||||
* (See @ref clanguml::class_diagram::model::class_parent).
|
||||
*
|
||||
* @embed{relationship_context_class.svg}
|
||||
*/
|
||||
class relationship : public common::model::decorated_element,
|
||||
public common::model::stylable_element {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param type Type of relationship
|
||||
* @param destination Id of the relationship target
|
||||
* @param access Access scope of the relationship
|
||||
* @param label Relationship label
|
||||
* @param multiplicity_source Multiplicity at the source
|
||||
* @param multiplicity_destination Multiplicity at the destination
|
||||
*/
|
||||
relationship(relationship_t type, int64_t destination,
|
||||
access_t access = access_t::kPublic, std::string label = "",
|
||||
std::string multiplicity_source = "",
|
||||
std::string multiplicity_destination = "");
|
||||
|
||||
virtual ~relationship() = default;
|
||||
~relationship() override = default;
|
||||
|
||||
/**
|
||||
* Set the type of relatinoship.
|
||||
*
|
||||
* @param type Type of relationship.
|
||||
*/
|
||||
void set_type(relationship_t type) noexcept;
|
||||
|
||||
/**
|
||||
* Get the type of relatinoship.
|
||||
*
|
||||
* @return Type of relationship.
|
||||
*/
|
||||
relationship_t type() const noexcept;
|
||||
|
||||
/**
|
||||
* Set id of the diagram element which is the target of this
|
||||
* relationship.
|
||||
*
|
||||
* @param destination Target element id.
|
||||
*/
|
||||
void set_destination(int64_t destination);
|
||||
|
||||
/**
|
||||
* Get the id of the target element of this relationship.
|
||||
*
|
||||
* @return Target element id.
|
||||
*/
|
||||
clanguml::common::id_t destination() const;
|
||||
|
||||
/**
|
||||
* Set the relationship multiplicity at the source.
|
||||
*
|
||||
* @param multiplicity_source Source multiplicity.
|
||||
*/
|
||||
void set_multiplicity_source(const std::string &multiplicity_source);
|
||||
|
||||
/**
|
||||
* Set the relationship multiplicity at the source.
|
||||
*
|
||||
* @return Source multiplicity.
|
||||
*/
|
||||
std::string multiplicity_source() const;
|
||||
|
||||
/**
|
||||
* Set the relationship multiplicity at the destination.
|
||||
*
|
||||
* @param multiplicity_destination Destination multiplicity.
|
||||
*/
|
||||
void set_multiplicity_destination(
|
||||
const std::string &multiplicity_destination);
|
||||
|
||||
/**
|
||||
* Set the relationship multiplicity at the destination.
|
||||
*
|
||||
* @return Destination multiplicity.
|
||||
*/
|
||||
std::string multiplicity_destination() const;
|
||||
|
||||
/**
|
||||
* Set relationship label.
|
||||
*
|
||||
* @param label Relationship label.
|
||||
*/
|
||||
void set_label(const std::string &label);
|
||||
|
||||
/**
|
||||
* Get the relationship label.
|
||||
*
|
||||
* @return Relationoship label.
|
||||
*/
|
||||
std::string label() const;
|
||||
|
||||
/**
|
||||
* Set the access scope for this relationship (e.g `public`)
|
||||
*
|
||||
* @param scope Access scope
|
||||
*/
|
||||
void set_access(access_t scope) noexcept;
|
||||
|
||||
/**
|
||||
* Get the relationship access scope (e.g. `public`).
|
||||
*
|
||||
* @return Access scope
|
||||
*/
|
||||
access_t access() const noexcept;
|
||||
|
||||
friend bool operator==(const relationship &l, const relationship &r);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/source_file.cc
|
||||
* @file src/common/model/source_file.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/source_file.h
|
||||
* @file src/common/model/source_file.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -34,7 +34,14 @@
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
enum class source_file_t { kDirectory, kHeader, kImplementation };
|
||||
/**
|
||||
* This enum represents different kinds of files in the diagram.
|
||||
*/
|
||||
enum class source_file_t {
|
||||
kDirectory, /*!< Diagram element is a directory */
|
||||
kHeader, /*!< Diagram element is a header */
|
||||
kImplementation /*!< Diagram element is a source file (e.g. cpp) */
|
||||
};
|
||||
|
||||
std::string to_string(source_file_t sf);
|
||||
|
||||
@@ -48,6 +55,11 @@ struct fs_path_sep {
|
||||
|
||||
using filesystem_path = common::model::path;
|
||||
|
||||
/**
|
||||
* @brief Diagram element representing some file or directory.
|
||||
*
|
||||
* @embed{source_file_hierarchy_class.svg}
|
||||
*/
|
||||
class source_file
|
||||
: public common::model::diagram_element,
|
||||
public common::model::stylable_element,
|
||||
@@ -66,16 +78,6 @@ public:
|
||||
set_id(common::to_id(preferred));
|
||||
}
|
||||
|
||||
void set_path(const filesystem_path &p) { path_ = p; }
|
||||
|
||||
void set_absolute() { is_absolute_ = true; }
|
||||
|
||||
bool is_absolute() const { return is_absolute_; }
|
||||
|
||||
void set_type(source_file_t type) { type_ = type; }
|
||||
|
||||
source_file_t type() const { return type_; }
|
||||
|
||||
source_file(const source_file &) = delete;
|
||||
source_file(source_file &&) = default;
|
||||
source_file &operator=(const source_file &) = delete;
|
||||
@@ -87,15 +89,64 @@ public:
|
||||
(type_ == right.type_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path to the element in the diagram.
|
||||
*
|
||||
* @param p Diagram path.
|
||||
*/
|
||||
void set_path(const filesystem_path &p) { path_ = p; }
|
||||
|
||||
/**
|
||||
* Is the elements path absolute?
|
||||
*
|
||||
* @return True if the elements path is absolute.
|
||||
*/
|
||||
bool is_absolute() const { return is_absolute_; }
|
||||
|
||||
/**
|
||||
* Set the type of the source file.
|
||||
*
|
||||
* @param type Type of the source file.
|
||||
*/
|
||||
void set_type(source_file_t type) { type_ = type; }
|
||||
|
||||
/**
|
||||
* Get the source file elements type.
|
||||
*
|
||||
* @return Type of the source file.
|
||||
*/
|
||||
source_file_t type() const { return type_; }
|
||||
|
||||
/**
|
||||
* Get the source file's parent path.
|
||||
*
|
||||
* @return Source file parent path.
|
||||
*/
|
||||
const filesystem_path &path() const { return path_; }
|
||||
|
||||
/**
|
||||
* Return the full path string, i.e. parent path and elements name.
|
||||
*
|
||||
* @return Full source file path as string.
|
||||
*/
|
||||
std::string full_name(bool /*relative*/) const override
|
||||
{
|
||||
return (path_ | name()).to_string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return full path, i.e. parent path and elements name.
|
||||
*
|
||||
* @return Full source file path.
|
||||
*/
|
||||
auto full_path() const { return path() | name(); }
|
||||
|
||||
/**
|
||||
* Convert the source file path to std::filesystem::path, relative to `base`
|
||||
*
|
||||
* @param base Base path
|
||||
* @return Filesystem path to the source file.
|
||||
*/
|
||||
std::filesystem::path fs_path(const std::filesystem::path &base = {}) const
|
||||
{
|
||||
std::filesystem::path res;
|
||||
@@ -114,6 +165,11 @@ public:
|
||||
return res.lexically_normal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return inja context for this element.
|
||||
*
|
||||
* @return Inja context.
|
||||
*/
|
||||
inja::json context() const override
|
||||
{
|
||||
inja::json ctx = diagram_element::context();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/source_location.cc
|
||||
* @file src/common/model/source_location.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/source_location.h
|
||||
* @file src/common/model/source_location.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -22,6 +22,11 @@
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
/**
|
||||
* @brief Base class of all diagram elements that have source location.
|
||||
*
|
||||
* @embed{source_location_hierarchy_class.svg}
|
||||
*/
|
||||
class source_location {
|
||||
public:
|
||||
source_location() = default;
|
||||
@@ -32,31 +37,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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/stylable_element.cc
|
||||
* @file src/common/model/stylable_element.cc
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/common/model/stylable_element.h
|
||||
* @file src/common/model/stylable_element.h
|
||||
*
|
||||
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -21,9 +21,25 @@
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
/**
|
||||
* @brief Diagram elements to which style can be applied.
|
||||
*
|
||||
* @embed{stylable_element_hierarchy_class.svg}
|
||||
*/
|
||||
class stylable_element {
|
||||
public:
|
||||
/**
|
||||
* Set style.
|
||||
*
|
||||
* @param style Style specification
|
||||
*/
|
||||
void set_style(const std::string &style);
|
||||
|
||||
/**
|
||||
* Get style
|
||||
*
|
||||
* @return Style specification
|
||||
*/
|
||||
std::string style() const;
|
||||
|
||||
private:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user