Merge pull request #288 from bkryza/improve-test-coverage

Improve test coverage
This commit is contained in:
Bartek Kryza
2024-06-10 20:46:33 +02:00
committed by GitHub
197 changed files with 1006 additions and 412 deletions

View File

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

View File

@@ -41,11 +41,12 @@ jobs:
make check-formatting
- name: Build and unit test
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
run: |
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
- name: Upload coverage
uses: codecov/codecov-action@v3

View File

@@ -61,6 +61,15 @@ setup_git_version()
message(STATUS "clang-uml version: "
"${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
#

View File

@@ -37,6 +37,7 @@ CMAKE_PREFIX ?=
CMAKE_CXX_FLAGS ?=
CMAKE_EXE_LINKER_FLAGS ?=
CMAKE_GENERATOR ?= Unix Makefiles
CODE_COVERAGE ?= OFF
ENABLE_CXX_MODULES_TEST_CASES ?= OFF
ENABLE_CUDA_TEST_CASES ?= OFF
@@ -50,7 +51,7 @@ DESTDIR ?=
.PHONY: clean
clean:
rm -rf debug release debug_tidy
rm -rf debug release debug_tidy coverage.info coverage-src.info
debug/CMakeLists.txt:
cmake -S . -B debug \
@@ -65,7 +66,8 @@ debug/CMakeLists.txt:
-DLINK_LLVM_SHARED=${LLVM_SHARED} \
-DCMAKE_PREFIX=${CMAKE_PREFIX} \
-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:
cmake -S . -B release \
@@ -115,6 +117,13 @@ test: debug
test_release: 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
make -C release install DESTDIR=${DESTDIR}

View File

@@ -1,6 +1,6 @@
# 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

View File

@@ -207,10 +207,6 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
auto &template_specialization = *template_specialization_ptr;
if (cls->hasBody()) {
process_template_specialization_children(cls, template_specialization);
}
if (cls->hasDefinition()) {
// Process template specialization bases
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(
const clang::RecordDecl *cls, class_ &c)
{

View File

@@ -224,7 +224,7 @@ private:
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 c Class diagram element model
*/

View File

@@ -389,6 +389,11 @@ runtime_config cli_handler::get_runtime_config() const
return cfg;
}
void cli_handler::set_config_path(const std::string &path)
{
config_path = path;
}
cli_flow_t cli_handler::print_version()
{
ostr_ << "clang-uml " << clanguml::version::CLANG_UML_VERSION << '\n';
@@ -477,7 +482,7 @@ cli_flow_t cli_handler::create_config_file()
{
namespace fs = std::filesystem;
fs::path config_file{"./.clang-uml"};
fs::path config_file{config_path};
if (fs::exists(config_file)) {
ostr_ << "ERROR: .clang-uml file already exists\n";

View File

@@ -153,6 +153,13 @@ public:
*/
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::optional<std::string> compilation_database_dir{};
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);
}
// Convert plantuml or mermaid to an image using command provided
// in the command line arguments
if (runtime_config.render_diagrams) {
render_diagram(generator_type, diagram);
}

View File

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

View File

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

View File

@@ -1086,7 +1086,7 @@ void diagram_filter::init_filters(const config::diagram &c)
element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kInclusive, relationship_t::kAssociation,
dependants));
dependants, false));
element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>(
@@ -1149,26 +1149,29 @@ void diagram_filter::init_filters(const config::diagram &c)
std::make_unique<specializations_filter_t>(filter_t::kExclusive,
relationship_t::kInstantiation, c.exclude().specializations));
add_exclusive_filter(
std::make_unique<class_dependants_filter_t>(filter_t::kExclusive,
relationship_t::kDependency, c.exclude().dependants));
if (c.type() == diagram_t::kClass) {
add_exclusive_filter(std::make_unique<class_dependants_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependants));
add_exclusive_filter(
std::make_unique<package_dependants_filter_t>(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));
add_exclusive_filter(std::make_unique<package_dependencies_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, true));
if (c.type() == diagram_t::kSequence) {
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(
std::make_unique<package_dependencies_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, true));
add_exclusive_filter(std::make_unique<package_dependants_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependants));
}
else if (c.type() == diagram_t::kInclude) {
std::vector<std::string> dependants;
std::vector<std::string> dependencies;
@@ -1176,10 +1179,6 @@ void diagram_filter::init_filters(const config::diagram &c)
for (auto &&path : c.exclude().dependants) {
if (auto p = path.get<std::string>(); p.has_value()) {
std::filesystem::path dep_path{*p};
if (dep_path.is_relative()) {
dep_path = relative(*p, c.root_directory());
}
dependants.emplace_back(
dep_path.lexically_normal().string());
}
@@ -1188,24 +1187,20 @@ void diagram_filter::init_filters(const config::diagram &c)
for (auto &&path : c.exclude().dependencies) {
if (auto p = path.get<std::string>(); p.has_value()) {
std::filesystem::path dep_path{*p};
if (dep_path.is_relative()) {
dep_path = relative(*p, c.root_directory());
}
dependencies.emplace_back(
dep_path.lexically_normal().string());
}
}
add_exclusive_filter(std::make_unique<
edge_traversal_filter<include_diagram::model::diagram,
common::model::source_file>>(filter_t::kExclusive,
relationship_t::kAssociation, dependencies, true));
add_exclusive_filter(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kExclusive, relationship_t::kAssociation,
dependants, false));
add_exclusive_filter(std::make_unique<
edge_traversal_filter<include_diagram::model::diagram,
common::model::source_file>>(filter_t::kExclusive,
relationship_t::kAssociation, dependants));
add_exclusive_filter(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kExclusive, relationship_t::kAssociation,
dependencies, true));
}
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
return std::any_of(matching_elements_.begin(), matching_elements_.end(),
[&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{true};
bool keep_looking{!matching_elements_.empty()};
while (keep_looking) {
keep_looking = false;
if (forward_) {
@@ -647,14 +651,22 @@ public:
*/
template <typename T> bool should_include(const T &e) const
{
auto exc = tvl::any_of(exclusive_.begin(), exclusive_.end(),
[this, &e](const auto &ex) { return ex->match(diagram_, e); });
auto exc = tvl::any_of(
exclusive_.begin(), exclusive_.end(), [this, &e](const auto &ex) {
assert(ex.get() != nullptr);
return ex->match(diagram_, e);
});
if (tvl::is_true(exc))
return false;
auto inc = tvl::all_of(inclusive_.begin(), inclusive_.end(),
[this, &e](const auto &in) { return in->match(diagram_, e); });
auto inc = tvl::all_of(
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));
}

View File

@@ -332,34 +332,6 @@ template_parameter::template_params() const
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::vector<std::string> deduced_contexts;

View File

@@ -143,12 +143,6 @@ public:
static template_parameter make_unexposed_argument(const std::string &type,
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
*

View File

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

View File

@@ -756,6 +756,8 @@ struct config : public inheritable_diagram_options {
void inherit();
};
using config_ptr = std::unique_ptr<config>;
/**
* @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
{
// Generate files and folders

View File

@@ -79,15 +79,6 @@ public:
*/
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
*
@@ -95,9 +86,6 @@ public:
* @param parent Output stream
*/
void generate(const source_file &e, std::ostream &ostr) const;
private:
mutable uint64_t note_id_{0UL};
};
} // 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));
}
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> &
diagram::files() const
{

View File

@@ -103,17 +103,6 @@ public:
*/
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.
*

View File

@@ -83,8 +83,12 @@ void translation_unit_visitor::include_visitor::InclusionDirective(
assert(diagram().get(current_file_id.value()));
#if LLVM_VERSION_MAJOR > 14
if (!file.has_value())
return;
auto include_path = std::filesystem::path(file->getDir().getName().str());
#else
if (file == nullptr)
return;
auto include_path = std::filesystem::path(file->getDir()->getName().str());
#endif
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] =
anonymous_struct_relationships_[cls->getID()];
c.set_name(parent_class.value().name() + "##" +
fmt::format("({})", label));
c.set_name(parent_class.value().name() +
"::" + fmt::format("({})", label));
parent_class.value().add_relationship(
{hint, common::to_id(c.full_name(false)), access, label});
}
else
c.set_name(parent_class.value().name() + "##" +
c.set_name(parent_class.value().name() + "::" +
fmt::format(
"(anonymous_{})", std::to_string(cls->getID())));
}
else {
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)));

