Added support for try/catch statements in sequence diagrams
This commit is contained in:
@@ -94,6 +94,12 @@ std::string to_string(message_t r)
|
||||
return "for";
|
||||
case message_t::kForEnd:
|
||||
return "end for";
|
||||
case message_t::kTry:
|
||||
return "try";
|
||||
case message_t::kCatch:
|
||||
return "catch";
|
||||
case message_t::kTryEnd:
|
||||
return "end try";
|
||||
default:
|
||||
assert(false);
|
||||
return "";
|
||||
|
||||
@@ -53,6 +53,9 @@ enum class message_t {
|
||||
kDoEnd,
|
||||
kFor,
|
||||
kForEnd,
|
||||
kTry,
|
||||
kCatch,
|
||||
kTryEnd,
|
||||
kNone
|
||||
};
|
||||
|
||||
|
||||
@@ -190,6 +190,15 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
||||
else if (m.type() == message_t::kDoEnd) {
|
||||
ostr << "end\n";
|
||||
}
|
||||
else if (m.type() == message_t::kTry) {
|
||||
ostr << "group try\n";
|
||||
}
|
||||
else if (m.type() == message_t::kCatch) {
|
||||
ostr << "else " << m.message_name() << '\n';
|
||||
}
|
||||
else if (m.type() == message_t::kTryEnd) {
|
||||
ostr << "end\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -224,6 +224,55 @@ void diagram::end_if_stmt(
|
||||
}
|
||||
}
|
||||
|
||||
void diagram::add_try_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
|
||||
if (sequences_.find(current_caller_id) == sequences_.end()) {
|
||||
activity a{current_caller_id};
|
||||
sequences_.insert({current_caller_id, std::move(a)});
|
||||
}
|
||||
|
||||
get_activity(current_caller_id)
|
||||
.add_message({message_t::kTry, current_caller_id});
|
||||
}
|
||||
|
||||
void diagram::end_try_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
|
||||
message m{message_t::kTryEnd, current_caller_id};
|
||||
|
||||
if (sequences_.find(current_caller_id) != sequences_.end()) {
|
||||
auto ¤t_messages = get_activity(current_caller_id).messages();
|
||||
|
||||
if (current_messages.back().type() == message_t::kTry) {
|
||||
current_messages.pop_back();
|
||||
}
|
||||
else {
|
||||
current_messages.emplace_back(std::move(m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void diagram::add_catch_stmt(
|
||||
const int64_t current_caller_id, std::string caught_type)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
|
||||
if (sequences_.find(current_caller_id) == sequences_.end()) {
|
||||
activity a{current_caller_id};
|
||||
sequences_.insert({current_caller_id, std::move(a)});
|
||||
}
|
||||
|
||||
message m{message_t::kCatch, current_caller_id};
|
||||
m.set_message_name(std::move(caught_type));
|
||||
|
||||
get_activity(current_caller_id).add_message(std::move(m));
|
||||
}
|
||||
|
||||
bool diagram::started() const { return started_; }
|
||||
|
||||
void diagram::started(bool s) { started_ = s; }
|
||||
@@ -255,13 +304,13 @@ diagram::participants() const
|
||||
std::set<common::model::diagram_element::id_t> &diagram::active_participants()
|
||||
{
|
||||
return active_participants_;
|
||||
};
|
||||
}
|
||||
|
||||
const std::set<common::model::diagram_element::id_t> &
|
||||
diagram::active_participants() const
|
||||
{
|
||||
return active_participants_;
|
||||
};
|
||||
}
|
||||
|
||||
void diagram::print() const
|
||||
{
|
||||
@@ -305,7 +354,6 @@ void diagram::print() const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
@@ -85,6 +85,9 @@ public:
|
||||
void end_if_stmt(common::model::diagram_element::id_t current_caller_id,
|
||||
common::model::message_t type);
|
||||
|
||||
void add_try_stmt(common::model::diagram_element::id_t current_caller_id);
|
||||
void end_try_stmt(common::model::diagram_element::id_t current_caller_id);
|
||||
|
||||
void add_loop_stmt(common::model::diagram_element::id_t current_caller_id,
|
||||
common::model::message_t type);
|
||||
void end_loop_stmt(common::model::diagram_element::id_t current_caller_id,
|
||||
@@ -119,6 +122,10 @@ public:
|
||||
const std::set<common::model::diagram_element::id_t> &
|
||||
active_participants() const;
|
||||
|
||||
void add_catch_stmt(
|
||||
const common::model::diagram_element::id_t current_caller_id,
|
||||
std::string caught_type);
|
||||
|
||||
private:
|
||||
bool started_{false};
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ clang::IfStmt *call_expression_context::current_ifstmt() const
|
||||
|
||||
void call_expression_context::enter_ifstmt(clang::IfStmt *stmt)
|
||||
{
|
||||
return if_stmt_stack_.push(stmt);
|
||||
if_stmt_stack_.push(stmt);
|
||||
}
|
||||
|
||||
void call_expression_context::leave_ifstmt()
|
||||
@@ -209,13 +209,13 @@ void call_expression_context::leave_ifstmt()
|
||||
|
||||
void call_expression_context::enter_elseifstmt(clang::IfStmt *stmt)
|
||||
{
|
||||
return elseif_stmt_stack_.push(stmt);
|
||||
elseif_stmt_stack_.push(stmt);
|
||||
}
|
||||
|
||||
void call_expression_context::leave_elseifstmt()
|
||||
{
|
||||
if (elseif_stmt_stack_.empty())
|
||||
return elseif_stmt_stack_.pop();
|
||||
elseif_stmt_stack_.pop();
|
||||
}
|
||||
|
||||
clang::IfStmt *call_expression_context::current_elseifstmt() const
|
||||
@@ -236,7 +236,7 @@ clang::Stmt *call_expression_context::current_loopstmt() const
|
||||
|
||||
void call_expression_context::enter_loopstmt(clang::Stmt *stmt)
|
||||
{
|
||||
return loop_stmt_stack_.push(stmt);
|
||||
loop_stmt_stack_.push(stmt);
|
||||
}
|
||||
|
||||
void call_expression_context::leave_loopstmt()
|
||||
@@ -245,6 +245,25 @@ void call_expression_context::leave_loopstmt()
|
||||
return loop_stmt_stack_.pop();
|
||||
}
|
||||
|
||||
clang::Stmt *call_expression_context::current_trystmt() const
|
||||
{
|
||||
if (try_stmt_stack_.empty())
|
||||
return nullptr;
|
||||
|
||||
return try_stmt_stack_.top();
|
||||
}
|
||||
|
||||
void call_expression_context::enter_trystmt(clang::Stmt *stmt)
|
||||
{
|
||||
try_stmt_stack_.push(stmt);
|
||||
}
|
||||
|
||||
void call_expression_context::leave_trystmt()
|
||||
{
|
||||
if (try_stmt_stack_.empty())
|
||||
try_stmt_stack_.pop();
|
||||
}
|
||||
|
||||
bool call_expression_context::is_expr_in_current_control_statement_condition(
|
||||
const clang::Stmt *stmt) const
|
||||
{
|
||||
|
||||
@@ -74,13 +74,16 @@ struct call_expression_context {
|
||||
|
||||
void enter_elseifstmt(clang::IfStmt *stmt);
|
||||
void leave_elseifstmt();
|
||||
|
||||
clang::IfStmt *current_elseifstmt() const;
|
||||
clang::Stmt *current_loopstmt() const;
|
||||
|
||||
clang::Stmt *current_loopstmt() const;
|
||||
void enter_loopstmt(clang::Stmt *stmt);
|
||||
void leave_loopstmt();
|
||||
|
||||
clang::Stmt *current_trystmt() const;
|
||||
void enter_trystmt(clang::Stmt *stmt);
|
||||
void leave_trystmt();
|
||||
|
||||
bool is_expr_in_current_control_statement_condition(
|
||||
const clang::Stmt *stmt) const;
|
||||
|
||||
@@ -101,6 +104,7 @@ private:
|
||||
std::stack<clang::IfStmt *> elseif_stmt_stack_;
|
||||
|
||||
std::stack<clang::Stmt *> loop_stmt_stack_;
|
||||
std::stack<clang::Stmt *> try_stmt_stack_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -705,6 +705,53 @@ bool translation_unit_visitor::TraverseForStmt(clang::ForStmt *stmt)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseCXXTryStmt(clang::CXXTryStmt *stmt)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
|
||||
const auto current_caller_id = context().caller_id();
|
||||
|
||||
if (current_caller_id) {
|
||||
context().enter_trystmt(stmt);
|
||||
diagram().add_try_stmt(current_caller_id);
|
||||
}
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXTryStmt(stmt);
|
||||
|
||||
if (current_caller_id) {
|
||||
context().leave_trystmt();
|
||||
diagram().end_try_stmt(current_caller_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseCXXCatchStmt(clang::CXXCatchStmt *stmt)
|
||||
{
|
||||
using clanguml::common::model::message_t;
|
||||
using clanguml::sequence_diagram::model::activity;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
|
||||
const auto current_caller_id = context().caller_id();
|
||||
|
||||
if (current_caller_id && context().current_trystmt()) {
|
||||
std::string caught_type;
|
||||
if (stmt->getCaughtType().isNull())
|
||||
caught_type = "...";
|
||||
else
|
||||
caught_type = common::to_string(
|
||||
stmt->getCaughtType(), *context().get_ast_context());
|
||||
|
||||
diagram().add_catch_stmt(current_caller_id, std::move(caught_type));
|
||||
}
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXCatchStmt(stmt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseCXXForRangeStmt(
|
||||
clang::CXXForRangeStmt *stmt)
|
||||
{
|
||||
|
||||
@@ -76,6 +76,10 @@ public:
|
||||
|
||||
bool TraverseCXXForRangeStmt(clang::CXXForRangeStmt *stmt);
|
||||
|
||||
bool TraverseCXXTryStmt(clang::CXXTryStmt *stmt);
|
||||
|
||||
bool TraverseCXXCatchStmt(clang::CXXCatchStmt *stmt);
|
||||
|
||||
clanguml::sequence_diagram::model::diagram &diagram();
|
||||
|
||||
const clanguml::sequence_diagram::model::diagram &diagram() const;
|
||||
|
||||
Reference in New Issue
Block a user