Added start_from function and method entrypoints in sequence diagrams

This commit is contained in:
Bartek Kryza
2022-12-09 22:12:24 +01:00
parent caf0ae7928
commit 69ca8c2d8e
8 changed files with 179 additions and 87 deletions

View File

@@ -248,7 +248,7 @@ void generator::generate(std::ostream &ostr) const
visited_participants;
const auto &from =
m_model.get_participant<model::participant>(start_from);
m_model.get_participant<model::function>(start_from);
if (!from.has_value()) {
LOG_WARN("Failed to find participant {} for start_from "
@@ -261,11 +261,29 @@ void generator::generate(std::ostream &ostr) const
std::string from_alias = generate_alias(from.value());
if (from.value().type_name() == "method" ||
m_config.combine_free_functions_into_file_participants()) {
ostr << "[->"
<< " " << from_alias << " : "
<< from.value().message_name(
model::function::message_render_mode::full)
<< std::endl;
}
ostr << "activate " << from_alias << std::endl;
generate_activity(
m_model.sequences[start_from], ostr, visited_participants);
if (from.value().type_name() == "method" ||
m_config.combine_free_functions_into_file_participants()) {
if (!from.value().is_void()) {
ostr << "[<--"
<< " " << from_alias << std::endl;
}
}
ostr << "deactivate " << from_alias << std::endl;
}
else {

View File

@@ -57,6 +57,10 @@ void template_trait::add_template(
templates_.push_back(std::move(tmplt));
}
bool template_trait::is_implicit() const { return is_implicit_; }
void template_trait::set_implicit(bool implicit) { is_implicit_ = implicit; }
const std::vector<class_diagram::model::template_parameter> &
template_trait::templates() const
{
@@ -95,6 +99,12 @@ int template_trait::calculate_template_specialization_match(
return res;
}
std::string participant::to_string() const
{
return fmt::format(
"Participant '{}': id={} name={}", type_name(), id(), full_name(false));
}
class_::class_(const common::model::namespace_ &using_namespace)
: participant{using_namespace}
{
@@ -154,6 +164,14 @@ std::string class_::full_name(bool relative) const
return res;
}
bool class_::is_alias() const { return is_alias_; }
void class_::is_alias(bool alias) { is_alias_ = alias; }
bool class_::is_lambda() const { return is_lambda_; }
void class_::is_lambda(bool is_lambda) { is_lambda_ = is_lambda; }
bool operator==(const class_ &l, const class_ &r) { return l.id() == r.id(); }
function::function(const common::model::namespace_ &using_namespace)
@@ -173,11 +191,38 @@ std::string function::full_name_no_ns() const
fmt::join(parameters_, ","), is_const() ? " const" : "");
}
std::string function::message_name(message_render_mode mode) const
{
if (mode == message_render_mode::no_arguments) {
return fmt::format("{}(){}", name(), is_const() ? " const" : "");
}
return fmt::format("{}({}){}", name(), fmt::join(parameters_, ","),
is_const() ? " const" : "");
}
bool function::is_const() const { return is_const_; }
void function::is_const(bool c) { is_const_ = c; }
bool function::is_void() const { return is_void_; }
void function::is_void(bool v) { is_void_ = v; }
void function::add_parameter(const std::string &a) { parameters_.push_back(a); }
const std::vector<std::string> &function::parameters() const
{
return parameters_;
}
method::method(const common::model::namespace_ &using_namespace)
: function{using_namespace}
{
}
const std::string method::method_name() const { return method_name_; }
std::string method::alias() const
{
assert(class_id_ >= 0);
@@ -185,6 +230,41 @@ std::string method::alias() const
return fmt::format("C_{:022}", class_id_);
}
void method::set_method_name(const std::string &name) { method_name_ = name; }
void method::set_class_id(diagram_element::id_t id) { class_id_ = id; }
void method::set_class_full_name(const std::string &name)
{
class_full_name_ = name;
}
const auto &method::class_full_name() const { return class_full_name_; }
std::string method::full_name(bool /*relative*/) const
{
return fmt::format("{}::{}({}){}", class_full_name(), method_name(),
fmt::join(parameters(), ","), is_const() ? " const" : "");
}
std::string method::message_name(message_render_mode mode) const
{
if (mode == message_render_mode::no_arguments) {
return fmt::format("{}(){}", method_name(), is_const() ? " const" : "");
}
return fmt::format("{}({}){}", method_name(), fmt::join(parameters(), ","),
is_const() ? " const" : "");
}
class_::diagram_element::id_t method::class_id() const { return class_id_; }
std::string method::to_string() const
{
return fmt::format("Participant '{}': id={}, name={}, class_id={}",
type_name(), id(), full_name(false), class_id());
}
function_template::function_template(
const common::model::namespace_ &using_namespace)
: function{using_namespace}
@@ -233,4 +313,19 @@ std::string function_template::full_name_no_ns() const
return ostr.str();
}
std::string function_template::message_name(message_render_mode mode) const
{
std::ostringstream s;
render_template_params(s, using_namespace(), true);
std::string template_params = s.str();
if (mode == message_render_mode::no_arguments) {
return fmt::format(
"{}{}(){}", name(), template_params, is_const() ? " const" : "");
}
return fmt::format("{}{}({}){}", name(), template_params,
fmt::join(parameters(), ","), is_const() ? " const" : "");
}
}

