Changed scope_t to access_t and fixed friend access specifier handling

This commit is contained in:
Bartek Kryza
2022-03-30 23:27:46 +02:00
parent a216a81e19
commit a8b57e4eb1
30 changed files with 134 additions and 137 deletions

View File

@@ -11,17 +11,19 @@
* `glob` - list of glob patterns to match source code files for analysis
* `include_relations_also_as_members` - when set to `false`, class members for relationships are rendered in UML are skipped from class definition (default: `true`)
* `generate_method_arguments` - determines whether the class diagrams methods contain full arguments (`full`), are abbreviated (`abbreviated`) or skipped (`none`)
* `using_namespace` - similar to C++ `using namespace`, a `A::B` value here will render a class `A::B::C::MyClass` in the diagram as `C::MyClass`
* `using_namespace` - similar to C++ `using namespace`, a `A::B` value here will render a class `A::B::C::MyClass` in the diagram as `C::MyClass`, at most 1 value is supported
* `include` - definition of inclusion patterns:
* `namespaces` - list of namespaces to include
* `relationships` - list of relationships to include
* `entity_types` - list of entity types to include (e.g. `class`, `enum`)
* `scopes` - list of visibility scopes to include (e.g. `private`)
* `elements` - list of elements, i.e. specific classes, enums, templates to include
* `access` - list of visibility scopes to include (e.g. `private`)
* `subclasses` - include only subclasses of specified classes (and themselves)
* `exclude` - definition of excqlusion patterns:
* `namespaces` - list of namespaces to exclude
* `relationships` - list of relationships to exclude
* `entity_types` - list of entity types to exclude (e.g. `class`, `enum`)
* `scopes` - list of visibility scopes to exclude (e.g. `private`)
* `elements` - list of elements, i.e. specific classes, enums, templates to exclude
* `access` - list of visibility scopes to exclude (e.g. `private`)
* `subclasses` - exclude subclasses of specified classes (and themselves)
* `layout` - add layout hints for entities (classes, packages)
* `plantuml` - verbatim PlantUML directives which should be added to a diagram
* `before` - list of directives which will be added before the generated diagram
@@ -81,7 +83,7 @@ diagrams:
- clanguml::class_diagram::model
exclude:
# Do not include private members and methods in the diagram
scopes:
access:
- private
layout:
# Add layout hints for PlantUML

View File

@@ -25,7 +25,7 @@ diagrams:
exclude:
namespaces:
- cppast::detail
scopes:
access:
- public
- protected
- private
@@ -73,7 +73,7 @@ diagrams:
- cppast::detail
entity_types:
- enums
scopes:
access:
- public
- protected
- private
@@ -93,7 +93,7 @@ diagrams:
exclude:
namespaces:
- cppast::detail
scopes:
access:
- public
- protected
- private

View File