View File

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

View File

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

View File

@@ -27,7 +27,7 @@ TEST_CASE("t00003")
REQUIRE(diagram->include().namespaces.size() == 1);
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(!IsDependency(src, "A", "A"));

View File

@@ -26,7 +26,7 @@ TEST_CASE("t00004")
REQUIRE(diagram->include().namespaces.size() == 1);
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::AA"));
REQUIRE(IsClass(src, "A::AA::AAA"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00005")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00006")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00007")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00008")
CHECK_CLASS_MODEL("t00008", "t00008_class");
CHECK_CLASS_DIAGRAM(
config, diagram, *model,
*config, diagram, *model,
[](const auto &src) {
// TODO: add option to resolve using declared types
// 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] =
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(IsClass(src, "B"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00010")
auto [config, db, diagram, model] =
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, "B<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00011")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(!IsClass(src, "external::C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00012")
auto [config, db, diagram, model] =
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, "B<int... Is>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00013")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00014")
auto [config, db, diagram, model] =
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(IsClassTemplate(src, "A<T,P>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00015")
auto [config, db, diagram, model] =
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::ns2_v0_9_0::A"));
REQUIRE(IsClass(src, "ns1::Anon"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00016")
auto [config, db, diagram, model] =
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<int>"));
REQUIRE(IsClassTemplate(src, "is_numeric<bool>"));

View File

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

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00018")
auto [config, db, diagram, model] =
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, "impl::widget"));
REQUIRE(IsDependency(src, "impl::widget", "widget"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00019")
auto [config, db, diagram, model] =
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(IsClassTemplate(src, "Layer1<LowerLayer>"));
REQUIRE(IsClassTemplate(src, "Layer2<LowerLayer>"));

View File

@@ -9,7 +9,13 @@ diagrams:
- clanguml::t00020
plantuml:
after:
- '@A(ProductA1) <.. @A(Factory1)'
- '@A(ProductB1) <.. @A(Factory1)'
- '{{ alias("ProductA2") }} <.. {{ alias("Factory2") }}'
- '{{ alias("ProductB2") }} <.. {{ alias("Factory2") }}'
- '@A(Factory1) ..> @A(ProductA1)'
- '@A(Factory1) ..> @A(ProductB1)'
- '{{ alias("Factory2") }} ..> {{ alias("ProductA2") }}'
- '{{ 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,15 +23,29 @@ TEST_CASE("t00020")
auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00020", "t00020_class");
CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) {
REQUIRE(IsAbstractClass(src, "AbstractFactory"));
REQUIRE(IsAbstractClass(src, "ProductA"));
REQUIRE(IsAbstractClass(src, "ProductB"));
REQUIRE(IsClass(src, "ProductA1"));
REQUIRE(IsClass(src, "ProductA2"));
REQUIRE(IsClass(src, "ProductB1"));
REQUIRE(IsClass(src, "ProductB2"));
REQUIRE(IsClass(src, "Factory1"));
REQUIRE(IsClass(src, "Factory2"));
});
CHECK_CLASS_DIAGRAM(
*config, diagram, *model,
[](const auto &src) {
REQUIRE(IsAbstractClass(src, "AbstractFactory"));
REQUIRE(IsAbstractClass(src, "ProductA"));
REQUIRE(IsAbstractClass(src, "ProductB"));
REQUIRE(IsClass(src, "ProductA1"));
REQUIRE(IsClass(src, "ProductA2"));
REQUIRE(IsClass(src, "ProductB1"));
REQUIRE(IsClass(src, "ProductB2"));
REQUIRE(IsClass(src, "Factory1"));
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] =
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, "Visitor"));
REQUIRE(IsClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00022")
auto [config, db, diagram, model] =
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, "A2"));
REQUIRE(IsAbstractClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00023")
auto [config, db, diagram, model] =
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(IsClass(src, "StrategyA"));
REQUIRE(IsClass(src, "StrategyB"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00024")
auto [config, db, diagram, model] =
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, "Target2"));
REQUIRE(IsClass(src, "Proxy"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00025")
auto [config, db, diagram, model] =
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, "Target2"));
REQUIRE(IsClassTemplate(src, "Proxy<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00026")
auto [config, db, diagram, model] =
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, "Originator<T>"));
REQUIRE(IsClassTemplate(src, "Caretaker<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00027")
auto [config, db, diagram, model] =
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, "ShapeDecorator"));

View File

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

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00029")
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, "B"));
REQUIRE(IsClassTemplate(src, "C<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00030")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00031")
auto [config, db, diagram, model] =
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(IsEnum(src, "B"));
REQUIRE(IsClass(src, "D"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00032")
auto [config, db, diagram, model] =
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, "TBase"));
REQUIRE(IsClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00033")
auto [config, db, diagram, model] =
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, "B<T>"));
REQUIRE(IsClassTemplate(src, "C<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00034")
auto [config, db, diagram, model] =
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, "drop_void<T>"));
REQUIRE(IsClass(src, "Void"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00035")
auto [config, db, diagram, model] =
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, "Bottom"));
REQUIRE(IsClass(src, "Center"));

