Added generate_message_comments configuration option

This commit is contained in:
Bartek Kryza
2023-10-15 19:59:06 +02:00
parent c4d3d61770
commit 03e8c867f4
14 changed files with 127 additions and 0 deletions

View File

@@ -849,4 +849,30 @@ bool parse_source_location(const std::string &location_str, std::string &file,
return true;
}
std::optional<std::string> get_expression_comment(
const clang::SourceManager &sm, const clang::ASTContext &context,
const clang::Stmt *stmt)
{
// First get the first line of the expression
auto expr_begin = stmt->getSourceRange().getBegin();
const auto expr_begin_line = sm.getSpellingLineNumber(expr_begin);
if (!context.Comments.empty())
for (const auto [offset, raw_comment] :
*context.Comments.getCommentsInFile(sm.getMainFileID())) {
auto comment =
raw_comment->getFormattedText(sm, sm.getDiagnostics());
const auto comment_end_line = sm.getSpellingLineNumber(
raw_comment->getSourceRange().getEnd());
if (expr_begin_line == comment_end_line ||
expr_begin_line == comment_end_line + 1)
return comment;
}
return {};
}
} // namespace clanguml::common

View File

@@ -282,4 +282,8 @@ clang::QualType dereference(clang::QualType type);
std::pair<clang::QualType, std::deque<common::model::context>>
consume_type_context(clang::QualType type);
std::optional<std::string> get_expression_comment(
const clang::SourceManager &sm, const clang::ASTContext &context,
const clang::Stmt *stmt);
} // namespace clanguml::common

View File

