cppast/test/cpp_class.cpp
2022-04-17 19:14:08 +02:00

309 lines
9 KiB
C++

// Copyright (C) 2017-2022 Jonathan Müller and cppast contributors
// SPDX-License-Identifier: MIT
#include <cppast/cpp_class.hpp>
#include "test_parser.hpp"
using namespace cppast;
TEST_CASE("cpp_class")
{
auto code = R"(
// forward declarations
/// struct a;
struct a;
/// class b;
class b;
/// struct unresolved;
struct unresolved;
// basic
/// struct a{
/// };
struct a {};
/// class b final{
/// };
class b final {};
/// union c{
/// };
union c {};
// members
/// struct d{
/// enum m1{
/// };
///
/// enum m2{
/// };
///
/// private:
/// enum m3{
/// };
///
/// protected:
/// enum m4{
/// };
/// };
struct d
{
enum m1 {};
public:
enum m2 {};
private:
private:
enum m3 {};
protected:
enum m4 {};
};
// bases
/// class e
/// :a,d{
/// };
class e
: a, private d {};
namespace ns
{
/// struct base;
struct base;
}
/// struct ns::base{
/// };
struct ns::base {};
/// struct f
/// :ns::base,virtual protected e{
/// };
struct f
: public ns::base, virtual protected e
{};
/// struct f2
/// :ns::base,virtual protected e{
/// };
struct f2
: public ns::base, protected virtual e
{};
using namespace ns;
/// struct g
/// :base{
/// };
struct g
: base {};
)";
cpp_entity_index idx;
auto file = parse(idx, "cpp_class.cpp", code);
auto count = test_visit<cpp_class>(*file, [&](const cpp_class& c) {
if (c.name() == "a" || c.name() == "base")
{
REQUIRE(c.class_kind() == cpp_class_kind::struct_t);
REQUIRE(!c.is_final());
REQUIRE(c.bases().begin() == c.bases().end());
REQUIRE(c.begin() == c.end());
auto definition = get_definition(idx, c);
REQUIRE(definition);
REQUIRE(definition.value().name() == c.name());
}
else if (c.name() == "b")
{
REQUIRE(c.class_kind() == cpp_class_kind::class_t);
REQUIRE(c.bases().begin() == c.bases().end());
REQUIRE(c.begin() == c.end());
if (c.is_definition())
REQUIRE(c.is_final());
else
REQUIRE(c.is_declaration());
auto definition = get_definition(idx, c);
REQUIRE(definition);
REQUIRE(definition.value().name() == "b");
}
else if (c.name() == "unresolved")
{
REQUIRE(c.is_declaration());
REQUIRE(!c.is_definition());
REQUIRE(c.class_kind() == cpp_class_kind::struct_t);
REQUIRE(!c.is_final());
REQUIRE(c.bases().begin() == c.bases().end());
REQUIRE(c.begin() == c.end());
auto definition = get_definition(idx, c);
REQUIRE(!definition);
}
else if (c.name() == "c")
{
REQUIRE(c.is_definition());
REQUIRE(!c.is_declaration());
REQUIRE(c.class_kind() == cpp_class_kind::union_t);
REQUIRE(!c.is_final());
REQUIRE(c.bases().begin() == c.bases().end());
REQUIRE(c.begin() == c.end());
}
else if (c.name() == "d")
{
REQUIRE(c.is_definition());
REQUIRE(!c.is_declaration());
REQUIRE(c.class_kind() == cpp_class_kind::struct_t);
REQUIRE(!c.is_final());
REQUIRE(c.bases().begin() == c.bases().end());
auto no_children = 0u;
for (auto& child : c)
{
switch (no_children++)
{
case 0:
REQUIRE(child.name() == "m1");
break;
case 1:
REQUIRE(child.name() == "public");
REQUIRE(child.kind() == cpp_entity_kind::access_specifier_t);
REQUIRE(static_cast<const cpp_access_specifier&>(child).access_specifier()
== cpp_public);
break;
case 2:
REQUIRE(child.name() == "m2");
break;
case 3:
REQUIRE(child.name() == "private");
REQUIRE(child.kind() == cpp_entity_kind::access_specifier_t);
REQUIRE(static_cast<const cpp_access_specifier&>(child).access_specifier()
== cpp_private);
break;
case 4:
REQUIRE(child.name() == "private");
REQUIRE(child.kind() == cpp_entity_kind::access_specifier_t);
REQUIRE(static_cast<const cpp_access_specifier&>(child).access_specifier()
== cpp_private);
break;
case 5:
REQUIRE(child.name() == "m3");
break;
case 6:
REQUIRE(child.name() == "protected");
REQUIRE(child.kind() == cpp_entity_kind::access_specifier_t);
REQUIRE(static_cast<const cpp_access_specifier&>(child).access_specifier()
== cpp_protected);
break;
case 7:
REQUIRE(child.name() == "m4");
break;
default:
REQUIRE(false);
break;
}
}
REQUIRE(no_children == 8u);
}
else if (c.name() == "e")
{
REQUIRE(c.is_definition());
REQUIRE(!c.is_declaration());
REQUIRE(c.class_kind() == cpp_class_kind::class_t);
REQUIRE(!c.is_final());
REQUIRE(c.begin() == c.end());
auto no_bases = 0u;
for (auto& base : c.bases())
{
++no_bases;
if (base.name() == "a")
{
REQUIRE(base.access_specifier() == cpp_private);
REQUIRE(!base.is_virtual());
REQUIRE(equal_types(idx, base.type(),
*cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "a"))));
}
else if (base.name() == "d")
{
REQUIRE(base.access_specifier() == cpp_private);
REQUIRE(!base.is_virtual());
REQUIRE(equal_types(idx, base.type(),
*cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "d"))));
}
else
REQUIRE(false);
}
REQUIRE(no_bases == 2u);
}
else if (c.name() == "f" || c.name() == "f2")
{
REQUIRE(c.is_definition());
REQUIRE(!c.is_declaration());
REQUIRE(c.class_kind() == cpp_class_kind::struct_t);
REQUIRE(!c.is_final());
REQUIRE(c.begin() == c.end());
auto no_bases = 0u;
for (auto& base : c.bases())
{
++no_bases;
if (base.name() == "ns::base")
{
REQUIRE(base.access_specifier() == cpp_public);
REQUIRE(!base.is_virtual());
REQUIRE(equal_types(idx, base.type(),
*cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "ns::base"))));
}
else if (base.name() == "e")
{
REQUIRE(base.access_specifier() == cpp_protected);
REQUIRE(base.is_virtual());
REQUIRE(equal_types(idx, base.type(),
*cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "e"))));
}
else
REQUIRE(false);
}
REQUIRE(no_bases == 2u);
}
else if (c.name() == "g")
{
REQUIRE(c.is_definition());
REQUIRE(!c.is_declaration());
REQUIRE(c.class_kind() == cpp_class_kind::struct_t);
REQUIRE(!c.is_final());
REQUIRE(c.begin() == c.end());
auto no_bases = 0u;
for (auto& base : c.bases())
{
++no_bases;
if (base.name() == "base")
{
REQUIRE(base.access_specifier() == cpp_public);
REQUIRE(!base.is_virtual());
REQUIRE(equal_types(idx, base.type(),
*cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "ns::base"))));
}
else
REQUIRE(false);
}
REQUIRE(no_bases == 1u);
}
else
REQUIRE(false);
});
REQUIRE(count == 13u);
}