View File

@@ -26,7 +26,7 @@ TEST_CASE("t00036")
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<int>"}));
REQUIRE(IsClass(src, {"ns1::ns11::ns111", "B"}));

View File

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

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00037")
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, "A"));
REQUIRE(IsClass(src, "ST::(units)"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00038")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00039")
auto [config, db, diagram, model] =
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, "AA"));
REQUIRE(IsClass(src, "AAA"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00040")
auto [config, db, diagram, model] =
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, "AA"));
REQUIRE(IsClass(src, "AAA"));

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00041")
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, "AA"));
REQUIRE(!IsClass(src, "AAA"));

View File

@@ -25,7 +25,7 @@ TEST_CASE("t00042")
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, "B<T,K>"));
REQUIRE(!IsClassTemplate(src, "C<T>"));

View File

@@ -11,4 +11,9 @@ diagrams:
dependencies:
- clanguml::t00043::dependencies::J
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) { }
};
struct EE {
void ee(E *e) { }
};
struct EEE {
void eee(EE *e) { }
};
struct F { };
} // namespace dependants
@@ -46,8 +54,18 @@ struct I {
void i(H *h) { }
};
struct II;
struct III {
void iii(II *i) { }
};
struct II {
void ii() { }
};
struct J {
void i(I *i) { }
void ii(II *ii) { }
};
} // namespace dependencies

