Added loop statement sequence diagram support
This commit is contained in:
@@ -39,7 +39,20 @@ enum class relationship_t {
|
||||
kDependency
|
||||
};
|
||||
|
||||
enum class message_t { kCall, kReturn, kIf, kElse, kElseIf, kIfEnd };
|
||||
enum class message_t {
|
||||
kCall,
|
||||
kReturn,
|
||||
kIf,
|
||||
kElse,
|
||||
kElseIf,
|
||||
kIfEnd,
|
||||
kWhile,
|
||||
kWhileEnd,
|
||||
kDo,
|
||||
kDoEnd,
|
||||
kFor,
|
||||
kForEnd
|
||||
};
|
||||
|
||||
std::string to_string(relationship_t r);
|
||||
|
||||
|
||||
@@ -159,6 +159,24 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
||||
else if (m.type == message_t::kIfEnd) {
|
||||
ostr << "end\n";
|
||||
}
|
||||
else if (m.type == message_t::kWhile) {
|
||||
ostr << "loop\n";
|
||||
}
|
||||
else if (m.type == message_t::kWhileEnd) {
|
||||
ostr << "end\n";
|
||||
}
|
||||
else if (m.type == message_t::kFor) {
|
||||
ostr << "loop\n";
|
||||
}
|
||||
else if (m.type == message_t::kForEnd) {
|
||||
ostr << "end\n";
|
||||
}
|
||||
else if (m.type == message_t::kDo) {
|
||||
ostr << "loop\n";
|
||||
}
|
||||
else if (m.type == message_t::kDoEnd) {
|
||||
ostr << "end\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,96 @@ void diagram::print() const
|
||||
}
|
||||
}
|
||||
|
||||
void diagram::add_for_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
add_loop_stmt(current_caller_id, common::model::message_t::kFor);
|
||||
}
|
||||
|
||||
void diagram::end_for_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
end_loop_stmt(current_caller_id, common::model::message_t::kForEnd);
|
||||
}
|
||||
|
||||
void diagram::add_while_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
add_loop_stmt(current_caller_id, common::model::message_t::kWhile);
|
||||
}
|
||||
|
||||
void diagram::end_while_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
end_loop_stmt(current_caller_id, common::model::message_t::kWhileEnd);
|
||||
}
|
||||
|
||||
void diagram::add_do_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
add_loop_stmt(current_caller_id, common::model::message_t::kDo);
|
||||
}
|
||||
|
||||
void diagram::end_do_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
end_loop_stmt(current_caller_id, common::model::message_t::kDoEnd);
|
||||
}
|
||||
|
||||
void diagram::add_loop_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id,
|
||||
common::model::message_t type)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
|
||||
if (current_caller_id == 0)
|
||||
return;
|
||||
|
||||
if (sequences.find(current_caller_id) == sequences.end()) {
|
||||
activity a;
|
||||
a.from = current_caller_id;
|
||||
sequences.insert({current_caller_id, std::move(a)});
|
||||
}
|
||||
|
||||
message m;
|
||||
m.from = current_caller_id;
|
||||
m.type = type;
|
||||
|
||||
sequences[current_caller_id].messages.emplace_back(std::move(m));
|
||||
}
|
||||
|
||||
void diagram::end_loop_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id,
|
||||
common::model::message_t type)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
|
||||
if (current_caller_id == 0)
|
||||
return;
|
||||
|
||||
message m;
|
||||
m.from = current_caller_id;
|
||||
m.type = type;
|
||||
|
||||
message_t loop_type = message_t::kWhile;
|
||||
|
||||
if (type == message_t::kForEnd)
|
||||
loop_type = message_t::kFor;
|
||||
else if (type == message_t::kDoEnd)
|
||||
loop_type = message_t::kDo;
|
||||
|
||||
if (sequences.find(current_caller_id) != sequences.end()) {
|
||||
auto ¤t_messages = sequences[current_caller_id].messages;
|
||||
|
||||
if (current_messages.back().type == loop_type) {
|
||||
current_messages.pop_back();
|
||||
}
|
||||
else {
|
||||
current_messages.emplace_back(std::move(m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
@@ -102,6 +102,19 @@ public:
|
||||
participants;
|
||||
|
||||
std::set<common::model::diagram_element::id_t> active_participants_;
|
||||
|
||||
void add_loop_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id,
|
||||
common::model::message_t type);
|
||||
void end_loop_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id,
|
||||
common::model::message_t type);
|
||||
void add_while_stmt(const common::model::diagram_element::id_t i);
|
||||
void end_while_stmt(const common::model::diagram_element::id_t i);
|
||||
void add_do_stmt(const common::model::diagram_element::id_t i);
|
||||
void end_do_stmt(const common::model::diagram_element::id_t i);
|
||||
void add_for_stmt(const common::model::diagram_element::id_t i);
|
||||
void end_for_stmt(const common::model::diagram_element::id_t i);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -107,6 +107,25 @@ struct call_expression_context {
|
||||
return elseif_stmt_stack_.top();
|
||||
}
|
||||
|
||||
clang::Stmt *current_loopstmt() const
|
||||
{
|
||||
if (loop_stmt_stack_.empty())
|
||||
return nullptr;
|
||||
|
||||
return loop_stmt_stack_.top();
|
||||
}
|
||||
|
||||
void enter_loopstmt(clang::Stmt *stmt)
|
||||
{
|
||||
return loop_stmt_stack_.push(stmt);
|
||||
}
|
||||
|
||||
void leave_loopstmt()
|
||||
{
|
||||
if (loop_stmt_stack_.empty())
|
||||
return loop_stmt_stack_.pop();
|
||||
}
|
||||
|
||||
clang::CXXRecordDecl *current_class_decl_;
|
||||
clang::ClassTemplateDecl *current_class_template_decl_;
|
||||
clang::ClassTemplateSpecializationDecl
|
||||
@@ -122,6 +141,8 @@ private:
|
||||
std::stack<std::int64_t> current_lambda_caller_id_;
|
||||
std::stack<clang::IfStmt *> if_stmt_stack_;
|
||||
std::stack<clang::IfStmt *> elseif_stmt_stack_;
|
||||
|
||||
std::stack<clang::Stmt *> loop_stmt_stack_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -566,7 +566,7 @@ bool translation_unit_visitor::TraverseCompoundStmt(clang::CompoundStmt *stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(current_ifstmt != nullptr) {
|
||||
else if (current_ifstmt != nullptr) {
|
||||
if (current_ifstmt->getElse() == stmt) {
|
||||
const auto current_caller_id = context().caller_id();
|
||||
|
||||
@@ -671,6 +671,92 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseWhileStmt(clang::WhileStmt *stmt)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
|
||||
context().enter_loopstmt(stmt);
|
||||
|
||||
const auto current_caller_id = context().caller_id();
|
||||
|
||||
diagram().add_while_stmt(current_caller_id);
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseWhileStmt(stmt);
|
||||
|
||||
diagram().end_while_stmt(current_caller_id);
|
||||
|
||||
context().leave_loopstmt();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseDoStmt(clang::DoStmt *stmt)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
|
||||
context().enter_loopstmt(stmt);
|
||||
|
||||
const auto current_caller_id = context().caller_id();
|
||||
|
||||
diagram().add_do_stmt(current_caller_id);
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseDoStmt(stmt);
|
||||
|
||||
context().leave_loopstmt();
|
||||
|
||||
diagram().end_do_stmt(current_caller_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseForStmt(clang::ForStmt *stmt)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
|
||||
context().enter_loopstmt(stmt);
|
||||
|
||||
const auto current_caller_id = context().caller_id();
|
||||
|
||||
diagram().add_for_stmt(current_caller_id);
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseForStmt(stmt);
|
||||
|
||||
context().leave_loopstmt();
|
||||
|
||||
diagram().end_for_stmt(current_caller_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseCXXForRangeStmt(
|
||||
clang::CXXForRangeStmt *stmt)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
|
||||
context().enter_loopstmt(stmt);
|
||||
|
||||
const auto current_caller_id = context().caller_id();
|
||||
|
||||
diagram().add_for_stmt(current_caller_id);
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXForRangeStmt(
|
||||
stmt);
|
||||
|
||||
context().leave_loopstmt();
|
||||
|
||||
diagram().end_for_stmt(current_caller_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
|
||||
@@ -68,6 +68,14 @@ public:
|
||||
|
||||
bool TraverseIfStmt(clang::IfStmt *stmt);
|
||||
|
||||
bool TraverseWhileStmt(clang::WhileStmt *stmt);
|
||||
|
||||
bool TraverseDoStmt(clang::DoStmt *stmt);
|
||||
|
||||
bool TraverseForStmt(clang::ForStmt *stmt);
|
||||
|
||||
bool TraverseCXXForRangeStmt(clang::CXXForRangeStmt *stmt);
|
||||
|
||||
clanguml::sequence_diagram::model::diagram &diagram();
|
||||
|
||||
const clanguml::sequence_diagram::model::diagram &diagram() const;
|
||||
|
||||
Reference in New Issue
Block a user