Fixed else if statement generation in sequence diagrams (Fixes #81)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# CHANGELOG
|
||||
|
||||
* Fixed 'else if' statement generation in sequence diagrams (#81)
|
||||
* Implemented removal of redundant dependency relationhips (#28)
|
||||
* Add option to disable generation of dependency relation to template
|
||||
arguments (#141)
|
||||
|
||||
@@ -211,7 +211,7 @@ void generate_diagrams(const std::vector<std::string> &diagram_names,
|
||||
if (indicator)
|
||||
indicator->complete(name);
|
||||
}
|
||||
catch (std::runtime_error &e) {
|
||||
catch (std::exception &e) {
|
||||
if (indicator)
|
||||
indicator->fail(name);
|
||||
|
||||
|
||||
@@ -181,22 +181,27 @@ void call_expression_context::enter_ifstmt(clang::IfStmt *stmt)
|
||||
void call_expression_context::leave_ifstmt()
|
||||
{
|
||||
if (!if_stmt_stack_.empty()) {
|
||||
elseif_stmt_stacks_.erase(current_ifstmt());
|
||||
if_stmt_stack_.pop();
|
||||
std::stack<clang::IfStmt *>{}.swap(elseif_stmt_stack_);
|
||||
}
|
||||
}
|
||||
|
||||
void call_expression_context::enter_elseifstmt(clang::IfStmt *stmt)
|
||||
{
|
||||
elseif_stmt_stack_.push(stmt);
|
||||
assert(current_ifstmt() != nullptr);
|
||||
|
||||
elseif_stmt_stacks_[current_ifstmt()].push(stmt);
|
||||
}
|
||||
|
||||
clang::IfStmt *call_expression_context::current_elseifstmt() const
|
||||
{
|
||||
if (elseif_stmt_stack_.empty())
|
||||
assert(current_ifstmt() != nullptr);
|
||||
|
||||
if (elseif_stmt_stacks_.count(current_ifstmt()) == 0 ||
|
||||
elseif_stmt_stacks_.at(current_ifstmt()).empty())
|
||||
return nullptr;
|
||||
|
||||
return elseif_stmt_stack_.top();
|
||||
return elseif_stmt_stacks_.at(current_ifstmt()).top();
|
||||
}
|
||||
|
||||
clang::Stmt *call_expression_context::current_loopstmt() const
|
||||
@@ -315,11 +320,11 @@ bool call_expression_context::is_expr_in_current_control_statement_condition(
|
||||
if (common::is_subexpr_of(condition_decl_stmt, stmt))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_elseifstmt() != nullptr) {
|
||||
if (common::is_subexpr_of(current_elseifstmt()->getCond(), stmt))
|
||||
return true;
|
||||
if (current_elseifstmt() != nullptr) {
|
||||
if (common::is_subexpr_of(current_elseifstmt()->getCond(), stmt))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_conditionaloperator() != nullptr) {
|
||||
|
||||
@@ -321,7 +321,7 @@ private:
|
||||
std::stack<callexpr_stack_t> call_expr_stack_;
|
||||
|
||||
std::stack<clang::IfStmt *> if_stmt_stack_;
|
||||
std::stack<clang::IfStmt *> elseif_stmt_stack_;
|
||||
std::map<clang::IfStmt *, std::stack<clang::IfStmt *>> elseif_stmt_stacks_;
|
||||
|
||||
std::stack<clang::Stmt *> loop_stmt_stack_;
|
||||
std::stack<clang::Stmt *> try_stmt_stack_;
|
||||
|
||||
@@ -539,7 +539,8 @@ bool translation_unit_visitor::TraverseCompoundStmt(clang::CompoundStmt *stmt)
|
||||
return true;
|
||||
|
||||
const auto *current_ifstmt = context().current_ifstmt();
|
||||
const auto *current_elseifstmt = context().current_elseifstmt();
|
||||
const auto *current_elseifstmt =
|
||||
current_ifstmt != nullptr ? context().current_elseifstmt() : nullptr;
|
||||
|
||||
//
|
||||
// Add final else block (not else if)
|
||||
@@ -583,6 +584,8 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
|
||||
|
||||
const auto current_caller_id = context().caller_id();
|
||||
const auto *current_ifstmt = context().current_ifstmt();
|
||||
const auto *current_elseifstmt =
|
||||
current_ifstmt != nullptr ? context().current_elseifstmt() : nullptr;
|
||||
|
||||
std::string condition_text;
|
||||
if (config().generate_condition_statements())
|
||||
@@ -590,14 +593,18 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
|
||||
|
||||
// Check if this is a beginning of a new if statement, or an
|
||||
// else if condition of the current if statement
|
||||
if (current_ifstmt != nullptr) {
|
||||
for (const auto *child_stmt : current_ifstmt->children()) {
|
||||
if (child_stmt == stmt) {
|
||||
elseif_block = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto child_stmt_compare = [stmt](auto *child_stmt) {
|
||||
return child_stmt == stmt;
|
||||
};
|
||||
|
||||
if (current_ifstmt != nullptr)
|
||||
elseif_block = elseif_block ||
|
||||
std::any_of(current_ifstmt->children().begin(),
|
||||
current_ifstmt->children().end(), child_stmt_compare);
|
||||
if (current_elseifstmt != nullptr)
|
||||
elseif_block = elseif_block ||
|
||||
std::any_of(current_elseifstmt->children().begin(),
|
||||
current_elseifstmt->children().end(), child_stmt_compare);
|
||||
|
||||
if ((current_caller_id != 0) && !stmt->isConstexpr()) {
|
||||
if (elseif_block) {
|
||||
@@ -620,10 +627,12 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseIfStmt(stmt);
|
||||
|
||||
if ((current_caller_id != 0) && !stmt->isConstexpr() && !elseif_block) {
|
||||
diagram().end_block_message(
|
||||
{message_t::kIfEnd, current_caller_id}, message_t::kIf);
|
||||
context().leave_ifstmt();
|
||||
if ((current_caller_id != 0) && !stmt->isConstexpr()) {
|
||||
if (!elseif_block) {
|
||||
diagram().end_block_message(
|
||||
{message_t::kIfEnd, current_caller_id}, message_t::kIf);
|
||||
context().leave_ifstmt();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -8,6 +8,7 @@ struct A {
|
||||
int a2() { return 1; }
|
||||
int a3() { return 2; }
|
||||
int a4() { return 3; }
|
||||
int a5() { return 4; }
|
||||
};
|
||||
|
||||
struct B {
|
||||
@@ -48,6 +49,9 @@ int tmain()
|
||||
if (reinterpret_cast<uint64_t>(&a) % 100 == 0ULL) {
|
||||
result = a.a1();
|
||||
}
|
||||
else if (reinterpret_cast<uint64_t>(&a) % 100 == 42ULL) {
|
||||
result = a.a5();
|
||||
}
|
||||
else if (reinterpret_cast<uint64_t>(&a) % 64 == 0ULL) {
|
||||
if (c.c3(a.a2()) > 2)
|
||||
result = b.b1();
|
||||
|
||||
@@ -63,6 +63,7 @@ TEST_CASE("t20020", "[test-case][sequence]")
|
||||
using namespace json;
|
||||
|
||||
std::vector<int> messages = {FindMessage(j, "tmain()", "A", "a1()"),
|
||||
FindMessage(j, "tmain()", "A", "a5()"),
|
||||
FindMessage(j, "tmain()", "A", "a2()"),
|
||||
FindMessage(j, "tmain()", "C", "c3(int)"),
|
||||
FindMessage(j, "tmain()", "B", "b1()"),
|
||||
|
||||
@@ -10,4 +10,4 @@ plantuml:
|
||||
before:
|
||||
- 'title clang-uml clanguml::class_diagram::generators::plantuml::generator sequence diagram'
|
||||
start_from:
|
||||
- function: "clanguml::class_diagram::generators::plantuml::generator::generate(std::ostream &) const"
|
||||
- function: "clanguml::common::generators::plantuml::generator<clanguml::config::class_diagram,clanguml::class_diagram::model::diagram>::generate(std::ostream &) const"
|
||||
Reference in New Issue
Block a user