Fixed nested call expressions order in sequence diagrams
This commit is contained in:
@@ -214,7 +214,7 @@ void call_expression_context::enter_elseifstmt(clang::IfStmt *stmt)
|
||||
|
||||
void call_expression_context::leave_elseifstmt()
|
||||
{
|
||||
if (elseif_stmt_stack_.empty())
|
||||
if (!elseif_stmt_stack_.empty())
|
||||
elseif_stmt_stack_.pop();
|
||||
}
|
||||
|
||||
@@ -241,10 +241,30 @@ void call_expression_context::enter_loopstmt(clang::Stmt *stmt)
|
||||
|
||||
void call_expression_context::leave_loopstmt()
|
||||
{
|
||||
if (loop_stmt_stack_.empty())
|
||||
if (!loop_stmt_stack_.empty())
|
||||
return loop_stmt_stack_.pop();
|
||||
}
|
||||
|
||||
clang::CallExpr *call_expression_context::current_callexpr() const
|
||||
{
|
||||
if (call_expr_stack_.empty())
|
||||
return nullptr;
|
||||
|
||||
return call_expr_stack_.top();
|
||||
}
|
||||
|
||||
void call_expression_context::enter_callexpr(clang::CallExpr *expr)
|
||||
{
|
||||
call_expr_stack_.push(expr);
|
||||
}
|
||||
|
||||
void call_expression_context::leave_callexpr()
|
||||
{
|
||||
if (!call_expr_stack_.empty()) {
|
||||
return call_expr_stack_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
clang::Stmt *call_expression_context::current_trystmt() const
|
||||
{
|
||||
if (try_stmt_stack_.empty())
|
||||
@@ -300,7 +320,7 @@ void call_expression_context::enter_conditionaloperator(
|
||||
|
||||
void call_expression_context::leave_conditionaloperator()
|
||||
{
|
||||
if (conditional_operator_stack_.empty())
|
||||
if (!conditional_operator_stack_.empty())
|
||||
conditional_operator_stack_.pop();
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,10 @@ struct call_expression_context {
|
||||
void enter_conditionaloperator(clang::ConditionalOperator *stmt);
|
||||
void leave_conditionaloperator();
|
||||
|
||||
clang::CallExpr *current_callexpr() const;
|
||||
void enter_callexpr(clang::CallExpr *expr);
|
||||
void leave_callexpr();
|
||||
|
||||
bool is_expr_in_current_control_statement_condition(
|
||||
const clang::Stmt *stmt) const;
|
||||
|
||||
@@ -103,11 +107,12 @@ struct call_expression_context {
|
||||
clang::FunctionDecl *current_function_decl_;
|
||||
clang::FunctionTemplateDecl *current_function_template_decl_;
|
||||
|
||||
clang::CallExpr *current_function_call_expr_{nullptr};
|
||||
|
||||
private:
|
||||
std::int64_t current_caller_id_;
|
||||
std::stack<std::int64_t> current_lambda_caller_id_;
|
||||
|
||||
std::stack<clang::CallExpr *> call_expr_stack_;
|
||||
|
||||
std::stack<clang::IfStmt *> if_stmt_stack_;
|
||||
std::stack<clang::IfStmt *> elseif_stmt_stack_;
|
||||
|
||||
|
||||
@@ -528,11 +528,35 @@ bool translation_unit_visitor::TraverseLambdaExpr(clang::LambdaExpr *expr)
|
||||
|
||||
bool translation_unit_visitor::TraverseCallExpr(clang::CallExpr *expr)
|
||||
{
|
||||
context().current_function_call_expr_ = expr;
|
||||
context().enter_callexpr(expr);
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCallExpr(expr);
|
||||
|
||||
context().current_function_call_expr_ = nullptr;
|
||||
context().leave_callexpr();
|
||||
|
||||
pop_message_to_diagram(expr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseCXXMemberCallExpr(
|
||||
clang::CXXMemberCallExpr *expr)
|
||||
{
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXMemberCallExpr(
|
||||
expr);
|
||||
|
||||
pop_message_to_diagram(expr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseCXXOperatorCallExpr(
|
||||
clang::CXXOperatorCallExpr *expr)
|
||||
{
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXOperatorCallExpr(
|
||||
expr);
|
||||
|
||||
pop_message_to_diagram(expr);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -874,7 +898,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
// message source rather then enclosing context
|
||||
// Unless the lambda is declared in a function or method call
|
||||
if (context().lambda_caller_id() != 0) {
|
||||
if (context().current_function_call_expr_ == nullptr) {
|
||||
if (context().current_callexpr() == nullptr) {
|
||||
m.set_from(context().lambda_caller_id());
|
||||
}
|
||||
else {
|
||||
@@ -969,7 +993,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
LOG_DBG("Found call {} from {} [{}] to {} [{}] ", m.message_name(),
|
||||
m.from(), m.from(), m.to(), m.to());
|
||||
|
||||
diagram().get_activity(m.from()).add_message(std::move(m));
|
||||
push_message(expr, std::move(m));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2090,6 +2114,29 @@ std::string translation_unit_visitor::make_lambda_name(
|
||||
return result;
|
||||
}
|
||||
|
||||
void translation_unit_visitor::push_message(
|
||||
clang::CallExpr *expr, model::message &&m)
|
||||
{
|
||||
call_expr_message_map_.emplace(expr, std::move(m));
|
||||
}
|
||||
|
||||
void translation_unit_visitor::pop_message_to_diagram(clang::CallExpr *expr)
|
||||
{
|
||||
assert(expr != nullptr);
|
||||
|
||||
// Skip if no message was generated from this expr
|
||||
if (call_expr_message_map_.find(expr) == call_expr_message_map_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto msg = std::move(call_expr_message_map_.at(expr));
|
||||
|
||||
auto caller_id = msg.from();
|
||||
diagram().get_activity(caller_id).add_message(std::move(msg));
|
||||
|
||||
call_expr_message_map_.erase(expr);
|
||||
}
|
||||
|
||||
void translation_unit_visitor::finalize()
|
||||
{
|
||||
std::set<common::model::diagram_element::id_t> active_participants_unique;
|
||||
|
||||
@@ -46,6 +46,13 @@ public:
|
||||
|
||||
bool TraverseCallExpr(clang::CallExpr *expr);
|
||||
|
||||
bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr *expr);
|
||||
|
||||
bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr);
|
||||
|
||||
// TODO
|
||||
// bool TraverseCXXConstructExpr(clang::CXXConstructExpr *expr);
|
||||
|
||||
bool VisitLambdaExpr(clang::LambdaExpr *expr);
|
||||
|
||||
bool TraverseLambdaExpr(clang::LambdaExpr *expr);
|
||||
@@ -245,6 +252,10 @@ private:
|
||||
bool process_unresolved_lookup_call_expression(
|
||||
model::message &m, const clang::CallExpr *expr);
|
||||
|
||||
void push_message(clang::CallExpr *expr, model::message &&m);
|
||||
|
||||
void pop_message_to_diagram(clang::CallExpr *expr);
|
||||
|
||||
// Reference to the output diagram model
|
||||
clanguml::sequence_diagram::model::diagram &diagram_;
|
||||
|
||||
@@ -253,6 +264,12 @@ private:
|
||||
|
||||
call_expression_context call_expression_context_;
|
||||
|
||||
/// This is used to generate messages in proper order in case of
|
||||
/// nested call expressions (e.g. a(b(c(), d())), as they need to
|
||||
/// be added to the diagram sequence after the visitor leaves the
|
||||
/// call expression AST node
|
||||
std::map<clang::CallExpr *, model::message> call_expr_message_map_;
|
||||
|
||||
std::map<common::model::diagram_element::id_t,
|
||||
std::unique_ptr<clanguml::sequence_diagram::model::class_>>
|
||||
forward_declarations_;
|
||||
|
||||
@@ -6,23 +6,17 @@
|
||||
|
||||
namespace clanguml {
|
||||
namespace t20029 {
|
||||
using encoder_function_t = std::function<std::string(std::string &&)>;
|
||||
|
||||
std::string encode_b64(std::string &&content) { return std::move(content); }
|
||||
|
||||
template <typename T> class Encoder : public T {
|
||||
public:
|
||||
bool send(std::string &&msg)
|
||||
{
|
||||
auto encoded = encode(std::move(msg));
|
||||
return T::send(std::move(encoded));
|
||||
return T::send(std::move(encode(std::move(msg))));
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string encode(std::string &&msg) { return encode_b64(std::move(msg)); }
|
||||
|
||||
private:
|
||||
encoder_function_t f_;
|
||||
};
|
||||
|
||||
template <typename T> class Retrier : public T {
|
||||
|
||||
@@ -319,7 +319,7 @@ int main(int argc, char *argv[])
|
||||
if (returnCode != 0)
|
||||
return returnCode;
|
||||
|
||||
clanguml::util::setup_logging(debug_log);
|
||||
clanguml::util::setup_logging(debug_log ? 3 : 1);
|
||||
|
||||
return session.run();
|
||||
}
|
||||
Reference in New Issue
Block a user