Compare commits

..

13 Commits

Author SHA1 Message Date
Bartek Kryza
4f9a09783f Fixed building on MSVC (#287) 2024-06-10 20:09:13 +02:00
Bartek Kryza
fa742a03c4 Improved test coverage (#287) 2024-06-10 15:51:27 +02:00
Bartek Kryza
514c439413 Changed std::tmpnam (deprecated) to a custom random name generator in cli tests 2024-06-09 22:37:34 +02:00
Bartek Kryza
94f5f445ee Improved test coverage (#287) 2024-06-09 21:10:09 +02:00
Bartek Kryza
82846dcc27 Extended cli_handler test cases (#287) 2024-06-08 13:29:22 +02:00
Bartek Kryza
beba7d16b9 Added test case for sequence diagram with nested classes (#287) 2024-06-07 19:45:15 +02:00
Bartek Kryza
5de512ad0b Improved error logging (#284) 2024-06-07 00:25:03 +02:00
Bartek Kryza
a66bbff900 Merge pull request #286 from hatch01/master
packaging: add nixpkgs avalability and make wrapped script the default
2024-06-06 21:00:04 +02:00
eymeric
37334d54cc small nix packaging shell completion cleanup 2024-06-06 20:51:12 +02:00
eymeric
aec9d553dd packaging: now wrapped is the default for nix 2024-06-06 20:48:06 +02:00
eymeric
1393afc146 doc: add nix version info 2024-06-06 17:29:00 +02:00
eymeric
ed6b78022a doc: add nixpkgs avalability 2024-06-06 15:26:36 +02:00
Bartek Kryza
6a1322b04c Merge pull request #285 from bkryza/refactor-id_t 2024-06-06 00:14:26 +02:00
201 changed files with 1041 additions and 435 deletions

View File

@@ -4,6 +4,7 @@ comment_parser: clang
add_compile_flags: add_compile_flags:
- -fparse-all-comments - -fparse-all-comments
- -Wno-deprecated-declarations - -Wno-deprecated-declarations
- -Wno-ignored-optimization-argument
remove_compile_flags: remove_compile_flags:
- -Wno-class-memaccess - -Wno-class-memaccess
- -Wno-dangling-reference - -Wno-dangling-reference

View File

@@ -41,11 +41,12 @@ jobs:
make check-formatting make check-formatting
- name: Build and unit test - name: Build and unit test
run: | run: |
NUMPROC=2 CMAKE_CXX_FLAGS="--coverage -fno-inline" CMAKE_EXE_LINKER_FLAGS="-lgcov --coverage" LLVM_VERSION=15 make test NUMPROC=2 CODE_COVERAGE=ON LLVM_VERSION=15 make test
- name: Run coverage - name: Run coverage
run: | run: |
lcov -c -d debug -o coverage.info lcov -c -d debug -o coverage.info
lcov -e coverage.info "$PWD/src/*" -o coverage-src.info lcov -r coverage.info -o coverage-src.info "$PWD/src/main.cc" "$PWD/src/common/generators/generators.cc"
lcov -e coverage-src.info -o coverage-src.info "$PWD/src/*"
lcov -l coverage-src.info lcov -l coverage-src.info
- name: Upload coverage - name: Upload coverage
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v3

View File

@@ -61,6 +61,15 @@ setup_git_version()
message(STATUS "clang-uml version: " message(STATUS "clang-uml version: "
"${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_PATCH}") "${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_PATCH}")
#
# Setup coverage
#
option(CODE_COVERAGE "" OFF)
if(CODE_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fno-inline")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov --coverage")
endif(CODE_COVERAGE)
# #
# Setup LLVM # Setup LLVM
# #

View File

@@ -37,6 +37,7 @@ CMAKE_PREFIX ?=
CMAKE_CXX_FLAGS ?= CMAKE_CXX_FLAGS ?=
CMAKE_EXE_LINKER_FLAGS ?= CMAKE_EXE_LINKER_FLAGS ?=
CMAKE_GENERATOR ?= Unix Makefiles CMAKE_GENERATOR ?= Unix Makefiles
CODE_COVERAGE ?= OFF
ENABLE_CXX_MODULES_TEST_CASES ?= OFF ENABLE_CXX_MODULES_TEST_CASES ?= OFF
ENABLE_CUDA_TEST_CASES ?= OFF ENABLE_CUDA_TEST_CASES ?= OFF
@@ -50,7 +51,7 @@ DESTDIR ?=
.PHONY: clean .PHONY: clean
clean: clean:
rm -rf debug release debug_tidy rm -rf debug release debug_tidy coverage.info coverage-src.info
debug/CMakeLists.txt: debug/CMakeLists.txt:
cmake -S . -B debug \ cmake -S . -B debug \
@@ -65,7 +66,8 @@ debug/CMakeLists.txt:
-DLINK_LLVM_SHARED=${LLVM_SHARED} \ -DLINK_LLVM_SHARED=${LLVM_SHARED} \
-DCMAKE_PREFIX=${CMAKE_PREFIX} \ -DCMAKE_PREFIX=${CMAKE_PREFIX} \
-DENABLE_CUDA_TEST_CASES=$(ENABLE_CUDA_TEST_CASES) \ -DENABLE_CUDA_TEST_CASES=$(ENABLE_CUDA_TEST_CASES) \
-DENABLE_CXX_MODULES_TEST_CASES=$(ENABLE_CXX_MODULES_TEST_CASES) -DENABLE_CXX_MODULES_TEST_CASES=$(ENABLE_CXX_MODULES_TEST_CASES) \
-DCODE_COVERAGE=$(CODE_COVERAGE)
release/CMakeLists.txt: release/CMakeLists.txt:
cmake -S . -B release \ cmake -S . -B release \
@@ -115,6 +117,13 @@ test: debug
test_release: release test_release: release
CTEST_OUTPUT_ON_FAILURE=1 ctest --test-dir release CTEST_OUTPUT_ON_FAILURE=1 ctest --test-dir release
coverage_report: test
lcov -c -d debug -o coverage.info
lcov -r coverage.info -o coverage-src.info "${PWD}/src/main.cc" "${PWD}/src/common/generators/generators.cc"
lcov -e coverage-src.info -o coverage-src.info "${PWD}/src/*"
lcov -l coverage-src.info
genhtml coverage-src.info --output-directory debug/coverage_html
install: release install: release
make -C release install DESTDIR=${DESTDIR} make -C release install DESTDIR=${DESTDIR}

View File

@@ -226,11 +226,10 @@ set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTOR
``` ```
### Nix wrapper ### Nix wrapper
On NixOS or when using `nix`, `clang-uml` provides a wrapper script called On NixOS or when using `nix`, `clang-uml` uses a wrapper script,
`clang-uml-wrapped`, which builds and exports `CPATH` and `CPLUS_INCLUDE_PATH` which builds and exports `CPATH` and `CPLUS_INCLUDE_PATH`
environment variables before running `clang-uml`, which contain valid environment variables before running `clang-uml`, which contain valid
system header Clang paths for the current Nix environment. system header Clang paths for the current Nix environment.
The `clang-uml-wrapped` script can be called the same way as `clang-uml` and If you want to use an unwrapped version, the `clang-uml-unwrapped` binary
should resolve the system include paths without the need for any of the above can be called the same way as `clang-uml`.
solutions.

View File

@@ -56,7 +56,16 @@ conda install -c bkryza/label/clang-uml clang-uml
#### Nix #### Nix
You can use the version packaged in nixpkgs like this:
Currently clang-uml version 0.5.1 is available in nixos-unstable and nixos-24.05
```bash ```bash
nix-shell -p clang-uml
```
Or you can build it by yourself
```bash
# To build it by yourself
git clone https://github.com/bkryza/clang-uml git clone https://github.com/bkryza/clang-uml
# To build using nix flakes # To build using nix flakes

View File

@@ -1,6 +1,6 @@
# This script assumes that all clang-uml dependencies are instaled in C:\clang-uml # This script assumes that all clang-uml dependencies are instaled in C:\clang-uml
param ($Prefix="C:\clang-uml-llvm17", $BuildType="Release") param ($Prefix="C:\clang-uml-llvm18", $BuildType="Release")
mkdir _BUILD mkdir _BUILD

View File

@@ -30,13 +30,16 @@ stdenv.mkDerivation {
clang = if enableLibcxx then llvmPackages.libcxxClang else llvmPackages.clang; clang = if enableLibcxx then llvmPackages.libcxxClang else llvmPackages.clang;
postInstall = '' postInstall = ''
export unwrapped_clang_uml="$out/bin/clang-uml" cp $out/bin/clang-uml $out/bin/clang-uml-unwrapped
rm $out/bin/clang-uml
export unwrapped_clang_uml="$out/bin/clang-uml-unwrapped"
# inject clang and unwrap_clang_uml variables into wrapper # inject clang and unwrapp_clang_uml variables into wrapper
substituteAll ${./wrapper} $out/bin/clang-uml-wrapped substituteAll ${./wrapper} $out/bin/clang-uml
chmod +x $out/bin/clang-uml-wrapped chmod +x $out/bin/clang-uml
installShellCompletion --bash $src/packaging/autocomplete/clang-uml installShellCompletion --cmd clang-uml \
installShellCompletion --zsh $src/packaging/autocomplete/_clang-uml --bash $src/packaging/autocomplete/clang-uml \
--zsh $src/packaging/autocomplete/_clang-uml
''; '';
} }

View File

@@ -207,10 +207,6 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
auto &template_specialization = *template_specialization_ptr; auto &template_specialization = *template_specialization_ptr;
if (cls->hasBody()) {
process_template_specialization_children(cls, template_specialization);
}
if (cls->hasDefinition()) { if (cls->hasDefinition()) {
// Process template specialization bases // Process template specialization bases
process_class_bases(cls, template_specialization); process_class_bases(cls, template_specialization);
@@ -1005,75 +1001,6 @@ void translation_unit_visitor::process_class_bases(
} }
} }
void translation_unit_visitor::process_template_specialization_children(
const clang::ClassTemplateSpecializationDecl *cls, class_ &c)
{
assert(cls != nullptr);
// Iterate over class methods (both regular and static)
for (const auto *method : cls->methods()) {
if (method != nullptr) {
process_method(*method, c);
}
}
// Iterate over class template methods
if (const auto *cls_decl_context =
clang::dyn_cast_or_null<clang::DeclContext>(cls);
cls_decl_context != nullptr) {
for (auto const *decl_iterator :
clang::dyn_cast_or_null<clang::DeclContext>(cls)->decls()) {
auto const *method_template =
llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(
decl_iterator);
if (method_template == nullptr)
continue;
process_template_method(*method_template, c);
}
}
// Iterate over regular class fields
for (const auto *field : cls->fields()) {
if (field != nullptr)
process_field(*field, c);
}
// Static fields have to be processed by iterating over variable
// declarations
for (const auto *decl : cls->decls()) {
if (decl->getKind() == clang::Decl::Var) {
const clang::VarDecl *variable_declaration{
dynamic_cast<const clang::VarDecl *>(decl)};
if ((variable_declaration != nullptr) &&
variable_declaration->isStaticDataMember()) {
process_static_field(*variable_declaration, c);
}
}
else if (decl->getKind() == clang::Decl::Enum) {
const auto *enum_decl =
clang::dyn_cast_or_null<clang::EnumDecl>(decl);
if (enum_decl == nullptr)
continue;
if (enum_decl->getNameAsString().empty()) {
for (const auto *enum_const : enum_decl->enumerators()) {
class_member m{common::access_specifier_to_access_t(
enum_decl->getAccess()),
enum_const->getNameAsString(), "enum"};
c.add_member(std::move(m));
}
}
}
}
if (cls->hasFriends()) {
for (const auto *friend_declaration : cls->friends()) {
process_friend(*friend_declaration, c);
}
}
}
void translation_unit_visitor::process_record_members( void translation_unit_visitor::process_record_members(
const clang::RecordDecl *cls, class_ &c) const clang::RecordDecl *cls, class_ &c)
{ {

View File

@@ -224,7 +224,7 @@ private:
clang::ClassTemplateSpecializationDecl *cls); clang::ClassTemplateSpecializationDecl *cls);
/** /**
* @brief Process template specialiaztion children (members and methods) * @brief Process template specialization children (members and methods)
* @param cls Class template specialization declaration * @param cls Class template specialization declaration
* @param c Class diagram element model * @param c Class diagram element model
*/ */

View File

@@ -40,16 +40,7 @@ void cli_handler::setup_logging()
{ {
spdlog::drop("clanguml-logger"); spdlog::drop("clanguml-logger");
if (!progress) {
spdlog::register_logger(logger_); spdlog::register_logger(logger_);
}
else {
// Setup null logger for clean progress indicators
std::vector<spdlog::sink_ptr> sinks;
logger_ = std::make_shared<spdlog::logger>(
"clanguml-logger", begin(sinks), end(sinks));
spdlog::register_logger(logger_);
}
logger_->set_pattern("[%^%l%^] [tid %t] %v"); logger_->set_pattern("[%^%l%^] [tid %t] %v");
@@ -196,6 +187,16 @@ cli_flow_t cli_handler::handle_options(int argc, const char **argv)
config.inherit(); config.inherit();
if (progress) {
spdlog::drop("clanguml-logger");
// Setup null logger for clean progress indicators
std::vector<spdlog::sink_ptr> sinks;
logger_ = std::make_shared<spdlog::logger>(
"clanguml-logger", begin(sinks), end(sinks));
spdlog::register_logger(logger_);
}
return res; return res;
} }
@@ -388,6 +389,11 @@ runtime_config cli_handler::get_runtime_config() const
return cfg; return cfg;
} }
void cli_handler::set_config_path(const std::string &path)
{
config_path = path;
}
cli_flow_t cli_handler::print_version() cli_flow_t cli_handler::print_version()
{ {
ostr_ << "clang-uml " << clanguml::version::CLANG_UML_VERSION << '\n'; ostr_ << "clang-uml " << clanguml::version::CLANG_UML_VERSION << '\n';
@@ -476,7 +482,7 @@ cli_flow_t cli_handler::create_config_file()
{ {
namespace fs = std::filesystem; namespace fs = std::filesystem;
fs::path config_file{"./.clang-uml"}; fs::path config_file{config_path};
if (fs::exists(config_file)) { if (fs::exists(config_file)) {
ostr_ << "ERROR: .clang-uml file already exists\n"; ostr_ << "ERROR: .clang-uml file already exists\n";

View File

@@ -153,6 +153,13 @@ public:
*/ */
runtime_config get_runtime_config() const; runtime_config get_runtime_config() const;
/**
* @brief Set the default config path
*
* @param path
*/
void set_config_path(const std::string &path);
std::string config_path{".clang-uml"}; std::string config_path{".clang-uml"};
std::optional<std::string> compilation_database_dir{}; std::optional<std::string> compilation_database_dir{};
std::vector<std::string> diagram_names{}; std::vector<std::string> diagram_names{};

View File

@@ -166,6 +166,8 @@ void generate_diagram_impl(const std::string &name,
runtime_config.output_directory, name, diagram, model); runtime_config.output_directory, name, diagram, model);
} }
// Convert plantuml or mermaid to an image using command provided
// in the command line arguments
if (runtime_config.render_diagrams) { if (runtime_config.render_diagrams) {
render_diagram(generator_type, diagram); render_diagram(generator_type, diagram);
} }

View File

@@ -23,6 +23,12 @@
namespace clanguml::common::generators { namespace clanguml::common::generators {
progress_indicator::progress_indicator() progress_indicator::progress_indicator()
: progress_indicator(std::cout)
{
}
progress_indicator::progress_indicator(std::ostream &ostream)
: ostream_(ostream)
{ {
progress_bars_.set_option(indicators::option::HideBarWhenComplete{false}); progress_bars_.set_option(indicators::option::HideBarWhenComplete{false});
} }
@@ -36,6 +42,7 @@ void progress_indicator::add_progress_bar(
const auto kPrefixTextWidth = 25U; const auto kPrefixTextWidth = 25U;
auto bar = std::make_shared<indicators::ProgressBar>( auto bar = std::make_shared<indicators::ProgressBar>(
indicators::option::Stream{ostream_},
indicators::option::BarWidth{kBarWidth}, indicators::option::BarWidth{kBarWidth},
indicators::option::ForegroundColor{color}, indicators::option::ForegroundColor{color},
indicators::option::ShowElapsedTime{true}, indicators::option::ShowElapsedTime{true},
@@ -78,6 +85,7 @@ void progress_indicator::increment(const std::string &name)
bar.set_progress((p.progress * kASTTraverseProgressPercent) / p.max); bar.set_progress((p.progress * kASTTraverseProgressPercent) / p.max);
bar.set_option(indicators::option::PostfixText{ bar.set_option(indicators::option::PostfixText{
fmt::format("{}/{}", p.progress, p.max)}); fmt::format("{}/{}", p.progress, p.max)});
progress_bars_mutex_.unlock(); progress_bars_mutex_.unlock();
} }
@@ -106,6 +114,8 @@ void progress_indicator::complete(const std::string &name)
auto &p = progress_bar_index_.at(name); auto &p = progress_bar_index_.at(name);
auto &bar = progress_bars_[p.index]; auto &bar = progress_bars_[p.index];
p.progress = p.max;
bar.set_progress(kCompleteProgressPercent); bar.set_progress(kCompleteProgressPercent);
#if _MSC_VER #if _MSC_VER
@@ -124,6 +134,12 @@ void progress_indicator::complete(const std::string &name)
void progress_indicator::fail(const std::string &name) void progress_indicator::fail(const std::string &name)
{ {
progress_bars_mutex_.lock(); progress_bars_mutex_.lock();
if (progress_bar_index_.count(name) == 0) {
progress_bars_mutex_.unlock();
return;
}
auto &p = progress_bar_index_.at(name); auto &p = progress_bar_index_.at(name);
auto &bar = progress_bars_[p.index]; auto &bar = progress_bars_[p.index];

View File

@@ -45,6 +45,8 @@ public:
progress_indicator(); progress_indicator();
progress_indicator(std::ostream &ostream);
/** /**
* Add a new progress bar to the indicator set * Add a new progress bar to the indicator set
* *
@@ -86,5 +88,6 @@ private:
std::vector<std::shared_ptr<indicators::ProgressBar>> bars_; std::vector<std::shared_ptr<indicators::ProgressBar>> bars_;
std::map<std::string, progress_state> progress_bar_index_; std::map<std::string, progress_state> progress_bar_index_;
std::mutex progress_bars_mutex_; std::mutex progress_bars_mutex_;
std::ostream &ostream_;
}; };
} // namespace clanguml::common::generators } // namespace clanguml::common::generators

View File

@@ -1086,7 +1086,7 @@ void diagram_filter::init_filters(const config::diagram &c)
element_filters.emplace_back( element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>( std::make_unique<source_file_dependency_filter_t>(
filter_t::kInclusive, relationship_t::kAssociation, filter_t::kInclusive, relationship_t::kAssociation,
dependants)); dependants, false));
element_filters.emplace_back( element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>( std::make_unique<source_file_dependency_filter_t>(
@@ -1149,25 +1149,28 @@ void diagram_filter::init_filters(const config::diagram &c)
std::make_unique<specializations_filter_t>(filter_t::kExclusive, std::make_unique<specializations_filter_t>(filter_t::kExclusive,
relationship_t::kInstantiation, c.exclude().specializations)); relationship_t::kInstantiation, c.exclude().specializations));
add_exclusive_filter( if (c.type() == diagram_t::kClass) {
std::make_unique<class_dependants_filter_t>(filter_t::kExclusive, add_exclusive_filter(std::make_unique<class_dependants_filter_t>(
relationship_t::kDependency, c.exclude().dependants)); filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependants));
add_exclusive_filter(std::make_unique<class_dependencies_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, true));
}
else if (c.type() == diagram_t::kSequence) {
add_exclusive_filter(std::make_unique<callee_filter>(
filter_t::kExclusive, c.exclude().callee_types));
}
else if (c.type() == diagram_t::kPackage) {
add_exclusive_filter( add_exclusive_filter(
std::make_unique<package_dependants_filter_t>(filter_t::kExclusive, std::make_unique<package_dependencies_filter_t>(
relationship_t::kDependency, c.exclude().dependants));
add_exclusive_filter(
std::make_unique<class_dependencies_filter_t>(filter_t::kExclusive,
relationship_t::kDependency, c.exclude().dependencies, true));
add_exclusive_filter(std::make_unique<package_dependencies_filter_t>(
filter_t::kExclusive, relationship_t::kDependency, filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, true)); c.exclude().dependencies, true));
if (c.type() == diagram_t::kSequence) { add_exclusive_filter(std::make_unique<package_dependants_filter_t>(
add_exclusive_filter(std::make_unique<callee_filter>( filter_t::kExclusive, relationship_t::kDependency,
filter_t::kExclusive, c.exclude().callee_types)); c.exclude().dependants));
} }
else if (c.type() == diagram_t::kInclude) { else if (c.type() == diagram_t::kInclude) {
std::vector<std::string> dependants; std::vector<std::string> dependants;
@@ -1176,10 +1179,6 @@ void diagram_filter::init_filters(const config::diagram &c)
for (auto &&path : c.exclude().dependants) { for (auto &&path : c.exclude().dependants) {
if (auto p = path.get<std::string>(); p.has_value()) { if (auto p = path.get<std::string>(); p.has_value()) {
std::filesystem::path dep_path{*p}; std::filesystem::path dep_path{*p};
if (dep_path.is_relative()) {
dep_path = relative(*p, c.root_directory());
}
dependants.emplace_back( dependants.emplace_back(
dep_path.lexically_normal().string()); dep_path.lexically_normal().string());
} }
@@ -1188,24 +1187,20 @@ void diagram_filter::init_filters(const config::diagram &c)
for (auto &&path : c.exclude().dependencies) { for (auto &&path : c.exclude().dependencies) {
if (auto p = path.get<std::string>(); p.has_value()) { if (auto p = path.get<std::string>(); p.has_value()) {
std::filesystem::path dep_path{*p}; std::filesystem::path dep_path{*p};
if (dep_path.is_relative()) {
dep_path = relative(*p, c.root_directory());
}
dependencies.emplace_back( dependencies.emplace_back(
dep_path.lexically_normal().string()); dep_path.lexically_normal().string());
} }
} }
add_exclusive_filter(std::make_unique< add_exclusive_filter(
edge_traversal_filter<include_diagram::model::diagram, std::make_unique<source_file_dependency_filter_t>(
common::model::source_file>>(filter_t::kExclusive, filter_t::kExclusive, relationship_t::kAssociation,
relationship_t::kAssociation, dependencies, true)); dependants, false));
add_exclusive_filter(std::make_unique< add_exclusive_filter(
edge_traversal_filter<include_diagram::model::diagram, std::make_unique<source_file_dependency_filter_t>(
common::model::source_file>>(filter_t::kExclusive, filter_t::kExclusive, relationship_t::kAssociation,
relationship_t::kAssociation, dependants)); dependencies, true));
} }
add_exclusive_filter(std::make_unique<context_filter>( add_exclusive_filter(std::make_unique<context_filter>(

View File

@@ -319,7 +319,13 @@ struct edge_traversal_filter : public filter_visitor {
// Now check if the e element is contained in the calculated set // Now check if the e element is contained in the calculated set
return std::any_of(matching_elements_.begin(), matching_elements_.end(), return std::any_of(matching_elements_.begin(), matching_elements_.end(),
[&e](const auto &te) { [&e](const auto &te) {
return te.get().full_name(false) == e.full_name(false); std::string tes = te.get().full_name(false);
std::string es = e.full_name(false);
if (tes == es)
return true;
return false;
}); });
} }
@@ -397,9 +403,7 @@ private:
} }
} }
assert(roots_.empty() == matching_elements_.empty()); bool keep_looking{!matching_elements_.empty()};
bool keep_looking{true};
while (keep_looking) { while (keep_looking) {
keep_looking = false; keep_looking = false;
if (forward_) { if (forward_) {
@@ -647,14 +651,22 @@ public:
*/ */
template <typename T> bool should_include(const T &e) const template <typename T> bool should_include(const T &e) const
{ {
auto exc = tvl::any_of(exclusive_.begin(), exclusive_.end(), auto exc = tvl::any_of(
[this, &e](const auto &ex) { return ex->match(diagram_, e); }); exclusive_.begin(), exclusive_.end(), [this, &e](const auto &ex) {
assert(ex.get() != nullptr);
return ex->match(diagram_, e);
});
if (tvl::is_true(exc)) if (tvl::is_true(exc))
return false; return false;
auto inc = tvl::all_of(inclusive_.begin(), inclusive_.end(), auto inc = tvl::all_of(
[this, &e](const auto &in) { return in->match(diagram_, e); }); inclusive_.begin(), inclusive_.end(), [this, &e](const auto &in) {
assert(in.get() != nullptr);
return in->match(diagram_, e);
});
return static_cast<bool>(tvl::is_undefined(inc) || tvl::is_true(inc)); return static_cast<bool>(tvl::is_undefined(inc) || tvl::is_true(inc));
} }

View File

@@ -332,34 +332,6 @@ template_parameter::template_params() const
return template_params_; return template_params_;
} }
bool operator==(const template_parameter &l, const template_parameter &r)
{
bool res{false};
if (l.is_template_parameter() != r.is_template_parameter())
return res;
if (l.is_function_template() != r.is_function_template())
return res;
if (l.is_template_parameter()) {
// If this is a template parameter (e.g. 'typename T' or 'typename U'
// we don't actually care what it is called
res = (l.is_variadic() == r.is_variadic()) &&
(l.default_value() == r.default_value());
}
else
res = (l.name() == r.name()) && (l.type() == r.type()) &&
(l.default_value() == r.default_value());
return res && (l.template_params_ == r.template_params_);
}
bool operator!=(const template_parameter &l, const template_parameter &r)
{
return !(l == r);
}
std::string template_parameter::deduced_context_str() const std::string template_parameter::deduced_context_str() const
{ {
std::vector<std::string> deduced_contexts; std::vector<std::string> deduced_contexts;

View File

@@ -143,12 +143,6 @@ public:
static template_parameter make_unexposed_argument(const std::string &type, static template_parameter make_unexposed_argument(const std::string &type,
const std::optional<std::string> &default_value = {}); const std::optional<std::string> &default_value = {});
friend bool operator==(
const template_parameter &l, const template_parameter &r);
friend bool operator!=(
const template_parameter &l, const template_parameter &r);
/** /**
* Set the type of template argument * Set the type of template argument
* *

View File

@@ -17,6 +17,7 @@
*/ */
#include "clang_visitor.h" #include "clang_visitor.h"
#include "util/util.h"
#if LLVM_VERSION_MAJOR > 17 #if LLVM_VERSION_MAJOR > 17
#define CLANG_UML_LLVM_COMMENT_KIND(COMMENT_KIND) \ #define CLANG_UML_LLVM_COMMENT_KIND(COMMENT_KIND) \
@@ -191,7 +192,7 @@ void clang_visitor::visit_param_command(
inja::json param = inja::json::object(); inja::json param = inja::json::object();
param["name"] = name; param["name"] = name;
param["description"] = description; param["description"] = util::trim(description);
cmt["param"].push_back(std::move(param)); cmt["param"].push_back(std::move(param));
} }
} }
@@ -226,7 +227,7 @@ void clang_visitor::visit_tparam_command(
inja::json param = inja::json::object(); inja::json param = inja::json::object();
param["name"] = name; param["name"] = name;
param["description"] = description; param["description"] = util::trim(description);
cmt["tparam"].push_back(std::move(param)); cmt["tparam"].push_back(std::move(param));
} }
} }

View File

@@ -756,6 +756,8 @@ struct config : public inheritable_diagram_options {
void inherit(); void inherit();
}; };
using config_ptr = std::unique_ptr<config>;
/** /**
* @brief Load and parse `.clang-uml` configuration file * @brief Load and parse `.clang-uml` configuration file
* *

View File

@@ -98,25 +98,6 @@ void generator::generate(const source_file &f, std::ostream &ostr) const
} }
} }
void generator::generate_notes(
std::ostream &ostr, const common::model::diagram_element &element) const
{
const auto &config =
common_generator<diagram_config, diagram_model>::config();
for (const auto &decorator : element.decorators()) {
auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
if (note && note->applies_to_diagram(config.name)) {
auto note_id_str = fmt::format("N_{}", note_id_++);
ostr << indent(1) << note_id_str << "(" << note->text << ")\n";
ostr << indent(1) << note_id_str << "-.-" << element.alias()
<< '\n';
}
}
}
void generator::generate_diagram(std::ostream &ostr) const void generator::generate_diagram(std::ostream &ostr) const
{ {
// Generate files and folders // Generate files and folders

View File

@@ -79,15 +79,6 @@ public:
*/ */
void generate_relationships(const source_file &p, std::ostream &ostr) const; void generate_relationships(const source_file &p, std::ostream &ostr) const;
/**
* @brief Generate notes attached to files
*
* @param ostr Output stream
* @param element Element with a note
*/
void generate_notes(std::ostream &ostr,
const common::model::diagram_element &element) const override;
/** /**
* @brief Generate diagram element * @brief Generate diagram element
* *
@@ -95,9 +86,6 @@ public:
* @param parent Output stream * @param parent Output stream
*/ */
void generate(const source_file &e, std::ostream &ostr) const; void generate(const source_file &e, std::ostream &ostr) const;
private:
mutable uint64_t note_id_{0UL};
}; };
} // namespace clanguml::include_diagram::generators::mermaid } // namespace clanguml::include_diagram::generators::mermaid

