This commit is contained in:
Bartek Kryza
2022-08-12 00:57:12 +02:00
parent e4289c4cab
commit 0cd6a9d36e
4 changed files with 145 additions and 65 deletions

View File

@@ -169,6 +169,7 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
p->set_name(name); p->set_name(name);
p->set_namespace(package_parent); p->set_namespace(package_parent);
p->set_id(common::to_id(*ns)); p->set_id(common::to_id(*ns));
set_ast_local_id(ns->getID(), p->id());
if (diagram().should_include(*p) && !diagram().get(p->id())) { if (diagram().should_include(*p) && !diagram().get(p->id())) {
process_comment(*ns, *p); process_comment(*ns, *p);
@@ -212,7 +213,8 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
ns.pop_back(); ns.pop_back();
e.set_name(enm->getNameAsString()); e.set_name(enm->getNameAsString());
e.set_namespace(ns); e.set_namespace(ns);
e.set_id(enm->getID()); e.set_id(common::to_id(*enm));
set_ast_local_id(enm->getID(), e.id());
process_comment(*enm, e); process_comment(*enm, e);
set_source_location(*enm, e); set_source_location(*enm, e);
@@ -257,11 +259,11 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
// definition (see t00036) // definition (see t00036)
return true; return true;
} }
else // else
// Check if the class was already processed within // // Check if the class was already processed within
// VisitClassTemplateDecl() // // VisitClassTemplateDecl()
if (diagram_.has_element(cls->getID())) // if (diagram_.has_element(cls->getID()))
return true; // return true;
// TODO: Add support for classes defined in function/method bodies // TODO: Add support for classes defined in function/method bodies
if (cls->isLocalClass()) if (cls->isLocalClass())
@@ -279,8 +281,11 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl(
// Process template specialization bases // Process template specialization bases
process_class_bases(cls, template_specialization); process_class_bases(cls, template_specialization);
template_specialization.add_relationship({relationship_t::kInstantiation, if (get_ast_local_id(cls->getSpecializedTemplate()->getID()).has_value())
cls->getSpecializedTemplate()->getID()}); template_specialization.add_relationship(
{relationship_t::kInstantiation,
get_ast_local_id(cls->getSpecializedTemplate()->getID())
.value()});
if (diagram_.should_include(template_specialization)) { if (diagram_.should_include(template_specialization)) {
LOG_DBG("Adding class template specialization {} with id {}", LOG_DBG("Adding class template specialization {} with id {}",
@@ -345,12 +350,17 @@ bool translation_unit_visitor::VisitClassTemplateDecl(
// Override the id with the template id, for now we don't care about the // Override the id with the template id, for now we don't care about the
// underlying templated class id // underlying templated class id
c_ptr->set_id(cls->getID());
auto id = c_ptr->id();
process_template_parameters(*cls, *c_ptr); process_template_parameters(*cls, *c_ptr);
const auto cls_full_name = c_ptr->full_name(false);
const auto id = common::to_id(cls_full_name);
c_ptr->set_id(id);
set_ast_local_id(cls->getID(), id);
if (!cls->getTemplatedDecl()->isCompleteDefinition()) { if (!cls->getTemplatedDecl()->isCompleteDefinition()) {
forward_declarations_.emplace(id, std::move(c_ptr)); forward_declarations_.emplace(id, std::move(c_ptr));
return true; return true;
@@ -361,8 +371,7 @@ bool translation_unit_visitor::VisitClassTemplateDecl(
} }
if (diagram_.should_include(*c_ptr)) { if (diagram_.should_include(*c_ptr)) {
LOG_DBG("Adding class template {} with id {}", c_ptr->full_name(), LOG_DBG("Adding class template {} with id {}", c_ptr->full_name(), id);
c_ptr->id());
diagram_.add_class(std::move(c_ptr)); diagram_.add_class(std::move(c_ptr));
} }
@@ -384,19 +393,25 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
// if (!cls->isCompleteDefinition()) // if (!cls->isCompleteDefinition())
// return true; // return true;
if (cls->getQualifiedNameAsString() == "cppast::cpp_function_parameter" && const auto cls_id = common::to_id(*cls);
cls->getLocation().printToString(source_manager_) ==
"/home/bartek/devel/clang-uml-showcases/cppast/src/../include/" set_ast_local_id(cls->getID(), cls_id);
"cppast/cpp_function.hpp:16:7") {
LOG_DBG("##############################################################" // if (cls->getQualifiedNameAsString() ==
"##########################"); // "cppast::cpp_function_parameter" &&
for (const auto &c : diagram().classes()) { // cls->getLocation().printToString(source_manager_) ==
LOG_DBG(" >> {} [{}]", c.get().full_name(false), c.get().id()); // "/home/bartek/devel/clang-uml-showcases/cppast/src/../include/"
} // "cppast/cpp_function.hpp:16:7") {
const auto &ccc = diagram().get_class(cls->getID()); // LOG_DBG("##############################################################"
if (ccc.has_value()) // "##########################");
LOG_DBG("---------- {}", ccc.get()->full_name(false)); // for (const auto &c : diagram().classes()) {
} // LOG_DBG(" >> {} [{}]", c.get().full_name(false),
// c.get().id());
// }
// const auto &ccc = diagram().get_class(cls_id);
// if (ccc.has_value())
// LOG_DBG("---------- {}", ccc.get()->full_name(false));
// }
// Templated records are handled by VisitClassTemplateDecl() // Templated records are handled by VisitClassTemplateDecl()
if (cls->isTemplated() || cls->isTemplateDecl() || if (cls->isTemplated() || cls->isTemplateDecl() ||
@@ -418,8 +433,8 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
if (!c_ptr) if (!c_ptr)
return true; return true;
auto &class_model = diagram().get_class(cls->getID()).has_value() auto &class_model = diagram().get_class(cls_id).has_value()
? *diagram().get_class(cls->getID()).get() ? *diagram().get_class(cls_id).get()
: *c_ptr; : *c_ptr;
if (cls->isCompleteDefinition()) if (cls->isCompleteDefinition())
@@ -589,8 +604,8 @@ void translation_unit_visitor::process_class_bases(
cp.set_name(name_and_ns.to_string()); cp.set_name(name_and_ns.to_string());
if (base.getType()->getAs<clang::RecordType>() != nullptr) if (base.getType()->getAs<clang::RecordType>() != nullptr)
cp.set_id( cp.set_id(common::to_id(
base.getType()->getAs<clang::RecordType>()->getDecl()->getID()); *base.getType()->getAs<clang::RecordType>()->getDecl()));
else if (base.getType()->getAs<clang::TemplateSpecializationType>() != else if (base.getType()->getAs<clang::TemplateSpecializationType>() !=
nullptr) { nullptr) {
cp.set_id(common::to_id( cp.set_id(common::to_id(
@@ -752,7 +767,7 @@ void translation_unit_visitor::process_friend(
friend_type->getAsRecordDecl()->getQualifiedNameAsString(); friend_type->getAsRecordDecl()->getQualifiedNameAsString();
if (diagram().should_include(friend_type_name)) { if (diagram().should_include(friend_type_name)) {
relationship r{relationship_t::kFriendship, relationship r{relationship_t::kFriendship,
friend_type->getAsRecordDecl()->getID(), common::to_id(*friend_type->getAsRecordDecl()),
detail::access_specifier_to_access_t(f.getAccess()), detail::access_specifier_to_access_t(f.getAccess()),
"<<friend>>"}; "<<friend>>"};
@@ -855,7 +870,7 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
} }
else if (type->isEnumeralType()) { else if (type->isEnumeralType()) {
relationships.emplace_back( relationships.emplace_back(
type->getAs<clang::EnumType>()->getDecl()->getID(), common::to_id(*type->getAs<clang::EnumType>()->getDecl()),
relationship_hint); relationship_hint);
} }
else if (type->isRecordType()) { else if (type->isRecordType()) {
@@ -914,7 +929,7 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
} }
} }
else { else {
const auto target_id = type->getAsCXXRecordDecl()->getID(); const auto target_id = common::to_id(*type->getAsCXXRecordDecl());
relationships.emplace_back(target_id, relationship_hint); relationships.emplace_back(target_id, relationship_hint);
result = true; result = true;
} }
@@ -998,12 +1013,19 @@ void translation_unit_visitor::
if (diagram().should_include(template_field_decl_name)) { if (diagram().should_include(template_field_decl_name)) {
if (template_instantiation_type.isDependentType()) { if (template_instantiation_type.isDependentType()) {
relationship r{relationship_t::kDependency, if (get_ast_local_id(template_instantiation_type.getTemplateName()
template_instantiation_type.getTemplateName() .getAsTemplateDecl()
.getAsTemplateDecl() ->getID())
->getID()}; .has_value()) {
relationship r{relationship_t::kDependency,
get_ast_local_id(
template_instantiation_type.getTemplateName()
.getAsTemplateDecl()
->getID())
.value()};
c.add_relationship(std::move(r)); c.add_relationship(std::move(r));
}
} }
else { else {
auto template_specialization_ptr = auto template_specialization_ptr =
@@ -1104,7 +1126,6 @@ translation_unit_visitor::process_template_specialization(
ns.pop_back(); ns.pop_back();
template_instantiation.set_name(cls->getNameAsString()); template_instantiation.set_name(cls->getNameAsString());
template_instantiation.set_namespace(ns); template_instantiation.set_namespace(ns);
template_instantiation.set_id(cls->getID());
template_instantiation.is_struct(cls->isStruct()); template_instantiation.is_struct(cls->isStruct());
@@ -1121,6 +1142,11 @@ translation_unit_visitor::process_template_specialization(
cls, template_instantiation, arg, arg_it); cls, template_instantiation, arg, arg_it);
} }
template_instantiation.set_id(
common::to_id(template_instantiation.full_name(false)));
set_ast_local_id(cls->getID(), template_instantiation.id());
return c_ptr; return c_ptr;
} }
@@ -1573,10 +1599,10 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
arg.getAsType() arg.getAsType()
->getAs<clang::RecordType>() ->getAs<clang::RecordType>()
->getAsRecordDecl()) { ->getAsRecordDecl()) {
argument.set_id(arg.getAsType() argument.set_id(
->getAs<clang::RecordType>() common::to_id(*arg.getAsType()
->getAsRecordDecl() ->getAs<clang::RecordType>()
->getID()); ->getAsRecordDecl()));
if (diagram().should_include( if (diagram().should_include(
full_template_specialization_name)) { full_template_specialization_name)) {
@@ -1584,10 +1610,9 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
// template // template
template_instantiation.add_relationship( template_instantiation.add_relationship(
{relationship_t::kDependency, {relationship_t::kDependency,
arg.getAsType() common::to_id(*arg.getAsType()
->getAs<clang::RecordType>() ->getAs<clang::RecordType>()
->getAsRecordDecl() ->getAsRecordDecl())});
->getID()});
} }
} }
else if (arg.getAsType()->getAs<clang::EnumType>()) { else if (arg.getAsType()->getAs<clang::EnumType>()) {
@@ -1596,10 +1621,9 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
->getAsTagDecl()) { ->getAsTagDecl()) {
template_instantiation.add_relationship( template_instantiation.add_relationship(
{relationship_t::kDependency, {relationship_t::kDependency,
arg.getAsType() common::to_id(*arg.getAsType()
->getAs<clang::EnumType>() ->getAs<clang::EnumType>()
->getAsTagDecl() ->getAsTagDecl())});
->getID()});
} }
} }
} }
@@ -1650,7 +1674,7 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
std::string best_match_full_name{}; std::string best_match_full_name{};
auto full_template_name = template_instantiation.full_name(false); auto full_template_name = template_instantiation.full_name(false);
int best_match{}; int best_match{};
common::model::diagram_element::id_t best_match_id{}; common::model::diagram_element::id_t best_match_id{0};
for (const auto c : diagram().classes()) { for (const auto c : diagram().classes()) {
if (c.get() == template_instantiation) if (c.get() == template_instantiation)
@@ -1667,18 +1691,25 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
} }
} }
if (!best_match_full_name.empty()) { auto templated_decl_id =
template_type.getTemplateName().getAsTemplateDecl()->getID();
auto templated_decl_local_id =
get_ast_local_id(templated_decl_id).value_or(0);
if (best_match_id > 0) {
destination = best_match_full_name; destination = best_match_full_name;
template_instantiation.add_relationship( template_instantiation.add_relationship(
{relationship_t::kInstantiation, best_match_id}); {relationship_t::kInstantiation, best_match_id});
} }
// If we can't find optimal match for parent template specialization, // If we can't find optimal match for parent template specialization,
// just use whatever clang suggests // just use whatever clang suggests
else if (diagram().has_element(template_type.getTemplateName() else if (diagram().has_element(templated_decl_local_id)) {
.getAsTemplateDecl() template_instantiation.add_relationship(
->getID())) { {relationship_t::kInstantiation, templated_decl_local_id});
template_instantiation.add_relationship({relationship_t::kInstantiation, }
template_type.getTemplateName().getAsTemplateDecl()->getID()}); else if (diagram().should_include(qualified_name)) {
LOG_DBG("Skipping instantiation relationship from {}",
template_instantiation_ptr->full_name(false));
} }
return template_instantiation_ptr; return template_instantiation_ptr;
@@ -1904,7 +1935,7 @@ void translation_unit_visitor::add_incomplete_forward_declarations()
void translation_unit_visitor::finalize() void translation_unit_visitor::finalize()
{ {
// add_incomplete_forward_declarations(); // add_incomplete_forward_declarations();
} }
bool translation_unit_visitor::simplify_system_template( bool translation_unit_visitor::simplify_system_template(

View File

@@ -174,6 +174,23 @@ private:
bool simplify_system_template( bool simplify_system_template(
model::template_parameter &ct, const std::string &full_name); model::template_parameter &ct, const std::string &full_name);
void set_ast_local_id(
int64_t local_id, common::model::diagram_element::id_t global_id)
{
LOG_DBG("{} >>>>>>>>>>>>>>>>>>>>>>>>> {}", local_id, global_id);
local_ast_id_map_[local_id] = global_id;
}
std::optional<common::model::diagram_element::id_t> get_ast_local_id(
int64_t local_id)
{
if (local_ast_id_map_.find(local_id) == local_ast_id_map_.end())
return {};
return local_ast_id_map_.at(local_id);
}
clang::SourceManager &source_manager_; clang::SourceManager &source_manager_;
// Reference to the output diagram model // Reference to the output diagram model
@@ -185,5 +202,7 @@ private:
std::map<common::model::diagram_element::id_t, std::map<common::model::diagram_element::id_t,
std::unique_ptr<clanguml::class_diagram::model::class_>> std::unique_ptr<clanguml::class_diagram::model::class_>>
forward_declarations_; forward_declarations_;
std::map<int64_t, common::model::diagram_element::id_t> local_ast_id_map_;
}; };
} }

View File

@@ -20,9 +20,34 @@
namespace clanguml::common { namespace clanguml::common {
template <> id_t to_id(const std::string &full_name)
{
return std::hash<std::string>{}(full_name) >> 3;
}
template <> id_t to_id(const clang::NamespaceDecl &declaration) template <> id_t to_id(const clang::NamespaceDecl &declaration)
{ {
return std::hash<std::string>{}(get_qualified_name(declaration)) >> 3; return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::RecordDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::EnumDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::TagDecl &declaration)
{
return to_id(get_qualified_name(declaration));
}
template <> id_t to_id(const clang::CXXRecordDecl &declaration)
{
return to_id(get_qualified_name(declaration));
} }
template <> id_t to_id(const clang::EnumType &t) { return to_id(*t.getDecl()); } template <> id_t to_id(const clang::EnumType &t) { return to_id(*t.getDecl()); }
@@ -34,7 +59,7 @@ template <> id_t to_id(const clang::TemplateSpecializationType &t)
template <> id_t to_id(const std::filesystem::path &file) template <> id_t to_id(const std::filesystem::path &file)
{ {
return std::hash<std::string>{}(file.lexically_normal()) >> 3; return to_id(file.lexically_normal());
} }
} }

View File

@@ -39,13 +39,18 @@ template <typename T> std::string get_qualified_name(const T &declaration)
return qualified_name; return qualified_name;
} }
template <typename T> id_t to_id(const T &declaration) template <typename T> id_t to_id(const T &declaration);
{
return declaration.getID(); template <> id_t to_id(const std::string &full_name);
}
template <> id_t to_id(const clang::NamespaceDecl &declaration); template <> id_t to_id(const clang::NamespaceDecl &declaration);
template <> id_t to_id(const clang::CXXRecordDecl &declaration);
template <> id_t to_id(const clang::EnumDecl &declaration);
template <> id_t to_id(const clang::TagDecl &declaration);
template <> id_t to_id(const clang::EnumType &type); template <> id_t to_id(const clang::EnumType &type);
template <> id_t to_id(const clang::TemplateSpecializationType &type); template <> id_t to_id(const clang::TemplateSpecializationType &type);