From feb19c23c77e000ec4e0f6a2eea20e7096e661e8 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Sun, 28 Aug 2022 19:46:01 +0200 Subject: [PATCH] Cleaned up code --- .../plantuml/class_diagram_generator.cc | 2 - src/class_diagram/model/class.cc | 13 +- src/class_diagram/model/diagram.cc | 7 - .../visitor/translation_unit_visitor.cc | 164 +++++------------- .../visitor/translation_unit_visitor.h | 19 +- src/common/clang_utils.cc | 81 ++++++++- src/common/clang_utils.h | 15 ++ src/common/generators/plantuml/generator.h | 7 +- src/common/model/diagram_filter.cc | 6 - .../plantuml/package_diagram_generator.cc | 2 - 10 files changed, 150 insertions(+), 166 deletions(-) diff --git a/src/class_diagram/generators/plantuml/class_diagram_generator.cc b/src/class_diagram/generators/plantuml/class_diagram_generator.cc index 626b99c3..86afa46e 100644 --- a/src/class_diagram/generators/plantuml/class_diagram_generator.cc +++ b/src/class_diagram/generators/plantuml/class_diagram_generator.cc @@ -244,8 +244,6 @@ void generator::generate_relationships( { namespace plantuml_common = clanguml::common::generators::plantuml; - // const auto &uns = m_config.using_namespace(); - // // Process relationships // diff --git a/src/class_diagram/model/class.cc b/src/class_diagram/model/class.cc index 59388157..88d365fc 100644 --- a/src/class_diagram/model/class.cc +++ b/src/class_diagram/model/class.cc @@ -59,6 +59,12 @@ void class_::add_method(class_method &&method) void class_::add_parent(class_parent &&parent) { + for (const auto &p : bases_) { + if (p.id() == parent.id()) { + return; + } + } + bases_.emplace_back(std::move(parent)); } @@ -85,12 +91,7 @@ void class_::set_base_template(const std::string &full_name) std::string class_::base_template() const { return base_template_full_name_; } -bool operator==(const class_ &l, const class_ &r) -{ - return l.id() == r.id(); - //(l.name_and_ns() == r.name_and_ns()) && - // (l.templates_ == r.templates_); -} +bool operator==(const class_ &l, const class_ &r) { return l.id() == r.id(); } void class_::add_type_alias(type_alias &&ta) { diff --git a/src/class_diagram/model/diagram.cc b/src/class_diagram/model/diagram.cc index d8f25175..dd1128d0 100644 --- a/src/class_diagram/model/diagram.cc +++ b/src/class_diagram/model/diagram.cc @@ -168,8 +168,6 @@ bool diagram::add_class(std::unique_ptr &&c) auto id = cc.id(); if (!has_class(cc)) { - if (base_name == "cpp_function_parameter") - LOG_DBG("AAAAAAAAAAAAAAAAAAAAAAA"); if (add_element(ns, std::move(c))) classes_.push_back(std::ref(cc)); @@ -219,8 +217,6 @@ void diagram::get_parents( bool found_new{false}; for (const auto &parent : parents) { for (const auto &pp : parent.get().parents()) { - LOG_DBG("=-=-=-=-=-=-= {} HAS PARENT {} [{}]", - parent.get().full_name(false), pp.name(), pp.id()); auto p = get_class(pp.id()); if (p.has_value()) { @@ -228,9 +224,6 @@ void diagram::get_parents( if (found) found_new = true; } - else { - LOG_DBG("=-=-=-=-=-=-= {} NOT FOUND IN DIAGRAM", pp.id()); - } } } diff --git a/src/class_diagram/visitor/translation_unit_visitor.cc b/src/class_diagram/visitor/translation_unit_visitor.cc index d4a57afa..ed3ead59 100644 --- a/src/class_diagram/visitor/translation_unit_visitor.cc +++ b/src/class_diagram/visitor/translation_unit_visitor.cc @@ -61,80 +61,6 @@ access_t access_specifier_to_access_t(clang::AccessSpecifier access_specifier) return access; } - -std::optional get_enclosing_namespace( - const clang::DeclContext *decl) -{ - if (!decl->getEnclosingNamespaceContext()->isNamespace()) - return {}; - - const auto *namespace_declaration = - clang::cast(decl->getEnclosingNamespaceContext()); - - if (namespace_declaration == nullptr) { - return {}; - } - - return namespace_{common::get_qualified_name(*namespace_declaration)}; -} -} - -std::string to_string(const clang::QualType &type, const clang::ASTContext &ctx, - bool try_canonical = true) -{ - const clang::PrintingPolicy print_policy(ctx.getLangOpts()); - - auto result{type.getAsString(print_policy)}; - - if (try_canonical && result.find('<') != std::string::npos) { - auto canonical_type_name = - type.getCanonicalType().getAsString(print_policy); - - auto result_qualified_template_name = - result.substr(0, result.find('<')); - auto result_template_arguments = result.substr(result.find('<')); - - 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; - } - } - - util::replace_all(result, ", ", ","); - - return result; -} - -std::string to_string(const clang::RecordType &type, - const clang::ASTContext &ctx, bool try_canonical = true) -{ - return to_string(type.desugar(), ctx, try_canonical); -} - -std::string get_source_text_raw( - clang::SourceRange range, const clang::SourceManager &sm) -{ - return clang::Lexer::getSourceText( - clang::CharSourceRange::getCharRange(range), sm, clang::LangOptions()) - .str(); -} - -std::string get_source_text( - clang::SourceRange range, const clang::SourceManager &sm) -{ - clang::LangOptions lo; - - auto start_loc = sm.getSpellingLoc(range.getBegin()); - auto last_token_loc = sm.getSpellingLoc(range.getEnd()); - auto end_loc = clang::Lexer::getLocForEndOfToken(last_token_loc, 0, sm, lo); - auto printable_range = clang::SourceRange{start_loc, end_loc}; - return get_source_text_raw(printable_range, sm); } translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm, @@ -238,7 +164,7 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm) process_record_containment(*enm, e); } - auto namespace_declaration = detail::get_enclosing_namespace(enm); + auto namespace_declaration = common::get_enclosing_namespace(enm); if (namespace_declaration.has_value()) { e.set_namespace(namespace_declaration.value()); } @@ -259,18 +185,6 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl( cls->getQualifiedNameAsString(), cls->getLocation().printToString(source_manager_)); - // Skip forward declarations - if (!cls->isCompleteDefinition()) { - // Register this forward declaration in case there is no complete - // definition (see t00036) - return true; - } - // else - // // Check if the class was already processed within - // // VisitClassTemplateDecl() - // if (diagram_.has_element(cls->getID())) - // return true; - // TODO: Add support for classes defined in function/method bodies if (cls->isLocalClass()) return true; @@ -394,10 +308,6 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls) cls->getQualifiedNameAsString(), cls->getLocation().printToString(source_manager_)); - // Skip forward declarations - // if (!cls->isCompleteDefinition()) - // return true; - const auto cls_id = common::to_id(*cls); set_ast_local_id(cls->getID(), cls_id); @@ -408,11 +318,6 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls) nullptr)) return true; - // Check if the class was already processed within VisitClassTemplateDecl() - // auto cls_id = cls->getID(); - // if (diagram_.has_element(cls_id)) - // return true; - // TODO: Add support for classes defined in function/method bodies if (cls->isLocalClass()) return true; @@ -481,9 +386,6 @@ std::unique_ptr translation_unit_visitor::create_class_declaration( c.set_style(c.style_spec()); - if (!cls->isCompleteDefinition()) - return c_ptr; - return c_ptr; } @@ -571,7 +473,7 @@ void translation_unit_visitor::process_record_containment( static_cast(record.getParent()) ->getQualifiedNameAsString(); - auto namespace_declaration = detail::get_enclosing_namespace(parent); + auto namespace_declaration = common::get_enclosing_namespace(parent); if (namespace_declaration.has_value()) { element.set_namespace(namespace_declaration.value()); } @@ -588,7 +490,7 @@ void translation_unit_visitor::process_class_bases( for (auto &base : cls->bases()) { class_parent cp; auto name_and_ns = common::model::namespace_{ - to_string(base.getType(), cls->getASTContext())}; + common::to_string(base.getType(), cls->getASTContext())}; cp.set_name(name_and_ns.to_string()); @@ -948,8 +850,8 @@ void translation_unit_visitor::process_function_parameter( if (p.hasDefaultArg()) { const auto *default_arg = p.getDefaultArg(); if (default_arg != nullptr) { - auto default_arg_str = - get_source_text(default_arg->getSourceRange(), source_manager_); + auto default_arg_str = common::get_source_text( + default_arg->getSourceRange(), source_manager_); parameter.set_default_value(default_arg_str); } } @@ -1068,7 +970,8 @@ void translation_unit_visitor::process_static_field( const clang::VarDecl &field_declaration, class_ &c) { const auto field_type = field_declaration.getType(); - auto type_name = to_string(field_type, field_declaration.getASTContext()); + auto type_name = + common::to_string(field_type, field_declaration.getASTContext()); if (type_name.empty()) type_name = "<>"; @@ -1176,14 +1079,15 @@ void translation_unit_visitor::process_template_specialization_argument( argument.to_string(config().using_namespace(), false)); } else if (arg.getAsType()->getAs()) { - auto type_name = to_string(arg.getAsType(), cls->getASTContext()); + auto type_name = + common::to_string(arg.getAsType(), cls->getASTContext()); // clang does not provide declared template parameter/argument names // in template specializations - so we have to extract them from // raw source code... if (type_name.find("type-parameter-") == 0) { - auto declaration_text = - get_source_text_raw(cls->getSourceRange(), source_manager_); + auto declaration_text = common::get_source_text_raw( + cls->getSourceRange(), source_manager_); declaration_text = declaration_text.substr( declaration_text.find(cls->getNameAsString()) + @@ -1206,7 +1110,8 @@ void translation_unit_visitor::process_template_specialization_argument( argument.set_name(type_name); } else { - auto type_name = to_string(arg.getAsType(), cls->getASTContext()); + auto type_name = + common::to_string(arg.getAsType(), cls->getASTContext()); if (type_name.find('<') != std::string::npos) { // Sometimes template instantiation is reported as // RecordType in the AST and getAs to @@ -1222,8 +1127,8 @@ void translation_unit_visitor::process_template_specialization_argument( argument.set_name(type_name.substr(0, type_name.find('<'))); } else if (type_name.find("type-parameter-") == 0) { - auto declaration_text = - get_source_text_raw(cls->getSourceRange(), source_manager_); + auto declaration_text = common::get_source_text_raw( + cls->getSourceRange(), source_manager_); declaration_text = declaration_text.substr( declaration_text.find(cls->getNameAsString()) + @@ -1267,7 +1172,7 @@ void translation_unit_visitor::process_template_specialization_argument( else if (argument_kind == clang::TemplateArgument::Expression) { template_parameter argument; argument.is_template_parameter(false); - argument.set_type(get_source_text( + argument.set_type(common::get_source_text( arg.getAsExpr()->getSourceRange(), source_manager_)); template_instantiation.add_template(std::move(argument)); } @@ -1359,7 +1264,7 @@ std::unique_ptr translation_unit_visitor:: auto &template_instantiation = *template_instantiation_ptr; std::string full_template_specialization_name = - to_string(record_type, template_specialization.getASTContext()); + common::to_string(record_type, template_specialization.getASTContext()); const auto *template_decl = template_specialization.getSpecializedTemplate(); @@ -1454,7 +1359,7 @@ std::unique_ptr translation_unit_visitor::build_template_instantiation( auto template_instantiation_ptr = std::make_unique(config_.using_namespace()); auto &template_instantiation = *template_instantiation_ptr; - std::string full_template_specialization_name = to_string( + std::string full_template_specialization_name = common::to_string( template_type.desugar(), template_type.getTemplateName().getAsTemplateDecl()->getASTContext()); @@ -1497,7 +1402,7 @@ std::unique_ptr translation_unit_visitor::build_template_instantiation( if (templated_class_decl && templated_class_decl->hasDefinition()) for (const auto &base : templated_class_decl->bases()) { - const auto base_class_name = to_string( + const auto base_class_name = common::to_string( base.getType(), templated_class_decl->getASTContext(), false); LOG_DBG("Found template instantiation base: {}, {}", @@ -1589,7 +1494,6 @@ void translation_unit_visitor:: build_template_instantiation_process_template_arguments( std::optional &parent, std::deque> &template_base_params, - // const clang::TemplateSpecializationType &template_type, const clang::ArrayRef &template_args, class_ &template_instantiation, const std::string &full_template_specialization_name, @@ -1772,7 +1676,7 @@ void translation_unit_visitor:: else if (arg.getAsType()->getAs()) { argument.is_template_parameter(true); argument.set_name( - to_string(arg.getAsType(), template_decl->getASTContext())); + common::to_string(arg.getAsType(), template_decl->getASTContext())); } else { // This is just a regular record type @@ -1799,8 +1703,8 @@ void translation_unit_visitor:: assert(arg.getKind() == clang::TemplateArgument::Expression); argument.is_template_parameter(false); - argument.set_type( - get_source_text(arg.getAsExpr()->getSourceRange(), source_manager_)); + argument.set_type(common::get_source_text( + arg.getAsExpr()->getSourceRange(), source_manager_)); } void translation_unit_visitor:: @@ -1815,7 +1719,7 @@ void translation_unit_visitor:: argument.is_template_parameter(false); argument.set_name( - to_string(arg.getAsType(), template_decl->getASTContext())); + common::to_string(arg.getAsType(), template_decl->getASTContext())); if (arg.getAsType()->getAs() && arg.getAsType()->getAs()->getAsRecordDecl()) { @@ -1884,7 +1788,8 @@ void translation_unit_visitor::process_field( // The actual field type auto field_type = field_declaration.getType(); // String representation of the field type - auto type_name = to_string(field_type, field_declaration.getASTContext()); + auto type_name = + common::to_string(field_type, field_declaration.getASTContext()); // The field name const auto field_name = field_declaration.getNameAsString(); // If for any reason clang reports the type as empty string, make sure @@ -1895,7 +1800,8 @@ void translation_unit_visitor::process_field( class_member field{ detail::access_specifier_to_access_t(field_declaration.getAccess()), field_name, - to_string(field_type, field_declaration.getASTContext(), false)}; + common::to_string( + field_type, field_declaration.getASTContext(), false)}; // Parse the field comment process_comment(field_declaration, field); @@ -2070,4 +1976,20 @@ bool translation_unit_visitor::simplify_system_template( else return false; } + +void translation_unit_visitor::set_ast_local_id( + int64_t local_id, common::model::diagram_element::id_t global_id) +{ + local_ast_id_map_[local_id] = global_id; +} + +std::optional +translation_unit_visitor::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); +} + } diff --git a/src/class_diagram/visitor/translation_unit_visitor.h b/src/class_diagram/visitor/translation_unit_visitor.h index 19f46890..809a82ca 100644 --- a/src/class_diagram/visitor/translation_unit_visitor.h +++ b/src/class_diagram/visitor/translation_unit_visitor.h @@ -150,7 +150,6 @@ private: void build_template_instantiation_process_template_arguments( std::optional &parent, std::deque> &template_base_params, - // const clang::TemplateSpecializationType &template_type, const clang::ArrayRef &template_args, model::class_ &template_instantiation, const std::string &full_template_specialization_name, @@ -216,22 +215,14 @@ private: bool simplify_system_template( model::template_parameter &ct, const std::string &full_name); + /// Store the mapping from local clang entity id (obtained using + /// getID()) method to clang-uml global id 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; - } + int64_t local_id, common::model::diagram_element::id_t global_id); + /// Retrieve the global clang-uml entity id based on the clang local id std::optional 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); - } + int64_t local_id); clang::SourceManager &source_manager_; diff --git a/src/common/clang_utils.cc b/src/common/clang_utils.cc index 2e49d80a..90ef71c1 100644 --- a/src/common/clang_utils.cc +++ b/src/common/clang_utils.cc @@ -18,8 +18,86 @@ #include "clang_utils.h" +#include + namespace clanguml::common { +std::optional get_enclosing_namespace( + const clang::DeclContext *decl) +{ + if (!decl->getEnclosingNamespaceContext()->isNamespace()) + return {}; + + const auto *namespace_declaration = + clang::cast(decl->getEnclosingNamespaceContext()); + + if (namespace_declaration == nullptr) { + return {}; + } + + return clanguml::common::model::namespace_{ + common::get_qualified_name(*namespace_declaration)}; +} + +std::string to_string(const clang::QualType &type, const clang::ASTContext &ctx, + bool try_canonical) +{ + const clang::PrintingPolicy print_policy(ctx.getLangOpts()); + + auto result{type.getAsString(print_policy)}; + + if (try_canonical && result.find('<') != std::string::npos) { + auto canonical_type_name = + type.getCanonicalType().getAsString(print_policy); + + auto result_qualified_template_name = + result.substr(0, result.find('<')); + auto result_template_arguments = result.substr(result.find('<')); + + 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; + } + } + + // Remove trailing spaces after commas in template arguments + clanguml::util::replace_all(result, ", ", ","); + + return result; +} + +std::string to_string(const clang::RecordType &type, + const clang::ASTContext &ctx, bool try_canonical) +{ + return to_string(type.desugar(), ctx, try_canonical); +} + +std::string get_source_text_raw( + clang::SourceRange range, const clang::SourceManager &sm) +{ + return clang::Lexer::getSourceText( + clang::CharSourceRange::getCharRange(range), sm, clang::LangOptions()) + .str(); +} + +std::string get_source_text( + clang::SourceRange range, const clang::SourceManager &sm) +{ + clang::LangOptions lo; + + auto start_loc = sm.getSpellingLoc(range.getBegin()); + auto last_token_loc = sm.getSpellingLoc(range.getEnd()); + auto end_loc = clang::Lexer::getLocForEndOfToken(last_token_loc, 0, sm, lo); + auto printable_range = clang::SourceRange{start_loc, end_loc}; + return get_source_text_raw(printable_range, sm); +} + template <> id_t to_id(const std::string &full_name) { return std::hash{}(full_name) >> 3; @@ -52,8 +130,6 @@ template <> id_t to_id(const clang::CXXRecordDecl &declaration) template <> id_t to_id(const clang::EnumType &t) { return to_id(*t.getDecl()); } -// template <> id_t to_id(const clang::TemplateSpecializationType &t); - template <> id_t to_id(const std::filesystem::path &file) { return to_id(file.lexically_normal().string()); @@ -74,5 +150,4 @@ template <> id_t to_id(const clang::TemplateArgument &template_argument) throw std::runtime_error("Cannot generate id for template argument"); } - } diff --git a/src/common/clang_utils.h b/src/common/clang_utils.h index f5e37f09..0395219c 100644 --- a/src/common/clang_utils.h +++ b/src/common/clang_utils.h @@ -39,6 +39,21 @@ template std::string get_qualified_name(const T &declaration) return qualified_name; } +std::optional get_enclosing_namespace( + const clang::DeclContext *decl); + +std::string to_string(const clang::QualType &type, const clang::ASTContext &ctx, + bool try_canonical = true); + +std::string to_string(const clang::RecordType &type, + const clang::ASTContext &ctx, bool try_canonical = true); + +std::string get_source_text_raw( + clang::SourceRange range, const clang::SourceManager &sm); + +std::string get_source_text( + clang::SourceRange range, const clang::SourceManager &sm); + template id_t to_id(const T &declaration); template <> id_t to_id(const std::string &full_name); diff --git a/src/common/generators/plantuml/generator.h b/src/common/generators/plantuml/generator.h index d8777295..c818d777 100644 --- a/src/common/generators/plantuml/generator.h +++ b/src/common/generators/plantuml/generator.h @@ -198,8 +198,8 @@ void generator::generate_plantuml_directives( directive.replace(std::get<1>(alias_match), std::get<2>(alias_match), element_opt.value().alias()); else { - LOG_ERROR( - "CANNOT FIND ALIAS TO ELEMENT {}", full_name.to_string()); + LOG_ERROR("Cannot find clang-uml alias for element {}", + full_name.to_string()); directive.replace(std::get<1>(alias_match), std::get<2>(alias_match), "UNKNOWN_ALIAS"); } @@ -262,9 +262,6 @@ public: { visitor_.TraverseDecl(ast_context.getTranslationUnitDecl()); visitor_.finalize(); - - // LOG_DBG("= Finalized translation unit: {}", - // ast_context.getTranslationUnitDecl()); } }; diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index d0e18d7a..3afe0534 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -229,8 +229,6 @@ tvl::value_t subclass_filter::match(const diagram &d, const element &e) const if (!class_ref.has_value()) return false; - LOG_DBG("====================== LOOKING FOR PARENTS OF {} ===========", fn); - parents.emplace(class_ref.value()); cd.get_parents(parents); @@ -239,15 +237,11 @@ tvl::value_t subclass_filter::match(const diagram &d, const element &e) const for (const auto p : parents) parents_names.push_back(p.get().full_name(false)); - LOG_DBG("====================== FOUND PARENTS {} ==========", - fmt::join(parents_names, ", ")); - // Now check if any of the parents matches the roots specified in the // filter config for (const auto &root : roots_) { for (const auto &parent : parents) { auto full_name = parent.get().full_name(false); - LOG_DBG("+++ COMPARING {} WITH {}", root, full_name); if (root == full_name) return true; } diff --git a/src/package_diagram/generators/plantuml/package_diagram_generator.cc b/src/package_diagram/generators/plantuml/package_diagram_generator.cc index a129efec..7afe6f97 100644 --- a/src/package_diagram/generators/plantuml/package_diagram_generator.cc +++ b/src/package_diagram/generators/plantuml/package_diagram_generator.cc @@ -32,8 +32,6 @@ void generator::generate_relationships( { LOG_DBG("Generating relationships for package {}", p.full_name(true)); - // const auto &uns = m_config.using_namespace(); - // Generate this packages relationship if (m_model.should_include(relationship_t::kDependency)) { for (const auto &r : p.relationships()) {