View File

@@ -42,9 +42,9 @@ struct template_trait {
int calculate_template_specialization_match(
const template_trait &other, const std::string &full_name) const;
bool is_implicit() const { return is_implicit_; }
bool is_implicit() const;
void set_implicit(bool implicit) { is_implicit_ = implicit; }
void set_implicit(bool implicit);
private:
std::vector<class_diagram::model::template_parameter> templates_;
@@ -74,11 +74,7 @@ struct participant : public common::model::element,
std::string type_name() const override { return "participant"; }
virtual std::string to_string() const
{
return fmt::format("Participant '{}': id={} name={}", type_name(), id(),
full_name(false));
}
virtual std::string to_string() const;
stereotype_t stereotype_{stereotype_t::participant};
};
@@ -111,13 +107,13 @@ public:
bool is_abstract() const;
bool is_alias() const { return is_alias_; }
bool is_alias() const;
void is_alias(bool alias) { is_alias_ = alias; }
void is_alias(bool alias);
bool is_lambda() const { return is_lambda_; }
bool is_lambda() const;
void is_lambda(bool is_lambda) { is_lambda_ = is_lambda; }
void is_lambda(bool is_lambda);
private:
bool is_struct_{false};
@@ -154,26 +150,23 @@ struct function : public participant {
std::string full_name_no_ns() const override;
virtual std::string message_name(message_render_mode mode) const
{
if (mode == message_render_mode::no_arguments) {
return fmt::format("{}(){}", name(), is_const() ? " const" : "");
}
virtual std::string message_name(message_render_mode mode) const;
return fmt::format("{}({}){}", name(), fmt::join(parameters_, ","),
is_const() ? " const" : "");
}
bool is_const() const;
bool is_const() const { return is_const_; }
void is_const(bool c);
void is_const(bool c) { is_const_ = c; }
bool is_void() const;
void add_parameter(const std::string &a) { parameters_.push_back(a); }
void is_void(bool v);
const std::vector<std::string> &parameters() const { return parameters_; }
void add_parameter(const std::string &a);
const std::vector<std::string> &parameters() const;
private:
bool is_const_{false};
bool is_void_{false};
std::vector<std::string> parameters_;
};
@@ -187,45 +180,25 @@ struct method : public function {
std::string type_name() const override { return "method"; }
const std::string method_name() const { return method_name_; }
const std::string method_name() const;
std::string alias() const override;
void set_method_name(const std::string &name) { method_name_ = name; }
void set_method_name(const std::string &name);
void set_class_id(diagram_element::id_t id) { class_id_ = id; }
void set_class_id(diagram_element::id_t id);
void set_class_full_name(const std::string &name)
{
class_full_name_ = name;
}
void set_class_full_name(const std::string &name);
const auto &class_full_name() const { return class_full_name_; }
const auto &class_full_name() const;
std::string full_name(bool /*relative*/) const override
{
return fmt::format("{}::{}({}){}", class_full_name(), method_name(),
fmt::join(parameters(), ","), is_const() ? " const" : "");
}
std::string full_name(bool /*relative*/) const override;
std::string message_name(message_render_mode mode) const override
{
if (mode == message_render_mode::no_arguments) {
return fmt::format(
"{}(){}", method_name(), is_const() ? " const" : "");
}
std::string message_name(message_render_mode mode) const override;
return fmt::format("{}({}){}", method_name(),
fmt::join(parameters(), ","), is_const() ? " const" : "");
}
diagram_element::id_t class_id() const;
diagram_element::id_t class_id() const { return class_id_; }
std::string to_string() const override
{
return fmt::format("Participant '{}': id={}, name={}, class_id={}",
type_name(), id(), full_name(false), class_id());
}
std::string to_string() const override;
private:
diagram_element::id_t class_id_;
@@ -247,20 +220,6 @@ struct function_template : public function, public template_trait {
std::string full_name_no_ns() const override;
std::string message_name(message_render_mode mode) const override
{
std::ostringstream s;
render_template_params(s, using_namespace(), true);
std::string template_params = s.str();
if (mode == message_render_mode::no_arguments) {
return fmt::format("{}{}(){}", name(), template_params,
is_const() ? " const" : "");
}
return fmt::format("{}{}({}){}", name(), template_params,
fmt::join(parameters(), ","), is_const() ? " const" : "");
}
std::string message_name(message_render_mode mode) const override;
};
}

