Improved test coverage (#287)
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user