Merge pull request #9 from bkryza/remove-usr-from-class-diagram-generator
Remove usr from class diagram generator
8
.github/workflows/build.yml
vendored
@@ -11,8 +11,12 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install deps
|
||||
run: sudo apt install ccache cmake libyaml-cpp-dev libfmt-dev libspdlog-dev clang-12 libclang-12-dev libclang-cpp12-dev
|
||||
run: sudo apt install git make gcc-10 g++-10 ccache cmake libyaml-cpp-dev libfmt-dev libspdlog-dev clang-12 libclang-12-dev libclang-cpp12-dev
|
||||
- name: Select g++ version
|
||||
run: |
|
||||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10
|
||||
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10
|
||||
- name: Build and unit test
|
||||
run: |
|
||||
make debug
|
||||
NUMPROC=2 make debug
|
||||
make test
|
||||
|
||||
1
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1 @@
|
||||
Just be nice
|
||||
5
Makefile
@@ -20,6 +20,8 @@
|
||||
|
||||
.DEFAULT_GOAL := debug
|
||||
|
||||
NUMPROC ?= $(shell nproc)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf debug release
|
||||
@@ -35,7 +37,8 @@ release/CMakeLists.txt:
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
debug: debug/CMakeLists.txt
|
||||
make -C debug -j
|
||||
echo "Using ${NUMPROC} cores"
|
||||
make -C debug -j$(NUMPROC)
|
||||
|
||||
release: release/CMakeLists.txt
|
||||
make -C release -j
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||

