Improved test coverage (#287)

This commit is contained in:
Bartek Kryza
2024-06-10 15:51:17 +02:00
parent 514c439413
commit fa742a03c4
170 changed files with 320 additions and 323 deletions

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

@@ -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

@@ -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
*