@@ -480,6 +480,7 @@ struct inheritable_diagram_options {
option<bool> generate_condition_statements{
"generate_condition_statements", false};
option<std::vector<std::string>> participants_order{"participants_order"};
option<bool> generate_message_comments{"generate_message_comments", false};
option<bool> debug_mode{"debug_mode", false};
option<bool> generate_metadata{"generate_metadata", true};

View File

@@ -201,6 +201,7 @@ types:
combine_free_functions_into_file_participants: !optional bool
generate_return_types: !optional bool
generate_condition_statements: !optional bool
generate_message_comments: !optional bool
participants_order: !optional [string]
start_from: !optional [source_location_t] # deprecated -> 'from'
from: !optional [source_location_t]
@@ -311,6 +312,7 @@ root:
combine_free_functions_into_file_participants: !optional bool
generate_return_types: !optional bool
generate_condition_statements: !optional bool
generate_message_comments: !optional bool
generate_packages: !optional bool
group_methods: !optional bool
package_type: !optional package_type_t

View File

@@ -603,6 +603,7 @@ template <> struct convert<sequence_diagram> {
get_option(node, rhs.relative_to);
get_option(node, rhs.participants_order);
get_option(node, rhs.generate_method_arguments);
get_option(node, rhs.generate_message_comments);
// Ensure relative_to has a value
if (!rhs.relative_to.has_value)
@@ -792,6 +793,7 @@ template <> struct convert<config> {
get_option(node, rhs.combine_free_functions_into_file_participants);
get_option(node, rhs.generate_return_types);
get_option(node, rhs.generate_condition_statements);
get_option(node, rhs.generate_message_comments);
rhs.base_directory.set(node["__parent_path"].as<std::string>());
get_option(node, rhs.relative_to);

View File

@@ -325,6 +325,7 @@ YAML::Emitter &operator<<(
out << c.generate_method_arguments;
out << c.generate_return_types;
out << c.participants_order;
out << c.generate_message_comments;
}
else if (const auto *pd = dynamic_cast<const package_diagram *>(&c);
pd != nullptr) {

View File

@@ -83,6 +83,8 @@ void generator::generate_call(const message &m, std::ostream &ostr) const
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << from_alias << " "
<< common::generators::plantuml::to_plantuml(message_t::kCall) << " ";
@@ -178,6 +180,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
else if (m.type() == message_t::kIf) {
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << "alt";
if (const auto &text = m.condition_text(); text.has_value())
ostr << " " << text.value();
@@ -199,6 +202,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
else if (m.type() == message_t::kWhile) {
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << "loop";
if (const auto &text = m.condition_text(); text.has_value())
ostr << " " << text.value();
@@ -209,6 +213,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
else if (m.type() == message_t::kFor) {
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << "loop";
if (const auto &text = m.condition_text(); text.has_value())
ostr << " " << text.value();
@@ -219,6 +224,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
else if (m.type() == message_t::kDo) {
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << "loop";
if (const auto &text = m.condition_text(); text.has_value())
ostr << " " << text.value();
@@ -229,6 +235,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
else if (m.type() == message_t::kTry) {
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << "group try\n";
}
else if (m.type() == message_t::kCatch) {
@@ -241,6 +248,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
else if (m.type() == message_t::kSwitch) {
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << "group switch\n";
}
else if (m.type() == message_t::kCase) {
@@ -252,6 +260,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
else if (m.type() == message_t::kConditional) {
print_debug(m, ostr);
generate_message_comment(ostr, m);
ostr << "alt";
if (const auto &text = m.condition_text(); text.has_value())
ostr << " " << text.value();
@@ -267,6 +276,33 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
}
}
void generator::generate_message_comment(
std::ostream &ostr, const model::message &m) const
{
if (!config().generate_message_comments() || !m.comment())
return;
const auto &from = model().get_participant<model::participant>(m.from());
if (!from)
return;
if (m.type() == message_t::kCall) {
const auto &to = model().get_participant<model::participant>(m.to());
if (!to)
return;
ostr << "note over " << generate_alias(from.value()) << ", "
<< generate_alias(to.value()) << '\n';
}
else {
ostr << "note over " << generate_alias(from.value()) << '\n';
}
ostr << m.comment().value() << '\n';
ostr << "end note" << '\n';
}
void generator::generate_participant(
std::ostream &ostr, const std::string &name) const
{

View File

@@ -147,6 +147,9 @@ private:
model::function::message_render_mode
select_method_arguments_render_mode() const;
void generate_message_comment(
std::ostream &ostr, const model::message &m) const;
mutable std::set<common::id_t> generated_participants_;
mutable std::vector<model::message> already_generated_in_static_context_;
};

View File

@@ -58,6 +58,16 @@ void message::set_return_type(std::string t) { return_type_ = std::move(t); }
const std::string &message::return_type() const { return return_type_; }
const std::optional<std::string> &message::comment() const { return comment_; }
void message::set_comment(std::string c) { comment_ = std::move(c); }
void message::set_comment(const std::optional<std::string> &c)
{
if (c)
set_comment(c.value());
}
void message::set_message_scope(common::model::message_scope_t scope)
{
scope_ = scope;

View File

@@ -119,6 +119,12 @@ public:
*/
const std::string &return_type() const;
const std::optional<std::string> &comment() const;
void set_comment(std::string c);
void set_comment(const std::optional<std::string> &c);
/**
* @brief Set message scope
*
@@ -172,6 +178,8 @@ private:
std::optional<std::string> condition_text_;
std::optional<std::string> comment_;
bool in_static_declaration_context_{false};
};

View File

@@ -613,6 +613,8 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
message m{message_t::kElseIf, current_caller_id};
set_source_location(*stmt, m);
m.condition_text(condition_text);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
else {
@@ -621,6 +623,8 @@ bool translation_unit_visitor::TraverseIfStmt(clang::IfStmt *stmt)
message m{message_t::kIf, current_caller_id};
set_source_location(*stmt, m);
m.condition_text(condition_text);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
}
@@ -655,6 +659,8 @@ bool translation_unit_visitor::TraverseWhileStmt(clang::WhileStmt *stmt)
message m{message_t::kWhile, current_caller_id};
set_source_location(*stmt, m);
m.condition_text(condition_text);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
RecursiveASTVisitor<translation_unit_visitor>::TraverseWhileStmt(stmt);
@@ -685,6 +691,8 @@ bool translation_unit_visitor::TraverseDoStmt(clang::DoStmt *stmt)
message m{message_t::kDo, current_caller_id};
set_source_location(*stmt, m);
m.condition_text(condition_text);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
@@ -716,6 +724,10 @@ bool translation_unit_visitor::TraverseForStmt(clang::ForStmt *stmt)
message m{message_t::kFor, current_caller_id};
set_source_location(*stmt, m);
m.condition_text(condition_text);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
@@ -742,6 +754,8 @@ bool translation_unit_visitor::TraverseCXXTryStmt(clang::CXXTryStmt *stmt)
context().enter_trystmt(stmt);
message m{message_t::kTry, current_caller_id};
set_source_location(*stmt, m);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
@@ -800,6 +814,8 @@ bool translation_unit_visitor::TraverseCXXForRangeStmt(
message m{message_t::kFor, current_caller_id};
set_source_location(*stmt, m);
m.condition_text(condition_text);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
@@ -825,6 +841,8 @@ bool translation_unit_visitor::TraverseSwitchStmt(clang::SwitchStmt *stmt)
context().enter_switchstmt(stmt);
model::message m{message_t::kSwitch, current_caller_id};
set_source_location(*stmt, m);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
@@ -891,6 +909,8 @@ bool translation_unit_visitor::TraverseConditionalOperator(
model::message m{message_t::kConditional, current_caller_id};
set_source_location(*stmt, m);
m.condition_text(condition_text);
m.set_comment(clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), stmt));
diagram().add_block_message(std::move(m));
}
@@ -1015,6 +1035,10 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
}
if (m.from() > 0 && m.to() > 0) {
auto expr_comment = clanguml::common::get_expression_comment(
source_manager(), *context().get_ast_context(), expr);
m.set_comment(expr_comment);
if (diagram().sequences().find(m.from()) ==
diagram().sequences().end()) {
activity a{m.from()};

View File

@@ -1,5 +1,7 @@
compilation_database_dir: ..
output_directory: diagrams
add_compile_flags:
- -fparse-all-comments
diagrams:
t20029_sequence:
type: sequence
@@ -15,6 +17,7 @@ diagrams:
- clanguml::t20029
from:
- function: clanguml::t20029::tmain()
generate_message_comments: true
participants_order:
- clanguml::t20029::tmain()
- clanguml::t20029::Encoder<clanguml::t20029::Retrier<clanguml::t20029::ConnectionPool>>

View File

@@ -56,8 +56,10 @@ int tmain()
{
auto pool = std::make_shared<Encoder<Retrier<ConnectionPool>>>();
// Establish connection to the remote server synchronously
pool->connect();
// Repeat for each line in the input stream
for (std::string line; std::getline(std::cin, line);) {
if (!pool->send(std::move(line)))
break;

View File

@@ -46,6 +46,11 @@ load_config(const std::string &test_name)
LOG_DBG("Loading compilation database from {}",
res.first.compilation_database_dir());
std::vector<std::string> remove_compile_flags{
std::string{"-Wno-class-memaccess"}};
res.first.remove_compile_flags.set(remove_compile_flags);
res.second =
clanguml::common::compilation_database::auto_detect_from_directory(
res.first);