Refactored id generation
This commit is contained in:
@@ -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
34
src/common/clang_utils.cc
Normal 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
52
src/common/clang_utils.h
Normal 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);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user