|
||||
|
||||
`clang-uml` is an automatic [PlantUML](https://plantuml.com) class and sequence
|
||||
`clang-uml` is an automatic C++ to [PlantUML](https://plantuml.com) class and sequence
|
||||
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
|
||||
existing project code. The configuration file or files for `clang-uml` define the
|
||||
|
||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
@@ -17,36 +17,6 @@ diagrams:
|
||||
|
||||
```
|
||||
## Source code
|
||||
File t00018_impl.cc
|
||||
```cpp
|
||||
#include "t00018_impl.h"
|
||||
#include "t00018.h"
|
||||
|
||||
namespace clanguml {
|
||||
namespace t00018 {
|
||||
namespace impl {
|
||||
|
||||
widget::widget(int n)
|
||||
: n(n)
|
||||
{
|
||||
}
|
||||
|
||||
void widget::draw(const clanguml::t00018::widget &w) const
|
||||
{
|
||||
if (w.shown())
|
||||
std::cout << "drawing a const widget " << n << '\n';
|
||||
}
|
||||
|
||||
void widget::draw(const clanguml::t00018::widget &w)
|
||||
{
|
||||
if (w.shown())
|
||||
std::cout << "drawing a non-const widget " << n << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
File t00018_impl.h
|
||||
```cpp
|
||||
#pragma once
|
||||
@@ -131,6 +101,36 @@ widget &widget::operator=(widget &&) = default;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
File t00018_impl.cc
|
||||
```cpp
|
||||
#include "t00018_impl.h"
|
||||
#include "t00018.h"
|
||||
|
||||
namespace clanguml {
|
||||
namespace t00018 {
|
||||
namespace impl {
|
||||
|
||||
widget::widget(int n)
|
||||
: n(n)
|
||||
{
|
||||
}
|
||||
|
||||
void widget::draw(const clanguml::t00018::widget &w) const
|
||||
{
|
||||
if (w.shown())
|
||||
std::cout << "drawing a const widget " << n << '\n';
|
||||
}
|
||||
|
||||
void widget::draw(const clanguml::t00018::widget &w)
|
||||
{
|
||||
if (w.shown())
|
||||
std::cout << "drawing a non-const widget " << n << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
## Generated UML diagrams
|
||||

|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
@@ -17,21 +17,25 @@ diagrams:
|
||||
|
||||
```
|
||||
## Source code
|
||||
File t00019.cc
|
||||
File t00019_layer2.h
|
||||
```cpp
|
||||
#include "t00019_base.h"
|
||||
#include "t00019_layer1.h"
|
||||
#include "t00019_layer2.h"
|
||||
#include "t00019_layer3.h"
|
||||
|
||||
#include <memory>
|
||||
#pragma once
|
||||
|
||||
namespace clanguml {
|
||||
namespace t00019 {
|
||||
|
||||
class A {
|
||||
public:
|
||||
std::unique_ptr<Layer1<Layer2<Layer3<Base>>>> layers;
|
||||
template <typename LowerLayer> class Layer2 : public LowerLayer {
|
||||
|
||||
using LowerLayer::LowerLayer;
|
||||
|
||||
using LowerLayer::m1;
|
||||
|
||||
using LowerLayer::m2;
|
||||
|
||||
int all_calls_count() const
|
||||
{
|
||||
return LowerLayer::m1_calls() + LowerLayer::m2_calls();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -89,6 +93,26 @@ template <typename LowerLayer> class Layer1 : public LowerLayer {
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
File t00019.cc
|
||||
```cpp
|
||||
#include "t00019_base.h"
|
||||
#include "t00019_layer1.h"
|
||||
#include "t00019_layer2.h"
|
||||
#include "t00019_layer3.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace clanguml {
|
||||
namespace t00019 {
|
||||
|
||||
class A {
|
||||
public:
|
||||
std::unique_ptr<Layer1<Layer2<Layer3<Base>>>> layers;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
File t00019_layer3.h
|
||||
```cpp
|
||||
@@ -126,30 +150,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
File t00019_layer2.h
|
||||
```cpp
|
||||
#pragma once
|
||||
|
||||
namespace clanguml {
|
||||
namespace t00019 {
|
||||
|
||||
template <typename LowerLayer> class Layer2 : public LowerLayer {
|
||||
|
||||
using LowerLayer::LowerLayer;
|
||||
|
||||
using LowerLayer::m1;
|
||||
|
||||
using LowerLayer::m2;
|
||||
|
||||
int all_calls_count() const
|
||||
{
|
||||
return LowerLayer::m1_calls() + LowerLayer::m2_calls();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
## Generated UML diagrams
|
||||

|
||||
|
||||
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/puml/class_diagram_generator.cc
|
||||
* src/class_diagram/generators/plantuml/class_diagram_generator.cc
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
#include "class_diagram_generator.h"
|
||||
|
||||
namespace clanguml::generators::class_diagram {
|
||||
#include "util/error.h"
|
||||
|
||||
namespace clanguml::class_diagram::generators::plantuml {
|
||||
|
||||
namespace puml {
|
||||
std::string relative_to(std::string n, std::string c)
|
||||
{
|
||||
if (c.rfind(n) == std::string::npos)
|
||||
@@ -29,10 +30,6 @@ std::string relative_to(std::string n, std::string c)
|
||||
return c.substr(n.size() + 2);
|
||||
}
|
||||
|
||||
//
|
||||
// generator
|
||||
//
|
||||
|
||||
generator::generator(
|
||||
clanguml::config::class_diagram &config, diagram_model &model)
|
||||
: m_config(config)
|
||||
@@ -106,7 +103,7 @@ void generator::generate_alias(const class_ &c, std::ostream &ostr) const
|
||||
if (c.is_abstract())
|
||||
class_type = "abstract";
|
||||
|
||||
ostr << class_type << " \"" << c.full_name(m_config.using_namespace);
|
||||
ostr << class_type << " \"" << c.full_name();
|
||||
|
||||
ostr << "\" as " << c.alias() << '\n';
|
||||
}
|
||||
@@ -114,7 +111,7 @@ void generator::generate_alias(const class_ &c, std::ostream &ostr) const
|
||||
void generator::generate_alias(const enum_ &e, std::ostream &ostr) const
|
||||
{
|
||||
ostr << "enum"
|
||||
<< " \"" << e.full_name(m_config.using_namespace);
|
||||
<< " \"" << e.full_name();
|
||||
|
||||
ostr << "\" as " << e.alias() << '\n';
|
||||
}
|
||||
@@ -130,32 +127,32 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
|
||||
|
||||
ostr << class_type << " " << c.alias();
|
||||
|
||||
if (!c.style.empty())
|
||||
ostr << " " << c.style;
|
||||
if (!c.style().empty())
|
||||
ostr << " " << c.style();
|
||||
|
||||
ostr << " {" << '\n';
|
||||
|
||||
//
|
||||
// Process methods
|
||||
//
|
||||
for (const auto &m : c.methods) {
|
||||
if (!m_config.should_include(m.scope))
|
||||
for (const auto &m : c.methods()) {
|
||||
if (!m_config.should_include(m.scope()))
|
||||
continue;
|
||||
|
||||
if (m.is_pure_virtual)
|
||||
if (m.is_pure_virtual())
|
||||
ostr << "{abstract} ";
|
||||
|
||||
if (m.is_static)
|
||||
if (m.is_static())
|
||||
ostr << "{static} ";
|
||||
|
||||
std::string type{m.type};
|
||||
std::string type{m.type()};
|
||||
|
||||
ostr << to_string(m.scope) << m.name;
|
||||
ostr << to_string(m.scope()) << m.name();
|
||||
|
||||
ostr << "(";
|
||||
if (true) { // TODO: add option to disable parameter generation
|
||||
std::vector<std::string> params;
|
||||
std::transform(m.parameters.begin(), m.parameters.end(),
|
||||
std::transform(m.parameters().cbegin(), m.parameters().cend(),
|
||||
std::back_inserter(params), [this](const auto &mp) {
|
||||
return mp.to_string(m_config.using_namespace);
|
||||
});
|
||||
@@ -163,15 +160,15 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
|
||||
}
|
||||
ostr << ")";
|
||||
|
||||
if (m.is_const)
|
||||
if (m.is_const())
|
||||
ostr << " const";
|
||||
|
||||
assert(!(m.is_pure_virtual && m.is_defaulted));
|
||||
assert(!(m.is_pure_virtual() && m.is_defaulted()));
|
||||
|
||||
if (m.is_pure_virtual)
|
||||
if (m.is_pure_virtual())
|
||||
ostr << " = 0";
|
||||
|
||||
if (m.is_defaulted)
|
||||
if (m.is_defaulted())
|
||||
ostr << " = default";
|
||||
|
||||
ostr << " : " << ns_relative(uns, type);
|
||||
@@ -186,49 +183,35 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
|
||||
|
||||
std::stringstream all_relations_str;
|
||||
std::set<std::string> unique_relations;
|
||||
for (const auto &r : c.relationships) {
|
||||
if (!m_config.should_include_relationship(name(r.type)))
|
||||
for (const auto &r : c.relationships()) {
|
||||
if (!m_config.should_include_relationship(name(r.type())))
|
||||
continue;
|
||||
|
||||
LOG_DBG("== Processing relationship {}", to_string(r.type));
|
||||
LOG_DBG("== Processing relationship {}", to_string(r.type()));
|
||||
|
||||
std::stringstream relstr;
|
||||
std::string destination;
|
||||
try {
|
||||
if (r.destination.find("#") != std::string::npos ||
|
||||
r.destination.find("@") != std::string::npos) {
|
||||
destination = m_model.usr_to_name(uns, r.destination);
|
||||
|
||||
// If something went wrong and we have an empty destination
|
||||
// generate the relationship but comment it out for
|
||||
// debugging
|
||||
if (destination.empty()) {
|
||||
relstr << "' ";
|
||||
destination = r.destination;
|
||||
}
|
||||
}
|
||||
else {
|
||||
destination = r.destination;
|
||||
}
|
||||
destination = r.destination();
|
||||
|
||||
LOG_DBG("=== Destination is: {}", destination);
|
||||
|
||||
std::string puml_relation;
|
||||
if (!r.multiplicity_source.empty())
|
||||
puml_relation += "\"" + r.multiplicity_source + "\" ";
|
||||
if (!r.multiplicity_source().empty())
|
||||
puml_relation += "\"" + r.multiplicity_source() + "\" ";
|
||||
|
||||
puml_relation += to_string(r.type, r.style);
|
||||
puml_relation += to_string(r.type(), r.style());
|
||||
|
||||
if (!r.multiplicity_destination.empty())
|
||||
puml_relation += " \"" + r.multiplicity_destination + "\"";
|
||||
if (!r.multiplicity_destination().empty())
|
||||
puml_relation += " \"" + r.multiplicity_destination() + "\"";
|
||||
|
||||
relstr << m_model.to_alias(uns, ns_relative(uns, c.full_name(uns)))
|
||||
<< " " << puml_relation << " "
|
||||
<< m_model.to_alias(uns, ns_relative(uns, destination));
|
||||
relstr << m_model.to_alias(ns_relative(uns, c.full_name())) << " "
|
||||
<< puml_relation << " "
|
||||
<< m_model.to_alias(ns_relative(uns, destination));
|
||||
|
||||
if (!r.label.empty()) {
|
||||
relstr << " : " << to_string(r.scope) << r.label;
|
||||
rendered_relations.emplace(r.label);
|
||||
if (!r.label().empty()) {
|
||||
relstr << " : " << to_string(r.scope()) << r.label();
|
||||
rendered_relations.emplace(r.label());
|
||||
}
|
||||
|
||||
if (unique_relations.count(relstr.str()) == 0) {
|
||||
@@ -244,52 +227,51 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
|
||||
catch (error::uml_alias_missing &e) {
|
||||
LOG_ERROR("=== Skipping {} relation from {} to {} due "
|
||||
"to: {}",
|
||||
to_string(r.type), c.full_name(uns), destination, e.what());
|
||||
to_string(r.type()), c.full_name(), destination, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Process members
|
||||
//
|
||||
for (const auto &m : c.members) {
|
||||
if (!m_config.should_include(m.scope))
|
||||
for (const auto &m : c.members()) {
|
||||
if (!m_config.should_include(m.scope()))
|
||||
continue;
|
||||
|
||||
if (!m_config.include_relations_also_as_members &&
|
||||
rendered_relations.find(m.name) != rendered_relations.end())
|
||||
rendered_relations.find(m.name()) != rendered_relations.end())
|
||||
continue;
|
||||
|
||||
if (m.is_static)
|
||||
if (m.is_static())
|
||||
ostr << "{static} ";
|
||||
|
||||
ostr << to_string(m.scope) << m.name << " : "
|
||||
<< ns_relative(uns, m.type) << '\n';
|
||||
ostr << to_string(m.scope()) << m.name() << " : "
|
||||
<< ns_relative(uns, m.type()) << '\n';
|
||||
}
|
||||
|
||||
ostr << "}" << '\n';
|
||||
|
||||
if (m_config.should_include_relationship("inheritance"))
|
||||
for (const auto &b : c.bases) {
|
||||
for (const auto &b : c.parents()) {
|
||||
std::stringstream relstr;
|
||||
try {
|
||||
relstr << m_model.to_alias(uns, ns_relative(uns, b.name))
|
||||
relstr << m_model.to_alias(ns_relative(uns, b.name()))
|
||||
<< " <|-- "
|
||||
<< m_model.to_alias(
|
||||
uns, ns_relative(uns, c.full_name(uns)))
|
||||
<< m_model.to_alias(ns_relative(uns, c.full_name()))
|
||||
<< '\n';
|
||||
ostr << relstr.str();
|
||||
}
|
||||
catch (error::uml_alias_missing &e) {
|
||||
LOG_ERROR("=== Skipping inheritance relation from {} to {} due "
|
||||
"to: {}",
|
||||
b.name, c.name, e.what());
|
||||
b.name(), c.name(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Process notes
|
||||
//
|
||||
for (auto decorator : c.decorators) {
|
||||
for (auto decorator : c.decorators()) {
|
||||
auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
|
||||
if (note && note->applies_to_diagram(m_config.name)) {
|
||||
ostr << "note " << note->position << " of " << c.alias() << '\n'
|
||||
@@ -306,45 +288,35 @@ void generator::generate(const enum_ &e, std::ostream &ostr) const
|
||||
{
|
||||
ostr << "enum " << e.alias();
|
||||
|
||||
if (!e.style.empty())
|
||||
ostr << " " << e.style;
|
||||
if (!e.style().empty())
|
||||
ostr << " " << e.style();
|
||||
|
||||
ostr << " {" << '\n';
|
||||
|
||||
for (const auto &enum_constant : e.constants) {
|
||||
for (const auto &enum_constant : e.constants()) {
|
||||
ostr << enum_constant << '\n';
|
||||
}
|
||||
|
||||
ostr << "}" << '\n';
|
||||
|
||||
for (const auto &r : e.relationships) {
|
||||
if (!m_config.should_include_relationship(name(r.type)))
|
||||
for (const auto &r : e.relationships()) {
|
||||
if (!m_config.should_include_relationship(name(r.type())))
|
||||
continue;
|
||||
|
||||
std::string destination;
|
||||
std::stringstream relstr;
|
||||
try {
|
||||
if (r.destination.find("#") != std::string::npos ||
|
||||
r.destination.find("@") != std::string::npos) {
|
||||
destination = m_model.usr_to_name(
|
||||
m_config.using_namespace, r.destination);
|
||||
if (destination.empty()) {
|
||||
relstr << "' ";
|
||||
destination = r.destination;
|
||||
}
|
||||
}
|
||||
else {
|
||||
destination = r.destination;
|
||||
}
|
||||
|
||||
relstr << m_model.to_alias(m_config.using_namespace,
|
||||
ns_relative(m_config.using_namespace, e.name))
|
||||
<< " " << to_string(r.type) << " "
|
||||
<< m_model.to_alias(m_config.using_namespace,
|
||||
destination = r.destination();
|
||||
|
||||
relstr << m_model.to_alias(
|
||||
ns_relative(m_config.using_namespace, e.name()))
|
||||
<< " " << to_string(r.type()) << " "
|
||||
<< m_model.to_alias(
|
||||
ns_relative(m_config.using_namespace, destination));
|
||||
|
||||
if (!r.label.empty())
|
||||
relstr << " : " << r.label;
|
||||
if (!r.label().empty())
|
||||
relstr << " : " << r.label();
|
||||
|
||||
relstr << '\n';
|
||||
|
||||
@@ -353,14 +325,14 @@ void generator::generate(const enum_ &e, std::ostream &ostr) const
|
||||
catch (error::uml_alias_missing &ex) {
|
||||
LOG_ERROR("Skipping {} relation from {} to {} due "
|
||||
"to: {}",
|
||||
to_string(r.type), e.name, destination, ex.what());
|
||||
to_string(r.type()), e.full_name(), destination, ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Process notes
|
||||
//
|
||||
for (auto decorator : e.decorators) {
|
||||
for (auto decorator : e.decorators()) {
|
||||
auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
|
||||
if (note && note->applies_to_diagram(m_config.name)) {
|
||||
ostr << "note " << note->position << " of " << e.alias() << '\n'
|
||||
@@ -378,9 +350,8 @@ void generator::generate(std::ostream &ostr) const
|
||||
std::string note{b};
|
||||
std::tuple<std::string, size_t, size_t> alias_match;
|
||||
while (util::find_element_alias(note, alias_match)) {
|
||||
auto alias = m_model.to_alias(m_config.using_namespace,
|
||||
ns_relative(
|
||||
m_config.using_namespace, std::get<0>(alias_match)));
|
||||
auto alias = m_model.to_alias(ns_relative(
|
||||
m_config.using_namespace, std::get<0>(alias_match)));
|
||||
note.replace(
|
||||
std::get<1>(alias_match), std::get<2>(alias_match), alias);
|
||||
}
|
||||
@@ -388,24 +359,24 @@ void generator::generate(std::ostream &ostr) const
|
||||
}
|
||||
|
||||
if (m_config.should_include_entities("classes")) {
|
||||
for (const auto &c : m_model.classes) {
|
||||
if (!c.is_template_instantiation &&
|
||||
!m_config.should_include(c.name))
|
||||
for (const auto &c : m_model.classes()) {
|
||||
if (!c.is_template_instantiation() &&
|
||||
!m_config.should_include(c.name()))
|
||||
continue;
|
||||
generate_alias(c, ostr);
|
||||
ostr << '\n';
|
||||
}
|
||||
|
||||
for (const auto &e : m_model.enums) {
|
||||
if (!m_config.should_include(e.name))
|
||||
for (const auto &e : m_model.enums()) {
|
||||
if (!m_config.should_include(e.name()))
|
||||
continue;
|
||||
generate_alias(e, ostr);
|
||||
ostr << '\n';
|
||||
}
|
||||
|
||||
for (const auto &c : m_model.classes) {
|
||||
if (!c.is_template_instantiation &&
|
||||
!m_config.should_include(c.name))
|
||||
for (const auto &c : m_model.classes()) {
|
||||
if (!c.is_template_instantiation() &&
|
||||
!m_config.should_include(c.name()))
|
||||
continue;
|
||||
generate(c, ostr);
|
||||
ostr << '\n';
|
||||
@@ -413,7 +384,7 @@ void generator::generate(std::ostream &ostr) const
|
||||
}
|
||||
|
||||
if (m_config.should_include_entities("enums"))
|
||||
for (const auto &e : m_model.enums) {
|
||||
for (const auto &e : m_model.enums()) {
|
||||
generate(e, ostr);
|
||||
ostr << '\n';
|
||||
}
|
||||
@@ -423,9 +394,8 @@ void generator::generate(std::ostream &ostr) const
|
||||
std::string note{b};
|
||||
std::tuple<std::string, size_t, size_t> alias_match;
|
||||
while (util::find_element_alias(note, alias_match)) {
|
||||
auto alias = m_model.to_alias(m_config.using_namespace,
|
||||
ns_relative(
|
||||
m_config.using_namespace, std::get<0>(alias_match)));
|
||||
auto alias = m_model.to_alias(ns_relative(
|
||||
m_config.using_namespace, std::get<0>(alias_match)));
|
||||
note.replace(
|
||||
std::get<1>(alias_match), std::get<2>(alias_match), alias);
|
||||
}
|
||||
@@ -439,15 +409,14 @@ std::ostream &operator<<(std::ostream &os, const generator &g)
|
||||
g.generate(os);
|
||||
return os;
|
||||
}
|
||||
} // namespace puml
|
||||
|
||||
clanguml::model::class_diagram::diagram generate(
|
||||
clanguml::class_diagram::model::diagram generate(
|
||||
cppast::libclang_compilation_database &db, const std::string &name,
|
||||
clanguml::config::class_diagram &diagram)
|
||||
{
|
||||
spdlog::info("Generating diagram {}.puml", name);
|
||||
clanguml::model::class_diagram::diagram d;
|
||||
d.name = name;
|
||||
clanguml::class_diagram::model::diagram d;
|
||||
d.set_name(name);
|
||||
|
||||
// Get all translation units matching the glob from diagram
|
||||
// configuration
|
||||
@@ -464,7 +433,8 @@ clanguml::model::class_diagram::diagram generate(
|
||||
type_safe::ref(idx)};
|
||||
|
||||
// Process all matching translation units
|
||||
clanguml::visitor::class_diagram::tu_visitor ctx(idx, d, diagram);
|
||||
clanguml::class_diagram::visitor::translation_unit_visitor ctx(
|
||||
idx, d, diagram);
|
||||
cppast::parse_files(parser, translation_units, db);
|
||||
for (auto &file : parser.files())
|
||||
ctx(file);
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/puml/class_diagram_generator.h
|
||||
* src/class_diagram/generators/plantuml/class_diagram_generator.h
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -17,10 +17,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class_diagram/model/class.h"
|
||||
#include "class_diagram/model/class_relationship.h"
|
||||
#include "class_diagram/model/diagram.h"
|
||||
#include "class_diagram/model/enum.h"
|
||||
#include "class_diagram/visitor/translation_unit_visitor.h"
|
||||
#include "config/config.h"
|
||||
#include "cx/compilation_database.h"
|
||||
#include "uml/class_diagram_model.h"
|
||||
#include "uml/class_diagram_visitor.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
@@ -33,16 +36,16 @@
|
||||
#include <sstream>
|
||||
|
||||
namespace clanguml {
|
||||
namespace generators {
|
||||
namespace class_diagram {
|
||||
namespace puml {
|
||||
namespace generators {
|
||||
namespace plantuml {
|
||||
|
||||
using diagram_config = clanguml::config::class_diagram::diagram;
|
||||
using diagram_model = clanguml::model::class_diagram::diagram;
|
||||
using clanguml::model::class_diagram::class_;
|
||||
using clanguml::model::class_diagram::enum_;
|
||||
using clanguml::model::class_diagram::relationship_t;
|
||||
using clanguml::model::class_diagram::scope_t;
|
||||
using diagram_config = clanguml::class_diagram::model::diagram;
|
||||
using diagram_model = clanguml::class_diagram::model::diagram;
|
||||
using clanguml::class_diagram::model::class_;
|
||||
using clanguml::class_diagram::model::enum_;
|
||||
using clanguml::class_diagram::model::relationship_t;
|
||||
using clanguml::class_diagram::model::scope_t;
|
||||
using namespace clanguml::util;
|
||||
|
||||
std::string relative_to(std::string n, std::string c);
|
||||
@@ -74,12 +77,11 @@ private:
|
||||
diagram_model &m_model;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
clanguml::model::class_diagram::diagram generate(
|
||||
clanguml::class_diagram::model::diagram generate(
|
||||
cppast::libclang_compilation_database &db, const std::string &name,
|
||||
clanguml::config::class_diagram &diagram);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
143
src/class_diagram/model/class.cc
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* src/class_diagram/model/class.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class.h"
|
||||
|
||||
#include "util/util.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class_::class_(const std::vector<std::string> &using_namespaces)
|
||||
: element{using_namespaces}
|
||||
{
|
||||
}
|
||||
|
||||
bool class_::is_struct() const { return is_struct_; }
|
||||
|
||||
void class_::is_struct(bool is_struct) { is_struct_ = is_struct; }
|
||||
|
||||
bool class_::is_template() const { return is_template_; }
|
||||
|
||||
void class_::is_template(bool is_template) { is_template_ = is_template; }
|
||||
|
||||
bool class_::is_template_instantiation() const
|
||||
{
|
||||
return is_template_instantiation_;
|
||||
}
|
||||
|
||||
void class_::is_template_instantiation(bool is_template_instantiation)
|
||||
{
|
||||
is_template_instantiation_ = is_template_instantiation;
|
||||
}
|
||||
|
||||
void class_::add_member(class_member &&member)
|
||||
{
|
||||
members_.emplace_back(std::move(member));
|
||||
}
|
||||
|
||||
void class_::add_method(class_method &&method)
|
||||
{
|
||||
methods_.emplace_back(std::move(method));
|
||||
}
|
||||
|
||||
void class_::add_parent(class_parent &&parent)
|
||||
{
|
||||
bases_.emplace_back(std::move(parent));
|
||||
}
|
||||
|
||||
void class_::add_template(class_template &&tmplt)
|
||||
{
|
||||
templates_.emplace_back(std::move(tmplt));
|
||||
}
|
||||
|
||||
const std::vector<class_member> &class_::members() const { return members_; }
|
||||
|
||||
const std::vector<class_method> &class_::methods() const { return methods_; }
|
||||
|
||||
const std::vector<class_parent> &class_::parents() const { return bases_; }
|
||||
|
||||
const std::vector<class_template> &class_::templates() const
|
||||
{
|
||||
return templates_;
|
||||
}
|
||||
|
||||
void class_::set_base_template(const std::string &full_name)
|
||||
{
|
||||
base_template_full_name_ = full_name;
|
||||
}
|
||||
|
||||
std::string class_::base_template() const { return base_template_full_name_; }
|
||||
|
||||
bool operator==(const class_ &l, const class_ &r)
|
||||
{
|
||||
return l.full_name() == r.full_name();
|
||||
}
|
||||
|
||||
void class_::add_type_alias(type_alias &&ta)
|
||||
{
|
||||
LOG_DBG("Adding class alias: {} -> {}", ta.alias(), ta.underlying_type());
|
||||
type_aliases_[ta.alias()] = std::move(ta);
|
||||
}
|
||||
|
||||
std::string class_::full_name(bool relative) const
|
||||
{
|
||||
using namespace clanguml::util;
|
||||
|
||||
std::ostringstream ostr;
|
||||
if (relative)
|
||||
ostr << ns_relative(using_namespaces(), name());
|
||||
else
|
||||
ostr << name();
|
||||
|
||||
if (!templates_.empty()) {
|
||||
std::vector<std::string> tnames;
|
||||
std::transform(templates_.cbegin(), templates_.cend(),
|
||||
std::back_inserter(tnames), [this](const auto &tmplt) {
|
||||
std::vector<std::string> res;
|
||||
|
||||
if (!tmplt.type().empty())
|
||||
res.push_back(
|
||||
ns_relative(using_namespaces(), tmplt.type()));
|
||||
|
||||
if (!tmplt.name().empty())
|
||||
res.push_back(
|
||||
ns_relative(using_namespaces(), tmplt.name()));
|
||||
|
||||
if (!tmplt.default_value().empty()) {
|
||||
res.push_back("=");
|
||||
res.push_back(tmplt.default_value());
|
||||
}
|
||||
|
||||
return fmt::format("{}", fmt::join(res, " "));
|
||||
});
|
||||
ostr << fmt::format("<{}>", fmt::join(tnames, ","));
|
||||
}
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
bool class_::is_abstract() const
|
||||
{
|
||||
// TODO check if all base abstract methods are overriden
|
||||
// with non-abstract methods
|
||||
return std::any_of(methods_.begin(), methods_.end(),
|
||||
[](const auto &method) { return method.is_pure_virtual(); });
|
||||
}
|
||||
}
|
||||
82
src/class_diagram/model/class.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* src/class_diagram/model/class.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class_member.h"
|
||||
#include "class_method.h"
|
||||
#include "class_parent.h"
|
||||
#include "class_template.h"
|
||||
#include "element.h"
|
||||
#include "enums.h"
|
||||
#include "stylable_element.h"
|
||||
#include "type_alias.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class class_ : public element, public stylable_element {
|
||||
public:
|
||||
class_(const std::vector<std::string> &using_namespaces);
|
||||
|
||||
bool is_struct() const;
|
||||
void is_struct(bool is_struct);
|
||||
|
||||
bool is_template() const;
|
||||
void is_template(bool is_template);
|
||||
|
||||
bool is_template_instantiation() const;
|
||||
void is_template_instantiation(bool is_template_instantiation);
|
||||
|
||||
void add_member(class_member &&member);
|
||||
void add_method(class_method &&method);
|
||||
void add_parent(class_parent &&parent);
|
||||
void add_template(class_template &&tmplt);
|
||||
|
||||
const std::vector<class_member> &members() const;
|
||||
const std::vector<class_method> &methods() const;
|
||||
const std::vector<class_parent> &parents() const;
|
||||
const std::vector<class_template> &templates() const;
|
||||
|
||||
void set_base_template(const std::string &full_name);
|
||||
std::string base_template() const;
|
||||
|
||||
friend bool operator==(const class_ &l, const class_ &r);
|
||||
|
||||
void add_type_alias(type_alias &&ta);
|
||||
|
||||
std::string full_name(bool relative = true) const override;
|
||||
|
||||
bool is_abstract() const;
|
||||
|
||||
private:
|
||||
bool is_struct_{false};
|
||||
bool is_template_{false};
|
||||
bool is_template_instantiation_{false};
|
||||
std::vector<class_member> members_;
|
||||
std::vector<class_method> methods_;
|
||||
std::vector<class_parent> bases_;
|
||||
std::vector<class_template> templates_;
|
||||
std::string base_template_full_name_;
|
||||
std::map<std::string, type_alias> type_aliases_;
|
||||
|
||||
std::string full_name_;
|
||||
};
|
||||
|
||||
}
|
||||
37
src/class_diagram/model/class_element.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_element.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class_element.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class_element::class_element(
|
||||
scope_t scope, const std::string &name, const std::string &type)
|
||||
: scope_{scope}
|
||||
, name_{name}
|
||||
, type_{type}
|
||||
{
|
||||
}
|
||||
|
||||
scope_t class_element::scope() const { return scope_; }
|
||||
|
||||
std::string class_element::name() const { return name_; }
|
||||
|
||||
std::string class_element::type() const { return type_; }
|
||||
|
||||
}
|
||||
41
src/class_diagram/model/class_element.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_element.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorated_element.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class class_element : public decorated_element {
|
||||
public:
|
||||
class_element(
|
||||
scope_t scope, const std::string &name, const std::string &type);
|
||||
|
||||
scope_t scope() const;
|
||||
std::string name() const;
|
||||
std::string type() const;
|
||||
|
||||
private:
|
||||
scope_t scope_;
|
||||
std::string name_;
|
||||
std::string type_;
|
||||
};
|
||||
|
||||
}
|
||||
40
src/class_diagram/model/class_member.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_member.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class_member.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class_member::class_member(
|
||||
scope_t scope, const std::string &name, const std::string &type)
|
||||
: class_element{scope, name, type}
|
||||
{
|
||||
}
|
||||
|
||||
bool class_member::is_relationship() const { return is_relationship_; }
|
||||
|
||||
void class_member::is_relationship(bool is_relationship)
|
||||
{
|
||||
is_relationship_ = is_relationship;
|
||||
}
|
||||
|
||||
bool class_member::is_static() const { return is_static_; }
|
||||
|
||||
void class_member::is_static(bool is_static) { is_static_ = is_static; }
|
||||
|
||||
}
|
||||
42
src/class_diagram/model/class_member.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_member.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class_element.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class class_member : public class_element {
|
||||
public:
|
||||
class_member(
|
||||
scope_t scope, const std::string &name, const std::string &type);
|
||||
|
||||
bool is_relationship() const;
|
||||
void is_relationship(bool is_relationship);
|
||||
|
||||
bool is_static() const;
|
||||
void is_static(bool is_static);
|
||||
|
||||
private:
|
||||
bool is_relationship_{false};
|
||||
bool is_static_{false};
|
||||
};
|
||||
|
||||
}
|
||||
64
src/class_diagram/model/class_method.cc
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_method.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class_method.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class_method::class_method(
|
||||
scope_t scope, const std::string &name, const std::string &type)
|
||||
: class_element{scope, name, type}
|
||||
{
|
||||
}
|
||||
|
||||
bool class_method::is_pure_virtual() const { return is_pure_virtual_; }
|
||||
|
||||
void class_method::is_pure_virtual(bool is_pure_virtual)
|
||||
{
|
||||
is_pure_virtual_ = is_pure_virtual;
|
||||
}
|
||||
|
||||
bool class_method::is_virtual() const { return is_virtual_; }
|
||||
|
||||
void class_method::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; }
|
||||
|
||||
bool class_method::is_const() const { return is_const_; }
|
||||
|
||||
void class_method::is_const(bool is_const) { is_const_ = is_const; }
|
||||
|
||||
bool class_method::is_defaulted() const { return is_defaulted_; }
|
||||
|
||||
void class_method::is_defaulted(bool is_defaulted)
|
||||
{
|
||||
is_defaulted_ = is_defaulted;
|
||||
}
|
||||
|
||||
bool class_method::is_static() const { return is_static_; }
|
||||
|
||||
void class_method::is_static(bool is_static) { is_static_ = is_static; }
|
||||
|
||||
const std::vector<method_parameter> &class_method::parameters() const
|
||||
{
|
||||
return parameters_;
|
||||
}
|
||||
|
||||
void class_method::add_parameter(method_parameter &¶meter)
|
||||
{
|
||||
parameters_.emplace_back(std::move(parameter));
|
||||
}
|
||||
}
|
||||
59
src/class_diagram/model/class_method.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_method.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class_element.h"
|
||||
#include "method_parameter.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class class_method : public class_element {
|
||||
public:
|
||||
class_method(
|
||||
scope_t scope, const std::string &name, const std::string &type);
|
||||
|
||||
bool is_pure_virtual() const;
|
||||
void is_pure_virtual(bool is_pure_virtual);
|
||||
|
||||
bool is_virtual() const;
|
||||
void is_virtual(bool is_virtual);
|
||||
|
||||
bool is_const() const;
|
||||
void is_const(bool is_const);
|
||||
|
||||
bool is_defaulted() const;
|
||||
void is_defaulted(bool is_defaulted);
|
||||
|
||||
bool is_static() const;
|
||||
void is_static(bool is_static);
|
||||
|
||||
const std::vector<method_parameter> ¶meters() const;
|
||||
void add_parameter(method_parameter &¶meter);
|
||||
|
||||
private:
|
||||
std::vector<method_parameter> parameters_;
|
||||
bool is_pure_virtual_{false};
|
||||
bool is_virtual_{false};
|
||||
bool is_const_{false};
|
||||
bool is_defaulted_{false};
|
||||
bool is_static_{false};
|
||||
};
|
||||
}
|
||||
35
src/class_diagram/model/class_parent.cc
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_parent.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class_parent.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
void class_parent::set_name(const std::string &name) { name_ = name; }
|
||||
|
||||
std::string class_parent::name() const { return name_; }
|
||||
|
||||
void class_parent::is_virtual(bool is_virtual) { is_virtual_ = is_virtual; }
|
||||
|
||||
bool class_parent::is_virtual() const { return is_virtual_; }
|
||||
|
||||
void class_parent::set_access(access_t access) { access_ = access; }
|
||||
|
||||
access_t class_parent::access() const { return access_; }
|
||||
|
||||
}
|
||||
42
src/class_diagram/model/class_parent.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_parent.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "enums.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class class_parent {
|
||||
public:
|
||||
void set_name(const std::string &name);
|
||||
std::string name() const;
|
||||
|
||||
void is_virtual(bool is_virtual);
|
||||
bool is_virtual() const;
|
||||
|
||||
void set_access(access_t access);
|
||||
access_t access() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
bool is_virtual_{false};
|
||||
access_t access_;
|
||||
};
|
||||
}
|
||||
113
src/class_diagram/model/class_relationship.cc
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_relationship.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class_relationship.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
std::string to_string(relationship_t r)
|
||||
{
|
||||
switch (r) {
|
||||
case relationship_t::kNone:
|
||||
return "none";
|
||||
case relationship_t::kExtension:
|
||||
return "extension";
|
||||
case relationship_t::kComposition:
|
||||
return "composition";
|
||||
case relationship_t::kAggregation:
|
||||
return "aggregation";
|
||||
case relationship_t::kContainment:
|
||||
return "containment";
|
||||
case relationship_t::kOwnership:
|
||||
return "ownership";
|
||||
case relationship_t::kAssociation:
|
||||
return "association";
|
||||
case relationship_t::kInstantiation:
|
||||
return "instantiation";
|
||||
case relationship_t::kFriendship:
|
||||
return "frendship";
|
||||
case relationship_t::kDependency:
|
||||
return "dependency";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
class_relationship::class_relationship(relationship_t type,
|
||||
const std::string &destination, scope_t scope, const std::string &label,
|
||||
const std::string &multiplicity_source,
|
||||
const std::string &multiplicity_destination)
|
||||
: type_{type}
|
||||
, destination_{destination}
|
||||
, scope_{scope}
|
||||
, label_{label}
|
||||
, multiplicity_source_{multiplicity_source}
|
||||
, multiplicity_destination_{multiplicity_destination}
|
||||
{
|
||||
}
|
||||
|
||||
void class_relationship::set_type(relationship_t type) noexcept
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
relationship_t class_relationship::type() const noexcept { return type_; }
|
||||
|
||||
void class_relationship::set_destination(const std::string &destination)
|
||||
{
|
||||
destination_ = destination;
|
||||
}
|
||||
|
||||
std::string class_relationship::destination() const { return destination_; }
|
||||
|
||||
void class_relationship::set_multiplicity_source(
|
||||
const std::string &multiplicity_source)
|
||||
{
|
||||
multiplicity_source_ = multiplicity_source;
|
||||
}
|
||||
|
||||
std::string class_relationship::multiplicity_source() const
|
||||
{
|
||||
return multiplicity_source_;
|
||||
}
|
||||
|
||||
void class_relationship::set_multiplicity_destination(
|
||||
const std::string &multiplicity_destination)
|
||||
{
|
||||
multiplicity_destination_ = multiplicity_destination;
|
||||
}
|
||||
|
||||
std::string class_relationship::multiplicity_destination() const
|
||||
{
|
||||
return multiplicity_destination_;
|
||||
}
|
||||
|
||||
void class_relationship::set_label(const std::string &label) { label_ = label; }
|
||||
|
||||
std::string class_relationship::label() const { return label_; }
|
||||
|
||||
void class_relationship::set_scope(scope_t scope) noexcept { scope_ = scope; }
|
||||
|
||||
scope_t class_relationship::scope() const noexcept { return scope_; }
|
||||
|
||||
bool operator==(const class_relationship &l, const class_relationship &r)
|
||||
{
|
||||
return l.type() == r.type() && l.destination() == r.destination() &&
|
||||
l.label() == r.label();
|
||||
}
|
||||
}
|
||||
68
src/class_diagram/model/class_relationship.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_relationship.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorated_element.h"
|
||||
#include "stylable_element.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
std::string to_string(relationship_t r);
|
||||
|
||||
class class_relationship : public decorated_element, public stylable_element {
|
||||
public:
|
||||
class_relationship(relationship_t type, const std::string &destination,
|
||||
scope_t scope = scope_t::kNone, const std::string &label = "",
|
||||
const std::string &multiplicity_source = "",
|
||||
const std::string &multiplicity_destination = "");
|
||||
|
||||
virtual ~class_relationship() = default;
|
||||
|
||||
void set_type(relationship_t type) noexcept;
|
||||
relationship_t type() const noexcept;
|
||||
|
||||
void set_destination(const std::string &destination);
|
||||
std::string destination() const;
|
||||
|
||||
void set_multiplicity_source(const std::string &multiplicity_source);
|
||||
std::string multiplicity_source() const;
|
||||
|
||||
void set_multiplicity_destination(
|
||||
const std::string &multiplicity_destination);
|
||||
std::string multiplicity_destination() const;
|
||||
|
||||
void set_label(const std::string &label);
|
||||
std::string label() const;
|
||||
|
||||
void set_scope(scope_t scope) noexcept;
|
||||
scope_t scope() const noexcept;
|
||||
|
||||
friend bool operator==(
|
||||
const class_relationship &l, const class_relationship &r);
|
||||
|
||||
private:
|
||||
relationship_t type_{relationship_t::kAssociation};
|
||||
std::string destination_;
|
||||
std::string multiplicity_source_;
|
||||
std::string multiplicity_destination_;
|
||||
std::string label_;
|
||||
scope_t scope_{scope_t::kNone};
|
||||
};
|
||||
}
|
||||
60
src/class_diagram/model/class_template.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_template.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class_template.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class_template::class_template(const std::string &type, const std::string &name,
|
||||
const std::string &default_value, bool is_variadic)
|
||||
: type_{type}
|
||||
, name_{name}
|
||||
, default_value_{default_value}
|
||||
, is_variadic_{is_variadic}
|
||||
{
|
||||
if (is_variadic)
|
||||
name_ = name_ + "...";
|
||||
}
|
||||
|
||||
void class_template::set_type(const std::string &type) { type_ = type; }
|
||||
|
||||
std::string class_template::type() const { return type_; }
|
||||
|
||||
void class_template::set_name(const std::string &name) { name_ = name; }
|
||||
|
||||
std::string class_template::name() const { return name_; }
|
||||
|
||||
void class_template::set_default_value(const std::string &value)
|
||||
{
|
||||
default_value_ = value;
|
||||
}
|
||||
|
||||
std::string class_template::default_value() const { return default_value_; }
|
||||
|
||||
void class_template::is_variadic(bool is_variadic) noexcept
|
||||
{
|
||||
is_variadic_ = is_variadic;
|
||||
}
|
||||
|
||||
bool class_template::is_variadic() const noexcept { return is_variadic_; }
|
||||
|
||||
bool operator==(const class_template &l, const class_template &r)
|
||||
{
|
||||
return (l.name() == r.name()) && (l.type() == r.type());
|
||||
}
|
||||
}
|
||||
50
src/class_diagram/model/class_template.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* src/class_diagram/model/class_template.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class class_template {
|
||||
public:
|
||||
class_template(const std::string &type = "", const std::string &name = "",
|
||||
const std::string &default_value = "", bool is_variadic = false);
|
||||
|
||||
void set_type(const std::string &type);
|
||||
std::string type() const;
|
||||
|
||||
void set_name(const std::string &name);
|
||||
std::string name() const;
|
||||
|
||||
void set_default_value(const std::string &value);
|
||||
std::string default_value() const;
|
||||
|
||||
void is_variadic(bool is_variadic) noexcept;
|
||||
bool is_variadic() const noexcept;
|
||||
|
||||
friend bool operator==(const class_template &l, const class_template &r);
|
||||
|
||||
private:
|
||||
std::string type_;
|
||||
std::string name_;
|
||||
std::string default_value_;
|
||||
bool is_variadic_{false};
|
||||
};
|
||||
}
|
||||
82
src/class_diagram/model/decorated_element.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* src/class_diagram/model/decorated_element.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "decorated_element.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
bool decorated_element::skip() const
|
||||
{
|
||||
for (auto d : decorators_)
|
||||
if (std::dynamic_pointer_cast<decorators::skip>(d))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool decorated_element::skip_relationship() const
|
||||
{
|
||||
for (auto d : decorators_)
|
||||
if (std::dynamic_pointer_cast<decorators::skip_relationship>(d))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<relationship_t, std::string> decorated_element::relationship() const
|
||||
{
|
||||
for (auto &d : decorators_)
|
||||
if (std::dynamic_pointer_cast<decorators::association>(d))
|
||||
return {relationship_t::kAssociation,
|
||||
std::dynamic_pointer_cast<decorators::relationship>(d)
|
||||
->multiplicity};
|
||||
else if (std::dynamic_pointer_cast<decorators::aggregation>(d))
|
||||
return {relationship_t::kAggregation,
|
||||
std::dynamic_pointer_cast<decorators::relationship>(d)
|
||||
->multiplicity};
|
||||
else if (std::dynamic_pointer_cast<decorators::composition>(d))
|
||||
return {relationship_t::kComposition,
|
||||
std::dynamic_pointer_cast<decorators::relationship>(d)
|
||||
->multiplicity};
|
||||
|
||||
return {relationship_t::kNone, ""};
|
||||
}
|
||||
|
||||
std::string decorated_element::style_spec()
|
||||
{
|
||||
for (auto d : decorators_)
|
||||
if (std::dynamic_pointer_cast<decorators::style>(d))
|
||||
return std::dynamic_pointer_cast<decorators::style>(d)->spec;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<decorators::decorator>> &
|
||||
decorated_element::decorators() const
|
||||
{
|
||||
return decorators_;
|
||||
}
|
||||
|
||||
void decorated_element::add_decorators(
|
||||
const std::vector<std::shared_ptr<decorators::decorator>> &decorators)
|
||||
{
|
||||
for (auto d : decorators) {
|
||||
decorators_.push_back(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/class_diagram/model/decorated_element.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* src/class_diagram/model/decorated_element.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "enums.h"
|
||||
|
||||
#include "decorators/decorators.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class decorated_element {
|
||||
public:
|
||||
bool skip() const;
|
||||
|
||||
bool skip_relationship() const;
|
||||
|
||||
std::pair<relationship_t, std::string> relationship() const;
|
||||
|
||||
std::string style_spec();
|
||||
|
||||
const std::vector<std::shared_ptr<decorators::decorator>> &
|
||||
decorators() const;
|
||||
|
||||
void add_decorators(
|
||||
const std::vector<std::shared_ptr<decorators::decorator>> &decorators);
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<decorators::decorator>> decorators_;
|
||||
};
|
||||
|
||||
}
|
||||
85
src/class_diagram/model/diagram.cc
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* src/class_diagram/model/diagram.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "diagram.h"
|
||||
|
||||
#include "util/error.h"
|
||||
#include "util/util.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
std::string diagram::name() const { return name_; }
|
||||
|
||||
void diagram::set_name(const std::string &name) { name_ = name; }
|
||||
|
||||
const std::vector<class_> diagram::classes() const { return classes_; }
|
||||
|
||||
const std::vector<enum_> diagram::enums() const { return enums_; }
|
||||
|
||||
bool diagram::has_class(const class_ &c) const
|
||||
{
|
||||
return std::any_of(classes_.cbegin(), classes_.cend(),
|
||||
[&c](const auto &cc) { return cc.full_name() == c.full_name(); });
|
||||
}
|
||||
|
||||
void diagram::add_type_alias(type_alias &&ta)
|
||||
{
|
||||
LOG_DBG("Adding global alias: {} -> {}", ta.alias(), ta.underlying_type());
|
||||
|
||||
type_aliases_[ta.alias()] = std::move(ta);
|
||||
}
|
||||
|
||||
void diagram::add_class(class_ &&c)
|
||||
{
|
||||
LOG_DBG("Adding class: {}, {}", c.name(), c.full_name());
|
||||
if (!has_class(c))
|
||||
classes_.emplace_back(std::move(c));
|
||||
else
|
||||
LOG_DBG("Class {} ({}) already in the model", c.name(), c.full_name());
|
||||
}
|
||||
|
||||
void diagram::add_enum(enum_ &&e)
|
||||
{
|
||||
LOG_DBG("Adding enum: {}", e.name());
|
||||
auto it = std::find(enums_.begin(), enums_.end(), e);
|
||||
if (it == enums_.end())
|
||||
enums_.emplace_back(std::move(e));
|
||||
else
|
||||
LOG_DBG("Enum {} already in the model", e.name());
|
||||
}
|
||||
|
||||
std::string diagram::to_alias(const std::string &full_name) const
|
||||
{
|
||||
LOG_DBG("Looking for alias for {}", full_name);
|
||||
|
||||
for (const auto &c : classes_) {
|
||||
if (c.full_name() == full_name) {
|
||||
return c.alias();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &e : enums_) {
|
||||
if (e.full_name() == full_name) {
|
||||
return e.alias();
|
||||
}
|
||||
}
|
||||
|
||||
throw error::uml_alias_missing(
|
||||
fmt::format("Missing alias for {}", full_name));
|
||||
}
|
||||
}
|
||||
55
src/class_diagram/model/diagram.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* src/class_diagram/model/diagram.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class.h"
|
||||
#include "enum.h"
|
||||
#include "type_alias.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class diagram {
|
||||
public:
|
||||
std::string name() const;
|
||||
|
||||
void set_name(const std::string &name);
|
||||
|
||||
const std::vector<class_> classes() const;
|
||||
|
||||
const std::vector<enum_> enums() const;
|
||||
|
||||
bool has_class(const class_ &c) const;
|
||||
|
||||
void add_type_alias(type_alias &&ta);
|
||||
|
||||
void add_class(class_ &&c);
|
||||
|
||||
void add_enum(enum_ &&e);
|
||||
|
||||
std::string to_alias(const std::string &full_name) const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::vector<class_> classes_;
|
||||
std::vector<enum_> enums_;
|
||||
std::map<std::string, type_alias> type_aliases_;
|
||||
};
|
||||
}
|
||||
68
src/class_diagram/model/element.cc
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* src/class_diagram/model/element.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "element.h"
|
||||
|
||||
#include "util/util.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
std::atomic_uint64_t element::m_nextId = 1;
|
||||
|
||||
element::element(const std::vector<std::string> &using_namespaces)
|
||||
: using_namespaces_{using_namespaces}
|
||||
, m_id{m_nextId++}
|
||||
{
|
||||
}
|
||||
|
||||
std::string element::alias() const { return fmt::format("C_{:010}", m_id); }
|
||||
|
||||
void element::add_relationship(class_relationship &&cr)
|
||||
{
|
||||
if (cr.destination().empty()) {
|
||||
LOG_WARN("Skipping relationship '{}' - {} - '{}' due empty "
|
||||
"destination",
|
||||
cr.destination(), to_string(cr.type()), full_name(true));
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::find(relationships_.begin(), relationships_.end(), cr);
|
||||
if (it == relationships_.end())
|
||||
relationships_.emplace_back(std::move(cr));
|
||||
}
|
||||
|
||||
void element::set_using_namespaces(const std::vector<std::string> &un)
|
||||
{
|
||||
using_namespaces_ = un;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &element::using_namespaces() const
|
||||
{
|
||||
return using_namespaces_;
|
||||
}
|
||||
|
||||
std::vector<class_relationship> &element::relationships()
|
||||
{
|
||||
return relationships_;
|
||||
}
|
||||
|
||||
const std::vector<class_relationship> &element::relationships() const
|
||||
{
|
||||
return relationships_;
|
||||
}
|
||||
}
|
||||
66
src/class_diagram/model/element.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* src/class_diagram/model/element.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class_relationship.h"
|
||||
#include "decorated_element.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class element : public decorated_element {
|
||||
public:
|
||||
element(const std::vector<std::string> &using_namespaces);
|
||||
|
||||
std::string alias() const;
|
||||
|
||||
void set_name(const std::string &name) { name_ = name; }
|
||||
|
||||
std::string name() const { return name_; }
|
||||
|
||||
void set_namespace(const std::vector<std::string> &ns) { namespace_ = ns; }
|
||||
|
||||
std::vector<std::string> get_namespace() const { return namespace_; }
|
||||
|
||||
virtual std::string full_name(bool relative) const { return name(); }
|
||||
|
||||
void set_using_namespaces(const std::vector<std::string> &un);
|
||||
|
||||
const std::vector<std::string> &using_namespaces() const;
|
||||
|
||||
std::vector<class_relationship> &relationships();
|
||||
|
||||
const std::vector<class_relationship> &relationships() const;
|
||||
|
||||
void add_relationship(class_relationship &&cr);
|
||||
|
||||
protected:
|
||||
const uint64_t m_id{0};
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::vector<std::string> namespace_;
|
||||
std::vector<std::string> using_namespaces_;
|
||||
std::vector<class_relationship> relationships_;
|
||||
|
||||
static std::atomic_uint64_t m_nextId;
|
||||
};
|
||||
}
|
||||
51
src/class_diagram/model/enum.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* src/class_diagram/model/enum.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "enum.h"
|
||||
|
||||
#include "util/util.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
enum_::enum_(const std::vector<std::string> &using_namespaces)
|
||||
: element{using_namespaces}
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const enum_ &l, const enum_ &r) { return l.name() == r.name(); }
|
||||
|
||||
std::string enum_::full_name(bool relative) const
|
||||
{
|
||||
using namespace clanguml::util;
|
||||
|
||||
std::ostringstream ostr;
|
||||
if (relative)
|
||||
ostr << ns_relative(using_namespaces(), name());
|
||||
else
|
||||
ostr << name();
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
std::vector<std::string> &enum_::constants() { return constants_; }
|
||||
|
||||
const std::vector<std::string> &enum_::constants() const { return constants_; }
|
||||
|
||||
}
|
||||
43
src/class_diagram/model/enum.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* src/class_diagram/model/enum.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class enum_ : public element, public stylable_element {
|
||||
public:
|
||||
enum_(const std::vector<std::string> &using_namespaces);
|
||||
|
||||
friend bool operator==(const enum_ &l, const enum_ &r);
|
||||
|
||||
std::string full_name(bool relative = true) const override;
|
||||
|
||||
std::vector<std::string> &constants();
|
||||
|
||||
const std::vector<std::string> &constants() const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> constants_;
|
||||
};
|
||||
|
||||
}
|
||||
39
src/class_diagram/model/enums.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* src/class_diagram/model/enums.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
enum class access_t { kPublic, kProtected, kPrivate };
|
||||
|
||||
enum class scope_t { kPublic, kProtected, kPrivate, kNone };
|
||||
|
||||
enum class relationship_t {
|
||||
kNone,
|
||||
kExtension,
|
||||
kComposition,
|
||||
kAggregation,
|
||||
kContainment,
|
||||
kOwnership,
|
||||
kAssociation,
|
||||
kInstantiation,
|
||||
kFriendship,
|
||||
kDependency
|
||||
};
|
||||
|
||||
}
|
||||
51
src/class_diagram/model/method_parameter.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* src/class_diagram/model/method_parameter.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "method_parameter.h"
|
||||
|
||||
#include "util/util.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
void method_parameter::set_type(const std::string &type) { type_ = type; }
|
||||
|
||||
std::string method_parameter::type() const { return type_; }
|
||||
|
||||
void method_parameter::set_name(const std::string &name) { name_ = name; }
|
||||
|
||||
std::string method_parameter::name() const { return name_; }
|
||||
|
||||
void method_parameter::set_default_value(const std::string &value)
|
||||
{
|
||||
default_value_ = value;
|
||||
}
|
||||
|
||||
std::string method_parameter::default_value() const { return default_value_; }
|
||||
|
||||
std::string method_parameter::to_string(
|
||||
const std::vector<std::string> &using_namespaces) const
|
||||
{
|
||||
using namespace clanguml::util;
|
||||
auto t = ns_relative(using_namespaces, type());
|
||||
if (default_value().empty())
|
||||
return fmt::format("{} {}", t, name());
|
||||
|
||||
return fmt::format("{} {} = {}", t, name(), default_value());
|
||||
}
|
||||
|
||||
}
|
||||
47
src/class_diagram/model/method_parameter.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* src/class_diagram/model/method_parameter.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorated_element.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class method_parameter : public decorated_element {
|
||||
public:
|
||||
void set_type(const std::string &type);
|
||||
std::string type() const;
|
||||
|
||||
void set_name(const std::string &name);
|
||||
std::string name() const;
|
||||
|
||||
void set_default_value(const std::string &value);
|
||||
std::string default_value() const;
|
||||
|
||||
std::string to_string(
|
||||
const std::vector<std::string> &using_namespaces) const;
|
||||
|
||||
private:
|
||||
std::string type_;
|
||||
std::string name_;
|
||||
std::string default_value_;
|
||||
};
|
||||
|
||||
}
|
||||
27
src/class_diagram/model/stylable_element.cc
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* src/class_diagram/model/stylable_element.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "stylable_element.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
void stylable_element::set_style(const std::string &style) { style_ = style; }
|
||||
|
||||
std::string stylable_element::style() const { return style_; }
|
||||
|
||||
}
|
||||
33
src/class_diagram/model/stylable_element.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* src/class_diagram/model/stylable_element.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class stylable_element {
|
||||
public:
|
||||
void set_style(const std::string &style);
|
||||
std::string style() const;
|
||||
|
||||
private:
|
||||
std::string style_;
|
||||
};
|
||||
|
||||
}
|
||||
34
src/class_diagram/model/type_alias.cc
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* src/class_diagram/model/type_alias.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "type_alias.h"
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
void type_alias::set_alias(const std::string &alias) { alias_ = alias; }
|
||||
|
||||
std::string type_alias::alias() const { return alias_; }
|
||||
|
||||
void type_alias::set_underlying_type(const std::string &type)
|
||||
{
|
||||
underlying_type_ = type;
|
||||
}
|
||||
|
||||
std::string type_alias::underlying_type() const { return underlying_type_; }
|
||||
|
||||
}
|
||||
37
src/class_diagram/model/type_alias.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* src/class_diagram/model/type_alias.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
|
||||
class type_alias {
|
||||
public:
|
||||
void set_alias(const std::string &alias);
|
||||
std::string alias() const;
|
||||
|
||||
void set_underlying_type(const std::string &type);
|
||||
std::string underlying_type() const;
|
||||
|
||||
private:
|
||||
std::string alias_;
|
||||
std::string underlying_type_;
|
||||
};
|
||||
|
||||
}
|
||||
57
src/class_diagram/visitor/element_visitor_context.cc
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* src/class_diagram/model/visitor/element_visitor_context.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "element_visitor_context.h"
|
||||
|
||||
#include "translation_unit_context.h"
|
||||
|
||||
namespace clanguml::class_diagram::visitor {
|
||||
|
||||
template <typename T>
|
||||
element_visitor_context<T>::element_visitor_context(
|
||||
clanguml::class_diagram::model::diagram &diagram, T &element)
|
||||
: element_{element}
|
||||
, diagram_{diagram}
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void element_visitor_context<T>::set_parent_class(
|
||||
clanguml::class_diagram::model::class_ *parent_class)
|
||||
{
|
||||
parent_class_ = parent_class;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
clanguml::class_diagram::model::class_ *
|
||||
element_visitor_context<T>::parent_class()
|
||||
{
|
||||
return parent_class_;
|
||||
}
|
||||
|
||||
template <typename T> T &element_visitor_context<T>::element()
|
||||
{
|
||||
return element_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
clanguml::class_diagram::model::diagram &element_visitor_context<T>::diagram()
|
||||
{
|
||||
return diagram_;
|
||||
}
|
||||
}
|
||||
48
src/class_diagram/visitor/element_visitor_context.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* src/class_diagram/model/visitor/element_visitor_context.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class_diagram/model/class.h"
|
||||
#include "class_diagram/model/diagram.h"
|
||||
|
||||
namespace clanguml::class_diagram::visitor {
|
||||
|
||||
class translation_unit_context;
|
||||
|
||||
template <typename T> class element_visitor_context {
|
||||
public:
|
||||
element_visitor_context(
|
||||
clanguml::class_diagram::model::diagram &diagram, T &element);
|
||||
|
||||
void set_parent_class(clanguml::class_diagram::model::class_ *parent_class);
|
||||
|
||||
clanguml::class_diagram::model::class_ *parent_class();
|
||||
|
||||
T &element();
|
||||
|
||||
clanguml::class_diagram::model::diagram &diagram();
|
||||
|
||||
private:
|
||||
translation_unit_context *ctx_;
|
||||
|
||||
T &element_;
|
||||
clanguml::class_diagram::model::class_ *parent_class_{};
|
||||
clanguml::class_diagram::model::diagram &diagram_;
|
||||
};
|
||||
|
||||
}
|
||||
135
src/class_diagram/visitor/translation_unit_context.cc
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* src/class_diagram/visitor/translation_unit_context.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "translation_unit_context.h"
|
||||
|
||||
#include "cx/util.h"
|
||||
|
||||
namespace clanguml::class_diagram::visitor {
|
||||
|
||||
translation_unit_context::translation_unit_context(
|
||||
cppast::cpp_entity_index &idx,
|
||||
clanguml::class_diagram::model::diagram &diagram,
|
||||
const clanguml::config::class_diagram &config)
|
||||
: entity_index_{idx}
|
||||
, diagram_{diagram}
|
||||
, config_{config}
|
||||
{
|
||||
}
|
||||
|
||||
bool translation_unit_context::has_type_alias(
|
||||
const std::string &full_name) const
|
||||
{
|
||||
bool res = alias_index_.find(full_name) != alias_index_.end();
|
||||
|
||||
LOG_DBG("Alias {} {} found in index", full_name, res ? "" : "not");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void translation_unit_context::add_type_alias(const std::string &full_name,
|
||||
type_safe::object_ref<const cppast::cpp_type> &&ref)
|
||||
{
|
||||
if (!has_type_alias(full_name)) {
|
||||
LOG_DBG("Stored type alias: {} -> {} ", full_name,
|
||||
cppast::to_string(ref.get()));
|
||||
|
||||
alias_index_.emplace(full_name, std::move(ref));
|
||||
}
|
||||
}
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type>
|
||||
translation_unit_context::get_type_alias(const std::string &full_name) const
|
||||
{
|
||||
assert(has_type_alias(full_name));
|
||||
|
||||
return alias_index_.at(full_name);
|
||||
}
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type>
|
||||
translation_unit_context::get_type_alias_final(const cppast::cpp_type &t) const
|
||||
{
|
||||
const auto type_full_name =
|
||||
cx::util::full_name(cppast::remove_cv(t), entity_index_, false);
|
||||
|
||||
if (has_type_alias(type_full_name)) {
|
||||
return get_type_alias_final(alias_index_.at(type_full_name).get());
|
||||
}
|
||||
|
||||
return type_safe::ref(t);
|
||||
}
|
||||
|
||||
bool translation_unit_context::has_type_alias_template(
|
||||
const std::string &full_name) const
|
||||
{
|
||||
bool res =
|
||||
alias_template_index_.find(full_name) != alias_template_index_.end();
|
||||
|
||||
LOG_DBG("Alias template {} {} found in index", full_name, res ? "" : "not");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void translation_unit_context::add_type_alias_template(
|
||||
const std::string &full_name,
|
||||
type_safe::object_ref<const cppast::cpp_type> &&ref)
|
||||
{
|
||||
if (!has_type_alias_template(full_name)) {
|
||||
LOG_DBG("Stored type alias template for: {} ", full_name);
|
||||
|
||||
alias_template_index_.emplace(full_name, std::move(ref));
|
||||
}
|
||||
}
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type>
|
||||
translation_unit_context::get_type_alias_template(
|
||||
const std::string &full_name) const
|
||||
{
|
||||
assert(has_type_alias_template(full_name));
|
||||
|
||||
return alias_template_index_.at(full_name);
|
||||
}
|
||||
|
||||
void translation_unit_context::push_namespace(const std::string &ns)
|
||||
{
|
||||
namespace_.push_back(ns);
|
||||
}
|
||||
|
||||
void translation_unit_context::pop_namespace() { namespace_.pop_back(); }
|
||||
|
||||
const std::vector<std::string> &translation_unit_context::get_namespace() const
|
||||
{
|
||||
return namespace_;
|
||||
}
|
||||
|
||||
const cppast::cpp_entity_index &translation_unit_context::entity_index() const
|
||||
{
|
||||
return entity_index_;
|
||||
}
|
||||
|
||||
const clanguml::config::class_diagram &translation_unit_context::config() const
|
||||
{
|
||||
return config_;
|
||||
}
|
||||
|
||||
clanguml::class_diagram::model::diagram &translation_unit_context::diagram()
|
||||
{
|
||||
return diagram_;
|
||||
}
|
||||
|
||||
}
|
||||
87
src/class_diagram/visitor/translation_unit_context.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* src/class_diagram/visitor/translation_unit_context.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "config/config.h"
|
||||
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
#include <cppast/cpp_type.hpp>
|
||||
#include <type_safe/reference.hpp>
|
||||
|
||||
namespace clanguml::class_diagram::visitor {
|
||||
|
||||
class translation_unit_context {
|
||||
public:
|
||||
translation_unit_context(cppast::cpp_entity_index &idx,
|
||||
clanguml::class_diagram::model::diagram &diagram,
|
||||
const clanguml::config::class_diagram &config);
|
||||
|
||||
bool has_type_alias(const std::string &full_name) const;
|
||||
|
||||
void add_type_alias(const std::string &full_name,
|
||||
type_safe::object_ref<const cppast::cpp_type> &&ref);
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type> get_type_alias(
|
||||
const std::string &full_name) const;
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type> get_type_alias_final(
|
||||
const cppast::cpp_type &t) const;
|
||||
|
||||
bool has_type_alias_template(const std::string &full_name) const;
|
||||
|
||||
void add_type_alias_template(const std::string &full_name,
|
||||
type_safe::object_ref<const cppast::cpp_type> &&ref);
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type> get_type_alias_template(
|
||||
const std::string &full_name) const;
|
||||
|
||||
void push_namespace(const std::string &ns);
|
||||
|
||||
void pop_namespace();
|
||||
|
||||
const std::vector<std::string> &get_namespace() const;
|
||||
|
||||
const cppast::cpp_entity_index &entity_index() const;
|
||||
|
||||
const clanguml::config::class_diagram &config() const;
|
||||
|
||||
clanguml::class_diagram::model::diagram &diagram();
|
||||
|
||||
private:
|
||||
// Current visitor namespace
|
||||
std::vector<std::string> namespace_;
|
||||
|
||||
// Reference to the cppast entity index
|
||||
cppast::cpp_entity_index &entity_index_;
|
||||
|
||||
// Reference to the output diagram model
|
||||
clanguml::class_diagram::model::diagram &diagram_;
|
||||
|
||||
// Reference to class diagram config
|
||||
const clanguml::config::class_diagram &config_;
|
||||
|
||||
// Map of discovered aliases (declared with 'using' keyword)
|
||||
std::map<std::string, type_safe::object_ref<const cppast::cpp_type>>
|
||||
alias_index_;
|
||||
|
||||
// Map of discovered template aliases (declared with 'using' keyword)
|
||||
std::map<std::string, type_safe::object_ref<const cppast::cpp_type>>
|
||||
alias_template_index_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/uml/class_diagram_visitor.h
|
||||
* src/class_diagram/visitor/translation_unit_visitor.h
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -17,7 +17,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "class_diagram_model.h"
|
||||
#include "class_diagram/model/diagram.h"
|
||||
#include "class_diagram/visitor/translation_unit_context.h"
|
||||
#include "config/config.h"
|
||||
#include "cx/cursor.h"
|
||||
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <cppast/cpp_function_template.hpp>
|
||||
#include <cppast/cpp_member_function.hpp>
|
||||
#include <cppast/cpp_member_variable.hpp>
|
||||
#include <cppast/cpp_template.hpp>
|
||||
#include <cppast/cpp_template_parameter.hpp>
|
||||
#include <cppast/cpp_type.hpp>
|
||||
#include <cppast/visitor.hpp>
|
||||
@@ -37,59 +39,13 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace clanguml {
|
||||
namespace visitor {
|
||||
namespace class_diagram {
|
||||
namespace clanguml::class_diagram::visitor {
|
||||
|
||||
struct tu_context {
|
||||
tu_context(cppast::cpp_entity_index &idx,
|
||||
clanguml::model::class_diagram::diagram &d_,
|
||||
const clanguml::config::class_diagram &config_);
|
||||
|
||||
bool has_type_alias(const std::string &full_name) const;
|
||||
|
||||
void add_type_alias(const std::string &full_name,
|
||||
type_safe::object_ref<const cppast::cpp_type> &&ref);
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type> get_type_alias(
|
||||
const std::string &full_name) const;
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type> get_type_alias_final(
|
||||
const cppast::cpp_type &t) const;
|
||||
|
||||
bool has_type_alias_template(const std::string &full_name) const;
|
||||
|
||||
void add_type_alias_template(const std::string &full_name,
|
||||
type_safe::object_ref<const cppast::cpp_type> &&ref);
|
||||
|
||||
type_safe::object_ref<const cppast::cpp_type> get_type_alias_template(
|
||||
const std::string &full_name) const;
|
||||
|
||||
std::vector<std::string> namespace_;
|
||||
cppast::cpp_entity_index &entity_index;
|
||||
clanguml::model::class_diagram::diagram &d;
|
||||
const clanguml::config::class_diagram &config;
|
||||
std::map<std::string, type_safe::object_ref<const cppast::cpp_type>>
|
||||
alias_index;
|
||||
std::map<std::string, type_safe::object_ref<const cppast::cpp_type>>
|
||||
alias_template_index;
|
||||
};
|
||||
|
||||
template <typename T> struct element_visitor_context {
|
||||
element_visitor_context(clanguml::model::class_diagram::diagram &d_, T &e);
|
||||
|
||||
tu_context *ctx;
|
||||
|
||||
T &element;
|
||||
clanguml::model::class_diagram::class_ *parent_class{};
|
||||
clanguml::model::class_diagram::diagram &d;
|
||||
};
|
||||
|
||||
class tu_visitor {
|
||||
class translation_unit_visitor {
|
||||
public:
|
||||
tu_visitor(cppast::cpp_entity_index &idx_,
|
||||
clanguml::model::class_diagram::diagram &d_,
|
||||
const clanguml::config::class_diagram &config_);
|
||||
translation_unit_visitor(cppast::cpp_entity_index &idx,
|
||||
clanguml::class_diagram::model::diagram &diagram,
|
||||
const clanguml::config::class_diagram &config);
|
||||
|
||||
void operator()(const cppast::cpp_entity &file);
|
||||
|
||||
@@ -100,78 +56,81 @@ public:
|
||||
void process_enum_declaration(const cppast::cpp_enum &enm);
|
||||
|
||||
void process_anonymous_enum(const cppast::cpp_enum &en,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_field(const cppast::cpp_member_variable &mv,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
bool process_field_with_template_instantiation(
|
||||
const cppast::cpp_member_variable &mv, const cppast::cpp_type &tr,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::model::class_diagram::class_member &m,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
clanguml::class_diagram::model::class_member &m,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_static_field(const cppast::cpp_variable &mv,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_method(const cppast::cpp_member_function &mf,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_template_method(const cppast::cpp_function_template &mf,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_static_method(const cppast::cpp_function &mf,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_constructor(const cppast::cpp_constructor &mf,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_destructor(const cppast::cpp_destructor &mf,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
cppast::cpp_access_specifier_kind as);
|
||||
|
||||
void process_function_parameter(const cppast::cpp_function_parameter ¶m,
|
||||
clanguml::model::class_diagram::class_method &m,
|
||||
clanguml::model::class_diagram::class_ &c,
|
||||
clanguml::class_diagram::model::class_method &m,
|
||||
clanguml::class_diagram::model::class_ &c,
|
||||
const std::set<std::string> &template_parameter_names = {});
|
||||
|
||||
bool find_relationships(const cppast::cpp_type &t,
|
||||
std::vector<std::pair<std::string,
|
||||
clanguml::model::class_diagram::relationship_t>> &relationships,
|
||||
clanguml::model::class_diagram::relationship_t relationship_hint =
|
||||
clanguml::model::class_diagram::relationship_t::kNone);
|
||||
clanguml::class_diagram::model::relationship_t>> &relationships,
|
||||
clanguml::class_diagram::model::relationship_t relationship_hint =
|
||||
clanguml::class_diagram::model::relationship_t::kNone);
|
||||
|
||||
void process_template_type_parameter(
|
||||
const cppast::cpp_template_type_parameter &t,
|
||||
clanguml::model::class_diagram::class_ &parent);
|
||||
clanguml::class_diagram::model::class_ &parent);
|
||||
|
||||
void process_template_nontype_parameter(
|
||||
const cppast::cpp_non_type_template_parameter &t,
|
||||
clanguml::model::class_diagram::class_ &parent);
|
||||
clanguml::class_diagram::model::class_ &parent);
|
||||
|
||||
void process_template_template_parameter(
|
||||
const cppast::cpp_template_template_parameter &t,
|
||||
clanguml::model::class_diagram::class_ &parent);
|
||||
clanguml::class_diagram::model::class_ &parent);
|
||||
|
||||
void process_friend(const cppast::cpp_friend &t,
|
||||
clanguml::model::class_diagram::class_ &parent);
|
||||
clanguml::class_diagram::model::class_ &parent);
|
||||
|
||||
private:
|
||||
clanguml::model::class_diagram::class_ build_template_instantiation(
|
||||
clanguml::class_diagram::model::class_ build_template_instantiation(
|
||||
const cppast::cpp_template_instantiation_type &t,
|
||||
std::optional<clanguml::model::class_diagram::class_ *> parent = {});
|
||||
std::optional<clanguml::class_diagram::model::class_ *> parent = {});
|
||||
|
||||
/**
|
||||
* Try to resolve a type instance into a type referenced through an alias.
|
||||
* If t does not represent an alias, returns t.
|
||||
*/
|
||||
const cppast::cpp_type &resolve_alias(const cppast::cpp_type &t);
|
||||
|
||||
tu_context ctx;
|
||||
// ctx allows to track current visitor context, e.g. current namespace
|
||||
translation_unit_context ctx;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,8 @@ bool diagram::should_include(const std::string &name_) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diagram::should_include(const model::class_diagram::scope_t scope) const
|
||||
bool diagram::should_include(
|
||||
const clanguml::class_diagram::model::scope_t scope) const
|
||||
{
|
||||
for (const auto &s : exclude.scopes) {
|
||||
if (s == scope)
|
||||
@@ -127,13 +128,13 @@ bool class_diagram::has_class(std::string clazz)
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
using clanguml::class_diagram::model::scope_t;
|
||||
using clanguml::config::class_diagram;
|
||||
using clanguml::config::config;
|
||||
using clanguml::config::filter;
|
||||
using clanguml::config::plantuml;
|
||||
using clanguml::config::sequence_diagram;
|
||||
using clanguml::config::source_location;
|
||||
using clanguml::model::class_diagram::scope_t;
|
||||
template <> struct convert<scope_t> {
|
||||
static bool decode(const Node &node, scope_t &rhs)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "uml/class_diagram_model.h"
|
||||
#include "class_diagram/model/diagram.h"
|
||||
#include "class_diagram/model/enums.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -55,7 +56,7 @@ struct filter {
|
||||
// E.g.:
|
||||
// - public
|
||||
// - private
|
||||
std::vector<model::class_diagram::scope_t> scopes;
|
||||
std::vector<class_diagram::model::scope_t> scopes;
|
||||
};
|
||||
|
||||
struct diagram {
|
||||
@@ -76,7 +77,7 @@ struct diagram {
|
||||
|
||||
bool should_include(const std::string &name_) const;
|
||||
|
||||
bool should_include(const model::class_diagram::scope_t scope) const;
|
||||
bool should_include(const class_diagram::model::scope_t scope) const;
|
||||
};
|
||||
|
||||
struct source_location {
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "cx/util.h"
|
||||
#include "uml/class_diagram_model.h"
|
||||
#include "util/util.h"
|
||||
|
||||
namespace clanguml {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/uml/decorators.cc
|
||||
* src/decorators/decorators.cc
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/uml/decorators.h
|
||||
* src/decorators/decorators.h
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
24
src/main.cc
@@ -18,13 +18,13 @@
|
||||
|
||||
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
|
||||
|
||||
#include "class_diagram/generators/plantuml/class_diagram_generator.h"
|
||||
#include "class_diagram/model/diagram.h"
|
||||
#include "class_diagram/visitor/translation_unit_visitor.h"
|
||||
#include "config/config.h"
|
||||
#include "cx/compilation_database.h"
|
||||
#include "puml/class_diagram_generator.h"
|
||||
#include "puml/sequence_diagram_generator.h"
|
||||
#include "uml/class_diagram_model.h"
|
||||
#include "uml/class_diagram_visitor.h"
|
||||
#include "uml/sequence_diagram_visitor.h"
|
||||
#include "sequence_diagram/generators/plantuml/sequence_diagram_generator.h"
|
||||
#include "sequence_diagram/visitor/translation_unit_context.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <cli11/CLI11.hpp>
|
||||
@@ -98,18 +98,20 @@ int main(int argc, const char *argv[])
|
||||
ofs.open(path, std::ofstream::out | std::ofstream::trunc);
|
||||
|
||||
if (std::dynamic_pointer_cast<class_diagram>(diagram)) {
|
||||
auto model = generators::class_diagram::generate(
|
||||
db2, name, dynamic_cast<class_diagram &>(*diagram));
|
||||
auto model =
|
||||
clanguml::class_diagram::generators::plantuml::generate(
|
||||
db2, name, dynamic_cast<class_diagram &>(*diagram));
|
||||
|
||||
ofs << clanguml::generators::class_diagram::puml::generator(
|
||||
ofs << clanguml::class_diagram::generators::plantuml::generator(
|
||||
dynamic_cast<clanguml::config::class_diagram &>(*diagram),
|
||||
model);
|
||||
}
|
||||
else if (std::dynamic_pointer_cast<sequence_diagram>(diagram)) {
|
||||
auto model = generators::sequence_diagram::generate(
|
||||
db, name, dynamic_cast<sequence_diagram &>(*diagram));
|
||||
auto model =
|
||||
clanguml::sequence_diagram::generators::plantuml::generate(
|
||||
db, name, dynamic_cast<sequence_diagram &>(*diagram));
|
||||
|
||||
ofs << clanguml::generators::sequence_diagram::puml::generator(
|
||||
ofs << clanguml::sequence_diagram::generators::plantuml::generator(
|
||||
dynamic_cast<clanguml::config::sequence_diagram &>(*diagram),
|
||||
model);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/puml/sequence_diagram_generator.h
|
||||
* src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -16,20 +16,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "puml/sequence_diagram_generator.h"
|
||||
#include "sequence_diagram_generator.h"
|
||||
|
||||
namespace clanguml::generators::sequence_diagram {
|
||||
namespace puml {
|
||||
using diagram_model = clanguml::model::sequence_diagram::diagram;
|
||||
#include "sequence_diagram/visitor/translation_unit_context.h"
|
||||
|
||||
namespace clanguml::sequence_diagram::generators::plantuml {
|
||||
|
||||
using diagram_model = clanguml::sequence_diagram::model::diagram;
|
||||
using diagram_config = clanguml::config::sequence_diagram::diagram;
|
||||
using clanguml::config::source_location;
|
||||
using clanguml::model::sequence_diagram::activity;
|
||||
using clanguml::model::sequence_diagram::message;
|
||||
using clanguml::model::sequence_diagram::message_t;
|
||||
using clanguml::visitor::sequence_diagram::tu_context;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
using clanguml::sequence_diagram::model::message_t;
|
||||
using clanguml::sequence_diagram::visitor::translation_unit_context;
|
||||
using namespace clanguml::util;
|
||||
|
||||
|
||||
//
|
||||
// generator
|
||||
//
|
||||
@@ -117,14 +118,13 @@ std::ostream &operator<<(std::ostream &os, const generator &g)
|
||||
g.generate(os);
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
clanguml::model::sequence_diagram::diagram generate(
|
||||
clanguml::sequence_diagram::model::diagram generate(
|
||||
clanguml::cx::compilation_database &db, const std::string &name,
|
||||
clanguml::config::sequence_diagram &diagram)
|
||||
{
|
||||
spdlog::info("Generating diagram {}.puml", name);
|
||||
clanguml::model::sequence_diagram::diagram d;
|
||||
clanguml::sequence_diagram::model::diagram d;
|
||||
d.name = name;
|
||||
|
||||
// Get all translation units matching the glob from diagram
|
||||
@@ -155,9 +155,10 @@ clanguml::model::sequence_diagram::diagram generate(
|
||||
spdlog::debug("Cursor name: {}",
|
||||
clang_getCString(clang_getCursorDisplayName(cursor)));
|
||||
|
||||
clanguml::visitor::sequence_diagram::tu_context ctx(d, diagram);
|
||||
clanguml::sequence_diagram::visitor::translation_unit_context ctx(
|
||||
d, diagram);
|
||||
auto res = clang_visitChildren(cursor,
|
||||
clanguml::visitor::sequence_diagram::translation_unit_visitor,
|
||||
clanguml::sequence_diagram::visitor::translation_unit_visitor,
|
||||
&ctx);
|
||||
|
||||
spdlog::debug("Processing result: {}", res);
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/puml/sequence_diagram_generator.h
|
||||
* src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "config/config.h"
|
||||
#include "cx/compilation_database.h"
|
||||
#include "uml/sequence_diagram_model.h"
|
||||
#include "uml/sequence_diagram_visitor.h"
|
||||
#include "sequence_diagram/model/diagram.h"
|
||||
#include "sequence_diagram/visitor/translation_unit_visitor.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <glob/glob.hpp>
|
||||
@@ -31,25 +31,25 @@
|
||||
#include <sstream>
|
||||
|
||||
namespace clanguml {
|
||||
namespace generators {
|
||||
namespace sequence_diagram {
|
||||
namespace puml {
|
||||
namespace generators {
|
||||
namespace plantuml {
|
||||
|
||||
using diagram_model = clanguml::model::sequence_diagram::diagram;
|
||||
using diagram_model = clanguml::sequence_diagram::model::diagram;
|
||||
|
||||
class generator {
|
||||
public:
|
||||
generator(clanguml::config::sequence_diagram &config, diagram_model &model);
|
||||
|
||||
std::string to_string(clanguml::model::sequence_diagram::message_t r) const;
|
||||
std::string to_string(clanguml::sequence_diagram::model::message_t r) const;
|
||||
|
||||
void generate_call(const clanguml::model::sequence_diagram::message &m,
|
||||
void generate_call(const clanguml::sequence_diagram::model::message &m,
|
||||
std::ostream &ostr) const;
|
||||
|
||||
void generate_return(const clanguml::model::sequence_diagram::message &m,
|
||||
void generate_return(const clanguml::sequence_diagram::model::message &m,
|
||||
std::ostream &ostr) const;
|
||||
|
||||
void generate_activity(const clanguml::model::sequence_diagram::activity &a,
|
||||
void generate_activity(const clanguml::sequence_diagram::model::activity &a,
|
||||
std::ostream &ostr) const;
|
||||
|
||||
void generate(std::ostream &ostr) const;
|
||||
@@ -58,15 +58,14 @@ public:
|
||||
|
||||
private:
|
||||
clanguml::config::sequence_diagram &m_config;
|
||||
clanguml::model::sequence_diagram::diagram &m_model;
|
||||
clanguml::sequence_diagram::model::diagram &m_model;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
clanguml::model::sequence_diagram::diagram generate(
|
||||
clanguml::sequence_diagram::model::diagram generate(
|
||||
clanguml::cx::compilation_database &db, const std::string &name,
|
||||
clanguml::config::sequence_diagram &diagram);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/uml/sequence_diagram_model.cc
|
||||
* src/sequence_diagram/model/activity.cc
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -16,8 +16,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "sequence_diagram_visitor.h"
|
||||
#include "activity.h"
|
||||
|
||||
namespace clanguml::model::sequence_diagram {
|
||||
namespace clanguml::sequence_diagram::model {
|
||||
|
||||
}
|
||||
33
src/sequence_diagram/model/activity.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* src/sequence_diagram/model/activity.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "message.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::sequence_diagram::model {
|
||||
|
||||
struct activity {
|
||||
std::string usr;
|
||||
std::string from;
|
||||
std::vector<message> messages;
|
||||
};
|
||||
|
||||
}
|
||||
32
src/sequence_diagram/model/diagram.cc
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* src/sequence_diagram/model/diagram.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "diagram.h"
|
||||
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <clang-c/Index.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml::sequence_diagram::model {
|
||||
|
||||
}
|
||||
34
src/sequence_diagram/model/diagram.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* src/sequence_diagram/model/diagram.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "activity.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::sequence_diagram::model {
|
||||
|
||||
struct diagram {
|
||||
bool started{false};
|
||||
std::string name;
|
||||
|
||||
std::map<std::string, activity> sequences;
|
||||
};
|
||||
|
||||
}
|
||||
24
src/sequence_diagram/model/enums.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* src/sequence_diagram/model/enums.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace clanguml::sequence_diagram::model {
|
||||
|
||||
enum class message_t { kCall, kReturn };
|
||||
|
||||
}
|
||||
23
src/sequence_diagram/model/message.cc
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* src/sequence_diagram/model/message.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "message.h"
|
||||
|
||||
namespace clanguml::sequence_diagram::model {
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/uml/sequence_diagram_model.h
|
||||
* src/sequence_diagram/model/message.h
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -17,20 +17,12 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <clang-c/Index.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "enums.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clanguml {
|
||||
namespace model {
|
||||
namespace sequence_diagram {
|
||||
|
||||
enum class message_t { kCall, kReturn };
|
||||
namespace clanguml::sequence_diagram::model {
|
||||
|
||||
struct message {
|
||||
message_t type;
|
||||
@@ -43,18 +35,4 @@ struct message {
|
||||
unsigned int line;
|
||||
};
|
||||
|
||||
struct activity {
|
||||
std::string usr;
|
||||
std::string from;
|
||||
std::vector<message> messages;
|
||||
};
|
||||
|
||||
struct diagram {
|
||||
bool started{false};
|
||||
std::string name;
|
||||
|
||||
std::map<std::string, activity> sequences;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
68
src/sequence_diagram/visitor/translation_unit_context.cc
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* src/sequence_diagram/visitor/translation_unit_context.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "translation_unit_context.h"
|
||||
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <clang-c/Index.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace clanguml::sequence_diagram::visitor {
|
||||
|
||||
translation_unit_context::translation_unit_context(
|
||||
clanguml::sequence_diagram::model::diagram &diagram,
|
||||
const clanguml::config::sequence_diagram &config)
|
||||
: diagram_{diagram}
|
||||
, config_{config}
|
||||
{
|
||||
}
|
||||
|
||||
void translation_unit_context::push_namespace(const std::string &ns)
|
||||
{
|
||||
namespace_.push_back(ns);
|
||||
}
|
||||
|
||||
void translation_unit_context::pop_namespace() { namespace_.pop_back(); }
|
||||
|
||||
const std::vector<std::string> &translation_unit_context::get_namespace() const
|
||||
{
|
||||
return namespace_;
|
||||
}
|
||||
|
||||
const clanguml::config::sequence_diagram &
|
||||
translation_unit_context::config() const
|
||||
{
|
||||
return config_;
|
||||
}
|
||||
|
||||
clanguml::sequence_diagram::model::diagram &translation_unit_context::diagram()
|
||||
{
|
||||
return diagram_;
|
||||
}
|
||||
|
||||
void translation_unit_context::set_current_method(cx::cursor method)
|
||||
{
|
||||
current_method_ = method;
|
||||
}
|
||||
|
||||
cx::cursor &translation_unit_context::current_method()
|
||||
{
|
||||
return current_method_;
|
||||
}
|
||||
|
||||
}
|
||||
59
src/sequence_diagram/visitor/translation_unit_context.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* src/sequence_diagram/visitor/translation_unit_context.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "config/config.h"
|
||||
#include "cx/cursor.h"
|
||||
#include "sequence_diagram/model/diagram.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::sequence_diagram::visitor {
|
||||
|
||||
class translation_unit_context {
|
||||
public:
|
||||
translation_unit_context(
|
||||
clanguml::sequence_diagram::model::diagram &diagram,
|
||||
const clanguml::config::sequence_diagram &config);
|
||||
|
||||
void push_namespace(const std::string &ns);
|
||||
|
||||
void pop_namespace();
|
||||
|
||||
const std::vector<std::string> &get_namespace() const;
|
||||
|
||||
const cppast::cpp_entity_index &entity_index() const;
|
||||
|
||||
const clanguml::config::sequence_diagram &config() const;
|
||||
|
||||
clanguml::sequence_diagram::model::diagram &diagram();
|
||||
|
||||
void set_current_method(cx::cursor method);
|
||||
|
||||
cx::cursor ¤t_method();
|
||||
|
||||
private:
|
||||
std::vector<std::string> namespace_;
|
||||
cx::cursor current_method_;
|
||||
clanguml::sequence_diagram::model::diagram &diagram_;
|
||||
const clanguml::config::sequence_diagram &config_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/uml/sequence_diagram_visitor.cc
|
||||
* src/sequence_diagram/visitor/translation_unit_visitor.cc
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -16,30 +16,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "sequence_diagram_visitor.h"
|
||||
#include "translation_unit_visitor.h"
|
||||
|
||||
namespace clanguml::visitor::sequence_diagram {
|
||||
#include "translation_unit_context.h"
|
||||
|
||||
//
|
||||
// tu_context
|
||||
//
|
||||
|
||||
tu_context::tu_context(clanguml::model::sequence_diagram::diagram &d_,
|
||||
const clanguml::config::sequence_diagram &config_)
|
||||
: d{d_}
|
||||
, config{config_}
|
||||
{
|
||||
}
|
||||
namespace clanguml::sequence_diagram::visitor {
|
||||
|
||||
enum CXChildVisitResult translation_unit_visitor(
|
||||
CXCursor cx_cursor, CXCursor cx_parent, CXClientData client_data)
|
||||
{
|
||||
using clanguml::model::sequence_diagram::activity;
|
||||
using clanguml::model::sequence_diagram::diagram;
|
||||
using clanguml::model::sequence_diagram::message;
|
||||
using clanguml::model::sequence_diagram::message_t;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::diagram;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
using clanguml::sequence_diagram::model::message_t;
|
||||
|
||||
struct tu_context *ctx = (struct tu_context *)client_data;
|
||||
auto *ctx = (struct translation_unit_context *)client_data;
|
||||
|
||||
enum CXChildVisitResult ret = CXChildVisit_Break;
|
||||
|
||||
@@ -54,7 +45,7 @@ enum CXChildVisitResult translation_unit_visitor(
|
||||
case CXCursor_FunctionTemplate:
|
||||
case CXCursor_CXXMethod:
|
||||
case CXCursor_FunctionDecl:
|
||||
ctx->current_method = cursor;
|
||||
ctx->set_current_method(cursor);
|
||||
ret = CXChildVisit_Recurse;
|
||||
break;
|
||||
case CXCursor_CallExpr: {
|
||||
@@ -74,25 +65,28 @@ enum CXChildVisitResult translation_unit_visitor(
|
||||
clang_getFileLocation(cursor.location(), &f, &line, &column, &offset);
|
||||
std::string file{clang_getCString(clang_getFileName(f))};
|
||||
|
||||
auto &d = ctx->d;
|
||||
auto &config = ctx->config;
|
||||
auto &d = ctx->diagram();
|
||||
auto &config = ctx->config();
|
||||
if (referenced.kind() == CXCursor_CXXMethod) {
|
||||
if (config.should_include(sp_name)) {
|
||||
// Get calling object
|
||||
std::string caller{};
|
||||
if (ctx->current_method.semantic_parent()
|
||||
if (ctx->current_method()
|
||||
.semantic_parent()
|
||||
.is_translation_unit() ||
|
||||
ctx->current_method.semantic_parent().is_namespace()) {
|
||||
caller = ctx->current_method.semantic_parent()
|
||||
ctx->current_method().semantic_parent().is_namespace()) {
|
||||
caller = ctx->current_method()
|
||||
.semantic_parent()
|
||||
.fully_qualified() +
|
||||
"::" + ctx->current_method.spelling() + "()";
|
||||
"::" + ctx->current_method().spelling() + "()";
|
||||
}
|
||||
else {
|
||||
caller =
|
||||
ctx->current_method.semantic_parent().fully_qualified();
|
||||
caller = ctx->current_method()
|
||||
.semantic_parent()
|
||||
.fully_qualified();
|
||||
}
|
||||
|
||||
auto caller_usr = ctx->current_method.usr();
|
||||
auto caller_usr = ctx->current_method().usr();
|
||||
// Get called object
|
||||
auto callee = referenced.semantic_parent().fully_qualified();
|
||||
auto callee_usr = referenced.semantic_parent().usr();
|
||||
@@ -105,8 +99,8 @@ enum CXChildVisitResult translation_unit_visitor(
|
||||
"\n\tCURRENT_METHOD: {}\n\tFROM: '{}'\n\tTO: "
|
||||
"{}\n\tMESSAGE: {}\n\tFROM_USR: {}\n\tTO_USR: "
|
||||
"{}\n\tRETURN_TYPE: {}",
|
||||
file, line, d.name, ctx->current_method.spelling(), caller,
|
||||
callee, called_message, caller_usr, callee_usr,
|
||||
file, line, d.name, ctx->current_method().spelling(),
|
||||
caller, callee, called_message, caller_usr, callee_usr,
|
||||
referenced.type().result_type().spelling());
|
||||
|
||||
message m;
|
||||
@@ -146,5 +140,4 @@ enum CXChildVisitResult translation_unit_visitor(
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* src/uml/sequence_diagram_visitor.h
|
||||
* src/sequence_diagram/visitor/translation_unit_visitor.h
|
||||
*
|
||||
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
@@ -17,35 +17,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "cx/cursor.h"
|
||||
#include "sequence_diagram_model.h"
|
||||
#include "config/config.h"
|
||||
#include "cx/cursor.h"
|
||||
#include "sequence_diagram/model/diagram.h"
|
||||
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <clang-c/Index.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace clanguml {
|
||||
namespace visitor {
|
||||
namespace sequence_diagram {
|
||||
|
||||
struct tu_context {
|
||||
tu_context(clanguml::model::sequence_diagram::diagram &d_,
|
||||
const clanguml::config::sequence_diagram &config_);
|
||||
|
||||
std::vector<std::string> namespace_;
|
||||
cx::cursor current_method;
|
||||
clanguml::model::sequence_diagram::diagram &d;
|
||||
const clanguml::config::sequence_diagram &config;
|
||||
};
|
||||
namespace clanguml::sequence_diagram::visitor {
|
||||
|
||||
enum CXChildVisitResult translation_unit_visitor(
|
||||
CXCursor cx_cursor, CXCursor cx_parent, CXClientData client_data);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
/**
|
||||
* src/uml/class_diagram_model.cc
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
#include "class_diagram_model.h"
|
||||
|
||||
namespace clanguml {
|
||||
namespace model {
|
||||
namespace class_diagram {
|
||||
std::atomic_uint64_t element::m_nextId = 1;
|
||||
|
||||
std::string to_string(relationship_t r)
|
||||
{
|
||||
switch (r) {
|
||||
case relationship_t::kNone:
|
||||
return "none";
|
||||
case relationship_t::kExtension:
|
||||
return "extension";
|
||||
case relationship_t::kComposition:
|
||||
return "composition";
|
||||
case relationship_t::kAggregation:
|
||||
return "aggregation";
|
||||
case relationship_t::kContainment:
|
||||
return "containment";
|
||||
case relationship_t::kOwnership:
|
||||
return "ownership";
|
||||
case relationship_t::kAssociation:
|
||||
return "association";
|
||||
case relationship_t::kInstantiation:
|
||||
return "instantiation";
|
||||
case relationship_t::kFriendship:
|
||||
return "frendship";
|
||||
case relationship_t::kDependency:
|
||||
return "dependency";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// decorated_element
|
||||
//
|
||||
|
||||
bool decorated_element::skip() const
|
||||
{
|
||||
for (auto d : decorators)
|
||||
if (std::dynamic_pointer_cast<decorators::skip>(d))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool decorated_element::skip_relationship() const
|
||||
{
|
||||
for (auto d : decorators)
|
||||
if (std::dynamic_pointer_cast<decorators::skip_relationship>(d))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<relationship_t, std::string> decorated_element::relationship() const
|
||||
{
|
||||
for (auto &d : decorators)
|
||||
if (std::dynamic_pointer_cast<decorators::association>(d))
|
||||
return {relationship_t::kAssociation,
|
||||
std::dynamic_pointer_cast<decorators::relationship>(d)
|
||||
->multiplicity};
|
||||
else if (std::dynamic_pointer_cast<decorators::aggregation>(d))
|
||||
return {relationship_t::kAggregation,
|
||||
std::dynamic_pointer_cast<decorators::relationship>(d)
|
||||
->multiplicity};
|
||||
else if (std::dynamic_pointer_cast<decorators::composition>(d))
|
||||
return {relationship_t::kComposition,
|
||||
std::dynamic_pointer_cast<decorators::relationship>(d)
|
||||
->multiplicity};
|
||||
|
||||
return {relationship_t::kNone, ""};
|
||||
}
|
||||
|
||||
std::string decorated_element::style_spec()
|
||||
{
|
||||
for (auto d : decorators)
|
||||
if (std::dynamic_pointer_cast<decorators::style>(d))
|
||||
return std::dynamic_pointer_cast<decorators::style>(d)->spec;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//
|
||||
// element
|
||||
//
|
||||
|
||||
element::element()
|
||||
: m_id{m_nextId++}
|
||||
{
|
||||
}
|
||||
|
||||
std::string element::alias() const { return fmt::format("C_{:010}", m_id); }
|
||||
|
||||
//
|
||||
// method_parameter
|
||||
//
|
||||
|
||||
std::string method_parameter::to_string(
|
||||
const std::vector<std::string> &using_namespaces) const
|
||||
{
|
||||
using namespace clanguml::util;
|
||||
auto t = ns_relative(using_namespaces, type);
|
||||
if (default_value.empty())
|
||||
return fmt::format("{} {}", t, name);
|
||||
|
||||
return fmt::format("{} {} = {}", t, name, default_value);
|
||||
}
|
||||
|
||||
//
|
||||
// class_relationship
|
||||
//
|
||||
|
||||
bool operator==(const class_relationship &l, const class_relationship &r)
|
||||
{
|
||||
return l.type == r.type && l.destination == r.destination &&
|
||||
l.label == r.label;
|
||||
}
|
||||
|
||||
//
|
||||
// class_template
|
||||
//
|
||||
|
||||
bool operator==(const class_template &l, const class_template &r)
|
||||
{
|
||||
return (l.name == r.name) && (l.type == r.type);
|
||||
}
|
||||
|
||||
//
|
||||
// class_
|
||||
//
|
||||
|
||||
bool operator==(const class_ &l, const class_ &r)
|
||||
{
|
||||
return (l.usr == r.usr) && (l.templates == r.templates);
|
||||
}
|
||||
|
||||
void class_::add_type_alias(type_alias &&ta)
|
||||
{
|
||||
LOG_DBG("Adding class alias: {} -> {}", ta.alias, ta.underlying_type);
|
||||
type_aliases[ta.alias] = std::move(ta);
|
||||
}
|
||||
|
||||
void class_::add_relationship(class_relationship &&cr)
|
||||
{
|
||||
if (cr.destination.empty()) {
|
||||
LOG_WARN("Skipping relationship '{}' - {} - '{}' due empty destination",
|
||||
cr.destination, to_string(cr.type), usr);
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::find(relationships.begin(), relationships.end(), cr);
|
||||
if (it == relationships.end())
|
||||
relationships.emplace_back(std::move(cr));
|
||||
}
|
||||
|
||||
std::string class_::full_name(
|
||||
const std::vector<std::string> &using_namespaces) const
|
||||
{
|
||||
using namespace clanguml::util;
|
||||
|
||||
std::ostringstream ostr;
|
||||
ostr << ns_relative(using_namespaces, name);
|
||||
|
||||
if (!templates.empty()) {
|
||||
std::vector<std::string> tnames;
|
||||
std::transform(templates.cbegin(), templates.cend(),
|
||||
std::back_inserter(tnames), [&using_namespaces](const auto &tmplt) {
|
||||
std::vector<std::string> res;
|
||||
|
||||
if (!tmplt.type.empty())
|
||||
res.push_back(ns_relative(using_namespaces, tmplt.type));
|
||||
|
||||
if (!tmplt.name.empty())
|
||||
res.push_back(ns_relative(using_namespaces, tmplt.name));
|
||||
|
||||
if (!tmplt.default_value.empty()) {
|
||||
res.push_back("=");
|
||||
res.push_back(tmplt.default_value);
|
||||
}
|
||||
|
||||
return fmt::format("{}", fmt::join(res, " "));
|
||||
});
|
||||
ostr << fmt::format("<{}>", fmt::join(tnames, ","));
|
||||
}
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
bool class_::is_abstract() const
|
||||
{
|
||||
// TODO check if all base abstract methods are overriden
|
||||
// with non-abstract methods
|
||||
return std::any_of(methods.begin(), methods.end(),
|
||||
[](const auto &method) { return method.is_pure_virtual; });
|
||||
}
|
||||
|
||||
//
|
||||
// enum_
|
||||
//
|
||||
|
||||
bool operator==(const enum_ &l, const enum_ &r) { return l.name == r.name; }
|
||||
|
||||
std::string enum_::full_name(
|
||||
const std::vector<std::string> &using_namespaces) const
|
||||
{
|
||||
using namespace clanguml::util;
|
||||
|
||||
std::ostringstream ostr;
|
||||
ostr << ns_relative(using_namespaces, name);
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
//
|
||||
// diagram
|
||||
//
|
||||
|
||||
bool diagram::has_class(const std::string &usr) const
|
||||
{
|
||||
return std::any_of(classes.cbegin(), classes.cend(),
|
||||
[&usr](const auto &c) { return c.usr == usr; });
|
||||
}
|
||||
|
||||
void diagram::add_type_alias(type_alias &&ta)
|
||||
{
|
||||
LOG_DBG("Adding global alias: {} -> {}", ta.alias, ta.underlying_type);
|
||||
|
||||
type_aliases[ta.alias] = std::move(ta);
|
||||
}
|
||||
|
||||
void diagram::add_class(class_ &&c)
|
||||
{
|
||||
LOG_DBG("Adding class: {}, {}", c.name, c.usr);
|
||||
if (!has_class(c.usr))
|
||||
classes.emplace_back(std::move(c));
|
||||
else
|
||||
LOG_DBG("Class {} ({}) already in the model", c.name, c.usr);
|
||||
}
|
||||
|
||||
void diagram::add_enum(enum_ &&e)
|
||||
{
|
||||
LOG_DBG("Adding enum: {}", e.name);
|
||||
auto it = std::find(enums.begin(), enums.end(), e);
|
||||
if (it == enums.end())
|
||||
enums.emplace_back(std::move(e));
|
||||
else
|
||||
LOG_DBG("Enum {} already in the model", e.name);
|
||||
}
|
||||
|
||||
std::string diagram::to_alias(const std::vector<std::string> &using_namespaces,
|
||||
const std::string &full_name) const
|
||||
{
|
||||
LOG_DBG("Looking for alias for {}", full_name);
|
||||
|
||||
for (const auto &c : classes) {
|
||||
if (c.full_name(using_namespaces) == full_name) {
|
||||
return c.alias();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &e : enums) {
|
||||
if (e.full_name(using_namespaces) == full_name) {
|
||||
return e.alias();
|
||||
}
|
||||
}
|
||||
|
||||
throw error::uml_alias_missing(
|
||||
fmt::format("Missing alias for {}", full_name));
|
||||
}
|
||||
|
||||
std::string diagram::usr_to_name(
|
||||
const std::vector<std::string> &using_namespaces,
|
||||
const std::string &usr) const
|
||||
{
|
||||
if (usr.empty())
|
||||
throw std::runtime_error("Empty USR");
|
||||
|
||||
for (const auto &c : classes) {
|
||||
if (c.usr == usr)
|
||||
return c.full_name(using_namespaces);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
/**
|
||||
* src/uml/class_diagram_model.h
|
||||
*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "decorators.h"
|
||||
#include "util/error.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <clang-c/Index.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace clanguml {
|
||||
namespace model {
|
||||
namespace class_diagram {
|
||||
|
||||
enum class scope_t { kPublic, kProtected, kPrivate, kNone };
|
||||
|
||||
enum class relationship_t {
|
||||
kNone,
|
||||
kExtension,
|
||||
kComposition,
|
||||
kAggregation,
|
||||
kContainment,
|
||||
kOwnership,
|
||||
kAssociation,
|
||||
kInstantiation,
|
||||
kFriendship,
|
||||
kDependency
|
||||
};
|
||||
|
||||
std::string to_string(relationship_t r);
|
||||
|
||||
struct stylable_element {
|
||||
std::string style;
|
||||
};
|
||||
|
||||
struct decorated_element {
|
||||
std::vector<std::shared_ptr<decorators::decorator>> decorators;
|
||||
|
||||
bool skip() const;
|
||||
|
||||
bool skip_relationship() const;
|
||||
|
||||
std::pair<relationship_t, std::string> relationship() const;
|
||||
|
||||
std::string style_spec();
|
||||
};
|
||||
|
||||
class element : public decorated_element {
|
||||
public:
|
||||
element();
|
||||
|
||||
std::string alias() const;
|
||||
|
||||
std::string name;
|
||||
std::vector<std::string> namespace_;
|
||||
|
||||
protected:
|
||||
const uint64_t m_id{0};
|
||||
|
||||
private:
|
||||
static std::atomic_uint64_t m_nextId;
|
||||
};
|
||||
|
||||
struct class_element : public decorated_element {
|
||||
scope_t scope;
|
||||
std::string name;
|
||||
std::string type;
|
||||
};
|
||||
|
||||
struct class_member : public class_element {
|
||||
bool is_relationship{false};
|
||||
bool is_static{false};
|
||||
};
|
||||
|
||||
struct method_parameter : public decorated_element {
|
||||
std::string type;
|
||||
std::string name;
|
||||
std::string default_value;
|
||||
|
||||
std::string to_string(
|
||||
const std::vector<std::string> &using_namespaces) const;
|
||||
};
|
||||
|
||||
struct class_method : public class_element {
|
||||
std::vector<method_parameter> parameters;
|
||||
bool is_pure_virtual{false};
|
||||
bool is_virtual{false};
|
||||
bool is_const{false};
|
||||
bool is_defaulted{false};
|
||||
bool is_static{false};
|
||||
};
|
||||
|
||||
struct class_parent {
|
||||
enum class access_t { kPublic, kProtected, kPrivate };
|
||||
std::string name;
|
||||
bool is_virtual{false};
|
||||
access_t access;
|
||||
};
|
||||
|
||||
struct class_relationship : public decorated_element, public stylable_element {
|
||||
relationship_t type{relationship_t::kAssociation};
|
||||
std::string destination;
|
||||
std::string multiplicity_source;
|
||||
std::string multiplicity_destination;
|
||||
std::string label;
|
||||
scope_t scope{scope_t::kNone};
|
||||
|
||||
friend bool operator==(
|
||||
const class_relationship &l, const class_relationship &r);
|
||||
};
|
||||
|
||||
struct class_template {
|
||||
std::string name;
|
||||
std::string type;
|
||||
std::string default_value;
|
||||
bool is_variadic{false};
|
||||
|
||||
friend bool operator==(const class_template &l, const class_template &r);
|
||||
};
|
||||
|
||||
struct type_alias {
|
||||
std::string alias;
|
||||
std::string underlying_type;
|
||||
};
|
||||
|
||||
class class_ : public element, public stylable_element {
|
||||
public:
|
||||
std::string usr;
|
||||
bool is_struct{false};
|
||||
bool is_template{false};
|
||||
bool is_template_instantiation{false};
|
||||
std::vector<class_member> members;
|
||||
std::vector<class_method> methods;
|
||||
std::vector<class_parent> bases;
|
||||
std::vector<std::string> inner_classes;
|
||||
std::vector<class_relationship> relationships;
|
||||
std::vector<class_template> templates;
|
||||
std::string base_template_usr;
|
||||
std::map<std::string, type_alias> type_aliases;
|
||||
|
||||
friend bool operator==(const class_ &l, const class_ &r);
|
||||
|
||||
void add_type_alias(type_alias &&ta);
|
||||
|
||||
void add_relationship(class_relationship &&cr);
|
||||
|
||||
std::string full_name(
|
||||
const std::vector<std::string> &using_namespaces) const;
|
||||
|
||||
bool is_abstract() const;
|
||||
};
|
||||
|
||||
struct enum_ : public element, public stylable_element {
|
||||
std::vector<std::string> constants;
|
||||
std::vector<class_relationship> relationships;
|
||||
|
||||
friend bool operator==(const enum_ &l, const enum_ &r);
|
||||
|
||||
std::string full_name(
|
||||
const std::vector<std::string> &using_namespaces) const;
|
||||
};
|
||||
|
||||
struct diagram {
|
||||
std::string name;
|
||||
std::vector<class_> classes;
|
||||
std::vector<enum_> enums;
|
||||
std::map<std::string, type_alias> type_aliases;
|
||||
|
||||
bool has_class(const std::string &usr) const;
|
||||
|
||||
void add_type_alias(type_alias &&ta);
|
||||
|
||||
void add_class(class_ &&c);
|
||||
|
||||
void add_enum(enum_ &&e);
|
||||
|
||||
std::string to_alias(const std::vector<std::string> &using_namespaces,
|
||||
const std::string &full_name) const;
|
||||
|
||||
std::string usr_to_name(const std::vector<std::string> &using_namespaces,
|
||||
const std::string &usr) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ TEST_CASE("t00002", "[test-case][class]")
|
||||
|
||||
auto model = generate_class_diagram(db, diagram);
|
||||
|
||||
REQUIRE(model.name == "t00002_class");
|
||||
REQUIRE(model.name() == "t00002_class");
|
||||
|
||||
auto puml = generate_class_puml(diagram, model);
|
||||
AliasMatcher _A(puml);
|
||||
|
||||
@@ -34,7 +34,7 @@ TEST_CASE("t00003", "[test-case][class]")
|
||||
|
||||
auto model = generate_class_diagram(db, diagram);
|
||||
|
||||
REQUIRE(model.name == "t00003_class");
|
||||
REQUIRE(model.name() == "t00003_class");
|
||||
|
||||
auto puml = generate_class_puml(diagram, model);
|
||||
AliasMatcher _A(puml);
|
||||
|
||||