Refactored sequence lambda inlining to diagram model (#261)
This commit is contained in:
@@ -409,6 +409,116 @@ bool diagram::is_empty() const
|
|||||||
return activities_.empty() || participants_.empty();
|
return activities_.empty() || participants_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void diagram::inline_lambda_operator_calls()
|
||||||
|
{
|
||||||
|
std::map<common::id_t, activity> activities;
|
||||||
|
std::map<common::id_t, std::unique_ptr<participant>> participants;
|
||||||
|
std::set<common::id_t> active_participants;
|
||||||
|
|
||||||
|
for (auto &[id, act] : sequences()) {
|
||||||
|
model::activity new_activity{id};
|
||||||
|
|
||||||
|
// If activity is a lambda operator() - skip it
|
||||||
|
auto maybe_lambda_activity = get_participant<model::method>(id);
|
||||||
|
|
||||||
|
if (maybe_lambda_activity) {
|
||||||
|
const auto parent_class_id =
|
||||||
|
maybe_lambda_activity.value().class_id();
|
||||||
|
auto maybe_parent_class =
|
||||||
|
get_participant<model::class_>(parent_class_id);
|
||||||
|
|
||||||
|
if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other activities, check each message - if it calls lambda
|
||||||
|
// operator() - reattach the message to the next activity in the chain
|
||||||
|
// (assuming it's not lambda)
|
||||||
|
for (auto &m : act.messages()) {
|
||||||
|
|
||||||
|
auto message_call_to_lambda{false};
|
||||||
|
|
||||||
|
message_call_to_lambda =
|
||||||
|
inline_lambda_operator_call(id, new_activity, m);
|
||||||
|
|
||||||
|
if (!message_call_to_lambda)
|
||||||
|
new_activity.add_message(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add activity
|
||||||
|
activities.insert({id, std::move(new_activity)});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &&[id, p] : this->participants()) {
|
||||||
|
// Skip participants which are lambda classes
|
||||||
|
if (const auto *maybe_class =
|
||||||
|
dynamic_cast<const model::class_ *>(p.get());
|
||||||
|
maybe_class && maybe_class->is_lambda()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip participants which are lambda operator methods
|
||||||
|
if (const auto *maybe_method =
|
||||||
|
dynamic_cast<const model::method *>(p.get());
|
||||||
|
maybe_method) {
|
||||||
|
auto maybe_class =
|
||||||
|
get_participant<model::class_>(maybe_method->class_id());
|
||||||
|
if (maybe_class && maybe_class.value().is_lambda())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise move the participant to the new diagram model
|
||||||
|
auto participant_id = p->id();
|
||||||
|
participants.emplace(participant_id, std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip active participants which are not in lambdaless_diagram participants
|
||||||
|
for (auto id : this->active_participants()) {
|
||||||
|
if (participants.count(id)) {
|
||||||
|
active_participants.emplace(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activities_ = std::move(activities);
|
||||||
|
participants_ = std::move(participants);
|
||||||
|
active_participants_ = std::move(active_participants);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool diagram::inline_lambda_operator_call(
|
||||||
|
const long id, model::activity &new_activity, const model::message &m)
|
||||||
|
{
|
||||||
|
bool message_call_to_lambda{false};
|
||||||
|
auto maybe_lambda_operator = get_participant<model::method>(m.to());
|
||||||
|
|
||||||
|
if (maybe_lambda_operator) {
|
||||||
|
const auto parent_class_id = maybe_lambda_operator.value().class_id();
|
||||||
|
auto maybe_parent_class =
|
||||||
|
get_participant<model::class_>(parent_class_id);
|
||||||
|
|
||||||
|
if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
|
||||||
|
// auto new_message{m};
|
||||||
|
// new_message.set_
|
||||||
|
auto lambda_operator_activity = get_activity(m.to());
|
||||||
|
|
||||||
|
// For each call in that lambda activity - reattach this
|
||||||
|
// call to the current activity
|
||||||
|
for (auto &mm : lambda_operator_activity.messages()) {
|
||||||
|
if (!inline_lambda_operator_call(id, new_activity, mm)) {
|
||||||
|
auto new_message{mm};
|
||||||
|
|
||||||
|
new_message.set_from(id);
|
||||||
|
new_activity.add_message(new_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message_call_to_lambda = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return message_call_to_lambda;
|
||||||
|
}
|
||||||
|
|
||||||
void diagram::print() const
|
void diagram::print() const
|
||||||
{
|
{
|
||||||
LOG_TRACE(" --- Participants ---");
|
LOG_TRACE(" --- Participants ---");
|
||||||
|
|||||||
@@ -295,12 +295,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool is_empty() const override;
|
bool is_empty() const override;
|
||||||
|
|
||||||
void update_sequences_from_diagram(diagram &other)
|
/**
|
||||||
{
|
* If option to inline lambda calls is enabled, we need to modify the
|
||||||
activities_ = std::move(other.activities_);
|
* sequences to skip the lambda calls. In case lambda call does not lead
|
||||||
participants_ = std::move(other.participants_);
|
* to a non-lambda call, omit it entirely
|
||||||
active_participants_ = std::move(other.active_participants_);
|
*/
|
||||||
}
|
void inline_lambda_operator_calls();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@@ -344,6 +344,9 @@ private:
|
|||||||
return block_end_types.count(mt) > 0;
|
return block_end_types.count(mt) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool inline_lambda_operator_call(
|
||||||
|
const long id, model::activity &new_activity, const model::message &m);
|
||||||
|
|
||||||
std::map<common::id_t, activity> activities_;
|
std::map<common::id_t, activity> activities_;
|
||||||
|
|
||||||
std::map<common::id_t, std::unique_ptr<participant>> participants_;
|
std::map<common::id_t, std::unique_ptr<participant>> participants_;
|
||||||
|
|||||||
@@ -2028,7 +2028,7 @@ void translation_unit_visitor::finalize()
|
|||||||
ensure_lambda_messages_have_operator_as_target();
|
ensure_lambda_messages_have_operator_as_target();
|
||||||
|
|
||||||
if (config().inline_lambda_messages())
|
if (config().inline_lambda_messages())
|
||||||
inline_lambda_operator_calls();
|
diagram().inline_lambda_operator_calls();
|
||||||
}
|
}
|
||||||
|
|
||||||
void translation_unit_visitor::ensure_lambda_messages_have_operator_as_target()
|
void translation_unit_visitor::ensure_lambda_messages_have_operator_as_target()
|
||||||
@@ -2075,116 +2075,6 @@ void translation_unit_visitor::resolve_ids_to_global()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void translation_unit_visitor::inline_lambda_operator_calls()
|
|
||||||
{ // If option to inline lambda calls is enabled, we need to modify the
|
|
||||||
// sequences to skip the lambda calls. In case lambda call does not lead
|
|
||||||
// to a non-lambda call, omit it entirely
|
|
||||||
|
|
||||||
model::diagram lambdaless_diagram;
|
|
||||||
|
|
||||||
for (auto &[id, act] : diagram().sequences()) {
|
|
||||||
model::activity new_activity{id};
|
|
||||||
|
|
||||||
// If activity is a lambda operator() - skip it
|
|
||||||
auto maybe_lambda_activity =
|
|
||||||
diagram().get_participant<model::method>(id);
|
|
||||||
|
|
||||||
if (maybe_lambda_activity) {
|
|
||||||
const auto parent_class_id =
|
|
||||||
maybe_lambda_activity.value().class_id();
|
|
||||||
auto maybe_parent_class =
|
|
||||||
diagram().get_participant<model::class_>(parent_class_id);
|
|
||||||
|
|
||||||
if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For other activities, check each message - if it calls lambda
|
|
||||||
// operator() - reattach the message to the next activity in the chain
|
|
||||||
// (assuming it's not lambda)
|
|
||||||
for (auto &m : act.messages()) {
|
|
||||||
|
|
||||||
auto message_call_to_lambda{false};
|
|
||||||
|
|
||||||
message_call_to_lambda =
|
|
||||||
inline_lambda_operator_call(id, new_activity, m);
|
|
||||||
|
|
||||||
if (!message_call_to_lambda)
|
|
||||||
new_activity.add_message(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add activity
|
|
||||||
lambdaless_diagram.sequences().insert({id, std::move(new_activity)});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &&[id, p] : diagram().participants()) {
|
|
||||||
// Skip participants which are lambda classes
|
|
||||||
if (const auto *maybe_class =
|
|
||||||
dynamic_cast<const model::class_ *>(p.get());
|
|
||||||
maybe_class && maybe_class->is_lambda()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip participants which are lambda operator methods
|
|
||||||
if (const auto *maybe_method =
|
|
||||||
dynamic_cast<const model::method *>(p.get());
|
|
||||||
maybe_method) {
|
|
||||||
auto maybe_class = diagram().get_participant<model::class_>(
|
|
||||||
maybe_method->class_id());
|
|
||||||
if (maybe_class && maybe_class.value().is_lambda())
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise move the participant to the new diagram model
|
|
||||||
lambdaless_diagram.add_participant(std::move(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip active participants which are not in lambdaless_diagram participants
|
|
||||||
for (auto id : diagram().active_participants()) {
|
|
||||||
if (lambdaless_diagram.participants().count(id)) {
|
|
||||||
lambdaless_diagram.add_active_participant(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diagram().update_sequences_from_diagram(lambdaless_diagram);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool translation_unit_visitor::inline_lambda_operator_call(
|
|
||||||
const long id, model::activity &new_activity, const model::message &m)
|
|
||||||
{
|
|
||||||
bool message_call_to_lambda{false};
|
|
||||||
auto maybe_lambda_operator =
|
|
||||||
diagram().get_participant<model::method>(m.to());
|
|
||||||
|
|
||||||
if (maybe_lambda_operator) {
|
|
||||||
const auto parent_class_id = maybe_lambda_operator.value().class_id();
|
|
||||||
auto maybe_parent_class =
|
|
||||||
diagram().get_participant<model::class_>(parent_class_id);
|
|
||||||
|
|
||||||
if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
|
|
||||||
// auto new_message{m};
|
|
||||||
// new_message.set_
|
|
||||||
auto lambda_operator_activity = diagram().get_activity(m.to());
|
|
||||||
|
|
||||||
// For each call in that lambda activity - reattach this
|
|
||||||
// call to the current activity
|
|
||||||
for (auto &mm : lambda_operator_activity.messages()) {
|
|
||||||
if (!inline_lambda_operator_call(id, new_activity, mm)) {
|
|
||||||
auto new_message{mm};
|
|
||||||
|
|
||||||
new_message.set_from(id);
|
|
||||||
new_activity.add_message(new_message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message_call_to_lambda = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return message_call_to_lambda;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<clanguml::sequence_diagram::model::method>
|
std::unique_ptr<clanguml::sequence_diagram::model::method>
|
||||||
translation_unit_visitor::create_lambda_method_model(
|
translation_unit_visitor::create_lambda_method_model(
|
||||||
clang::CXXMethodDecl *declaration)
|
clang::CXXMethodDecl *declaration)
|
||||||
|
|||||||
@@ -487,10 +487,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
template_builder_t &tbuilder() { return template_builder_; }
|
template_builder_t &tbuilder() { return template_builder_; }
|
||||||
|
|
||||||
void inline_lambda_operator_calls();
|
void resolve_ids_to_global();
|
||||||
|
|
||||||
bool inline_lambda_operator_call(
|
void ensure_lambda_messages_have_operator_as_target();
|
||||||
const long id, model::activity &new_activity, const model::message &m);
|
|
||||||
|
|
||||||
call_expression_context call_expression_context_;
|
call_expression_context call_expression_context_;
|
||||||
|
|
||||||
@@ -527,7 +526,5 @@ private:
|
|||||||
processed_comments_by_caller_id_;
|
processed_comments_by_caller_id_;
|
||||||
|
|
||||||
template_builder_t template_builder_;
|
template_builder_t template_builder_;
|
||||||
void resolve_ids_to_global();
|
|
||||||
void ensure_lambda_messages_have_operator_as_target();
|
|
||||||
};
|
};
|
||||||
} // namespace clanguml::sequence_diagram::visitor
|
} // namespace clanguml::sequence_diagram::visitor
|
||||||
|
|||||||
Reference in New Issue
Block a user