Fixed up to t00011
This commit is contained in:
@@ -85,6 +85,18 @@ std::optional<std::reference_wrapper<const class_>> diagram::get_class(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const class_>> diagram::get_class(
|
||||||
|
clanguml::common::model::diagram_element::id_t id) const
|
||||||
|
{
|
||||||
|
for (const auto &c : classes_) {
|
||||||
|
if (c.get().id() == id) {
|
||||||
|
return {c};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::reference_wrapper<const enum_>> diagram::get_enum(
|
std::optional<std::reference_wrapper<const enum_>> diagram::get_enum(
|
||||||
const std::string &name) const
|
const std::string &name) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ public:
|
|||||||
std::optional<std::reference_wrapper<const class_>> get_class(
|
std::optional<std::reference_wrapper<const class_>> get_class(
|
||||||
const std::string &name) const;
|
const std::string &name) const;
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const class_>> get_class(
|
||||||
|
clanguml::common::model::diagram_element::id_t id) const;
|
||||||
|
|
||||||
std::optional<std::reference_wrapper<const enum_>> get_enum(
|
std::optional<std::reference_wrapper<const enum_>> get_enum(
|
||||||
const std::string &name) const;
|
const std::string &name) const;
|
||||||
|
|
||||||
|
|||||||
@@ -87,11 +87,20 @@ std::string to_string(const clang::QualType &type, const clang::ASTContext &ctx)
|
|||||||
auto canonical_type_name =
|
auto canonical_type_name =
|
||||||
type.getCanonicalType().getAsString(print_policy);
|
type.getCanonicalType().getAsString(print_policy);
|
||||||
|
|
||||||
auto canonical_qualified_name =
|
auto result_qualified_template_name =
|
||||||
canonical_type_name.substr(0, canonical_type_name.find('<'));
|
result.substr(0, result.find('<'));
|
||||||
auto result_template_arguments = result.substr(result.find('<'));
|
auto result_template_arguments = result.substr(result.find('<'));
|
||||||
|
|
||||||
result = canonical_qualified_name + result_template_arguments;
|
auto canonical_qualified_template_name =
|
||||||
|
canonical_type_name.substr(0, canonical_type_name.find('<'));
|
||||||
|
|
||||||
|
// Choose the longer name (why do I have to do this?)
|
||||||
|
if (result_qualified_template_name.size() <
|
||||||
|
canonical_qualified_template_name.size()) {
|
||||||
|
|
||||||
|
result =
|
||||||
|
canonical_qualified_template_name + result_template_arguments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -153,11 +162,6 @@ bool translation_unit_visitor::VisitClassTemplateDecl(
|
|||||||
|
|
||||||
auto c_ptr = process_class_declaration(cls->getTemplatedDecl());
|
auto c_ptr = process_class_declaration(cls->getTemplatedDecl());
|
||||||
|
|
||||||
c_ptr->set_id(cls->getID());
|
|
||||||
|
|
||||||
if (!c_ptr)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
process_template_parameters(*cls, *c_ptr);
|
process_template_parameters(*cls, *c_ptr);
|
||||||
|
|
||||||
if (diagram_.should_include(*c_ptr)) {
|
if (diagram_.should_include(*c_ptr)) {
|
||||||
@@ -169,9 +173,14 @@ bool translation_unit_visitor::VisitClassTemplateDecl(
|
|||||||
|
|
||||||
bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
|
bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
|
||||||
{
|
{
|
||||||
|
// Skip system headers
|
||||||
if (source_manager_.isInSystemHeader(cls->getSourceRange().getBegin()))
|
if (source_manager_.isInSystemHeader(cls->getSourceRange().getBegin()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Skip forward declarations
|
||||||
|
if (!cls->isCompleteDefinition())
|
||||||
|
return true;
|
||||||
|
|
||||||
// Check if the class was already processed within VisitClassTemplateDecl()
|
// Check if the class was already processed within VisitClassTemplateDecl()
|
||||||
if (diagram_.has_element(cls->getID()))
|
if (diagram_.has_element(cls->getID()))
|
||||||
return true;
|
return true;
|
||||||
@@ -195,17 +204,17 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
|
|||||||
std::unique_ptr<class_> translation_unit_visitor::process_class_declaration(
|
std::unique_ptr<class_> translation_unit_visitor::process_class_declaration(
|
||||||
clang::CXXRecordDecl *cls)
|
clang::CXXRecordDecl *cls)
|
||||||
{
|
{
|
||||||
auto c_ptr = std::make_unique<class_>(config_.using_namespace());
|
auto c_ptr{std::make_unique<class_>(config_.using_namespace())};
|
||||||
auto &c = *c_ptr;
|
auto &c = *c_ptr;
|
||||||
|
|
||||||
c.is_struct(cls->isStruct());
|
|
||||||
|
|
||||||
namespace_ ns{cls->getQualifiedNameAsString()};
|
namespace_ ns{cls->getQualifiedNameAsString()};
|
||||||
ns.pop_back();
|
ns.pop_back();
|
||||||
c.set_name(cls->getNameAsString());
|
c.set_name(cls->getNameAsString());
|
||||||
c.set_namespace(ns);
|
c.set_namespace(ns);
|
||||||
c.set_id(cls->getID());
|
c.set_id(cls->getID());
|
||||||
|
|
||||||
|
c.is_struct(cls->isStruct());
|
||||||
|
|
||||||
process_comment(*cls, c);
|
process_comment(*cls, c);
|
||||||
set_source_location(*cls, c);
|
set_source_location(*cls, c);
|
||||||
|
|
||||||
@@ -256,14 +265,32 @@ bool translation_unit_visitor::process_template_parameters(
|
|||||||
clang::dyn_cast_or_null<clang::NonTypeTemplateParmDecl>(
|
clang::dyn_cast_or_null<clang::NonTypeTemplateParmDecl>(
|
||||||
parameter);
|
parameter);
|
||||||
template_parameter ct;
|
template_parameter ct;
|
||||||
ct.set_type("");
|
ct.set_type(template_nontype_parameter->getType().getAsString());
|
||||||
ct.is_template_parameter(false);
|
|
||||||
ct.set_name(template_nontype_parameter->getNameAsString());
|
ct.set_name(template_nontype_parameter->getNameAsString());
|
||||||
|
ct.is_template_parameter(false);
|
||||||
ct.set_default_value("");
|
ct.set_default_value("");
|
||||||
ct.is_variadic(template_nontype_parameter->isParameterPack());
|
ct.is_variadic(template_nontype_parameter->isParameterPack());
|
||||||
|
|
||||||
c.add_template(std::move(ct));
|
c.add_template(std::move(ct));
|
||||||
}
|
}
|
||||||
|
else if (clang::dyn_cast_or_null<clang::TemplateTemplateParmDecl>(
|
||||||
|
parameter)) {
|
||||||
|
const auto *template_template_parameter =
|
||||||
|
clang::dyn_cast_or_null<clang::TemplateTemplateParmDecl>(
|
||||||
|
parameter);
|
||||||
|
template_parameter ct;
|
||||||
|
ct.set_type("");
|
||||||
|
ct.set_name(template_template_parameter->getNameAsString() + "<>");
|
||||||
|
ct.is_template_parameter(true);
|
||||||
|
ct.set_default_value("");
|
||||||
|
ct.is_variadic(template_template_parameter->isParameterPack());
|
||||||
|
|
||||||
|
c.add_template(std::move(ct));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_DBG("============= UNKNOWN TEMPLATE PARAMETER TYPE:");
|
||||||
|
parameter->dump();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -371,6 +398,34 @@ void translation_unit_visitor::process_class_children(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto *friend_declaration : cls->friends()) {
|
||||||
|
process_friend(*friend_declaration, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void translation_unit_visitor::process_friend(
|
||||||
|
const clang::FriendDecl &f, class_ &c)
|
||||||
|
{
|
||||||
|
if (const auto *friend_type_info = f.getFriendType()) {
|
||||||
|
const auto friend_type = friend_type_info->getType();
|
||||||
|
if (friend_type->getAs<clang::TemplateSpecializationType>() !=
|
||||||
|
nullptr) {
|
||||||
|
// TODO: handle template friend
|
||||||
|
}
|
||||||
|
else if (friend_type->getAs<clang::RecordType>()) {
|
||||||
|
const auto friend_type_name =
|
||||||
|
friend_type->getAsRecordDecl()->getQualifiedNameAsString();
|
||||||
|
if (diagram().should_include(friend_type_name)) {
|
||||||
|
relationship r{relationship_t::kFriendship,
|
||||||
|
friend_type->getAsRecordDecl()->getID(),
|
||||||
|
detail::access_specifier_to_access_t(f.getAccess()),
|
||||||
|
"<<friend>>"};
|
||||||
|
|
||||||
|
c.add_relationship(std::move(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void translation_unit_visitor::process_method(
|
void translation_unit_visitor::process_method(
|
||||||
@@ -433,9 +488,9 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
|
|||||||
relationships, relationship_t::kAggregation);
|
relationships, relationship_t::kAggregation);
|
||||||
}
|
}
|
||||||
else if (type->isRecordType()) {
|
else if (type->isRecordType()) {
|
||||||
if(type_name.find("std::shared_ptr") == 0)
|
if (type_name.find("std::shared_ptr") == 0)
|
||||||
relationship_hint = relationship_t::kAssociation;
|
relationship_hint = relationship_t::kAssociation;
|
||||||
if(type_name.find("std::weak_ptr") == 0)
|
if (type_name.find("std::weak_ptr") == 0)
|
||||||
relationship_hint = relationship_t::kAssociation;
|
relationship_hint = relationship_t::kAssociation;
|
||||||
|
|
||||||
const auto *type_instantiation_decl =
|
const auto *type_instantiation_decl =
|
||||||
@@ -485,10 +540,11 @@ void translation_unit_visitor::process_function_parameter(
|
|||||||
/*
|
/*
|
||||||
if (!parameter.skip_relationship()) {
|
if (!parameter.skip_relationship()) {
|
||||||
// find relationship for the type
|
// find relationship for the type
|
||||||
std::vector<std::pair<std::string, relationship_t>> relationships;
|
std::vector<std::pair<std::string, relationship_t>>
|
||||||
|
relationships;
|
||||||
|
|
||||||
find_relationships(cppast::remove_cv(param.type()), relationships,
|
find_relationships(cppast::remove_cv(param.type()),
|
||||||
relationship_t::kDependency);
|
relationships, relationship_t::kDependency);
|
||||||
|
|
||||||
for (const auto &[type, relationship_type] : relationships) {
|
for (const auto &[type, relationship_type] : relationships) {
|
||||||
if (type.empty())
|
if (type.empty())
|
||||||
@@ -513,8 +569,8 @@ void translation_unit_visitor::process_function_parameter(
|
|||||||
instantiation
|
instantiation
|
||||||
// it's arguments could count as reference to relevant types
|
// it's arguments could count as reference to relevant types
|
||||||
const auto &t =
|
const auto &t =
|
||||||
cppast::remove_cv(cx::util::unreferenced(param.type())); if (t.kind() ==
|
cppast::remove_cv(cx::util::unreferenced(param.type())); if (t.kind()
|
||||||
cppast::cpp_type_kind::template_instantiation_t) {
|
== cppast::cpp_type_kind::template_instantiation_t) {
|
||||||
process_function_parameter_find_relationships_in_template(
|
process_function_parameter_find_relationships_in_template(
|
||||||
c, template_parameter_names, t);
|
c, template_parameter_names, t);
|
||||||
}
|
}
|
||||||
@@ -589,34 +645,34 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
|||||||
auto template_instantiation_ptr =
|
auto template_instantiation_ptr =
|
||||||
std::make_unique<class_>(config_.using_namespace());
|
std::make_unique<class_>(config_.using_namespace());
|
||||||
auto &template_instantiation = *template_instantiation_ptr;
|
auto &template_instantiation = *template_instantiation_ptr;
|
||||||
std::string full_template_specialization_name =
|
std::string full_template_specialization_name = to_string(
|
||||||
to_string(template_type.desugar(),
|
template_type.desugar(),
|
||||||
template_type.getAsCXXRecordDecl()->getASTContext());
|
template_type.getTemplateName().getAsTemplateDecl()->getASTContext());
|
||||||
|
|
||||||
const auto *template_record{
|
const auto *template_decl{
|
||||||
template_type.getTemplateName().getAsTemplateDecl()};
|
template_type.getTemplateName().getAsTemplateDecl()};
|
||||||
std::string qualified_name = template_record->getQualifiedNameAsString();
|
auto qualified_name = template_decl->getQualifiedNameAsString();
|
||||||
namespace_ ns{qualified_name};
|
namespace_ ns{qualified_name};
|
||||||
ns.pop_back();
|
ns.pop_back();
|
||||||
template_instantiation.set_name(template_record->getNameAsString());
|
template_instantiation.set_name(template_decl->getNameAsString());
|
||||||
template_instantiation.set_namespace(ns);
|
template_instantiation.set_namespace(ns);
|
||||||
template_instantiation.set_id(template_record->getID() +
|
template_instantiation.set_id(template_decl->getID() +
|
||||||
std::hash<std::string>{}(full_template_specialization_name));
|
(std::hash<std::string>{}(full_template_specialization_name) >> 4));
|
||||||
|
|
||||||
for (const auto &arg : template_type) {
|
for (const auto &arg : template_type) {
|
||||||
auto argument_kind = arg.getKind();
|
auto argument_kind = arg.getKind();
|
||||||
if (argument_kind == clang::TemplateArgument::ArgKind::Type) {
|
if (argument_kind == clang::TemplateArgument::ArgKind::Type) {
|
||||||
// const auto *argument_record_decl =
|
// const auto *argument_record_decl =
|
||||||
// arg.getAsType()->getAsRecordDecl();
|
// arg.getAsType()->getAsRecordDecl();
|
||||||
template_parameter argument;
|
template_parameter argument;
|
||||||
argument.is_template_parameter(false);
|
argument.is_template_parameter(false);
|
||||||
argument.set_name(to_string(
|
argument.set_name(
|
||||||
arg.getAsType(), template_record->getASTContext()));
|
to_string(arg.getAsType(), template_decl->getASTContext()));
|
||||||
|
|
||||||
template_instantiation.add_template(std::move(argument));
|
template_instantiation.add_template(std::move(argument));
|
||||||
|
|
||||||
template_instantiation.add_relationship(
|
template_instantiation.add_relationship(
|
||||||
{relationship_t::kInstantiation, template_record->getID()});
|
{relationship_t::kInstantiation, template_decl->getID()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,15 +682,17 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
|||||||
void translation_unit_visitor::process_field(
|
void translation_unit_visitor::process_field(
|
||||||
const clang::FieldDecl &field_declaration, class_ &c)
|
const clang::FieldDecl &field_declaration, class_ &c)
|
||||||
{
|
{
|
||||||
|
auto relationship_hint = relationship_t::kAggregation;
|
||||||
// bool template_instantiation_added_as_aggregation{false};
|
// bool template_instantiation_added_as_aggregation{false};
|
||||||
const auto field_type = field_declaration.getType();
|
auto field_type = field_declaration.getType();
|
||||||
|
const auto field_name = field_declaration.getNameAsString();
|
||||||
auto type_name = to_string(field_type, field_declaration.getASTContext());
|
auto type_name = to_string(field_type, field_declaration.getASTContext());
|
||||||
if (type_name.empty())
|
if (type_name.empty())
|
||||||
type_name = "<<anonymous>>";
|
type_name = "<<anonymous>>";
|
||||||
|
|
||||||
class_member field{
|
class_member field{
|
||||||
detail::access_specifier_to_access_t(field_declaration.getAccess()),
|
detail::access_specifier_to_access_t(field_declaration.getAccess()),
|
||||||
field_declaration.getNameAsString(), type_name};
|
field_name, type_name};
|
||||||
|
|
||||||
process_comment(field_declaration, field);
|
process_comment(field_declaration, field);
|
||||||
set_source_location(field_declaration, field);
|
set_source_location(field_declaration, field);
|
||||||
@@ -642,13 +700,32 @@ void translation_unit_visitor::process_field(
|
|||||||
if (field.skip())
|
if (field.skip())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (field_type->getAs<clang::TemplateSpecializationType>()) {
|
if (field_type->isPointerType()) {
|
||||||
if (diagram().should_include(type_name)) {
|
relationship_hint = relationship_t::kAssociation;
|
||||||
|
field_type = field_type->getPointeeType();
|
||||||
|
}
|
||||||
|
else if (field_type->isLValueReferenceType()) {
|
||||||
|
relationship_hint = relationship_t::kAssociation;
|
||||||
|
field_type = field_type.getNonReferenceType();
|
||||||
|
}
|
||||||
|
else if (field_type->isRValueReferenceType()) {
|
||||||
|
field_type = field_type.getNonReferenceType();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto *template_field_type =
|
||||||
|
field_type->getAs<clang::TemplateSpecializationType>();
|
||||||
|
|
||||||
|
if (template_field_type != nullptr) {
|
||||||
|
const auto template_field_decl_name =
|
||||||
|
template_field_type->getTemplateName()
|
||||||
|
.getAsTemplateDecl()
|
||||||
|
->getQualifiedNameAsString();
|
||||||
|
if (diagram().should_include(template_field_decl_name)) {
|
||||||
auto template_specialization_ptr = build_template_instantiation(
|
auto template_specialization_ptr = build_template_instantiation(
|
||||||
*field_type->getAs<clang::TemplateSpecializationType>());
|
*field_type->getAs<clang::TemplateSpecializationType>());
|
||||||
|
|
||||||
relationship r{relationship_t::kAggregation,
|
relationship r{
|
||||||
template_specialization_ptr->id()};
|
relationship_hint, template_specialization_ptr->id()};
|
||||||
r.set_label(field_declaration.getNameAsString());
|
r.set_label(field_declaration.getNameAsString());
|
||||||
r.set_access(detail::access_specifier_to_access_t(
|
r.set_access(detail::access_specifier_to_access_t(
|
||||||
field_declaration.getAccess()));
|
field_declaration.getAccess()));
|
||||||
@@ -663,8 +740,8 @@ void translation_unit_visitor::process_field(
|
|||||||
if (!field.skip_relationship()) {
|
if (!field.skip_relationship()) {
|
||||||
found_relationships_t relationships;
|
found_relationships_t relationships;
|
||||||
// find relationship for the type
|
// find relationship for the type
|
||||||
find_relationships(field_declaration.getType(), relationships,
|
find_relationships(
|
||||||
relationship_t::kAggregation);
|
field_type, relationships, relationship_hint);
|
||||||
|
|
||||||
add_relationships(c, relationships,
|
add_relationships(c, relationships,
|
||||||
detail::access_specifier_to_access_t(
|
detail::access_specifier_to_access_t(
|
||||||
@@ -677,8 +754,7 @@ void translation_unit_visitor::process_field(
|
|||||||
if (!field.skip_relationship()) {
|
if (!field.skip_relationship()) {
|
||||||
found_relationships_t relationships;
|
found_relationships_t relationships;
|
||||||
// find relationship for the type
|
// find relationship for the type
|
||||||
find_relationships(field_declaration.getType(), relationships,
|
find_relationships(field_type, relationships, relationship_hint);
|
||||||
relationship_t::kAggregation);
|
|
||||||
|
|
||||||
add_relationships(c, relationships,
|
add_relationships(c, relationships,
|
||||||
detail::access_specifier_to_access_t(
|
detail::access_specifier_to_access_t(
|
||||||
@@ -694,9 +770,9 @@ void translation_unit_visitor::process_field(
|
|||||||
`-TemplateSpecializationType 0x5555587d0810 'vector<class
|
`-TemplateSpecializationType 0x5555587d0810 'vector<class
|
||||||
clanguml::t00002::A *>' sugar vector
|
clanguml::t00002::A *>' sugar vector
|
||||||
|-TemplateArgument type 'class clanguml::t00002::A *'
|
|-TemplateArgument type 'class clanguml::t00002::A *'
|
||||||
| `-PointerType 0x5555587ce870 'class clanguml::t00002::A *'
|
| `-PointerType 0x5555587ce870 'class clanguml::t00002::A
|
||||||
| `-RecordType 0x5555587ce700 'class clanguml::t00002::A'
|
*' | `-RecordType 0x5555587ce700 'class clanguml::t00002::A' |
|
||||||
| `-CXXRecord 0x5555587ce668 'A'
|
`-CXXRecord 0x5555587ce668 'A'
|
||||||
`-RecordType 0x5555587d07f0 'class std::vector<class
|
`-RecordType 0x5555587d07f0 'class std::vector<class
|
||||||
clanguml::t00002::A *>'
|
clanguml::t00002::A *>'
|
||||||
`-ClassTemplateSpecialization 0x5555587d06f0 'vector'
|
`-ClassTemplateSpecialization 0x5555587d06f0 'vector'
|
||||||
@@ -749,7 +825,8 @@ void translation_unit_visitor::process_field(
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
/*
|
/*
|
||||||
const auto &tr = cx::util::unreferenced(cppast::remove_cv(mv.type()));
|
const auto &tr =
|
||||||
|
cx::util::unreferenced(cppast::remove_cv(mv.type()));
|
||||||
|
|
||||||
auto tr_declaration = cppast::to_string(tr);
|
auto tr_declaration = cppast::to_string(tr);
|
||||||
|
|
||||||
@@ -765,10 +842,13 @@ void translation_unit_visitor::process_field(
|
|||||||
if (resolve_alias(tr).kind() ==
|
if (resolve_alias(tr).kind() ==
|
||||||
cppast::cpp_type_kind::template_instantiation_t)
|
cppast::cpp_type_kind::template_instantiation_t)
|
||||||
template_instantiation_added_as_aggregation =
|
template_instantiation_added_as_aggregation =
|
||||||
process_field_with_template_instantiation(mv, tr, c, m, as);
|
process_field_with_template_instantiation(mv, tr, c, m,
|
||||||
|
as);
|
||||||
}
|
}
|
||||||
else if (tr.kind() == cppast::cpp_type_kind::template_instantiation_t) {
|
else if (tr.kind() ==
|
||||||
// This can be either template instantiation or an alias template
|
cppast::cpp_type_kind::template_instantiation_t) {
|
||||||
|
// This can be either template instantiation or an alias
|
||||||
|
template
|
||||||
// instantiation
|
// instantiation
|
||||||
template_instantiation_added_as_aggregation =
|
template_instantiation_added_as_aggregation =
|
||||||
process_field_with_template_instantiation(mv, tr, c, m, as);
|
process_field_with_template_instantiation(mv, tr, c, m, as);
|
||||||
@@ -781,7 +861,8 @@ void translation_unit_visitor::process_field(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try to find relationships in the type of the member, unless it has
|
// Try to find relationships in the type of the member, unless it
|
||||||
|
has
|
||||||
// been already added as part of template processing or it is marked
|
// been already added as part of template processing or it is marked
|
||||||
// to be skipped in the comment
|
// to be skipped in the comment
|
||||||
//
|
//
|
||||||
@@ -802,9 +883,8 @@ void translation_unit_visitor::process_field(
|
|||||||
auto [decorator_rtype, decorator_rmult] =
|
auto [decorator_rtype, decorator_rmult] =
|
||||||
m.get_relationship(); if (decorator_rtype != relationship_t::kNone) {
|
m.get_relationship(); if (decorator_rtype != relationship_t::kNone) {
|
||||||
r.set_type(decorator_rtype);
|
r.set_type(decorator_rtype);
|
||||||
auto mult = util::split(decorator_rmult, ":", false);
|
auto mult = util::split(decorator_rmult, ":",
|
||||||
if (mult.size() == 2) {
|
false); if (mult.size() == 2) { r.set_multiplicity_source(mult[0]);
|
||||||
r.set_multiplicity_source(mult[0]);
|
|
||||||
r.set_multiplicity_destination(mult[1]);
|
r.set_multiplicity_destination(mult[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -831,5 +911,4 @@ void translation_unit_visitor::set_source_location(
|
|||||||
source_manager_.getSpellingLineNumber(decl.getLocation()));
|
source_manager_.getSpellingLineNumber(decl.getLocation()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ private:
|
|||||||
clanguml::class_diagram::model::class_ &c,
|
clanguml::class_diagram::model::class_ &c,
|
||||||
const std::set<std::string> &template_parameter_names = {});
|
const std::set<std::string> &template_parameter_names = {});
|
||||||
|
|
||||||
|
void process_friend(
|
||||||
|
const clang::FriendDecl &f, clanguml::class_diagram::model::class_ &c);
|
||||||
|
|
||||||
bool find_relationships(const clang::QualType &type,
|
bool find_relationships(const clang::QualType &type,
|
||||||
found_relationships_t &,
|
found_relationships_t &,
|
||||||
clanguml::common::model::relationship_t relationship_hint);
|
clanguml::common::model::relationship_t relationship_hint);
|
||||||
@@ -99,7 +102,8 @@ private:
|
|||||||
clanguml::common::model::source_location &element);
|
clanguml::common::model::source_location &element);
|
||||||
|
|
||||||
std::unique_ptr<clanguml::class_diagram::model::class_>
|
std::unique_ptr<clanguml::class_diagram::model::class_>
|
||||||
build_template_instantiation(const clang::TemplateSpecializationType& template_type,
|
build_template_instantiation(
|
||||||
|
const clang::TemplateSpecializationType &template_type,
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> parent = {});
|
std::optional<clanguml::class_diagram::model::class_ *> parent = {});
|
||||||
|
|
||||||
template <typename ClangDecl>
|
template <typename ClangDecl>
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ TEST_CASE("t00008", "[test-case][class]")
|
|||||||
REQUIRE_THAT(puml, IsClassTemplate("B", "T,C<>"));
|
REQUIRE_THAT(puml, IsClassTemplate("B", "T,C<>"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("value", "T")));
|
REQUIRE_THAT(puml, (IsField<Public>("value", "T")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("pointer", "T*")));
|
REQUIRE_THAT(puml, (IsField<Public>("pointer", "T *")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("reference", "T&")));
|
REQUIRE_THAT(puml, (IsField<Public>("reference", "T &")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("values", "std::vector<P>")));
|
REQUIRE_THAT(puml, (IsField<Public>("values", "std::vector<P>")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("ints", "std::array<int,N>")));
|
REQUIRE_THAT(puml, (IsField<Public>("ints", "std::array<int, N>")));
|
||||||
// TODO: add option to resolve using declared types
|
// TODO: add option to resolve using declared types
|
||||||
// REQUIRE_THAT(puml, IsField(Public("bool (*)(int, int) comparator")));
|
// REQUIRE_THAT(puml, IsField(Public("bool (*)(int, int) comparator")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("comparator", "CMP")));
|
REQUIRE_THAT(puml, (IsField<Public>("comparator", "CMP")));
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ TEST_CASE("t00009", "[test-case][class]")
|
|||||||
|
|
||||||
REQUIRE(diagram->name == "t00009_class");
|
REQUIRE(diagram->name == "t00009_class");
|
||||||
|
|
||||||
auto model = generate_class_diagram(db, diagram);
|
auto model = generate_class_diagram(*db, diagram);
|
||||||
|
|
||||||
REQUIRE(model->name() == "t00009_class");
|
REQUIRE(model->name() == "t00009_class");
|
||||||
|
|
||||||
@@ -38,9 +38,9 @@ TEST_CASE("t00009", "[test-case][class]")
|
|||||||
|
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("value", "T")));
|
REQUIRE_THAT(puml, (IsField<Public>("value", "T")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("aint", "A<int>")));
|
REQUIRE_THAT(puml, (IsField<Public>("aint", "A<int>")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("astring", "A<std::string>*")));
|
REQUIRE_THAT(puml, (IsField<Public>("astring", "A<std::string> *")));
|
||||||
REQUIRE_THAT(
|
REQUIRE_THAT(
|
||||||
puml, (IsField<Public>("avector", "A<std::vector<std::string>>&")));
|
puml, (IsField<Public>("avector", "A<std::vector<std::string>> &")));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<int>")));
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<int>")));
|
||||||
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<std::string>")));
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<std::string>")));
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ TEST_CASE("t00010", "[test-case][class]")
|
|||||||
|
|
||||||
REQUIRE(diagram->name == "t00010_class");
|
REQUIRE(diagram->name == "t00010_class");
|
||||||
|
|
||||||
auto model = generate_class_diagram(db, diagram);
|
auto model = generate_class_diagram(*db, diagram);
|
||||||
|
|
||||||
REQUIRE(model->name() == "t00010_class");
|
REQUIRE(model->name() == "t00010_class");
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ TEST_CASE("t00010", "[test-case][class]")
|
|||||||
REQUIRE_THAT(puml, IsClassTemplate("A", "T,P"));
|
REQUIRE_THAT(puml, IsClassTemplate("A", "T,P"));
|
||||||
REQUIRE_THAT(puml, IsClassTemplate("B", "T"));
|
REQUIRE_THAT(puml, IsClassTemplate("B", "T"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("astring", "A<T,std::string>")));
|
REQUIRE_THAT(puml, (IsField<Public>("astring", "A<T, std::string>")));
|
||||||
REQUIRE_THAT(puml, (IsField<Public>("aintstring", "B<int>")));
|
REQUIRE_THAT(puml, (IsField<Public>("aintstring", "B<int>")));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, IsInstantiation(_A("A<T,P>"), _A("A<T,std::string>")));
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T,P>"), _A("A<T,std::string>")));
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ template <typename T> class D {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
private:
|
public:
|
||||||
void foo() { }
|
void foo() { }
|
||||||
friend class B;
|
friend class B;
|
||||||
friend class external::C;
|
friend class external::C;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ TEST_CASE("t00011", "[test-case][class]")
|
|||||||
|
|
||||||
REQUIRE(diagram->name == "t00011_class");
|
REQUIRE(diagram->name == "t00011_class");
|
||||||
|
|
||||||
auto model = generate_class_diagram(db, diagram);
|
auto model = generate_class_diagram(*db, diagram);
|
||||||
|
|
||||||
REQUIRE(model->name() == "t00011_class");
|
REQUIRE(model->name() == "t00011_class");
|
||||||
|
|
||||||
@@ -35,9 +35,11 @@ TEST_CASE("t00011", "[test-case][class]")
|
|||||||
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
||||||
REQUIRE_THAT(puml, IsClass(_A("A")));
|
REQUIRE_THAT(puml, IsClass(_A("A")));
|
||||||
REQUIRE_THAT(puml, IsClass(_A("B")));
|
REQUIRE_THAT(puml, IsClass(_A("B")));
|
||||||
|
REQUIRE_THAT(puml, !IsClass(_A("external::C")));
|
||||||
REQUIRE_THAT(puml, IsClass(_A("D<T>")));
|
REQUIRE_THAT(puml, IsClass(_A("D<T>")));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, IsFriend<Private>(_A("A"), _A("B")));
|
REQUIRE_THAT(puml, IsAssociation(_A("B"), _A("A")));
|
||||||
|
REQUIRE_THAT(puml, IsFriend<Public>(_A("A"), _A("B")));
|
||||||
// REQUIRE_THAT(puml, IsFriend(_A("A"), _A("D<T>")));
|
// REQUIRE_THAT(puml, IsFriend(_A("A"), _A("D<T>")));
|
||||||
|
|
||||||
save_puml(
|
save_puml(
|
||||||
|
|||||||
@@ -197,9 +197,9 @@ using namespace clanguml::test::matchers;
|
|||||||
#include "t00006/test_case.h"
|
#include "t00006/test_case.h"
|
||||||
#include "t00007/test_case.h"
|
#include "t00007/test_case.h"
|
||||||
#include "t00008/test_case.h"
|
#include "t00008/test_case.h"
|
||||||
//#include "t00009/test_case.h"
|
#include "t00009/test_case.h"
|
||||||
//#include "t00010/test_case.h"
|
#include "t00010/test_case.h"
|
||||||
//#include "t00011/test_case.h"
|
#include "t00011/test_case.h"
|
||||||
//#include "t00012/test_case.h"
|
//#include "t00012/test_case.h"
|
||||||
//#include "t00013/test_case.h"
|
//#include "t00013/test_case.h"
|
||||||
//#include "t00014/test_case.h"
|
//#include "t00014/test_case.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user