View File

@@ -23,13 +23,16 @@ TEST_CASE("t00043")
auto [config, db, diagram, model] =
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", "B"}));
REQUIRE(IsClass(src, {"dependants", "C"}));
REQUIRE(IsClass(src, {"dependants", "D"}));
REQUIRE(IsClass(src, {"dependants", "BB"}));
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", "BB"}, {"dependants", "A"}));
REQUIRE(IsDependency(src, {"dependants", "C"}, {"dependants", "B"}));
@@ -40,6 +43,8 @@ TEST_CASE("t00043")
REQUIRE(IsClass(src, {"dependencies", "GG"}));
REQUIRE(IsClass(src, {"dependencies", "H"}));
REQUIRE(!IsClass(src, {"dependencies", "HH"}));
REQUIRE(!IsClass(src, {"dependencies", "II"}));
REQUIRE(!IsClass(src, {"dependencies", "III"}));
REQUIRE(
IsDependency(src, {"dependencies", "J"}, {"dependencies", "I"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00044")
auto [config, db, diagram, model] =
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(IsClassTemplate(src, "sink<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00045")
auto [config, db, diagram, model] =
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, {"ns1", "A"}));
REQUIRE(IsClass(src, {"ns1::ns2", "A"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00046")
auto [config, db, diagram, model] =
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, "AA"));
REQUIRE(IsClass(src, {"ns1::ns2", "B"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00047")
auto [config, db, diagram, model] =
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(IsClass(src, "conditional_t<Else>"));
REQUIRE(IsClass(src, "conditional_t<std::true_type,Result,Tail...>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00048")
auto [config, db, diagram, model] =
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
REQUIRE(IsAbstractClass(src, "Base"));
REQUIRE(IsClass(src, "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00049")
auto [config, db, diagram, model] =
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(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 {
T t[N];
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.

View File

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

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00051")
auto [config, db, diagram, model] =
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(IsInnerClass(src, "A", "A::custom_thread1"));
REQUIRE(IsInnerClass(src, "A", "A::custom_thread2"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00052")
auto [config, db, diagram, model] =
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(IsClassTemplate(src, "B<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00053")
auto [config, db, diagram, model] =
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, "b"));
REQUIRE(IsClass(src, "c"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00054")
auto [config, db, diagram, model] =
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, "b"));
REQUIRE(IsClass(src, {"detail", "c"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00055")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00056")
auto [config, db, diagram, model] =
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_with_requires<T,P>"));
REQUIRE(IsConcept(src, "max_four_bytes<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00057")
auto [config, db, diagram, model] =
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_B"));
REQUIRE(IsClass(src, "t00057_C"));

View File

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

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00059")
auto [config, db, diagram, model] =
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, "apple_c<T>"));
REQUIRE(IsConcept(src, "orange_c<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00060")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00061")
auto [config, db, diagram, model] =
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, "B"));
REQUIRE(!IsClass(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00062")
auto [config, db, diagram, model] =
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(IsClassTemplate(src, "A<T>"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00063")
auto [config, db, diagram, model] =
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(!IsEnum(src, "B"));
REQUIRE(!IsEnum(src, "C"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00064")
auto [config, db, diagram, model] =
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(IsClass(src, "A"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00065")
auto [config, db, diagram, model] =
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, "A"));
REQUIRE(IsClass(src, {"detail", "AImpl"}));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00066")
auto [config, db, diagram, model] =
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(!IsDependency(src, "A", "A"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00067")
auto [config, db, diagram, model] =
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", "void", "A &&"));
REQUIRE(!IsMethod<Public, Deleted>(src, "A", "void", "const A &"));

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00068_r0")
auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00068", "t00068_r0_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, "AA"));
REQUIRE(IsClass(src, "AAA"));
@@ -45,7 +45,7 @@ TEST_CASE("t00068_r1")
auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00068", "t00068_r1_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, "AA"));
REQUIRE(IsClass(src, "AAA"));
@@ -67,7 +67,7 @@ TEST_CASE("t00068_r2")
auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00068", "t00068_r2_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, "AA"));
REQUIRE(IsClass(src, "AAA"));

View File

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

View File

@@ -23,7 +23,7 @@ TEST_CASE("t00070")
auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00070", "t00070_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, "B"));
REQUIRE(!IsClass(src, "C"));

View File

@@ -24,7 +24,7 @@ TEST_CASE("t00071")
auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00071", "t00071_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, "R"));

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