View File

@@ -307,6 +307,8 @@ bool translation_unit_visitor::VisitCXXMethodDecl(clang::CXXMethodDecl *m)
const auto &method_class =
get_participant<model::class_>(parent_decl).value();
m_ptr->is_void(m->getReturnType()->isVoidType());
m_ptr->set_class_id(method_class.id());
m_ptr->set_class_full_name(method_class.full_name(false));
m_ptr->set_name(
@@ -370,6 +372,8 @@ bool translation_unit_visitor::VisitFunctionDecl(clang::FunctionDecl *f)
f_ptr->set_id(common::to_id(f_ptr->full_name(false)));
f_ptr->is_void(f->getReturnType()->isVoidType());
context().update(f);
context().set_caller_id(f_ptr->id());
@@ -397,6 +401,8 @@ bool translation_unit_visitor::VisitFunctionDecl(clang::FunctionDecl *f)
f_ptr->set_id(common::to_id(f_ptr->full_name(false)));
f_ptr->is_void(f->getReturnType()->isVoidType());
context().update(f);
context().set_caller_id(f_ptr->id());
@@ -441,6 +447,9 @@ bool translation_unit_visitor::VisitFunctionTemplateDecl(
f_ptr->set_id(common::to_id(f_ptr->full_name(false)));
f_ptr->is_void(
function_template->getAsFunction()->getReturnType()->isVoidType());
set_source_location(*function_template, *f_ptr);
context().update(function_template);

View File

@@ -35,9 +35,10 @@ TEST_CASE("t20005", "[test-case][sequence]")
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
// Check if all calls exist
REQUIRE_THAT(puml, HasEntrypoint(_A("C<T>"), "c(T)"));
REQUIRE_THAT(puml, HasCall(_A("C<T>"), _A("B<T>"), "b(T)"));
REQUIRE_THAT(puml, HasCall(_A("B<T>"), _A("A<T>"), "a(T)"));
REQUIRE_THAT(puml, HasExitpoint(_A("C<T>")));
save_puml(
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
}

View File

@@ -35,16 +35,19 @@ TEST_CASE("t20017", "[test-case][sequence]")
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
// Check if all calls exist
REQUIRE_THAT(puml, HasEntrypoint(_A("t20017.cc"), "tmain()"));
REQUIRE_THAT(puml,
HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a1(int,int)"));
REQUIRE_THAT(
puml, HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a2(int,int)"));
REQUIRE_THAT(puml,
HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a2(int,int)"));
REQUIRE_THAT(puml,
HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a3(int,int)"));
REQUIRE_THAT(puml,
HasCall(_A("t20017.cc"), _A("include/t20017_b.h"), "b1(int,int)"));
REQUIRE_THAT(puml,
HasCall(_A("t20017.cc"), _A("include/t20017_b.h"), "b2<int>(int,int)"));
HasCall(
_A("t20017.cc"), _A("include/t20017_b.h"), "b2<int>(int,int)"));
REQUIRE_THAT(puml, HasExitpoint(_A("t20017.cc")));
save_puml(
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);

View File

@@ -79,26 +79,19 @@ template <typename T, typename... Ts> constexpr bool has_type() noexcept
return (std::is_same_v<T, Ts> || ... || false);
}
struct Public {
};
struct Public { };
struct Protected {
};
struct Protected { };
struct Private {
};
struct Private { };
struct Abstract {
};
struct Abstract { };
struct Static {
};
struct Static { };
struct Const {
};
struct Const { };
struct Default {
};
struct Default { };
struct HasCallWithResultMatcher : ContainsMatcher {
HasCallWithResultMatcher(
@@ -144,6 +137,20 @@ auto HasCallWithResponse(std::string const &from, std::string const &to,
CasedString(fmt::format("{} --> {}", to, from), caseSensitivity));
}
ContainsMatcher HasEntrypoint(std::string const &to, std::string const &message,
CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
{
return ContainsMatcher(
CasedString(fmt::format("[-> {} : {}", to, message), caseSensitivity));
}
ContainsMatcher HasExitpoint(std::string const &to,
CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
{
return ContainsMatcher(
CasedString(fmt::format("[<-- {}", to), caseSensitivity));
}
struct AliasMatcher {
AliasMatcher(const std::string &puml_)
: puml{split(puml_, "\n")}