Fixed handling of nested lambda expressions in sequence diagrams
This commit is contained in:
@@ -132,6 +132,9 @@ void call_expression_context::update(
|
||||
|
||||
std::int64_t call_expression_context::caller_id() const
|
||||
{
|
||||
if (lambda_caller_id() != 0)
|
||||
return lambda_caller_id();
|
||||
|
||||
return current_caller_id_;
|
||||
}
|
||||
|
||||
|
||||
@@ -455,8 +455,10 @@ bool translation_unit_visitor::VisitLambdaExpr(clang::LambdaExpr *expr)
|
||||
lambda_method_model_ptr->set_method_name(method_name);
|
||||
|
||||
lambda_method_model_ptr->set_class_id(cls_id);
|
||||
lambda_method_model_ptr->set_class_full_name(
|
||||
lambda_class_model_ptr->full_name(false));
|
||||
|
||||
// If this is a nested lambda, prepend the parent lambda name to this lambda
|
||||
auto lambda_class_full_name = lambda_class_model_ptr->full_name(false);
|
||||
lambda_method_model_ptr->set_class_full_name(lambda_class_full_name);
|
||||
|
||||
diagram().add_participant(std::move(lambda_class_model_ptr));
|
||||
|
||||
@@ -469,9 +471,8 @@ bool translation_unit_visitor::VisitLambdaExpr(clang::LambdaExpr *expr)
|
||||
// If lambda expression is in an argument to a method/function, and that
|
||||
// method function would be excluded by filters
|
||||
if (std::holds_alternative<clang::CallExpr *>(
|
||||
context().current_callexpr())/* &&
|
||||
!should_include(
|
||||
std::get<clang::CallExpr *>(context().current_callexpr()))*/) {
|
||||
context().current_callexpr()) &&
|
||||
(context().lambda_caller_id() == 0)) {
|
||||
using clanguml::common::model::message_t;
|
||||
using clanguml::sequence_diagram::model::message;
|
||||
|
||||
@@ -504,9 +505,6 @@ bool translation_unit_visitor::VisitLambdaExpr(clang::LambdaExpr *expr)
|
||||
|
||||
bool translation_unit_visitor::TraverseLambdaExpr(clang::LambdaExpr *expr)
|
||||
{
|
||||
const auto lambda_full_name =
|
||||
expr->getLambdaClass()->getCanonicalDecl()->getNameAsString();
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseLambdaExpr(expr);
|
||||
|
||||
// lambda context is entered inside the visitor
|
||||
@@ -543,10 +541,8 @@ bool translation_unit_visitor::TraverseCXXMemberCallExpr(
|
||||
if (source_manager().isInSystemHeader(expr->getSourceRange().getBegin()))
|
||||
return true;
|
||||
|
||||
LOG_DBG("Entering member call expression at {} to {}::{}",
|
||||
expr->getBeginLoc().printToString(source_manager()),
|
||||
common::to_string(expr->getObjectType(), context().get_ast_context()),
|
||||
common::to_string(expr->getMethodDecl()));
|
||||
LOG_DBG("Entering member call expression at {}",
|
||||
expr->getBeginLoc().printToString(source_manager()));
|
||||
|
||||
context().enter_callexpr(expr);
|
||||
|
||||
@@ -599,6 +595,9 @@ bool translation_unit_visitor::TraverseCXXTemporaryObjectExpr(
|
||||
bool translation_unit_visitor::TraverseCXXConstructExpr(
|
||||
clang::CXXConstructExpr *expr)
|
||||
{
|
||||
LOG_DBG("Entering cxx construct call expression at {}",
|
||||
expr->getBeginLoc().printToString(source_manager()));
|
||||
|
||||
context().enter_callexpr(expr);
|
||||
|
||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCXXConstructExpr(
|
||||
@@ -606,6 +605,9 @@ bool translation_unit_visitor::TraverseCXXConstructExpr(
|
||||
|
||||
translation_unit_visitor::VisitCXXConstructExpr(expr);
|
||||
|
||||
LOG_DBG("Leaving member call expression at {}",
|
||||
expr->getBeginLoc().printToString(source_manager()));
|
||||
|
||||
context().leave_callexpr();
|
||||
|
||||
pop_message_to_diagram(expr);
|
||||
@@ -1057,13 +1059,6 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
if (!generated_message_from_comment && !should_include(expr))
|
||||
return true;
|
||||
|
||||
// If we're currently inside a lambda expression, set it's id as
|
||||
// message source rather then enclosing context
|
||||
// Unless the lambda is declared in a function or method call
|
||||
if (context().lambda_caller_id() != 0) {
|
||||
m.set_from(context().lambda_caller_id());
|
||||
}
|
||||
|
||||
if (context().is_expr_in_current_control_statement_condition(expr)) {
|
||||
m.set_message_scope(common::model::message_scope_t::kCondition);
|
||||
}
|
||||
@@ -1100,9 +1095,12 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
if (callee_decl == nullptr) {
|
||||
LOG_DBG("Cannot get callee declaration - trying direct function "
|
||||
"callee...");
|
||||
|
||||
callee_decl = expr->getDirectCallee();
|
||||
LOG_DBG(
|
||||
"Found function/method callee in: {}", common::to_string(expr));
|
||||
|
||||
if (callee_decl != nullptr)
|
||||
LOG_DBG("Found function/method callee in: {}",
|
||||
common::to_string(expr));
|
||||
}
|
||||
|
||||
if (callee_decl == nullptr) {
|
||||
@@ -1124,6 +1122,17 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
if (!process_unresolved_lookup_call_expression(m, expr))
|
||||
return true;
|
||||
}
|
||||
else if (clang::dyn_cast_or_null<clang::LambdaExpr>(
|
||||
expr->getCallee()) != nullptr) {
|
||||
LOG_DBG("Processing lambda expression callee");
|
||||
if (!process_lambda_call_expression(m, expr))
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LOG_DBG("Found unsupported callee decl type for: {} at {}",
|
||||
common::to_string(expr),
|
||||
expr->getBeginLoc().printToString(source_manager()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto success = process_function_call_expression(m, expr);
|
||||
@@ -1219,10 +1228,6 @@ bool translation_unit_visitor::VisitCXXConstructExpr(
|
||||
|
||||
set_source_location(*expr, m);
|
||||
|
||||
if (context().lambda_caller_id() != 0) {
|
||||
m.set_from(context().lambda_caller_id());
|
||||
}
|
||||
|
||||
if (context().is_expr_in_current_control_statement_condition(expr)) {
|
||||
m.set_message_scope(common::model::message_scope_t::kCondition);
|
||||
}
|
||||
@@ -1487,6 +1492,26 @@ bool translation_unit_visitor::process_function_call_expression(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::process_lambda_call_expression(
|
||||
model::message &m, const clang::CallExpr *expr) const
|
||||
{
|
||||
const auto *lambda_expr =
|
||||
clang::dyn_cast_or_null<clang::LambdaExpr>(expr->getCallee());
|
||||
|
||||
if (lambda_expr == nullptr)
|
||||
return true;
|
||||
|
||||
const auto lambda_class_id = lambda_expr->getLambdaClass()->getID();
|
||||
const auto maybe_id = get_unique_id(lambda_class_id);
|
||||
if (!maybe_id.has_value())
|
||||
m.set_to(lambda_class_id);
|
||||
else {
|
||||
m.set_to(maybe_id.value());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::process_unresolved_lookup_call_expression(
|
||||
model::message &m, const clang::CallExpr *expr) const
|
||||
{
|
||||
@@ -1498,7 +1523,6 @@ bool translation_unit_visitor::process_unresolved_lookup_call_expression(
|
||||
for (const auto *decl : unresolved_expr->decls()) {
|
||||
if (clang::dyn_cast_or_null<clang::FunctionTemplateDecl>(decl) !=
|
||||
nullptr) {
|
||||
// Yes, it's a template
|
||||
const auto *ftd =
|
||||
clang::dyn_cast_or_null<clang::FunctionTemplateDecl>(decl);
|
||||
|
||||
@@ -1511,6 +1535,23 @@ bool translation_unit_visitor::process_unresolved_lookup_call_expression(
|
||||
|
||||
break;
|
||||
}
|
||||
else if (clang::dyn_cast_or_null<clang::FunctionDecl>(decl) !=
|
||||
nullptr) {
|
||||
const auto *fd =
|
||||
clang::dyn_cast_or_null<clang::FunctionDecl>(decl);
|
||||
|
||||
const auto maybe_id = get_unique_id(fd->getID());
|
||||
if (!maybe_id.has_value())
|
||||
m.set_to(fd->getID());
|
||||
else {
|
||||
m.set_to(maybe_id.value());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
LOG_DBG("Unknown unresolved lookup expression");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,9 +1609,10 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls)
|
||||
const auto *parent = cls->getParent();
|
||||
|
||||
if ((parent != nullptr) && parent->isRecord()) {
|
||||
// Here we have 2 options, either:
|
||||
// Here we have 3 options, either:
|
||||
// - the parent is a regular C++ class/struct
|
||||
// - the parent is a class template declaration/specialization
|
||||
// - the parent is a lambda (i.e. this is a nested lambda expression)
|
||||
std::optional<common::id_t> id_opt;
|
||||
const auto *parent_record_decl =
|
||||
clang::dyn_cast<clang::RecordDecl>(parent);
|
||||
@@ -1817,7 +1859,31 @@ std::string translation_unit_visitor::make_lambda_name(
|
||||
const auto location = cls->getLocation();
|
||||
const std::string source_location{lambda_source_location(location)};
|
||||
|
||||
if (context().caller_id() != 0 &&
|
||||
if (context().lambda_caller_id() != 0) {
|
||||
// Parent is also a lambda (this id points to a lambda operator())
|
||||
std::string parent_lambda_class_name{"()"};
|
||||
if (diagram().get_participant<model::method>(
|
||||
context().lambda_caller_id())) {
|
||||
auto parent_lambda_class_id = diagram()
|
||||
.get_participant<model::method>(
|
||||
context().lambda_caller_id())
|
||||
.value()
|
||||
.class_id();
|
||||
|
||||
if (diagram().get_participant<model::class_>(
|
||||
parent_lambda_class_id)) {
|
||||
parent_lambda_class_name =
|
||||
diagram()
|
||||
.get_participant<model::class_>(parent_lambda_class_id)
|
||||
.value()
|
||||
.full_name(false);
|
||||
}
|
||||
}
|
||||
|
||||
result = fmt::format(
|
||||
"{}##(lambda {})", parent_lambda_class_name, source_location);
|
||||
}
|
||||
else if (context().caller_id() != 0 &&
|
||||
get_participant(context().caller_id()).has_value()) {
|
||||
auto parent_full_name =
|
||||
get_participant(context().caller_id()).value().full_name_no_ns();
|
||||
|
||||
@@ -436,6 +436,9 @@ private:
|
||||
bool process_unresolved_lookup_call_expression(
|
||||
model::message &m, const clang::CallExpr *expr) const;
|
||||
|
||||
bool process_lambda_call_expression(
|
||||
model::message &m, const clang::CallExpr *expr) const;
|
||||
|
||||
/**
|
||||
* @brief Register a message model `m` with a call expression
|
||||
*
|
||||
|
||||
13
tests/t20045/.clang-uml
Normal file
13
tests/t20045/.clang-uml
Normal file
@@ -0,0 +1,13 @@
|
||||
add_compile_flags:
|
||||
- -fparse-all-comments
|
||||
diagrams:
|
||||
t20045_sequence:
|
||||
type: sequence
|
||||
glob:
|
||||
- t20045.cc
|
||||
include:
|
||||
namespaces:
|
||||
- clanguml::t20045
|
||||
using_namespace: clanguml::t20045
|
||||
from:
|
||||
- function: "clanguml::t20045::tmain()"
|
||||
47
tests/t20045/t20045.cc
Normal file
47
tests/t20045/t20045.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
namespace clanguml {
|
||||
namespace t20045 {
|
||||
|
||||
template <typename F> int a1(F &&f) { return f(42); }
|
||||
|
||||
int a2(int x) { return 2; }
|
||||
|
||||
int a3(int x) { return 3; }
|
||||
|
||||
struct B {
|
||||
int b1(int x) { return x + 1; }
|
||||
int b2(int x) { return x + 2; }
|
||||
};
|
||||
|
||||
class C {
|
||||
public:
|
||||
explicit C(int x)
|
||||
: x_{x}
|
||||
{
|
||||
}
|
||||
|
||||
int get_x() const { return x_; }
|
||||
|
||||
private:
|
||||
int x_;
|
||||
};
|
||||
|
||||
int tmain()
|
||||
{
|
||||
B b;
|
||||
|
||||
// \uml{call clanguml::t20045::a2(int)}
|
||||
auto v1 = a1(a2);
|
||||
|
||||
auto v2 = a1([](auto &&arg) { return a3(arg); });
|
||||
|
||||
auto v3 = a1([&](auto &&arg) { return b.b1(arg); });
|
||||
|
||||
auto v4 = a1([](auto &&arg) {
|
||||
C c(arg);
|
||||
return c.get_x();
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
82
tests/t20045/test_case.h
Normal file
82
tests/t20045/test_case.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* tests/t20045/test_case.h
|
||||
*
|
||||
* Copyright (c) 2021-2024 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
TEST_CASE("t20045", "[test-case][sequence]")
|
||||
{
|
||||
auto [config, db] = load_config("t20045");
|
||||
|
||||
auto diagram = config.diagrams["t20045_sequence"];
|
||||
|
||||
REQUIRE(diagram->name == "t20045_sequence");
|
||||
|
||||
auto model = generate_sequence_diagram(*db, diagram);
|
||||
|
||||
REQUIRE(model->name() == "t20045_sequence");
|
||||
|
||||
{
|
||||
auto src = generate_sequence_puml(diagram, *model);
|
||||
AliasMatcher _A(src);
|
||||
|
||||
REQUIRE_THAT(src, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(src, EndsWith("@enduml\n"));
|
||||
|
||||
REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a2(int)"), ""));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("tmain()"),
|
||||
_A("a1<(lambda at t20045.cc:35:18)>((lambda at "
|
||||
"t20045.cc:35:18) &&)"),
|
||||
""));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("a1<(lambda at t20045.cc:35:18)>((lambda at "
|
||||
"t20045.cc:35:18) &&)"),
|
||||
_A("tmain()::(lambda t20045.cc:35:18)"), "operator()()"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(
|
||||
_A("tmain()::(lambda t20045.cc:35:18)"), _A("a3(int)"), ""));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(
|
||||
_A("tmain()::(lambda t20045.cc:37:18)"), _A("B"), "b1(int)"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(
|
||||
_A("tmain()::(lambda t20045.cc:39:18)"), _A("C"), "get_x()"));
|
||||
|
||||
save_puml(config.output_directory(), diagram->name + ".puml", src);
|
||||
}
|
||||
|
||||
{
|
||||
auto j = generate_sequence_json(diagram, *model);
|
||||
|
||||
using namespace json;
|
||||
|
||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||
}
|
||||
|
||||
{
|
||||
auto src = generate_sequence_mermaid(diagram, *model);
|
||||
|
||||
mermaid::AliasMatcher _A(src);
|
||||
using mermaid::IsClass;
|
||||
|
||||
save_mermaid(config.output_directory(), diagram->name + ".mmd", src);
|
||||
}
|
||||
}
|
||||
13
tests/t20046/.clang-uml
Normal file
13
tests/t20046/.clang-uml
Normal file
@@ -0,0 +1,13 @@
|
||||
add_compile_flags:
|
||||
- -fparse-all-comments
|
||||
diagrams:
|
||||
t20046_sequence:
|
||||
type: sequence
|
||||
glob:
|
||||
- t20046.cc
|
||||
include:
|
||||
namespaces:
|
||||
- clanguml::t20046
|
||||
using_namespace: clanguml::t20046
|
||||
from:
|
||||
- function: "clanguml::t20046::tmain()"
|
||||
24
tests/t20046/t20046.cc
Normal file
24
tests/t20046/t20046.cc
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace clanguml {
|
||||
namespace t20046 {
|
||||
|
||||
template <typename F> int a1(F &&f) { return f(42); }
|
||||
|
||||
int a2(int x) { return 2; }
|
||||
|
||||
int a3(int x) { return 3; }
|
||||
|
||||
int tmain()
|
||||
{
|
||||
// Call expression in a nested lambda
|
||||
auto v1 = [](auto &&arg1) {
|
||||
return [](auto &&arg2) { return a2(arg2); }(arg1);
|
||||
}(0);
|
||||
|
||||
// Call expression in a nested lambda in call expression
|
||||
auto v4 = a1(
|
||||
[](auto &&arg1) { return [](auto &&arg2) { return a3(arg2); }(arg1); });
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
94
tests/t20046/test_case.h
Normal file
94
tests/t20046/test_case.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* tests/t20046/test_case.h
|
||||
*
|
||||
* Copyright (c) 2021-2024 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
TEST_CASE("t20046", "[test-case][sequence]")
|
||||
{
|
||||
auto [config, db] = load_config("t20046");
|
||||
|
||||
auto diagram = config.diagrams["t20046_sequence"];
|
||||
|
||||
REQUIRE(diagram->name == "t20046_sequence");
|
||||
|
||||
auto model = generate_sequence_diagram(*db, diagram);
|
||||
|
||||
REQUIRE(model->name() == "t20046_sequence");
|
||||
|
||||
{
|
||||
auto src = generate_sequence_puml(diagram, *model);
|
||||
AliasMatcher _A(src);
|
||||
|
||||
REQUIRE_THAT(src, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(src, EndsWith("@enduml\n"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("tmain()"), _A("tmain()::(lambda t20046.cc:13:15)"),
|
||||
"operator()()"));
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("tmain()::(lambda t20046.cc:13:15)"),
|
||||
_A("tmain()::(lambda t20046.cc:13:15)::(lambda "
|
||||
"t20046.cc:14:16)"),
|
||||
"operator()()"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("tmain()::(lambda t20046.cc:13:15)::(lambda "
|
||||
"t20046.cc:14:16)"),
|
||||
_A("a2(int)"), ""));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("tmain()"),
|
||||
_A("a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) "
|
||||
"&&)"),
|
||||
""));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(
|
||||
_A("a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) "
|
||||
"&&)"),
|
||||
_A("tmain()::(lambda t20046.cc:19:9)"), "operator()()"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("tmain()::(lambda t20046.cc:19:9)"),
|
||||
_A("tmain()::(lambda t20046.cc:19:9)::(lambda "
|
||||
"t20046.cc:19:34)"),
|
||||
"operator()()"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("tmain()::(lambda t20046.cc:19:9)::(lambda "
|
||||
"t20046.cc:19:34)"),
|
||||
_A("a3(int)"), ""));
|
||||
|
||||
save_puml(config.output_directory(), diagram->name + ".puml", src);
|
||||
}
|
||||
|
||||
{
|
||||
auto j = generate_sequence_json(diagram, *model);
|
||||
|
||||
using namespace json;
|
||||
|
||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||
}
|
||||
|
||||
{
|
||||
auto src = generate_sequence_mermaid(diagram, *model);
|
||||
|
||||
mermaid::AliasMatcher _A(src);
|
||||
using mermaid::IsClass;
|
||||
|
||||
save_mermaid(config.output_directory(), diagram->name + ".mmd", src);
|
||||
}
|
||||
}
|
||||
@@ -471,6 +471,8 @@ using namespace clanguml::test::matchers;
|
||||
#include "t20042/test_case.h"
|
||||
#include "t20043/test_case.h"
|
||||
#include "t20044/test_case.h"
|
||||
#include "t20045/test_case.h"
|
||||
#include "t20046/test_case.h"
|
||||
|
||||
///
|
||||
/// Package diagram tests
|
||||
|
||||
@@ -400,7 +400,7 @@ struct AliasMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
return "__INVALID__ALIAS__";
|
||||
return fmt::format("__INVALID__ALIAS__({})", name);
|
||||
}
|
||||
|
||||
const std::vector<std::string> puml;
|
||||
|
||||
@@ -352,6 +352,15 @@ test_cases:
|
||||
- name: t20043
|
||||
title: Test case for elements diagram filter in sequence diagrams
|
||||
description:
|
||||
- name: t20044
|
||||
title: Test case for template method call expressions with callables
|
||||
description:
|
||||
- name: t20045
|
||||
title: Test case for template function call expressions with callables
|
||||
description:
|
||||
- name: t20046
|
||||
title: Test case for call expressions in nested lambdas
|
||||
description:
|
||||
Package diagrams:
|
||||
- name: t30001
|
||||
title: Basic package diagram test case
|
||||
|
||||
@@ -26,63 +26,64 @@ TEST_CASE_MULTIPLIER = 10000
|
||||
|
||||
CLASS_DIAGRAM_TEST_CASE_EXAMPLES = """
|
||||
// Check if all classes exist
|
||||
//REQUIRE_THAT(puml, IsClass(_A("A")));
|
||||
//REQUIRE_THAT(src, IsClass(_A("A")));
|
||||
|
||||
// Check if class templates exist
|
||||
//REQUIRE_THAT(puml, IsClassTemplate("A", "T,P,CMP,int N"));
|
||||
//REQUIRE_THAT(src, IsClassTemplate("A", "T,P,CMP,int N"));
|
||||
|
||||
// Check concepts
|
||||
//REQUIRE_THAT(puml, IsConcept(_A("AConcept<T>")));
|
||||
//REQUIRE_THAT(puml,
|
||||
//REQUIRE_THAT(src, IsConcept(_A("AConcept<T>")));
|
||||
//REQUIRE_THAT(src,
|
||||
// IsConceptRequirement(
|
||||
// _A("AConcept<T,P>"), "sizeof (T) > sizeof (P)"));
|
||||
|
||||
// Check if all enums exist
|
||||
//REQUIRE_THAT(puml, IsEnum(_A("Lights")));
|
||||
//REQUIRE_THAT(src, IsEnum(_A("Lights")));
|
||||
|
||||
// Check if all inner classes exist
|
||||
//REQUIRE_THAT(puml, IsInnerClass(_A("A"), _A("AA")));
|
||||
//REQUIRE_THAT(src, IsInnerClass(_A("A"), _A("AA")));
|
||||
|
||||
// Check if all inheritance relationships exist
|
||||
//REQUIRE_THAT(puml, IsBaseClass(_A("Base"), _A("Child")));
|
||||
//REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("Child")));
|
||||
|
||||
// Check if all methods exist
|
||||
//REQUIRE_THAT(puml, (IsMethod<Public, Const>("foo")));
|
||||
//REQUIRE_THAT(src, (IsMethod<Public, Const>("foo")));
|
||||
|
||||
// Check if all fields exist
|
||||
//REQUIRE_THAT(puml, (IsField<Private>("private_member", "int")));
|
||||
//REQUIRE_THAT(src, (IsField<Private>("private_member", "int")));
|
||||
|
||||
// Check if all relationships exist
|
||||
//REQUIRE_THAT(puml, IsAssociation(_A("D"), _A("A"), "-as"));
|
||||
//REQUIRE_THAT(puml, IsDependency(_A("R"), _A("B")));
|
||||
//REQUIRE_THAT(puml, IsAggregation(_A("R"), _A("D"), "-ag"));
|
||||
//REQUIRE_THAT(puml, IsComposition(_A("R"), _A("D"), "-ac"));
|
||||
//REQUIRE_THAT(puml, IsInstantiation(_A("ABCD::F<T>"), _A("F<int>")));
|
||||
//REQUIRE_THAT(src, IsAssociation(_A("D"), _A("A"), "-as"));
|
||||
//REQUIRE_THAT(src, IsDependency(_A("R"), _A("B")));
|
||||
//REQUIRE_THAT(src, IsAggregation(_A("R"), _A("D"), "-ag"));
|
||||
//REQUIRE_THAT(src, IsComposition(_A("R"), _A("D"), "-ac"));
|
||||
//REQUIRE_THAT(src, IsInstantiation(_A("ABCD::F<T>"), _A("F<int>")));
|
||||
"""
|
||||
|
||||
SEQUENCE_DIAGRAM_TEST_CASE_EXAMPLES = """
|
||||
// Check if all calls exist
|
||||
//REQUIRE_THAT(puml, HasCall(_A("tmain()"), _A("A"), "a()"));
|
||||
//REQUIRE_THAT(puml, HasCall(_A("A"), "a()"));
|
||||
//REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()"));
|
||||
//REQUIRE_THAT(src, HasCall(_A("A"), "a()"));
|
||||
"""
|
||||
|
||||
PACKAGE_DIAGRAM_TEST_CASE_EXAMPLES = """
|
||||
// Check if all packages exist
|
||||
//REQUIRE_THAT(puml, IsPackage("ns1"));
|
||||
//REQUIRE_THAT(src, IsPackage("ns1"));
|
||||
"""
|
||||
|
||||
INCLUDE_DIAGRAM_TEST_CASE_EXAMPLES = """
|
||||
// Check all folders exist
|
||||
//REQUIRE_THAT(puml, IsFolder("lib1"));
|
||||
//REQUIRE_THAT(src, IsFolder("lib1"));
|
||||
|
||||
// Check if all files exist
|
||||
//REQUIRE_THAT(puml, IsFile("lib1.h"));
|
||||
//REQUIRE_THAT(src, IsFile("lib1.h"));
|
||||
|
||||
// Check if all includes exists
|
||||
//REQUIRE_THAT(puml, IsAssociation(_A("t40002.cc"), _A("lib1.h")));
|
||||
//REQUIRE_THAT(puml, IsDependency(_A("t40001_include1.h"), _A("string")));
|
||||
//REQUIRE_THAT(src, IsAssociation(_A("t40002.cc"), _A("lib1.h")));
|
||||
//REQUIRE_THAT(src, IsDependency(_A("t40001_include1.h"), _A("string")));
|
||||
"""
|
||||
|
||||
|
||||
def test_case_already_exists(name):
|
||||
return os.path.isdir(os.path.join(os.path.dirname(__file__), '..', name))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user