View File

@@ -89,25 +89,6 @@ void diagram::add_file(std::unique_ptr<common::model::source_file> &&f)
add_element(p, std::move(f)); add_element(p, std::move(f));
} }
std::string diagram::to_alias(const std::string &full_name) const
{
LOG_DBG("Looking for alias for {}", full_name);
auto path = common::model::filesystem_path{full_name};
if (path.is_empty())
throw error::uml_alias_missing(
fmt::format("Missing alias for '{}'", path.to_string()));
auto source_file = get_element<common::model::source_file>(path);
if (!source_file)
throw error::uml_alias_missing(
fmt::format("Missing alias for '{}'", path.to_string()));
return source_file.value().alias();
}
const common::reference_vector<common::model::source_file> & const common::reference_vector<common::model::source_file> &
diagram::files() const diagram::files() const
{ {

View File

@@ -103,17 +103,6 @@ public:
*/ */
template <typename ElementT> opt_ref<ElementT> find(eid_t id) const; template <typename ElementT> opt_ref<ElementT> find(eid_t id) const;
/**
* @brief Convert element id to PlantUML alias.
*
* @todo This method does not belong here - refactor to PlantUML specific
* code.
*
* @param full_name Full name of the diagram element.
* @return PlantUML alias.
*/
std::string to_alias(const std::string &full_name) const;
/** /**
* @brief Get list of references to files in the diagram model. * @brief Get list of references to files in the diagram model.
* *

View File

@@ -83,8 +83,12 @@ void translation_unit_visitor::include_visitor::InclusionDirective(
assert(diagram().get(current_file_id.value())); assert(diagram().get(current_file_id.value()));
#if LLVM_VERSION_MAJOR > 14 #if LLVM_VERSION_MAJOR > 14
if (!file.has_value())
return;
auto include_path = std::filesystem::path(file->getDir().getName().str()); auto include_path = std::filesystem::path(file->getDir().getName().str());
#else #else
if (file == nullptr)
return;
auto include_path = std::filesystem::path(file->getDir()->getName().str()); auto include_path = std::filesystem::path(file->getDir()->getName().str());
#endif #endif
include_path = include_path / file->getName().str(); include_path = include_path / file->getName().str();

View File

@@ -1717,20 +1717,20 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls)
const auto &[label, hint, access] = const auto &[label, hint, access] =
anonymous_struct_relationships_[cls->getID()]; anonymous_struct_relationships_[cls->getID()];
c.set_name(parent_class.value().name() + "##" + c.set_name(parent_class.value().name() +
fmt::format("({})", label)); "::" + fmt::format("({})", label));
parent_class.value().add_relationship( parent_class.value().add_relationship(
{hint, common::to_id(c.full_name(false)), access, label}); {hint, common::to_id(c.full_name(false)), access, label});
} }
else else
c.set_name(parent_class.value().name() + "##" + c.set_name(parent_class.value().name() + "::" +
fmt::format( fmt::format(
"(anonymous_{})", std::to_string(cls->getID()))); "(anonymous_{})", std::to_string(cls->getID())));
} }
else { else {
c.set_name( c.set_name(
parent_class.value().name() + "##" + cls->getNameAsString()); parent_class.value().name() + "::" + cls->getNameAsString());
} }
c.set_id(common::to_id(c.full_name(false))); c.set_id(common::to_id(c.full_name(false)));

View File

@@ -35,7 +35,7 @@ public:
: result_{result} : result_{result}
, ,
#if defined(__linux) || defined(__unix) || defined(__APPLE__) #if defined(__linux) || defined(__unix) || defined(__APPLE__)
pipe_{popen(command.c_str(), "r")} pipe_{popen(fmt::format("{} 2>&1", command).c_str(), "r")}
#elif defined(_WIN32) #elif defined(_WIN32)
pipe_{_popen(command.c_str(), "r")} pipe_{_popen(command.c_str(), "r")}
#endif #endif

View File

@@ -94,7 +94,8 @@ set(TEST_NAMES
test_cli_handler test_cli_handler
test_filters test_filters
test_thread_pool_executor test_thread_pool_executor
test_query_driver_output_extractor) test_query_driver_output_extractor
test_progress_indicator)
foreach(TEST_NAME ${TEST_NAMES}) foreach(TEST_NAME ${TEST_NAMES})
add_executable(${TEST_NAME}) add_executable(${TEST_NAME})

View File

@@ -31,7 +31,7 @@ TEST_CASE("t00002")
REQUIRE(!model->should_include({"std"}, "vector")); REQUIRE(!model->should_include({"std"}, "vector"));
CHECK_CLASS_DIAGRAM( CHECK_CLASS_DIAGRAM(
config, diagram, *model, *config, diagram, *model,
// Common test case for all diagram types // Common test case for all diagram types
[](const auto &src) { [](const auto &src) {
REQUIRE(HasTitle(src, "Basic class diagram example")); REQUIRE(HasTitle(src, "Basic class diagram example"));

View File

@@ -27,7 +27,7 @@ TEST_CASE("t00003")
REQUIRE(diagram->include().namespaces.size() == 1); REQUIRE(diagram->include().namespaces.size() == 1);
REQUIRE(diagram->exclude().namespaces.size() == 0); REQUIRE(diagram->exclude().namespaces.size() == 0);
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(!IsDependency(src, "A", "A")); REQUIRE(!IsDependency(src, "A", "A"));

View File

@@ -26,7 +26,7 @@ TEST_CASE("t00004")
REQUIRE(diagram->include().namespaces.size() == 1); REQUIRE(diagram->include().namespaces.size() == 1);
REQUIRE(diagram->exclude().namespaces.size() == 0); REQUIRE(diagram->exclude().namespaces.size() == 0);
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "A::AA")); REQUIRE(IsClass(src, "A::AA"));
REQUIRE(IsClass(src, "A::AA::AAA")); REQUIRE(IsClass(src, "A::AA::AAA"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00005")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00005", "t00005_class"); CHECK_CLASS_MODEL("t00005", "t00005_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00006")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00006", "t00006_class"); CHECK_CLASS_MODEL("t00006", "t00006_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00007")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00007", "t00007_class"); CHECK_CLASS_MODEL("t00007", "t00007_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00008")
CHECK_CLASS_MODEL("t00008", "t00008_class"); CHECK_CLASS_MODEL("t00008", "t00008_class");
CHECK_CLASS_DIAGRAM( CHECK_CLASS_DIAGRAM(
config, diagram, *model, *config, diagram, *model,
[](const auto &src) { [](const auto &src) {
// TODO: add option to resolve using declared types // TODO: add option to resolve using declared types
// REQUIRE(IsClassTemplate(src, "A<T,P,bool (*)(int, int),int N>")); // REQUIRE(IsClassTemplate(src, "A<T,P,bool (*)(int, int),int N>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00009")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00009", "t00009_class"); CHECK_CLASS_MODEL("t00009", "t00009_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "A<T>")); REQUIRE(IsClassTemplate(src, "A<T>"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00010")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00010", "t00010_class"); CHECK_CLASS_MODEL("t00010", "t00010_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "A<T,P>")); REQUIRE(IsClassTemplate(src, "A<T,P>"));
REQUIRE(IsClassTemplate(src, "B<T>")); REQUIRE(IsClassTemplate(src, "B<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00011")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00011", "t00011_class"); CHECK_CLASS_MODEL("t00011", "t00011_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(!IsClass(src, "external::C")); REQUIRE(!IsClass(src, "external::C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00012")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00012", "t00012_class"); CHECK_CLASS_MODEL("t00012", "t00012_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "A<T,Ts...>")); REQUIRE(IsClassTemplate(src, "A<T,Ts...>"));
REQUIRE(IsClassTemplate(src, "B<int... Is>")); REQUIRE(IsClassTemplate(src, "B<int... Is>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00013")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00013", "t00013_class"); CHECK_CLASS_MODEL("t00013", "t00013_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00014")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00014", "t00014_class"); CHECK_CLASS_MODEL("t00014", "t00014_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(!src.contains("type-parameter-")); REQUIRE(!src.contains("type-parameter-"));
REQUIRE(IsClassTemplate(src, "A<T,P>")); REQUIRE(IsClassTemplate(src, "A<T,P>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00015")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00015", "t00015_class"); CHECK_CLASS_MODEL("t00015", "t00015_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "ns1::A")); REQUIRE(IsClass(src, "ns1::A"));
REQUIRE(IsClass(src, "ns1::ns2_v0_9_0::A")); REQUIRE(IsClass(src, "ns1::ns2_v0_9_0::A"));
REQUIRE(IsClass(src, "ns1::Anon")); REQUIRE(IsClass(src, "ns1::Anon"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00016")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00016", "t00016_class"); CHECK_CLASS_MODEL("t00016", "t00016_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "is_numeric<typename>")); REQUIRE(IsClassTemplate(src, "is_numeric<typename>"));
REQUIRE(IsClassTemplate(src, "is_numeric<int>")); REQUIRE(IsClassTemplate(src, "is_numeric<int>"));
REQUIRE(IsClassTemplate(src, "is_numeric<bool>")); REQUIRE(IsClassTemplate(src, "is_numeric<bool>"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00017")
CHECK_CLASS_MODEL("t00017", "t00017_class"); CHECK_CLASS_MODEL("t00017", "t00017_class");
CHECK_CLASS_DIAGRAM( CHECK_CLASS_DIAGRAM(
config, diagram, *model, *config, diagram, *model,
[](const auto &src) { [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00018")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00018", "t00018_class"); CHECK_CLASS_MODEL("t00018", "t00018_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "widget")); REQUIRE(IsClass(src, "widget"));
REQUIRE(IsClass(src, "impl::widget")); REQUIRE(IsClass(src, "impl::widget"));
REQUIRE(IsDependency(src, "impl::widget", "widget")); REQUIRE(IsDependency(src, "impl::widget", "widget"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00019")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00019", "t00019_class"); CHECK_CLASS_MODEL("t00019", "t00019_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "Base")); REQUIRE(IsClass(src, "Base"));
REQUIRE(IsClassTemplate(src, "Layer1<LowerLayer>")); REQUIRE(IsClassTemplate(src, "Layer1<LowerLayer>"));
REQUIRE(IsClassTemplate(src, "Layer2<LowerLayer>")); REQUIRE(IsClassTemplate(src, "Layer2<LowerLayer>"));

View File

@@ -9,7 +9,13 @@ diagrams:
- clanguml::t00020 - clanguml::t00020
plantuml: plantuml:
after: after:
- '@A(ProductA1) <.. @A(Factory1)' - '@A(Factory1) ..> @A(ProductA1)'
- '@A(ProductB1) <.. @A(Factory1)' - '@A(Factory1) ..> @A(ProductB1)'
- '{{ alias("ProductA2") }} <.. {{ alias("Factory2") }}' - '{{ alias("Factory2") }} ..> {{ alias("ProductA2") }}'
- '{{ alias("ProductB2") }} <.. {{ alias("Factory2") }}' - '{{ alias("Factory2") }} ..> {{ alias("ProductB2") }}'
mermaid:
after:
- '@A(Factory1) ..> @A(ProductA1)'
- '@A(Factory1) ..> @A(ProductB1)'
- '{{ alias("Factory2") }} ..> {{ alias("ProductA2") }}'
- '{{ alias("Factory2") }} ..> {{ alias("ProductB2") }}'

View File

@@ -23,7 +23,9 @@ TEST_CASE("t00020")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00020", "t00020_class"); CHECK_CLASS_MODEL("t00020", "t00020_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(
*config, diagram, *model,
[](const auto &src) {
REQUIRE(IsAbstractClass(src, "AbstractFactory")); REQUIRE(IsAbstractClass(src, "AbstractFactory"));
REQUIRE(IsAbstractClass(src, "ProductA")); REQUIRE(IsAbstractClass(src, "ProductA"));
REQUIRE(IsAbstractClass(src, "ProductB")); REQUIRE(IsAbstractClass(src, "ProductB"));
@@ -33,5 +35,17 @@ TEST_CASE("t00020")
REQUIRE(IsClass(src, "ProductB2")); REQUIRE(IsClass(src, "ProductB2"));
REQUIRE(IsClass(src, "Factory1")); REQUIRE(IsClass(src, "Factory1"));
REQUIRE(IsClass(src, "Factory2")); REQUIRE(IsClass(src, "Factory2"));
},
[](const plantuml_t &src) {
REQUIRE(IsDependency(src, "Factory1", "ProductA1"));
REQUIRE(IsDependency(src, "Factory1", "ProductB1"));
REQUIRE(IsDependency(src, "Factory2", "ProductA2"));
REQUIRE(IsDependency(src, "Factory2", "ProductB2"));
},
[](const mermaid_t &src) {
REQUIRE(IsDependency(src, "Factory1", "ProductA1"));
REQUIRE(IsDependency(src, "Factory1", "ProductB1"));
REQUIRE(IsDependency(src, "Factory2", "ProductA2"));
REQUIRE(IsDependency(src, "Factory2", "ProductB2"));
}); });
} }

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00021")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00021", "t00021_class"); CHECK_CLASS_MODEL("t00021", "t00021_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsAbstractClass(src, "Item")); REQUIRE(IsAbstractClass(src, "Item"));
REQUIRE(IsAbstractClass(src, "Visitor")); REQUIRE(IsAbstractClass(src, "Visitor"));
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00022")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00022", "t00022_class"); CHECK_CLASS_MODEL("t00022", "t00022_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A1")); REQUIRE(IsClass(src, "A1"));
REQUIRE(IsClass(src, "A2")); REQUIRE(IsClass(src, "A2"));
REQUIRE(IsAbstractClass(src, "A")); REQUIRE(IsAbstractClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00023")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00023", "t00023_class"); CHECK_CLASS_MODEL("t00023", "t00023_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsAbstractClass(src, "Strategy")); REQUIRE(IsAbstractClass(src, "Strategy"));
REQUIRE(IsClass(src, "StrategyA")); REQUIRE(IsClass(src, "StrategyA"));
REQUIRE(IsClass(src, "StrategyB")); REQUIRE(IsClass(src, "StrategyB"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00024")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00024", "t00024_class"); CHECK_CLASS_MODEL("t00024", "t00024_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "Target1")); REQUIRE(IsClass(src, "Target1"));
REQUIRE(IsClass(src, "Target2")); REQUIRE(IsClass(src, "Target2"));
REQUIRE(IsClass(src, "Proxy")); REQUIRE(IsClass(src, "Proxy"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00025")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00025", "t00025_class"); CHECK_CLASS_MODEL("t00025", "t00025_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "Target1")); REQUIRE(IsClass(src, "Target1"));
REQUIRE(IsClass(src, "Target2")); REQUIRE(IsClass(src, "Target2"));
REQUIRE(IsClassTemplate(src, "Proxy<T>")); REQUIRE(IsClassTemplate(src, "Proxy<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00026")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00026", "t00026_class"); CHECK_CLASS_MODEL("t00026", "t00026_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "Memento<T>")); REQUIRE(IsClassTemplate(src, "Memento<T>"));
REQUIRE(IsClassTemplate(src, "Originator<T>")); REQUIRE(IsClassTemplate(src, "Originator<T>"));
REQUIRE(IsClassTemplate(src, "Caretaker<T>")); REQUIRE(IsClassTemplate(src, "Caretaker<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00027")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00027", "t00027_class"); CHECK_CLASS_MODEL("t00027", "t00027_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsAbstractClass(src, "Shape")); REQUIRE(IsAbstractClass(src, "Shape"));
REQUIRE(IsAbstractClass(src, "ShapeDecorator")); REQUIRE(IsAbstractClass(src, "ShapeDecorator"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00028")
CHECK_CLASS_MODEL("t00028", "t00028_class"); CHECK_CLASS_MODEL("t00028", "t00028_class");
CHECK_CLASS_DIAGRAM( CHECK_CLASS_DIAGRAM(
config, diagram, *model, *config, diagram, *model,
[](const auto &src) { [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00029")
REQUIRE(model->name() == "t00029_class"); REQUIRE(model->name() == "t00029_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(!IsClass(src, "B")); REQUIRE(!IsClass(src, "B"));
REQUIRE(IsClassTemplate(src, "C<T>")); REQUIRE(IsClassTemplate(src, "C<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00030")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00030", "t00030_class"); CHECK_CLASS_MODEL("t00030", "t00030_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00031")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00031", "t00031_class"); CHECK_CLASS_MODEL("t00031", "t00031_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsEnum(src, "B")); REQUIRE(IsEnum(src, "B"));
REQUIRE(IsClass(src, "D")); REQUIRE(IsClass(src, "D"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00032")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00032", "t00032_class"); CHECK_CLASS_MODEL("t00032", "t00032_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "Base")); REQUIRE(IsClass(src, "Base"));
REQUIRE(IsClass(src, "TBase")); REQUIRE(IsClass(src, "TBase"));
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00033")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00033", "t00033_class"); CHECK_CLASS_MODEL("t00033", "t00033_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "A<T>")); REQUIRE(IsClassTemplate(src, "A<T>"));
REQUIRE(IsClassTemplate(src, "B<T>")); REQUIRE(IsClassTemplate(src, "B<T>"));
REQUIRE(IsClassTemplate(src, "C<T>")); REQUIRE(IsClassTemplate(src, "C<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00034")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00034", "t00034_class"); CHECK_CLASS_MODEL("t00034", "t00034_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "lift_void<T>")); REQUIRE(IsClassTemplate(src, "lift_void<T>"));
REQUIRE(IsClassTemplate(src, "drop_void<T>")); REQUIRE(IsClassTemplate(src, "drop_void<T>"));
REQUIRE(IsClass(src, "Void")); REQUIRE(IsClass(src, "Void"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00035")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00035", "t00035_class"); CHECK_CLASS_MODEL("t00035", "t00035_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "Top")); REQUIRE(IsClass(src, "Top"));
REQUIRE(IsClass(src, "Bottom")); REQUIRE(IsClass(src, "Bottom"));
REQUIRE(IsClass(src, "Center")); REQUIRE(IsClass(src, "Center"));

View File

@@ -26,7 +26,7 @@ TEST_CASE("t00036")
REQUIRE(diagram->generate_packages() == true); REQUIRE(diagram->generate_packages() == true);
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, {"ns1::ns11", "A<T>"})); REQUIRE(IsClassTemplate(src, {"ns1::ns11", "A<T>"}));
REQUIRE(IsClassTemplate(src, {"ns1::ns11", "A<int>"})); REQUIRE(IsClassTemplate(src, {"ns1::ns11", "A<int>"}));
REQUIRE(IsClass(src, {"ns1::ns11::ns111", "B"})); REQUIRE(IsClass(src, {"ns1::ns11::ns111", "B"}));

View File

@@ -20,7 +20,11 @@ public:
struct { struct {
int len; int len;
int flags; int flags;
} __attribute__((packed)) bars[LENGTH]; }
#ifndef _MSC_VER
__attribute__((packed))
#endif
bars[LENGTH];
private: private:
struct { struct {

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00037")
REQUIRE(diagram->generate_packages() == true); REQUIRE(diagram->generate_packages() == true);
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "ST")); REQUIRE(IsClass(src, "ST"));
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "ST::(units)")); REQUIRE(IsClass(src, "ST::(units)"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00038")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00038", "t00038_class"); CHECK_CLASS_MODEL("t00038", "t00038_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00039")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00039", "t00039_class"); CHECK_CLASS_MODEL("t00039", "t00039_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "AA")); REQUIRE(IsClass(src, "AA"));
REQUIRE(IsClass(src, "AAA")); REQUIRE(IsClass(src, "AAA"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00040")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00040", "t00040_class"); CHECK_CLASS_MODEL("t00040", "t00040_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "AA")); REQUIRE(IsClass(src, "AA"));
REQUIRE(IsClass(src, "AAA")); REQUIRE(IsClass(src, "AAA"));

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00041")
REQUIRE(diagram->generate_packages() == false); REQUIRE(diagram->generate_packages() == false);
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(!IsClass(src, "A")); REQUIRE(!IsClass(src, "A"));
REQUIRE(!IsClass(src, "AA")); REQUIRE(!IsClass(src, "AA"));
REQUIRE(!IsClass(src, "AAA")); REQUIRE(!IsClass(src, "AAA"));

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00042")
REQUIRE(diagram->generate_packages() == false); REQUIRE(diagram->generate_packages() == false);
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "A<T>")); REQUIRE(IsClassTemplate(src, "A<T>"));
REQUIRE(IsClassTemplate(src, "B<T,K>")); REQUIRE(IsClassTemplate(src, "B<T,K>"));
REQUIRE(!IsClassTemplate(src, "C<T>")); REQUIRE(!IsClassTemplate(src, "C<T>"));

View File

@@ -12,3 +12,8 @@ diagrams:
- clanguml::t00043::dependencies::J - clanguml::t00043::dependencies::J
relationships: relationships:
- dependency - dependency
exclude:
dependants:
- clanguml::t00043::dependants::EE
dependencies:
- clanguml::t00043::dependencies::II

View File

@@ -24,6 +24,14 @@ struct E {
void e(D *d) { } void e(D *d) { }
}; };
struct EE {
void ee(E *e) { }
};
struct EEE {
void eee(EE *e) { }
};
struct F { }; struct F { };
} // namespace dependants } // namespace dependants
@@ -46,8 +54,18 @@ struct I {
void i(H *h) { } void i(H *h) { }
}; };
struct II;
struct III {
void iii(II *i) { }
};
struct II {
void ii() { }
};
struct J { struct J {
void i(I *i) { } void i(I *i) { }
void ii(II *ii) { }
}; };
} // namespace dependencies } // namespace dependencies

View File

@@ -23,13 +23,16 @@ TEST_CASE("t00043")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00043", "t00043_class"); CHECK_CLASS_MODEL("t00043", "t00043_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, {"dependants", "A"})); REQUIRE(IsClass(src, {"dependants", "A"}));
REQUIRE(IsClass(src, {"dependants", "B"})); REQUIRE(IsClass(src, {"dependants", "B"}));
REQUIRE(IsClass(src, {"dependants", "C"})); REQUIRE(IsClass(src, {"dependants", "C"}));
REQUIRE(IsClass(src, {"dependants", "D"})); REQUIRE(IsClass(src, {"dependants", "D"}));
REQUIRE(IsClass(src, {"dependants", "BB"})); REQUIRE(IsClass(src, {"dependants", "BB"}));
REQUIRE(IsClass(src, {"dependants", "E"})); REQUIRE(IsClass(src, {"dependants", "E"}));
REQUIRE(!IsClass(src, {"dependants", "EE"}));
REQUIRE(!IsClass(src, {"dependants", "EEE"}));
REQUIRE(IsDependency(src, {"dependants", "B"}, {"dependants", "A"})); REQUIRE(IsDependency(src, {"dependants", "B"}, {"dependants", "A"}));
REQUIRE(IsDependency(src, {"dependants", "BB"}, {"dependants", "A"})); REQUIRE(IsDependency(src, {"dependants", "BB"}, {"dependants", "A"}));
REQUIRE(IsDependency(src, {"dependants", "C"}, {"dependants", "B"})); REQUIRE(IsDependency(src, {"dependants", "C"}, {"dependants", "B"}));
@@ -40,6 +43,8 @@ TEST_CASE("t00043")
REQUIRE(IsClass(src, {"dependencies", "GG"})); REQUIRE(IsClass(src, {"dependencies", "GG"}));
REQUIRE(IsClass(src, {"dependencies", "H"})); REQUIRE(IsClass(src, {"dependencies", "H"}));
REQUIRE(!IsClass(src, {"dependencies", "HH"})); REQUIRE(!IsClass(src, {"dependencies", "HH"}));
REQUIRE(!IsClass(src, {"dependencies", "II"}));
REQUIRE(!IsClass(src, {"dependencies", "III"}));
REQUIRE( REQUIRE(
IsDependency(src, {"dependencies", "J"}, {"dependencies", "I"})); IsDependency(src, {"dependencies", "J"}, {"dependencies", "I"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00044")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00044", "t00044_class"); CHECK_CLASS_MODEL("t00044", "t00044_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(!src.contains("type-parameter-")); REQUIRE(!src.contains("type-parameter-"));
REQUIRE(IsClassTemplate(src, "sink<T>")); REQUIRE(IsClassTemplate(src, "sink<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00045")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00045", "t00045_class"); CHECK_CLASS_MODEL("t00045", "t00045_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, {"ns1", "A"})); REQUIRE(IsClass(src, {"ns1", "A"}));
REQUIRE(IsClass(src, {"ns1::ns2", "A"})); REQUIRE(IsClass(src, {"ns1::ns2", "A"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00046")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00046", "t00046_class"); CHECK_CLASS_MODEL("t00046", "t00046_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "AA")); REQUIRE(IsClass(src, "AA"));
REQUIRE(IsClass(src, {"ns1::ns2", "B"})); REQUIRE(IsClass(src, {"ns1::ns2", "B"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00047")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00047", "t00047_class"); CHECK_CLASS_MODEL("t00047", "t00047_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClassTemplate(src, "conditional_t<Ts...>")); REQUIRE(IsClassTemplate(src, "conditional_t<Ts...>"));
REQUIRE(IsClass(src, "conditional_t<Else>")); REQUIRE(IsClass(src, "conditional_t<Else>"));
REQUIRE(IsClass(src, "conditional_t<std::true_type,Result,Tail...>")); REQUIRE(IsClass(src, "conditional_t<std::true_type,Result,Tail...>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00048")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00048", "t00048_class"); CHECK_CLASS_MODEL("t00048", "t00048_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
// Check if all classes exist // Check if all classes exist
REQUIRE(IsAbstractClass(src, "Base")); REQUIRE(IsAbstractClass(src, "Base"));
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00049")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00049", "t00049_class"); CHECK_CLASS_MODEL("t00049", "t00049_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "R")); REQUIRE(IsClass(src, "R"));
REQUIRE(IsClassTemplate(src, "A<T>")); REQUIRE(IsClassTemplate(src, "A<T>"));

View File

@@ -81,6 +81,11 @@ enum class E { E1, E2, E3 };
template <typename T, typename V, int N> class F { template <typename T, typename V, int N> class F {
T t[N]; T t[N];
V v; V v;
/// \brief Set value of v
///
/// \param v_ New value for v
V set_value(V v_) const { return v = v_; }
}; };
/// This is a short description of class G. /// This is a short description of class G.

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00050")
CHECK_CLASS_MODEL("t00050", "t00050_class"); CHECK_CLASS_MODEL("t00050", "t00050_class");
CHECK_CLASS_DIAGRAM( CHECK_CLASS_DIAGRAM(
config, diagram, *model, *config, diagram, *model,
[](const auto &src) { [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00051")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00051", "t00051_class"); CHECK_CLASS_MODEL("t00051", "t00051_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsInnerClass(src, "A", "A::custom_thread1")); REQUIRE(IsInnerClass(src, "A", "A::custom_thread1"));
REQUIRE(IsInnerClass(src, "A", "A::custom_thread2")); REQUIRE(IsInnerClass(src, "A", "A::custom_thread2"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00052")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00052", "t00052_class"); CHECK_CLASS_MODEL("t00052", "t00052_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClassTemplate(src, "B<T>")); REQUIRE(IsClassTemplate(src, "B<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00053")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00053", "t00053_class"); CHECK_CLASS_MODEL("t00053", "t00053_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "a")); REQUIRE(IsClass(src, "a"));
REQUIRE(IsClass(src, "b")); REQUIRE(IsClass(src, "b"));
REQUIRE(IsClass(src, "c")); REQUIRE(IsClass(src, "c"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00054")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00054", "t00054_class"); CHECK_CLASS_MODEL("t00054", "t00054_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "a")); REQUIRE(IsClass(src, "a"));
REQUIRE(IsClass(src, "b")); REQUIRE(IsClass(src, "b"));
REQUIRE(IsClass(src, {"detail", "c"})); REQUIRE(IsClass(src, {"detail", "c"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00055")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00055", "t00055_class"); CHECK_CLASS_MODEL("t00055", "t00055_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00056")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00056", "t00056_class"); CHECK_CLASS_MODEL("t00056", "t00056_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsConcept(src, "greater_than_simple<T,L>")); REQUIRE(IsConcept(src, "greater_than_simple<T,L>"));
REQUIRE(IsConcept(src, "greater_than_with_requires<T,P>")); REQUIRE(IsConcept(src, "greater_than_with_requires<T,P>"));
REQUIRE(IsConcept(src, "max_four_bytes<T>")); REQUIRE(IsConcept(src, "max_four_bytes<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00057")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00057", "t00057_class"); CHECK_CLASS_MODEL("t00057", "t00057_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "t00057_A")); REQUIRE(IsClass(src, "t00057_A"));
REQUIRE(IsClass(src, "t00057_B")); REQUIRE(IsClass(src, "t00057_B"));
REQUIRE(IsClass(src, "t00057_C")); REQUIRE(IsClass(src, "t00057_C"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00058")
CHECK_CLASS_MODEL("t00058", "t00058_class"); CHECK_CLASS_MODEL("t00058", "t00058_class");
CHECK_CLASS_DIAGRAM( CHECK_CLASS_DIAGRAM(
config, diagram, *model, *config, diagram, *model,
[](const auto &src) { [](const auto &src) {
REQUIRE(IsClassTemplate(src, "A<int,int,double,std::string>")); REQUIRE(IsClassTemplate(src, "A<int,int,double,std::string>"));
REQUIRE(IsClassTemplate( REQUIRE(IsClassTemplate(

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00059")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00059", "t00059_class"); CHECK_CLASS_MODEL("t00059", "t00059_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsConcept(src, "fruit_c<T>")); REQUIRE(IsConcept(src, "fruit_c<T>"));
REQUIRE(IsConcept(src, "apple_c<T>")); REQUIRE(IsConcept(src, "apple_c<T>"));
REQUIRE(IsConcept(src, "orange_c<T>")); REQUIRE(IsConcept(src, "orange_c<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00060")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00060", "t00060_class"); CHECK_CLASS_MODEL("t00060", "t00060_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, "B")); REQUIRE(IsClass(src, "B"));
REQUIRE(IsClass(src, "C")); REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00061")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00061", "t00061_class"); CHECK_CLASS_MODEL("t00061", "t00061_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(!IsClass(src, "B")); REQUIRE(!IsClass(src, "B"));
REQUIRE(!IsClass(src, "C")); REQUIRE(!IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00062")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00062", "t00062_class"); CHECK_CLASS_MODEL("t00062", "t00062_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(!src.contains("type-parameter-")); REQUIRE(!src.contains("type-parameter-"));
REQUIRE(IsClassTemplate(src, "A<T>")); REQUIRE(IsClassTemplate(src, "A<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00063")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00063", "t00063_class"); CHECK_CLASS_MODEL("t00063", "t00063_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(!IsEnum(src, "B")); REQUIRE(!IsEnum(src, "B"));
REQUIRE(!IsEnum(src, "C")); REQUIRE(!IsEnum(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00064")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00064", "t00064_class"); CHECK_CLASS_MODEL("t00064", "t00064_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(!src.contains("type-parameter-")); REQUIRE(!src.contains("type-parameter-"));
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00065")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00065", "t00065_class"); CHECK_CLASS_MODEL("t00065", "t00065_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "R")); REQUIRE(IsClass(src, "R"));
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(IsClass(src, {"detail", "AImpl"})); REQUIRE(IsClass(src, {"detail", "AImpl"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00066")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00066", "t00066_class"); CHECK_CLASS_MODEL("t00066", "t00066_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "A")); REQUIRE(IsClass(src, "A"));
REQUIRE(!IsDependency(src, "A", "A")); REQUIRE(!IsDependency(src, "A", "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00067")
auto [config, db, diagram, model] = auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00067", "t00067_class"); CHECK_CLASS_MODEL("t00067", "t00067_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(!IsMethod<Public, Default>(src, "A", "A")); REQUIRE(!IsMethod<Public, Default>(src, "A", "A"));
REQUIRE(!IsMethod<Public, Default>(src, "A", "void", "A &&")); REQUIRE(!IsMethod<Public, Default>(src, "A", "void", "A &&"));
REQUIRE(!IsMethod<Public, Deleted>(src, "A", "void", "const A &")); REQUIRE(!IsMethod<Public, Deleted>(src, "A", "void", "const A &"));

Some files were not shown because too many files have changed in this diff Show More