Fixed handling of array template specialization types

This commit is contained in:
Bartek Kryza
2023-05-02 16:10:14 +02:00
parent 640c5263ce
commit f01ddc63f2
8 changed files with 207 additions and 52 deletions

View File

@@ -17,6 +17,10 @@ template <typename U> struct A<std::map<std::string, U> &> {
template <>
struct A<std::map<std::string, std::map<std::string, std::string>> &> { };
template <typename U> struct A<U **> {
U **u;
};
template <typename U> struct A<U **const *> {
U ***u;
};
@@ -75,6 +79,13 @@ template <int N> struct A<char[N]> {
template <> struct A<char[1000]> {
std::vector<char> n;
};
template <int K, int L, int M> struct A<char[K][L][M]> { char klm[K][L][M]; };
template <typename U> struct A<U(...)> {
bool u;
};
//
// template <typename T> struct eval;
//

View File

@@ -51,36 +51,22 @@ TEST_CASE("t00062", "[test-case][class]")
REQUIRE_THAT(puml, IsClassTemplate("A", "char[N]"));
REQUIRE_THAT(puml, IsClassTemplate("A", "char[1000]"));
// Check if class templates exist
// REQUIRE_THAT(puml, IsClassTemplate("A", "T,P,CMP,int N"));
REQUIRE_THAT(puml, IsClassTemplate("A", "U(...)"));
// Check concepts
// REQUIRE_THAT(puml, IsConcept(_A("AConcept<T>")));
// REQUIRE_THAT(puml,
// IsConceptRequirement(
// _A("AConcept<T,P>"), "sizeof (T) > sizeof (P)"));
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<U &>")));
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<U &&>")));
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<M C::*>")));
REQUIRE_THAT(puml, IsInstantiation(_A("A<U &&>"), _A("A<M C::* &&>")));
// Check if all enums exist
// REQUIRE_THAT(puml, IsEnum(_A("Lights")));
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<M (C::*)(Arg)>")));
REQUIRE_THAT(puml,
IsInstantiation(_A("A<M (C::*)(Arg)>"), _A("A<int (C::*)(bool)>")));
// Check if all inner classes exist
// REQUIRE_THAT(puml, IsInnerClass(_A("A"), _A("AA")));
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<char[N]>")));
REQUIRE_THAT(
puml, IsInstantiation(_A("A<char[N]>"), _A("A<char[1000]>")));
// Check if all inheritance relationships exist
// REQUIRE_THAT(puml, IsBaseClass(_A("Base"), _A("Child")));
// Check if all methods exist
// REQUIRE_THAT(puml, (IsMethod<Public, Const>("foo")));
// Check if all fields exist
// REQUIRE_THAT(puml, (IsField<Private>("private_member", "int")));
// Check if all relationships exist
// REQUIRE_THAT(puml, IsAssociation(_A("D"), _A("A"), "-as"));
// REQUIRE_THAT(puml, IsDependency(_A("R"), _A("B")));
// REQUIRE_THAT(puml, IsAggregation(_A("R"), _A("D"), "-ag"));
// REQUIRE_THAT(puml, IsComposition(_A("R"), _A("D"), "-ac"));
// REQUIRE_THAT(puml, IsInstantiation(_A("ABCD::F<T>"), _A("F<int>")));
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<U(...)>")));
save_puml(
config.output_directory() + "/" + diagram->name + ".puml", puml);

View File

@@ -236,6 +236,8 @@ struct AliasMatcher {
util::replace_all(name, ")", "\\)");
util::replace_all(name, " ", "\\s");
util::replace_all(name, "*", "\\*");
util::replace_all(name, "[", "\\[");
util::replace_all(name, "]", "\\]");
patterns.push_back(
std::regex{"class\\s\"" + name + "\"\\sas\\s" + alias_regex});

View File

@@ -318,4 +318,92 @@ TEST_CASE(
CHECK(tp2.calculate_specialization_match(tp1));
}
{
using clanguml::common::model::context;
using clanguml::common::model::rpqualifier;
auto tp1 = template_parameter::make_template_type({});
tp1.is_data_pointer(true);
tp1.add_template_param(template_parameter::make_template_type("T"));
tp1.add_template_param(template_parameter::make_template_type("C"));
CHECK(tp1.is_specialization());
auto tp2 = template_parameter::make_template_type({});
tp2.is_data_pointer(true);
tp2.add_template_param(template_parameter::make_argument("T"));
tp2.add_template_param(template_parameter::make_template_type("C"));
tp2.push_context(context{.pr = rpqualifier::kRValueReference});
CHECK(tp2.is_specialization());
CHECK(tp2.calculate_specialization_match(tp1) == 0);
CHECK(tp1.calculate_specialization_match(tp2) == 0);
}
{
using clanguml::common::model::context;
using clanguml::common::model::rpqualifier;
auto tp1 = template_parameter::make_template_type("T");
tp1.push_context(context{.pr = rpqualifier::kRValueReference});
CHECK(tp1.is_specialization());
auto tp2 = template_parameter::make_template_type({});
tp2.is_data_pointer(true);
tp2.add_template_param(template_parameter::make_template_type("T"));
tp2.add_template_param(template_parameter::make_template_type("C"));
tp2.push_context(context{.pr = rpqualifier::kRValueReference});
CHECK(tp2.is_specialization());
CHECK(tp2.calculate_specialization_match(tp1) > 1);
CHECK(tp1.calculate_specialization_match(tp2) == 0);
}
{
using clanguml::common::model::context;
using clanguml::common::model::rpqualifier;
auto tp1 = template_parameter::make_template_type({});
tp1.is_array(true);
tp1.add_template_param(template_parameter::make_template_type("int"));
tp1.add_template_param(template_parameter::make_template_type("N"));
CHECK(tp1.to_string({}, false) == "int[N]");
CHECK(tp1.is_specialization());
auto tp2 = template_parameter::make_argument({});
tp2.is_array(true);
tp2.add_template_param(template_parameter::make_argument("int"));
tp2.add_template_param(template_parameter::make_argument("1000"));
CHECK(tp2.to_string({}, false) == "int[1000]");
CHECK(tp2.is_specialization());
CHECK(tp2.calculate_specialization_match(tp1) > 1);
CHECK(tp1.calculate_specialization_match(tp2) == 0);
}
{
using clanguml::common::model::context;
using clanguml::common::model::rpqualifier;
auto tp1 = template_parameter::make_template_type("T");
tp1.push_context(context{.pr = rpqualifier::kLValueReference});
CHECK(tp1.is_specialization());
CHECK(tp1.to_string({}, false) == "T &");
auto tp2 = template_parameter::make_template_type({});
tp2.is_array(true);
tp2.add_template_param(template_parameter::make_template_type("int"));
tp2.add_template_param(template_parameter::make_template_type("N"));
CHECK(tp2.is_specialization());
CHECK(tp2.to_string({}, false) == "int[N]");
CHECK(tp2.calculate_specialization_match(tp1) == 0);
CHECK(tp1.calculate_specialization_match(tp2) == 0);
}
}