From f07b35802aa4851538694d6c4e664e15f1ebd5aa Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Sun, 4 Dec 2022 12:42:36 +0100 Subject: [PATCH] Refactored call expression context in sequence diagram visitor --- .../visitor/call_expression_context.cc | 188 ++++++++++++++++++ .../visitor/call_expression_context.h | 86 ++++++++ .../visitor/translation_unit_visitor.cc | 35 ---- .../visitor/translation_unit_visitor.h | 168 +--------------- 4 files changed, 275 insertions(+), 202 deletions(-) create mode 100644 src/sequence_diagram/visitor/call_expression_context.cc create mode 100644 src/sequence_diagram/visitor/call_expression_context.h diff --git a/src/sequence_diagram/visitor/call_expression_context.cc b/src/sequence_diagram/visitor/call_expression_context.cc new file mode 100644 index 00000000..784db53a --- /dev/null +++ b/src/sequence_diagram/visitor/call_expression_context.cc @@ -0,0 +1,188 @@ +/** + * src/sequence_diagram/visitor/call_expression_context.cc + * + * Copyright (c) 2021-2022 Bartek Kryza + * + * 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 "call_expression_context.h" + +namespace clanguml::sequence_diagram::visitor { + +call_expression_context::call_expression_context() + : current_class_decl_{nullptr} + , current_class_template_decl_{nullptr} + , current_class_template_specialization_decl_{nullptr} + , current_method_decl_{nullptr} + , current_function_decl_{nullptr} + , current_function_template_decl_{nullptr} + , current_caller_id_{0} +{ +} + +void call_expression_context::reset() +{ + current_caller_id_ = 0; + current_class_decl_ = nullptr; + current_class_template_decl_ = nullptr; + current_class_template_specialization_decl_ = nullptr; + current_method_decl_ = nullptr; + current_function_decl_ = nullptr; + current_function_template_decl_ = nullptr; +} + +void call_expression_context::dump() +{ + LOG_DBG("current_caller_id_ = {}", current_caller_id_); + LOG_DBG("current_class_decl_ = {}", (void *)current_class_decl_); + LOG_DBG("current_class_template_decl_ = {}", + (void *)current_class_template_decl_); + LOG_DBG("current_class_template_specialization_decl_ = {}", + (void *)current_class_template_specialization_decl_); + LOG_DBG("current_method_decl_ = {}", (void *)current_method_decl_); + LOG_DBG("current_function_decl_ = {}", (void *)current_function_decl_); + LOG_DBG("current_function_template_decl_ = {}", + (void *)current_function_template_decl_); +} + +bool call_expression_context::valid() const +{ + return (current_class_decl_ != nullptr) || + (current_class_template_decl_ != nullptr) || + (current_class_template_specialization_decl_ != nullptr) || + (current_method_decl_ != nullptr) || + (current_function_decl_ != nullptr) || + (current_function_template_decl_ != nullptr); +} + +clang::ASTContext *call_expression_context::get_ast_context() +{ + if (current_class_template_specialization_decl_) + return ¤t_class_template_specialization_decl_->getASTContext(); + + if (current_class_template_decl_) + return ¤t_class_template_decl_->getASTContext(); + + if (current_class_decl_) + return ¤t_class_decl_->getASTContext(); + + if (current_function_template_decl_) + return ¤t_function_template_decl_->getASTContext(); + + return ¤t_function_decl_->getASTContext(); +} + +void call_expression_context::update(clang::CXXRecordDecl *cls) +{ + current_class_decl_ = cls; +} + +void call_expression_context::update( + clang::ClassTemplateSpecializationDecl *clst) +{ + current_class_template_specialization_decl_ = clst; +} + +void call_expression_context::update(clang::ClassTemplateDecl *clst) +{ + current_class_template_decl_ = clst; +} + +void call_expression_context::update(clang::CXXMethodDecl *method) +{ + current_method_decl_ = method; +} + +void call_expression_context::update(clang::FunctionDecl *function) +{ + if (!function->isCXXClassMember()) + reset(); + + current_function_decl_ = function; + + // Check if this function is a part of template function declaration, + // If no - reset the current_function_template_decl_ + if (current_function_template_decl_ && + current_function_template_decl_->getQualifiedNameAsString() != + function->getQualifiedNameAsString()) { + current_function_template_decl_ = nullptr; + } +} + +void call_expression_context::update( + clang::FunctionTemplateDecl *function_template) +{ + current_function_template_decl_ = function_template; + + if (!function_template->isCXXClassMember()) + current_class_decl_ = nullptr; + + current_function_template_decl_ = function_template; +} + +bool call_expression_context::in_class_method() const +{ + return current_class_decl_ != nullptr; +} + +bool call_expression_context::in_function() const +{ + return current_class_decl_ == nullptr && current_function_decl_ != nullptr; +} + +bool call_expression_context::in_function_template() const +{ + return current_function_decl_ != nullptr && + current_function_template_decl_ != nullptr; +} + +std::int64_t call_expression_context::caller_id() const +{ + return current_caller_id_; +} + +std::int64_t call_expression_context::lambda_caller_id() const +{ + if (current_lambda_caller_id_.empty()) + return 0; + + return current_lambda_caller_id_.top(); +} + +void call_expression_context::set_caller_id(std::int64_t id) +{ + LOG_DBG("Setting current caller id to {}", id); + current_caller_id_ = id; +} + +void call_expression_context::enter_lambda_expression(std::int64_t id) +{ + LOG_DBG("Setting current lambda caller id to {}", id); + + assert(id != 0); + + current_lambda_caller_id_.push(id); +} + +void call_expression_context::leave_lambda_expression() +{ + assert(!current_lambda_caller_id_.empty()); + + LOG_DBG("Leaving current lambda expression id to {}", + current_lambda_caller_id_.top()); + + current_lambda_caller_id_.pop(); +} + +} \ No newline at end of file diff --git a/src/sequence_diagram/visitor/call_expression_context.h b/src/sequence_diagram/visitor/call_expression_context.h new file mode 100644 index 00000000..7e869603 --- /dev/null +++ b/src/sequence_diagram/visitor/call_expression_context.h @@ -0,0 +1,86 @@ +/** + * src/sequence_diagram/visitor/call_expression_context.h + * + * Copyright (c) 2021-2022 Bartek Kryza + * + * 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 "common/visitor/translation_unit_visitor.h" +//#include "config/config.h" +//#include "sequence_diagram/model/diagram.h" + +#include "util/util.h" + +#include +#include +#include + +#include + +namespace clanguml::sequence_diagram::visitor { + +struct call_expression_context { + call_expression_context(); + + void reset(); + + void dump(); + + bool valid() const; + + clang::ASTContext *get_ast_context(); + + void update(clang::CXXRecordDecl *cls); + + void update(clang::ClassTemplateSpecializationDecl *clst); + + void update(clang::ClassTemplateDecl *clst); + + void update(clang::CXXMethodDecl *method); + + void update(clang::FunctionDecl *function); + + void update(clang::FunctionTemplateDecl *function_template); + + bool in_class_method() const; + + bool in_function() const; + + bool in_function_template() const; + + std::int64_t caller_id() const; + + std::int64_t lambda_caller_id() const; + + void set_caller_id(std::int64_t id); + + void enter_lambda_expression(std::int64_t id); + + void leave_lambda_expression(); + + clang::CXXRecordDecl *current_class_decl_; + clang::ClassTemplateDecl *current_class_template_decl_; + clang::ClassTemplateSpecializationDecl + *current_class_template_specialization_decl_; + clang::CXXMethodDecl *current_method_decl_; + clang::FunctionDecl *current_function_decl_; + clang::FunctionTemplateDecl *current_function_template_decl_; + +private: + std::int64_t current_caller_id_; + std::stack current_lambda_caller_id_; +}; + +} \ No newline at end of file diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.cc b/src/sequence_diagram/visitor/translation_unit_visitor.cc index 324b5d79..a813b64e 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.cc +++ b/src/sequence_diagram/visitor/translation_unit_visitor.cc @@ -1457,41 +1457,6 @@ void translation_unit_visitor::process_template_specialization_argument( cls->getLocation().dump(source_manager()); } - // else if (arg.getKind() == clang::TemplateArgument::Expression) { - // if (clang::dyn_cast(arg.getAsExpr()) != - // nullptr) { - // class_diagram::model::template_parameter argument; - //// const auto location = - //// arg.getAsType()->getAsCXXRecordDecl()->getLocation(); - //// - //// auto type_name = fmt::format("(lambda {}:{}:{})", - //// source_manager().getFilename(location).str(), - //// source_manager().getSpellingLineNumber(location), - //// source_manager().getSpellingColumnNumber(location)); - //// - //// argument.set_name(type_name); - // - // if (get_unique_id( - // arg.getAsType()->getAsCXXRecordDecl()->getID()) - // .has_value()) { - // argument.set_name(get_participant( - // get_unique_id( - // arg.getAsType()->getAsCXXRecordDecl()->getID()) - // .value()) - // .value() - // .full_name(false)); - // } - // else { - // const auto location = - // arg.getAsType()->getAsCXXRecordDecl()->getLocation(); - // auto type_name = fmt::format("(lambda {}:{}:{})", - // source_manager().getFilename(location).str(), - // source_manager().getSpellingLineNumber(location), - // source_manager().getSpellingColumnNumber(location)); - // argument.set_name(type_name); - // } - // } - // } else if (argument_kind == clang::TemplateArgument::Pack) { // This will only work for now if pack is at the end size_t argument_pack_index{argument_index}; diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.h b/src/sequence_diagram/visitor/translation_unit_visitor.h index a5223121..060d49cd 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.h +++ b/src/sequence_diagram/visitor/translation_unit_visitor.h @@ -20,6 +20,7 @@ #include "common/visitor/translation_unit_visitor.h" #include "config/config.h" #include "sequence_diagram/model/diagram.h" +#include "call_expression_context.h" #include #include @@ -31,173 +32,6 @@ namespace clanguml::sequence_diagram::visitor { std::string to_string(const clang::FunctionTemplateDecl *decl); -struct call_expression_context { - call_expression_context() - : current_class_decl_{nullptr} - , current_class_template_decl_{nullptr} - , current_class_template_specialization_decl_{nullptr} - , current_method_decl_{nullptr} - , current_function_decl_{nullptr} - , current_function_template_decl_{nullptr} - , current_caller_id_{0} - { - } - - void reset() - { - current_caller_id_ = 0; - current_class_decl_ = nullptr; - current_class_template_decl_ = nullptr; - current_class_template_specialization_decl_ = nullptr; - current_method_decl_ = nullptr; - current_function_decl_ = nullptr; - current_function_template_decl_ = nullptr; - } - - void dump() - { - LOG_DBG("current_caller_id_ = {}", current_caller_id_); - LOG_DBG("current_class_decl_ = {}", (void *)current_class_decl_); - LOG_DBG("current_class_template_decl_ = {}", - (void *)current_class_template_decl_); - LOG_DBG("current_class_template_specialization_decl_ = {}", - (void *)current_class_template_specialization_decl_); - LOG_DBG("current_method_decl_ = {}", (void *)current_method_decl_); - LOG_DBG("current_function_decl_ = {}", (void *)current_function_decl_); - LOG_DBG("current_function_template_decl_ = {}", - (void *)current_function_template_decl_); - } - - bool valid() const - { - return (current_class_decl_ != nullptr) || - (current_class_template_decl_ != nullptr) || - (current_class_template_specialization_decl_ != nullptr) || - (current_method_decl_ != nullptr) || - (current_function_decl_ != nullptr) || - (current_function_template_decl_ != nullptr); - } - - clang::ASTContext *get_ast_context() - { - if (current_class_template_specialization_decl_) - return ¤t_class_template_specialization_decl_ - ->getASTContext(); - - if (current_class_template_decl_) - return ¤t_class_template_decl_->getASTContext(); - - if (current_class_decl_) - return ¤t_class_decl_->getASTContext(); - - if (current_function_template_decl_) - return ¤t_function_template_decl_->getASTContext(); - - return ¤t_function_decl_->getASTContext(); - } - - void update(clang::CXXRecordDecl *cls) { current_class_decl_ = cls; } - - void update(clang::ClassTemplateSpecializationDecl *clst) - { - current_class_template_specialization_decl_ = clst; - } - - void update(clang::ClassTemplateDecl *clst) - { - current_class_template_decl_ = clst; - } - - void update(clang::CXXMethodDecl *method) { current_method_decl_ = method; } - - void update(clang::FunctionDecl *function) - { - if (!function->isCXXClassMember()) - reset(); - - current_function_decl_ = function; - - // Check if this function is a part of template function declaration, - // If no - reset the current_function_template_decl_ - if (current_function_template_decl_ && - current_function_template_decl_->getQualifiedNameAsString() != - function->getQualifiedNameAsString()) { - current_function_template_decl_ = nullptr; - } - } - - void update(clang::FunctionTemplateDecl *function_template) - { - current_function_template_decl_ = function_template; - - if (!function_template->isCXXClassMember()) - current_class_decl_ = nullptr; - - current_function_template_decl_ = function_template; - } - - bool in_class_method() const { return current_class_decl_ != nullptr; } - - bool in_function() const - { - return current_class_decl_ == nullptr && - current_function_decl_ != nullptr; - } - - bool in_function_template() const - { - return current_function_decl_ != nullptr && - current_function_template_decl_ != nullptr; - } - - std::int64_t caller_id() const { return current_caller_id_; } - - std::int64_t lambda_caller_id() const - { - if(current_lambda_caller_id_.empty()) - return 0; - - return current_lambda_caller_id_.top(); - } - - void set_caller_id(std::int64_t id) - { - LOG_DBG("Setting current caller id to {}", id); - current_caller_id_ = id; - } - - void enter_lambda_expression(std::int64_t id) - { - LOG_DBG("Setting current lambda caller id to {}", id); - - assert(id != 0); - - current_lambda_caller_id_.push(id); - } - - void leave_lambda_expression() - { - assert(!current_lambda_caller_id_.empty()); - - LOG_DBG("Leaving current lambda expression id to {}", - current_lambda_caller_id_.top()); - - current_lambda_caller_id_.pop(); - } - - clang::CXXRecordDecl *current_class_decl_; - clang::ClassTemplateDecl *current_class_template_decl_; - clang::ClassTemplateSpecializationDecl - *current_class_template_specialization_decl_; - clang::CXXMethodDecl *current_method_decl_; - clang::FunctionDecl *current_function_decl_; - clang::FunctionTemplateDecl *current_function_template_decl_; - -private: - std::int64_t current_caller_id_; - std::stack current_lambda_caller_id_; -}; - class translation_unit_visitor : public clang::RecursiveASTVisitor, public common::visitor::translation_unit_visitor {