Refactored id generation
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "translation_unit_visitor.h"
|
#include "translation_unit_visitor.h"
|
||||||
|
#include "common/clang_utils.h"
|
||||||
#include "cx/util.h"
|
#include "cx/util.h"
|
||||||
|
|
||||||
#include <clang/Basic/FileManager.h>
|
#include <clang/Basic/FileManager.h>
|
||||||
@@ -74,7 +75,7 @@ std::optional<clanguml::common::model::namespace_> get_enclosing_namespace(
|
|||||||
return {};
|
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)
|
bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
|
||||||
{
|
{
|
||||||
|
assert(ns != nullptr);
|
||||||
|
|
||||||
if (ns->isAnonymousNamespace() || ns->isInline())
|
if (ns->isAnonymousNamespace() || ns->isInline())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto package_path = namespace_{ns->getQualifiedNameAsString()};
|
auto package_path = namespace_{common::get_qualified_name(*ns)};
|
||||||
auto package_parent = package_path;
|
auto package_parent = package_path;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -163,9 +166,9 @@ 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(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);
|
process_comment(*ns, *p);
|
||||||
set_source_location(*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)
|
bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
|
||||||
{
|
{
|
||||||
|
assert(enm != nullptr);
|
||||||
|
|
||||||
// Anonymous enum values should be rendered as class fields
|
// Anonymous enum values should be rendered as class fields
|
||||||
// with type enum
|
// with type enum
|
||||||
if (enm->getNameAsString().empty())
|
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_ptr = std::make_unique<enum_>(config_.using_namespace());
|
||||||
auto &e = *e_ptr;
|
auto &e = *e_ptr;
|
||||||
|
|
||||||
std::string qualified_name = enm->getQualifiedNameAsString();
|
std::string qualified_name = common::get_qualified_name(*enm);
|
||||||
namespace_ ns{qualified_name};
|
namespace_ ns{qualified_name};
|
||||||
ns.pop_back();
|
ns.pop_back();
|
||||||
e.set_name(enm->getNameAsString());
|
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(
|
std::unique_ptr<class_> translation_unit_visitor::create_class_declaration(
|
||||||
clang::CXXRecordDecl *cls)
|
clang::CXXRecordDecl *cls)
|
||||||
{
|
{
|
||||||
|
assert(cls != nullptr);
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
// TODO: refactor to method get_qualified_name()
|
// TODO: refactor to method get_qualified_name()
|
||||||
auto qualified_name = cls->getQualifiedNameAsString();
|
auto qualified_name = common::get_qualified_name(*cls);
|
||||||
util::replace_all(qualified_name, "(anonymous namespace)", "");
|
|
||||||
util::replace_all(qualified_name, "::::", "::");
|
|
||||||
|
|
||||||
namespace_ ns{qualified_name};
|
namespace_ ns{qualified_name};
|
||||||
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(common::to_id(*cls));
|
||||||
|
|
||||||
c.is_struct(cls->isStruct());
|
c.is_struct(cls->isStruct());
|
||||||
|
|
||||||
@@ -449,7 +454,7 @@ bool translation_unit_visitor::process_template_parameters(
|
|||||||
const clang::ClassTemplateDecl &template_declaration, class_ &c)
|
const clang::ClassTemplateDecl &template_declaration, class_ &c)
|
||||||
{
|
{
|
||||||
LOG_DBG("Processing class {} template parameters...",
|
LOG_DBG("Processing class {} template parameters...",
|
||||||
template_declaration.getQualifiedNameAsString());
|
common::get_qualified_name(template_declaration));
|
||||||
|
|
||||||
if (template_declaration.getTemplateParameters() == nullptr)
|
if (template_declaration.getTemplateParameters() == nullptr)
|
||||||
return false;
|
return false;
|
||||||
@@ -520,8 +525,8 @@ void translation_unit_visitor::process_record_containment(
|
|||||||
element.set_namespace(namespace_declaration.value());
|
element.set_namespace(namespace_declaration.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto id =
|
const auto id = common::to_id(
|
||||||
static_cast<const clang::RecordDecl *>(record.getParent())->getID();
|
*static_cast<const clang::RecordDecl *>(record.getParent()));
|
||||||
|
|
||||||
element.add_relationship({relationship_t::kContainment, id});
|
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());
|
base.getType()->getAs<clang::RecordType>()->getDecl()->getID());
|
||||||
else if (base.getType()->getAs<clang::TemplateSpecializationType>() !=
|
else if (base.getType()->getAs<clang::TemplateSpecializationType>() !=
|
||||||
nullptr) {
|
nullptr) {
|
||||||
cp.set_id(base.getType()
|
cp.set_id(common::to_id(
|
||||||
->getAs<clang::TemplateSpecializationType>()
|
*base.getType()->getAs<clang::TemplateSpecializationType>()));
|
||||||
->getTemplateName()
|
|
||||||
.getAsTemplateDecl()
|
|
||||||
->getID());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// This could be a template parameter - we don't want it here
|
// 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 "translation_unit_visitor.h"
|
||||||
|
|
||||||
|
#include "common/clang_utils.h"
|
||||||
#include "common/model/namespace.h"
|
#include "common/model/namespace.h"
|
||||||
#include "cx/util.h"
|
#include "cx/util.h"
|
||||||
|
|
||||||
@@ -35,15 +36,6 @@ using clanguml::common::model::relationship;
|
|||||||
using clanguml::common::model::relationship_t;
|
using clanguml::common::model::relationship_t;
|
||||||
using clanguml::package_diagram::model::diagram;
|
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,
|
translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm,
|
||||||
clanguml::package_diagram::model::diagram &diagram,
|
clanguml::package_diagram::model::diagram &diagram,
|
||||||
const clanguml::config::package_diagram &config)
|
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)
|
bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
|
||||||
{
|
{
|
||||||
|
assert(ns != nullptr);
|
||||||
|
|
||||||
if (ns->isAnonymousNamespace() || ns->isInline())
|
if (ns->isAnonymousNamespace() || ns->isInline())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto qualified_name = ns->getQualifiedNameAsString();
|
auto qualified_name = common::get_qualified_name(*ns);
|
||||||
util::replace_all(qualified_name, "(anonymous namespace)", "");
|
|
||||||
util::replace_all(qualified_name, "::::", "::");
|
|
||||||
|
|
||||||
LOG_DBG("Visiting namespace declaration: {}", qualified_name);
|
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_name(name);
|
||||||
p->set_namespace(package_parent);
|
p->set_namespace(package_parent);
|
||||||
p->set_id(to_id(ns));
|
p->set_id(common::to_id(*ns));
|
||||||
|
|
||||||
assert(p->id() > 0);
|
assert(p->id() > 0);
|
||||||
|
|
||||||
@@ -160,7 +152,7 @@ void translation_unit_visitor::add_relationships(
|
|||||||
const auto *namespace_context = cls->getEnclosingNamespaceContext();
|
const auto *namespace_context = cls->getEnclosingNamespaceContext();
|
||||||
if (namespace_context != nullptr && namespace_context->isNamespace()) {
|
if (namespace_context != nullptr && namespace_context->isNamespace()) {
|
||||||
current_package_id =
|
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);
|
assert(current_package_id != 0);
|
||||||
@@ -333,8 +325,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>()), relationship_hint);
|
||||||
relationship_hint);
|
|
||||||
}
|
}
|
||||||
else if (auto *template_specialization_type =
|
else if (auto *template_specialization_type =
|
||||||
type->getAs<clang::TemplateSpecializationType>()) {
|
type->getAs<clang::TemplateSpecializationType>()) {
|
||||||
@@ -398,10 +389,11 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
|
|||||||
const auto *namespace_declaration =
|
const auto *namespace_declaration =
|
||||||
clang::cast<clang::NamespaceDecl>(namespace_context);
|
clang::cast<clang::NamespaceDecl>(namespace_context);
|
||||||
|
|
||||||
if (diagram().should_include(
|
if (namespace_declaration != nullptr &&
|
||||||
namespace_declaration->getQualifiedNameAsString())) {
|
diagram().should_include(
|
||||||
const auto target_id =
|
common::get_qualified_name(*namespace_declaration))) {
|
||||||
to_id(clang::cast<clang::NamespaceDecl>(namespace_context));
|
const auto target_id = common::to_id(
|
||||||
|
*clang::cast<clang::NamespaceDecl>(namespace_context));
|
||||||
relationships.emplace_back(target_id, relationship_hint);
|
relationships.emplace_back(target_id, relationship_hint);
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user