Fixed class template handling
This commit is contained in:
@@ -87,7 +87,8 @@ std::string class_::base_template() const { return base_template_full_name_; }
|
||||
|
||||
bool operator==(const class_ &l, const class_ &r)
|
||||
{
|
||||
return l.full_name() == r.full_name();
|
||||
return (l.name_and_ns() == r.name_and_ns()) &&
|
||||
(l.templates_ == r.templates_);
|
||||
}
|
||||
|
||||
void class_::add_type_alias(type_alias &&ta)
|
||||
@@ -148,6 +149,7 @@ std::ostringstream &class_::render_template_params(
|
||||
|
||||
ostr << fmt::format("<{}>", fmt::join(tnames, ","));
|
||||
}
|
||||
|
||||
return ostr;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,27 +24,33 @@ namespace clanguml::class_diagram::model {
|
||||
|
||||
class_template::class_template(const std::string &type, const std::string &name,
|
||||
const std::string &default_value, bool is_variadic)
|
||||
: name_{name}
|
||||
, default_value_{default_value}
|
||||
: default_value_{default_value}
|
||||
, is_variadic_{is_variadic}
|
||||
{
|
||||
set_name(name);
|
||||
set_type(type);
|
||||
if (is_variadic)
|
||||
name_ = name_ + "...";
|
||||
}
|
||||
|
||||
void class_template::set_type(const std::string &type) {
|
||||
type_ = type;
|
||||
// TODO: Add a configurable mapping for simplifying non-interesting
|
||||
// std templates
|
||||
util::replace_all(type_, "std::basic_string<char>", "std::string");
|
||||
}
|
||||
void class_template::set_type(const std::string &type) { type_ = type; }
|
||||
|
||||
std::string class_template::type() const { return type_; }
|
||||
|
||||
void class_template::set_name(const std::string &name) { name_ = name; }
|
||||
void class_template::set_name(const std::string &name)
|
||||
{
|
||||
name_ = name;
|
||||
// TODO: Add a configurable mapping for simplifying non-interesting
|
||||
// std templates
|
||||
util::replace_all(name_, "std::basic_string<char>", "std::string");
|
||||
util::replace_all(name_, "std::basic_string<wchar_t>", "std::wstring");
|
||||
}
|
||||
|
||||
std::string class_template::name() const { return name_; }
|
||||
std::string class_template::name() const
|
||||
{
|
||||
if (is_variadic_)
|
||||
return name_ + "...";
|
||||
|
||||
return name_;
|
||||
}
|
||||
|
||||
void class_template::set_default_value(const std::string &value)
|
||||
{
|
||||
@@ -60,9 +66,33 @@ void class_template::is_variadic(bool is_variadic) noexcept
|
||||
|
||||
bool class_template::is_variadic() const noexcept { return is_variadic_; }
|
||||
|
||||
bool class_template::is_specialization_of(const class_template &ct) const
|
||||
{
|
||||
if ((ct.is_template_parameter() || ct.is_template_template_parameter()) &&
|
||||
!is_template_parameter())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const class_template &l, const class_template &r)
|
||||
{
|
||||
return (l.name() == r.name()) && (l.type() == r.type());
|
||||
bool res{false};
|
||||
|
||||
if (l.is_template_parameter() != r.is_template_parameter())
|
||||
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 class_template &l, const class_template &r)
|
||||
|
||||
@@ -41,11 +41,11 @@ public:
|
||||
void is_variadic(bool is_variadic) noexcept;
|
||||
bool is_variadic() const noexcept;
|
||||
|
||||
bool is_specialization_of(const class_template &ct) const;
|
||||
|
||||
friend bool operator==(const class_template &l, const class_template &r);
|
||||
friend bool operator!=(const class_template &l, const class_template &r);
|
||||
|
||||
std::vector<class_template> template_params_;
|
||||
|
||||
bool is_template_parameter() const { return is_template_parameter_; }
|
||||
|
||||
void is_template_parameter(bool is_template_parameter)
|
||||
@@ -53,14 +53,41 @@ public:
|
||||
is_template_parameter_ = is_template_parameter;
|
||||
}
|
||||
|
||||
bool is_template_template_parameter() const
|
||||
{
|
||||
return is_template_template_parameter_;
|
||||
}
|
||||
|
||||
void is_template_template_parameter(bool is_template_template_parameter)
|
||||
{
|
||||
is_template_template_parameter_ = is_template_template_parameter;
|
||||
}
|
||||
|
||||
std::string to_string(
|
||||
const clanguml::common::model::namespace_ &using_namespace) const;
|
||||
|
||||
std::vector<class_template> template_params_;
|
||||
|
||||
private:
|
||||
/// Represents the type of non-type template parameters
|
||||
/// e.g. 'int'
|
||||
std::string type_;
|
||||
|
||||
/// The name of the parameter (e.g. 'T' or 'N')
|
||||
std::string name_;
|
||||
|
||||
/// Default value of the template parameter
|
||||
std::string default_value_;
|
||||
|
||||
/// Whether the template parameter is a regular template parameter
|
||||
/// When false, it is a non-type template parameter
|
||||
bool is_template_parameter_{false};
|
||||
|
||||
/// Whether the template parameter is a template template parameter
|
||||
/// Can only be true when is_template_parameter_ is true
|
||||
bool is_template_template_parameter_{false};
|
||||
|
||||
/// Whether the template parameter is variadic
|
||||
bool is_variadic_{false};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ diagram::get(const std::string &full_name) const
|
||||
bool diagram::has_class(const class_ &c) const
|
||||
{
|
||||
return std::any_of(classes_.cbegin(), classes_.cend(),
|
||||
[&c](const auto &cc) { return cc.get().full_name() == c.full_name(); });
|
||||
[&c](const auto &cc) { return cc.get() == c; });
|
||||
}
|
||||
|
||||
bool diagram::has_enum(const enum_ &e) const
|
||||
@@ -109,30 +109,37 @@ void diagram::add_package(std::unique_ptr<common::model::package> &&p)
|
||||
|
||||
void diagram::add_class(std::unique_ptr<class_> &&c)
|
||||
{
|
||||
const auto base_name = c->name();
|
||||
const auto full_name = c->full_name(false);
|
||||
|
||||
LOG_DBG("Adding class: {}::{}, {}", c->get_namespace().to_string(),
|
||||
c->name(), c->full_name());
|
||||
base_name, full_name);
|
||||
|
||||
if (util::contains(c->name(), "::"))
|
||||
throw std::runtime_error("Name cannot contain namespace: " + c->name());
|
||||
if (util::contains(base_name, "::"))
|
||||
throw std::runtime_error("Name cannot contain namespace: " + base_name);
|
||||
|
||||
if (util::contains(c->name(), "<"))
|
||||
throw std::runtime_error("Name cannot contain <: " + c->name());
|
||||
if (util::contains(base_name, "<"))
|
||||
throw std::runtime_error("Name cannot contain <: " + base_name);
|
||||
|
||||
if (util::contains(c->name(), "*"))
|
||||
throw std::runtime_error("Name cannot contain *: " + c->name());
|
||||
if (util::contains(base_name, "*"))
|
||||
throw std::runtime_error("Name cannot contain *: " + base_name);
|
||||
|
||||
const auto ns = c->get_relative_namespace();
|
||||
auto name = base_name;
|
||||
auto name_with_ns = c->name_and_ns();
|
||||
auto name_and_ns = ns | name;
|
||||
|
||||
if (!has_class(*c)) {
|
||||
classes_.emplace_back(*c);
|
||||
auto ns = c->get_relative_namespace();
|
||||
auto name = c->name();
|
||||
classes_.push_back(type_safe::ref(*c));
|
||||
|
||||
add_element(ns, std::move(c));
|
||||
ns |= name;
|
||||
const auto ccc = get_element<class_>(ns);
|
||||
assert(ccc.value().name() == name);
|
||||
|
||||
const auto &el = get_element<class_>(name_and_ns).value();
|
||||
assert(el.name() == name);
|
||||
assert(el.get_relative_namespace() == ns);
|
||||
}
|
||||
else
|
||||
LOG_DBG(
|
||||
"Class {} ({}) already in the model", c->name(), c->full_name());
|
||||
LOG_DBG("Class {} ({}) already in the model", base_name, full_name);
|
||||
}
|
||||
|
||||
void diagram::add_enum(std::unique_ptr<enum_> &&e)
|
||||
|
||||
Reference in New Issue
Block a user