@@ -110,7 +110,7 @@ void generator::generate(
// Process methods
//
for (const auto &m : c.methods()) {
if (!m_model.should_include(m.scope()))
if (!m_model.should_include(m.access()))
continue;
if (m.is_pure_virtual())
@@ -121,7 +121,7 @@ void generator::generate(
std::string type{m.type()};
ostr << plantuml_common::to_plantuml(m.scope()) << m.name();
ostr << plantuml_common::to_plantuml(m.access()) << m.name();
ostr << "(";
if (m_config.generate_method_arguments() !=
@@ -195,7 +195,7 @@ void generator::generate(
<< m_model.to_alias(uns.relative(destination));
if (!r.label().empty()) {
relstr << " : " << plantuml_common::to_plantuml(r.scope())
relstr << " : " << plantuml_common::to_plantuml(r.access())
<< r.label();
rendered_relations.emplace(r.label());
}
@@ -222,7 +222,7 @@ void generator::generate(
// Process members
//
for (const auto &m : c.members()) {
if (!m_model.should_include(m.scope()))
if (!m_model.should_include(m.access()))
continue;
if (!m_config.include_relations_also_as_members() &&
@@ -232,7 +232,7 @@ void generator::generate(
if (m.is_static())
ostr << "{static} ";
ostr << plantuml_common::to_plantuml(m.scope()) << m.name() << " : "
ostr << plantuml_common::to_plantuml(m.access()) << m.name() << " : "
<< uns.relative(m.type());
if (m_config.generate_links) {

View File

@@ -49,9 +49,9 @@ using common_generator =
using clanguml::class_diagram::model::class_;
using clanguml::class_diagram::model::enum_;
using clanguml::common::model::access_t;
using clanguml::common::model::package;
using clanguml::common::model::relationship_t;
using clanguml::common::model::scope_t;
using namespace clanguml::util;

View File

@@ -20,15 +20,15 @@
namespace clanguml::class_diagram::model {
class_element::class_element(common::model::scope_t scope,
class_element::class_element(common::model::access_t access,
const std::string &name, const std::string &type)
: scope_{scope}
: access_{access}
, name_{name}
, type_{type}
{
}
common::model::scope_t class_element::scope() const { return scope_; }
common::model::access_t class_element::access() const { return access_; }
std::string class_element::name() const { return name_; }
@@ -39,7 +39,7 @@ inja::json class_element::context() const
inja::json ctx;
ctx["name"] = name();
ctx["type"] = type();
ctx["scope"] = to_string(scope());
ctx["access"] = to_string(access());
return ctx;
}
}

View File

@@ -29,17 +29,17 @@ namespace clanguml::class_diagram::model {
class class_element : public common::model::decorated_element,
public common::model::source_location {
public:
class_element(common::model::scope_t scope, const std::string &name,
class_element(common::model::access_t scope, const std::string &name,
const std::string &type);
common::model::scope_t scope() const;
common::model::access_t access() const;
std::string name() const;
std::string type() const;
virtual inja::json context() const;
private:
common::model::scope_t scope_;
common::model::access_t access_;
std::string name_;
std::string type_;
};

View File

@@ -20,9 +20,9 @@
namespace clanguml::class_diagram::model {
class_member::class_member(common::model::scope_t scope,
class_member::class_member(common::model::access_t access,
const std::string &name, const std::string &type)
: class_element{scope, name, type}
: class_element{access, name, type}
{
}

View File

@@ -25,7 +25,7 @@ namespace clanguml::class_diagram::model {
class class_member : public class_element {
public:
class_member(common::model::scope_t scope, const std::string &name,
class_member(common::model::access_t access, const std::string &name,
const std::string &type);
bool is_relationship() const;

View File

@@ -20,9 +20,9 @@
namespace clanguml::class_diagram::model {
class_method::class_method(common::model::scope_t scope,
class_method::class_method(common::model::access_t access,
const std::string &name, const std::string &type)
: class_element{scope, name, type}
: class_element{access, name, type}
{
}

View File

@@ -27,7 +27,7 @@ namespace clanguml::class_diagram::model {
class class_method : public class_element {
public:
class_method(common::model::scope_t scope, const std::string &name,
class_method(common::model::access_t access, const std::string &name,
const std::string &type);
bool is_pure_virtual() const;

View File

@@ -46,28 +46,27 @@ using clanguml::class_diagram::model::type_alias;
using clanguml::common::model::access_t;
using clanguml::common::model::relationship;
using clanguml::common::model::relationship_t;
using clanguml::common::model::scope_t;
namespace detail {
scope_t cpp_access_specifier_to_scope(
access_t cpp_access_specifier_to_access(
cppast::cpp_access_specifier_kind access_specifier)
{
scope_t scope = scope_t::kPublic;
auto access = access_t::kPublic;
switch (access_specifier) {
case cppast::cpp_access_specifier_kind::cpp_public:
scope = scope_t::kPublic;
access = access_t::kPublic;
break;
case cppast::cpp_access_specifier_kind::cpp_private:
scope = scope_t::kPrivate;
access = access_t::kPrivate;
break;
case cppast::cpp_access_specifier_kind::cpp_protected:
scope = scope_t::kProtected;
access = access_t::kProtected;
break;
default:
break;
}
return scope;
return access;
}
}
@@ -662,7 +661,7 @@ void translation_unit_visitor::process_class_children(
child.scope_name() ? child.scope_name().value().name()
: "<no-scope>");
process_friend(fr, c);
process_friend(fr, c, last_access_specifier);
}
else if (cppast::is_friended(child)) {
auto &fr =
@@ -670,7 +669,7 @@ void translation_unit_visitor::process_class_children(
LOG_DBG("Found friend template: {}", child.name());
process_friend(fr, c);
process_friend(fr, c, last_access_specifier);
}
else {
LOG_DBG("Found some other class child: {} ({})", child.name(),
@@ -717,7 +716,7 @@ bool translation_unit_visitor::process_field_with_template_instantiation(
relationship_type = relationship_t::kAggregation;
relationship rr{relationship_type, tinst.full_name(),
detail::cpp_access_specifier_to_scope(as), mv.name()};
detail::cpp_access_specifier_to_access(as), mv.name()};
rr.set_style(m.style_spec());
// Process field decorators
@@ -765,7 +764,7 @@ void translation_unit_visitor::process_field(
type_name = "<<anonymous>>";
class_member m{
detail::cpp_access_specifier_to_scope(as), mv.name(), type_name};
detail::cpp_access_specifier_to_access(as), mv.name(), type_name};
if (mv.location().has_value()) {
m.set_file(mv.location().value().file);
@@ -816,7 +815,7 @@ void translation_unit_visitor::process_field(
for (const auto &[type, relationship_type] : relationships) {
if (relationship_type != relationship_t::kNone) {
relationship r{relationship_type, type, m.scope(), m.name()};
relationship r{relationship_type, type, m.access(), m.name()};
r.set_style(m.style_spec());
auto [decorator_rtype, decorator_rmult] = m.get_relationship();
@@ -848,7 +847,7 @@ void translation_unit_visitor::process_anonymous_enum(
for (const auto &ev : en) {
if (ev.kind() == cppast::cpp_entity_kind::enum_value_t) {
class_member m{
detail::cpp_access_specifier_to_scope(as), ev.name(), "enum"};
detail::cpp_access_specifier_to_access(as), ev.name(), "enum"};
c.add_member(std::move(m));
}
}
@@ -858,7 +857,7 @@ void translation_unit_visitor::process_static_field(
const cppast::cpp_variable &mv, class_ &c,
cppast::cpp_access_specifier_kind as)
{
class_member m{detail::cpp_access_specifier_to_scope(as), mv.name(),
class_member m{detail::cpp_access_specifier_to_access(as), mv.name(),
cppast::to_string(mv.type())};
if (mv.location().has_value()) {
@@ -881,7 +880,7 @@ void translation_unit_visitor::process_method(
const cppast::cpp_member_function &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
class_method m{detail::cpp_access_specifier_to_scope(as),
class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), cppast::to_string(mf.return_type())};
m.is_pure_virtual(cppast::is_pure(mf.virtual_info()));
m.is_virtual(cppast::is_virtual(mf.virtual_info()));
@@ -923,8 +922,8 @@ void translation_unit_visitor::process_template_method(
static_cast<const cppast::cpp_member_function &>(mf.function())
.return_type());
class_method m{
detail::cpp_access_specifier_to_scope(as), util::trim(mf.name()), type};
class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), type};
m.is_pure_virtual(false);
m.is_virtual(false);
m.is_const(cppast::is_const(
@@ -964,7 +963,7 @@ void translation_unit_visitor::process_static_method(
const cppast::cpp_function &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
class_method m{detail::cpp_access_specifier_to_scope(as),
class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), cppast::to_string(mf.return_type())};
m.is_pure_virtual(false);
m.is_virtual(false);
@@ -998,7 +997,7 @@ void translation_unit_visitor::process_constructor(
const cppast::cpp_constructor &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
class_method m{detail::cpp_access_specifier_to_scope(as),
class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), "void"};
m.is_pure_virtual(false);
m.is_virtual(false);
@@ -1030,7 +1029,7 @@ void translation_unit_visitor::process_destructor(
const cppast::cpp_destructor &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
class_method m{detail::cpp_access_specifier_to_scope(as),
class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), "void"};
m.is_pure_virtual(false);
m.is_virtual(cppast::is_virtual(mf.virtual_info()));
@@ -1230,8 +1229,8 @@ void translation_unit_visitor::process_template_template_parameter(
parent.add_template({"", t.name() + "<>"});
}
void translation_unit_visitor::process_friend(
const cppast::cpp_friend &f, class_ &parent)
void translation_unit_visitor::process_friend(const cppast::cpp_friend &f,
class_ &parent, cppast::cpp_access_specifier_kind as)
{
// Only process friends to other classes or class templates
if (!f.entity() ||
@@ -1240,8 +1239,8 @@ void translation_unit_visitor::process_friend(
cppast::cpp_entity_kind::class_template_t))
return;
relationship r{
relationship_t::kFriendship, "", scope_t::kNone, "<<friend>>"};
relationship r{relationship_t::kFriendship, "",
detail::cpp_access_specifier_to_access(as), "<<friend>>"};
if (f.comment().has_value())
r.add_decorators(decorators::parse(f.comment().value()));

View File

@@ -124,7 +124,8 @@ public:
clanguml::class_diagram::model::class_ &parent);
void process_friend(const cppast::cpp_friend &t,
clanguml::class_diagram::model::class_ &parent);
clanguml::class_diagram::model::class_ &parent,
cppast::cpp_access_specifier_kind as);
void process_namespace(const cppast::cpp_entity &e,
const cppast::cpp_namespace &ns_declaration);

View File

@@ -42,14 +42,14 @@ std::string to_plantuml(relationship_t r, std::string style)
}
}
std::string to_plantuml(scope_t scope)
std::string to_plantuml(access_t scope)
{
switch (scope) {
case scope_t::kPublic:
case access_t::kPublic:
return "+";
case scope_t::kProtected:
case access_t::kProtected:
return "#";
case scope_t::kPrivate:
case access_t::kPrivate:
return "-";
default:
return "";

View File

@@ -30,13 +30,13 @@
namespace clanguml::common::generators::plantuml {
using clanguml::common::model::access_t;
using clanguml::common::model::element;
using clanguml::common::model::message_t;
using clanguml::common::model::relationship_t;
using clanguml::common::model::scope_t;
std::string to_plantuml(relationship_t r, std::string style);
std::string to_plantuml(scope_t scope);
std::string to_plantuml(access_t scope);
std::string to_plantuml(message_t r);
template <typename ConfigType, typename DiagramType> class generator {

View File

@@ -68,7 +68,7 @@ bool diagram::should_include(const relationship_t r) const
return filter_->should_include(r);
}
bool diagram::should_include(const scope_t s) const
bool diagram::should_include(const access_t s) const
{
if (filter_.get() == nullptr)
return true;

View File

@@ -52,7 +52,7 @@ public:
bool should_include(const std::string &e) const;
bool should_include(const relationship r) const;
bool should_include(const relationship_t r) const;
bool should_include(const scope_t s) const;
bool should_include(const access_t s) const;
bool should_include(const namespace_ &ns, const std::string &name) const;
private:

View File

@@ -20,6 +20,11 @@
namespace clanguml::common::model {
filter_visitor::filter_visitor(filter_t type)
: type_{type}
{
}
std::optional<bool> filter_visitor::match(
const diagram &d, const common::model::element &e) const
{
@@ -33,7 +38,7 @@ std::optional<bool> filter_visitor::match(
}
std::optional<bool> filter_visitor::match(
const diagram &d, const common::model::scope_t &r) const
const diagram &d, const common::model::access_t &a) const
{
return {};
}
@@ -172,20 +177,20 @@ std::optional<bool> relationship_filter::match(
[&r](const auto &rel) { return r == rel; });
}
scope_filter::scope_filter(filter_t type, std::vector<scope_t> scopes)
access_filter::access_filter(filter_t type, std::vector<access_t> access)
: filter_visitor{type}
, scopes_{scopes}
, access_{access}
{
}
std::optional<bool> scope_filter::match(
const diagram &d, const scope_t &s) const
std::optional<bool> access_filter::match(
const diagram &d, const access_t &a) const
{
if (scopes_.empty())
if (access_.empty())
return {};
return std::any_of(scopes_.begin(), scopes_.end(),
[&s](const auto &scope) { return s == scope; });
return std::any_of(access_.begin(), access_.end(),
[&a](const auto &access) { return a == access; });
}
context_filter::context_filter(filter_t type, std::vector<std::string> context)
@@ -246,8 +251,8 @@ void diagram_filter::init_filters(const config::diagram &c)
filter_t::kInclusive, c.include().namespaces));
inclusive_.emplace_back(std::make_unique<relationship_filter>(
filter_t::kInclusive, c.include().relationships));
inclusive_.emplace_back(std::make_unique<scope_filter>(
filter_t::kInclusive, c.include().scopes));
inclusive_.emplace_back(std::make_unique<access_filter>(
filter_t::kInclusive, c.include().access));
inclusive_.emplace_back(std::make_unique<element_filter>(
filter_t::kInclusive, c.include().elements));
inclusive_.emplace_back(std::make_unique<subclass_filter>(
@@ -264,8 +269,8 @@ void diagram_filter::init_filters(const config::diagram &c)
filter_t::kExclusive, c.exclude().elements));
exclusive_.emplace_back(std::make_unique<relationship_filter>(
filter_t::kExclusive, c.exclude().relationships));
exclusive_.emplace_back(std::make_unique<scope_filter>(
filter_t::kExclusive, c.exclude().scopes));
exclusive_.emplace_back(std::make_unique<access_filter>(
filter_t::kExclusive, c.exclude().access));
exclusive_.emplace_back(std::make_unique<subclass_filter>(
filter_t::kExclusive, c.exclude().subclasses));
exclusive_.emplace_back(std::make_unique<context_filter>(

View File

@@ -32,10 +32,7 @@ enum filter_t { kInclusive, kExclusive };
class filter_visitor {
public:
filter_visitor(filter_t type)
: type_{type}
{
}
filter_visitor(filter_t type);
virtual std::optional<bool> match(
const diagram &d, const common::model::element &e) const;
@@ -44,7 +41,7 @@ public:
const diagram &d, const common::model::relationship_t &r) const;
virtual std::optional<bool> match(
const diagram &d, const common::model::scope_t &r) const;
const diagram &d, const common::model::access_t &a) const;
virtual std::optional<bool> match(
const diagram &d, const common::model::namespace_ &ns) const;
@@ -102,14 +99,14 @@ private:
std::vector<relationship_t> relationships_;
};
struct scope_filter : public filter_visitor {
scope_filter(filter_t type, std::vector<scope_t> scopes);
struct access_filter : public filter_visitor {
access_filter(filter_t type, std::vector<access_t> access);
std::optional<bool> match(
const diagram &d, const scope_t &s) const override;
const diagram &d, const access_t &a) const override;
private:
std::vector<scope_t> scopes_;
std::vector<access_t> access_;
};
struct context_filter : public filter_visitor {

View File

@@ -49,22 +49,6 @@ std::string to_string(relationship_t r)
}
}
std::string to_string(scope_t s)
{
switch (s) {
case scope_t::kPublic:
return "public";
case scope_t::kProtected:
return "protected";
case scope_t::kPrivate:
return "private";
case scope_t::kNone:
return "none";
default:
assert(false);
}
}
std::string to_string(access_t a)
{
switch (a) {

View File

@@ -23,8 +23,6 @@ namespace clanguml::common::model {
enum class access_t { kPublic, kProtected, kPrivate };
enum class scope_t { kPublic, kProtected, kPrivate, kNone };
enum class relationship_t {
kNone,
kExtension,
@@ -42,8 +40,6 @@ enum class message_t { kCall, kReturn };
std::string to_string(relationship_t r);
std::string to_string(scope_t r);
std::string to_string(access_t r);
std::string to_string(message_t r);

View File

@@ -21,12 +21,12 @@
namespace clanguml::common::model {
relationship::relationship(relationship_t type, const std::string &destination,
scope_t scope, const std::string &label,
access_t access, const std::string &label,
const std::string &multiplicity_source,
const std::string &multiplicity_destination)
: type_{type}
, destination_{destination}
, scope_{scope}
, access_{access}
, label_{label}
, multiplicity_source_{multiplicity_source}
, multiplicity_destination_{multiplicity_destination}
@@ -70,9 +70,9 @@ void relationship::set_label(const std::string &label) { label_ = label; }
std::string relationship::label() const { return label_; }
void relationship::set_scope(scope_t scope) noexcept { scope_ = scope; }
void relationship::set_access(access_t access) noexcept { access_ = access; }
scope_t relationship::scope() const noexcept { return scope_; }
access_t relationship::access() const noexcept { return access_; }
bool operator==(const relationship &l, const relationship &r)
{

View File

@@ -28,7 +28,7 @@ class relationship : public common::model::decorated_element,
public common::model::stylable_element {
public:
relationship(relationship_t type, const std::string &destination,
scope_t scope = scope_t::kNone, const std::string &label = "",
access_t access = access_t::kPublic, const std::string &label = "",
const std::string &multiplicity_source = "",
const std::string &multiplicity_destination = "");
@@ -50,8 +50,8 @@ public:
void set_label(const std::string &label);
std::string label() const;
void set_scope(scope_t scope) noexcept;
scope_t scope() const noexcept;
void set_access(access_t scope) noexcept;
access_t access() const noexcept;
friend bool operator==(const relationship &l, const relationship &r);
@@ -61,6 +61,6 @@ private:
std::string multiplicity_source_;
std::string multiplicity_destination_;
std::string label_;
scope_t scope_{scope_t::kNone};
access_t access_{access_t::kPublic};
};
}

View File

@@ -151,8 +151,8 @@ template <> void append_value<plantuml>(plantuml &l, const plantuml &r)
}
namespace YAML {
using clanguml::common::model::access_t;
using clanguml::common::model::relationship_t;
using clanguml::common::model::scope_t;
using clanguml::config::class_diagram;
using clanguml::config::config;
using clanguml::config::filter;
@@ -234,15 +234,18 @@ std::shared_ptr<clanguml::config::diagram> parse_diagram_config(const Node &d)
return {};
}
template <> struct convert<scope_t> {
static bool decode(const Node &node, scope_t &rhs)
//
// config access_t decoder
//
template <> struct convert<access_t> {
static bool decode(const Node &node, access_t &rhs)
{
if (node.as<std::string>() == "public")
rhs = scope_t::kPublic;
rhs = access_t::kPublic;
else if (node.as<std::string>() == "protected")
rhs = scope_t::kProtected;
rhs = access_t::kProtected;
else if (node.as<std::string>() == "private")
rhs = scope_t::kPrivate;
rhs = access_t::kPrivate;
else
return false;
@@ -368,8 +371,8 @@ template <> struct convert<filter> {
if (node["elements"])
rhs.elements = node["elements"].as<decltype(rhs.elements)>();
if (node["scopes"])
rhs.scopes = node["scopes"].as<decltype(rhs.scopes)>();
if (node["access"])
rhs.access = node["access"].as<decltype(rhs.access)>();
if (node["subclasses"])
rhs.subclasses = node["subclasses"].as<decltype(rhs.subclasses)>();

View File

@@ -60,7 +60,7 @@ struct filter {
// - public
// - protected
// - private
std::vector<common::model::scope_t> scopes;
std::vector<common::model::access_t> access;
std::vector<std::string> subclasses;

View File

@@ -46,9 +46,9 @@ template <typename C, typename D>
using common_generator =
clanguml::common::generators::plantuml::generator<C, D>;
using clanguml::common::model::access_t;
using clanguml::common::model::package;
using clanguml::common::model::relationship_t;
using clanguml::common::model::scope_t;
using namespace clanguml::util;
class generator : public common_generator<diagram_config, diagram_model> {

View File

@@ -42,29 +42,28 @@ using clanguml::common::model::access_t;
using clanguml::common::model::package;
using clanguml::common::model::relationship;
using clanguml::common::model::relationship_t;
using clanguml::common::model::scope_t;
using clanguml::package_diagram::model::diagram;
namespace detail {
scope_t cpp_access_specifier_to_scope(
access_t cpp_access_specifier_to_access(
cppast::cpp_access_specifier_kind access_specifier)
{
scope_t scope = scope_t::kPublic;
access_t access = access_t::kPublic;
switch (access_specifier) {
case cppast::cpp_access_specifier_kind::cpp_public:
scope = scope_t::kPublic;
access = access_t::kPublic;
break;
case cppast::cpp_access_specifier_kind::cpp_private:
scope = scope_t::kPrivate;
access = access_t::kPrivate;
break;
case cppast::cpp_access_specifier_kind::cpp_protected:
scope = scope_t::kProtected;
access = access_t::kProtected;
break;
default:
break;
}
return scope;
return access;
}
}

View File

@@ -37,7 +37,7 @@ TEST_CASE("t00011", "[test-case][class]")
REQUIRE_THAT(puml, IsClass(_A("B")));
REQUIRE_THAT(puml, IsClass(_A("D<T>")));
REQUIRE_THAT(puml, IsFriend(_A("A"), _A("B")));
REQUIRE_THAT(puml, IsFriend<Private>(_A("A"), _A("B")));
// REQUIRE_THAT(puml, IsFriend(_A("A"), _A("D<T>")));
save_puml(

View File

@@ -11,7 +11,7 @@ diagrams:
include:
namespaces:
- clanguml::t00040
scopes:
access:
- public
- protected
exclude:

View File

@@ -264,13 +264,6 @@ ContainsMatcher IsAssociation(std::string const &from, std::string const &to,
fmt::format(format_string, from, to, label), caseSensitivity));
}
ContainsMatcher IsFriend(std::string const &from, std::string const &to,
CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
{
return ContainsMatcher(CasedString(
fmt::format("{} <.. {} : <<friend>>", from, to), caseSensitivity));
}
ContainsMatcher IsComposition(std::string const &from, std::string const &to,
std::string const &label, std::string multiplicity_source = "",
std::string multiplicity_dest = "",
@@ -424,6 +417,24 @@ ContainsMatcher IsField(std::string const &name,
CasedString(pattern + " : " + type, caseSensitivity));
}
template <typename... Ts>
ContainsMatcher IsFriend(std::string const &from, std::string const &to,
CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
{
std::string pattern;
if constexpr (has_type<Public, Ts...>())
pattern = "+";
else if constexpr (has_type<Protected, Ts...>())
pattern = "#";
else
pattern = "-";
return ContainsMatcher(
CasedString(fmt::format("{} <.. {} : {}<<friend>>", from, to, pattern),
caseSensitivity));
}
ContainsMatcher IsPackage(std::string const &str,
CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
{

View File

@@ -115,7 +115,7 @@ test_cases:
title: Subclass class diagram filter test
description:
- name: t00040
title: Relationship and scope filter test
title: Relationship and access filter test
description:
Sequence diagrams:
- name: t20001