Added initial abstract class rendering

This commit is contained in:
Bartek Kryza
2021-02-23 22:20:00 +01:00
parent 919ba40434
commit a3459035d7
6 changed files with 82 additions and 5 deletions

View File

@@ -132,6 +132,23 @@ public:
bool is_preprocessing() const { return clang_isPreprocessing(kind()); }
bool is_method_virtual() const
{
return clang_CXXMethod_isVirtual(m_cursor);
}
bool is_method_const() const { return clang_CXXMethod_isConst(m_cursor); }
bool is_method_pure_virtual() const
{
return clang_CXXMethod_isPureVirtual(m_cursor);
}
bool is_method_defaulted() const
{
return clang_CXXMethod_isDefaulted(m_cursor);
}
CXVisibilityKind visibitity() const
{
return clang_getCursorVisibility(m_cursor);

View File

@@ -94,11 +94,23 @@ public:
void generate(const class_ &c, std::ostream &ostr) const
{
ostr << "Class " << c.name << " {" << std::endl;
if (c.is_abstract())
ostr << "abstract ";
else
ostr << "class ";
ostr << c.name << " {" << std::endl;
for (const auto &m : c.methods) {
ostr << to_string(m.scope) << m.type << " " << m.name + "()"
<< std::endl;
if (m.is_pure_virtual)
ostr << "{abstract} ";
ostr << to_string(m.scope) << m.type << " " << m.name + "()";
if (m.is_pure_virtual)
ostr << " = 0";
ostr << std::endl;
}
for (const auto &m : c.members) {

View File

@@ -63,6 +63,10 @@ struct method_argument {
struct class_method : public class_element {
std::vector<method_argument> arguments;
bool is_pure_virtual{false};
bool is_virtual{false};
bool is_const{false};
bool is_defaulted{false};
};
struct class_parent {
@@ -89,6 +93,14 @@ struct class_ : public element {
std::vector<std::string> inner_classes;
std::vector<class_relationship> relationships;
bool is_abstract() const
{
// TODO check if all base abstract methods are overriden
// with non-abstract methods
return std::any_of(methods.begin(), methods.end(),
[](const auto &method) { return method.is_pure_virtual; });
}
};
struct enum_ : public element {

View File

@@ -84,6 +84,15 @@ enum CXChildVisitResult visit_if_cursor_valid(
ret = CXChildVisit_Recurse;
}
}
else if (cursor.is_declaration()) {
if (cursor.is_method_pure_virtual()) {
f(cursor);
ret = CXChildVisit_Continue;
}
else {
ret = CXChildVisit_Recurse;
}
}
else {
ret = CXChildVisit_Continue;
}
@@ -143,7 +152,11 @@ static enum CXChildVisitResult class_visitor(
visit_if_cursor_valid(cursor, [c](cx::cursor cursor) {
class_method m;
m.name = cursor.spelling();
m.type = cursor.type().spelling();
m.type = cursor.type().result_type().spelling();
m.is_pure_virtual = cursor.is_method_pure_virtual();
m.is_virtual = cursor.is_method_virtual();
m.is_const = cursor.is_method_const();
m.is_defaulted = cursor.is_method_defaulted();
spdlog::info("Adding method {} {}::{}()", m.type, c->name,
cursor.spelling());

View File

@@ -5,16 +5,35 @@ namespace t00002 {
class A {
public:
virtual void foo() {}
virtual void foo_a() = 0;
virtual void foo_c() = 0;
};
class B : public A {
public:
virtual void foo_a() override {}
};
class C : public A {
public:
virtual void foo_c() override {}
};
class D : public B, public C {
public:
void foo_a() override
{
for (auto a : as)
a->foo_a();
}
void foo_c() override
{
for (auto a : as)
a->foo_c();
}
private:
std::vector<A *> as;
};
}

View File

@@ -152,6 +152,10 @@ TEST_CASE("Test t00002", "[unit-test]")
REQUIRE_THAT(puml, StartsWith("@startuml"));
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
REQUIRE_THAT(puml, Contains("abstract A"));
REQUIRE_THAT(puml, Contains("class B"));
REQUIRE_THAT(puml, Contains("class C"));
REQUIRE_THAT(puml, Contains("class D"));
save_puml(
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);