Refactored id generation

This commit is contained in:
Bartek Kryza
2022-07-31 17:59:39 +02:00
parent 913ade2349
commit cd9d9cf5a7
4 changed files with 117 additions and 37 deletions

View File

@@ -17,6 +17,7 @@
*/
#include "translation_unit_visitor.h"
#include "common/clang_utils.h"
#include "cx/util.h"
#include <clang/Basic/FileManager.h>
@@ -74,7 +75,7 @@ std::optional<clanguml::common::model::namespace_> get_enclosing_namespace(
return {};
}
return namespace_{namespace_declaration->getQualifiedNameAsString()};
return namespace_{common::get_qualified_name(*namespace_declaration)};
}
}
@@ -143,10 +144,12 @@ translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm,
bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
{
assert(ns != nullptr);
if (ns->isAnonymousNamespace() || ns->isInline())
return true;
auto package_path = namespace_{ns->getQualifiedNameAsString()};
auto package_path = namespace_{common::get_qualified_name(*ns)};
auto package_parent = package_path;
std::string name;
@@ -163,9 +166,9 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
p->set_name(name);
p->set_namespace(package_parent);
p->set_id(ns->getID());
p->set_id(common::to_id(*ns));
if (diagram().should_include(*p)) {
if (diagram().should_include(*p) && !diagram().get(p->id())) {
process_comment(*ns, *p);
set_source_location(*ns, *p);
@@ -188,6 +191,8 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
{
assert(enm != nullptr);
// Anonymous enum values should be rendered as class fields
// with type enum
if (enm->getNameAsString().empty())
@@ -196,7 +201,7 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
auto e_ptr = std::make_unique<enum_>(config_.using_namespace());
auto &e = *e_ptr;
std::string qualified_name = enm->getQualifiedNameAsString();
std::string qualified_name = common::get_qualified_name(*enm);
namespace_ ns{qualified_name};
ns.pop_back();
e.set_name(enm->getNameAsString());
@@ -401,19 +406,19 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
std::unique_ptr<class_> translation_unit_visitor::create_class_declaration(
clang::CXXRecordDecl *cls)
{
assert(cls != nullptr);
auto c_ptr{std::make_unique<class_>(config_.using_namespace())};
auto &c = *c_ptr;
// TODO: refactor to method get_qualified_name()
auto qualified_name = cls->getQualifiedNameAsString();
util::replace_all(qualified_name, "(anonymous namespace)", "");
util::replace_all(qualified_name, "::::", "::");
auto qualified_name = common::get_qualified_name(*cls);
namespace_ ns{qualified_name};
ns.pop_back();
c.set_name(cls->getNameAsString());
c.set_namespace(ns);
c.set_id(cls->getID());
c.set_id(common::to_id(*cls));
c.is_struct(cls->isStruct());
@@ -449,7 +454,7 @@ bool translation_unit_visitor::process_template_parameters(
const clang::ClassTemplateDecl &template_declaration, class_ &c)
{
LOG_DBG("Processing class {} template parameters...",
template_declaration.getQualifiedNameAsString());
common::get_qualified_name(template_declaration));
if (template_declaration.getTemplateParameters() == nullptr)
return false;
@@ -520,8 +525,8 @@ void translation_unit_visitor::process_record_containment(
element.set_namespace(namespace_declaration.value());
}
const auto id =
static_cast<const clang::RecordDecl *>(record.getParent())->getID();
const auto id = common::to_id(
*static_cast<const clang::RecordDecl *>(record.getParent()));
element.add_relationship({relationship_t::kContainment, id});
}
@@ -541,11 +546,8 @@ void translation_unit_visitor::process_class_bases(
base.getType()->getAs<clang::RecordType>()->getDecl()->getID());
else if (base.getType()->getAs<clang::TemplateSpecializationType>() !=
nullptr) {
cp.set_id(base.getType()
->getAs<clang::TemplateSpecializationType>()
->getTemplateName()
.getAsTemplateDecl()
->getID());
cp.set_id(common::to_id(
*base.getType()->getAs<clang::TemplateSpecializationType>()));
}
else
// This could be a template parameter - we don't want it here

34
src/common/clang_utils.cc Normal file
View File

@@ -0,0 +1,34 @@
/**
* src/common/visitor/clang_utils.cc
*
* Copyright (c) 2021-2022 Bartek Kryza <bkryza@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "clang_utils.h"
namespace clanguml::common {
template <> id_t to_id(const clang::NamespaceDecl &declaration)
{
return std::hash<std::string>{}(get_qualified_name(declaration)) >> 3;
}
template <> id_t to_id(const clang::EnumType &t) { return to_id(*t.getDecl()); }
template <> id_t to_id(const clang::TemplateSpecializationType &t)
{
return t.getTemplateName().getAsTemplateDecl()->getID();
}
}

52
src/common/clang_utils.h Normal file
View File

@@ -0,0 +1,52 @@
/**
* src/common/clang_utils.h
*
* Copyright (c) 2021-2022 Bartek Kryza <bkryza@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "cx/util.h"
#include "types.h"
#include <clang/AST/RecursiveASTVisitor.h>
#include <string>
namespace clang {
class NamespaceDecl;
}
namespace clanguml::common {
template <typename T> std::string get_qualified_name(const T &declaration)
{
auto qualified_name = declaration.getQualifiedNameAsString();
util::replace_all(qualified_name, "(anonymous namespace)", "");
util::replace_all(qualified_name, "::::", "::");
return qualified_name;
}
template <typename T> id_t to_id(const T &declaration)
{
return declaration.getID();
}
template <> id_t to_id(const clang::NamespaceDecl &declaration);
template <> id_t to_id(const clang::EnumType &type);
template <> id_t to_id(const clang::TemplateSpecializationType &type);
}

View File

@@ -18,6 +18,7 @@
#include "translation_unit_visitor.h"
#include "common/clang_utils.h"
#include "common/model/namespace.h"
#include "cx/util.h"
@@ -35,15 +36,6 @@ using clanguml::common::model::relationship;
using clanguml::common::model::relationship_t;
using clanguml::package_diagram::model::diagram;
int64_t to_id(const clang::NamespaceDecl *ns)
{
auto qualified_name = ns->getQualifiedNameAsString();
util::replace_all(qualified_name, "(anonymous namespace)", "");
util::replace_all(qualified_name, "::::", "::");
return std::hash<std::string>{}(qualified_name) >> 3;
}
translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm,
clanguml::package_diagram::model::diagram &diagram,
const clanguml::config::package_diagram &config)
@@ -55,12 +47,12 @@ translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm,
bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
{
assert(ns != nullptr);
if (ns->isAnonymousNamespace() || ns->isInline())
return true;
auto qualified_name = ns->getQualifiedNameAsString();
util::replace_all(qualified_name, "(anonymous namespace)", "");
util::replace_all(qualified_name, "::::", "::");
auto qualified_name = common::get_qualified_name(*ns);
LOG_DBG("Visiting namespace declaration: {}", qualified_name);
@@ -81,7 +73,7 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
p->set_name(name);
p->set_namespace(package_parent);
p->set_id(to_id(ns));
p->set_id(common::to_id(*ns));
assert(p->id() > 0);
@@ -160,7 +152,7 @@ void translation_unit_visitor::add_relationships(
const auto *namespace_context = cls->getEnclosingNamespaceContext();
if (namespace_context != nullptr && namespace_context->isNamespace()) {
current_package_id =
to_id(llvm::cast<clang::NamespaceDecl>(namespace_context));
common::to_id(*llvm::cast<clang::NamespaceDecl>(namespace_context));
}
assert(current_package_id != 0);
@@ -333,8 +325,7 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
}
else if (type->isEnumeralType()) {
relationships.emplace_back(
type->getAs<clang::EnumType>()->getDecl()->getID(),
relationship_hint);
common::to_id(*type->getAs<clang::EnumType>()), relationship_hint);
}
else if (auto *template_specialization_type =
type->getAs<clang::TemplateSpecializationType>()) {
@@ -398,10 +389,11 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
const auto *namespace_declaration =
clang::cast<clang::NamespaceDecl>(namespace_context);
if (diagram().should_include(
namespace_declaration->getQualifiedNameAsString())) {
const auto target_id =
to_id(clang::cast<clang::NamespaceDecl>(namespace_context));
if (namespace_declaration != nullptr &&
diagram().should_include(
common::get_qualified_name(*namespace_declaration))) {
const auto target_id = common::to_id(
*clang::cast<clang::NamespaceDecl>(namespace_context));
relationships.emplace_back(target_id, relationship_hint);
result = true;
}