Added option --print-start-from to list all possible 'start_from' values (fixes #94)
This commit is contained in:
@@ -129,6 +129,8 @@ cli_flow_t cli_handler::parse(int argc, const char **argv)
|
|||||||
"instead of actual location of `.clang-uml` file.");
|
"instead of actual location of `.clang-uml` file.");
|
||||||
app.add_flag("--no-metadata", no_metadata,
|
app.add_flag("--no-metadata", no_metadata,
|
||||||
"Skip metadata (e.g. clang-uml version) from diagrams");
|
"Skip metadata (e.g. clang-uml version) from diagrams");
|
||||||
|
app.add_flag("--print-start-from", print_start_from,
|
||||||
|
"Print all possible 'start_from' values for a given diagram");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
app.parse(argc, argv);
|
app.parse(argc, argv);
|
||||||
@@ -143,7 +145,7 @@ cli_flow_t cli_handler::parse(int argc, const char **argv)
|
|||||||
exit(app.exit(e)); // NOLINT(concurrency-mt-unsafe)
|
exit(app.exit(e)); // NOLINT(concurrency-mt-unsafe)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quiet || dump_config)
|
if (quiet || dump_config || print_start_from)
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
else
|
else
|
||||||
verbose++;
|
verbose++;
|
||||||
@@ -196,6 +198,16 @@ cli_flow_t cli_handler::handle_pre_config_options()
|
|||||||
return cli_flow_t::kError;
|
return cli_flow_t::kError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (print_start_from) {
|
||||||
|
if (diagram_names.size() != 1) {
|
||||||
|
LOG_ERROR(
|
||||||
|
"ERROR: '--print-start-from' requires specifying one diagram "
|
||||||
|
"name using '-n' option");
|
||||||
|
|
||||||
|
return cli_flow_t::kError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (initialize) {
|
if (initialize) {
|
||||||
return create_config_file();
|
return create_config_file();
|
||||||
}
|
}
|
||||||
@@ -319,6 +331,18 @@ cli_flow_t cli_handler::handle_post_config_options()
|
|||||||
return cli_flow_t::kContinue;
|
return cli_flow_t::kContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runtime_config cli_handler::get_runtime_config() const
|
||||||
|
{
|
||||||
|
runtime_config cfg;
|
||||||
|
cfg.generators = generators;
|
||||||
|
cfg.verbose = verbose;
|
||||||
|
cfg.print_start_from = print_start_from;
|
||||||
|
cfg.progress = progress;
|
||||||
|
cfg.thread_count = thread_count;
|
||||||
|
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
cli_flow_t cli_handler::print_version()
|
cli_flow_t cli_handler::print_version()
|
||||||
{
|
{
|
||||||
ostr_ << "clang-uml " << clanguml::version::CLANG_UML_VERSION << std::endl;
|
ostr_ << "clang-uml " << clanguml::version::CLANG_UML_VERSION << std::endl;
|
||||||
@@ -546,8 +570,8 @@ cli_flow_t cli_handler::add_config_diagram_from_template(
|
|||||||
return cli_flow_t::kError;
|
return cli_flow_t::kError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, try to render the template using inja and create a YAML node from
|
// First, try to render the template using inja and create a YAML node
|
||||||
// it
|
// from it
|
||||||
inja::json ctx;
|
inja::json ctx;
|
||||||
for (const auto &tv : template_variables) {
|
for (const auto &tv : template_variables) {
|
||||||
const auto var = util::split(tv, "=");
|
const auto var = util::split(tv, "=");
|
||||||
|
|||||||
@@ -25,6 +25,19 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace clanguml::cli {
|
namespace clanguml::cli {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class holds command line parameters not directly related to
|
||||||
|
* specific diagram configurations.
|
||||||
|
*/
|
||||||
|
struct runtime_config {
|
||||||
|
int verbose{};
|
||||||
|
std::vector<clanguml::common::generator_type_t> generators{};
|
||||||
|
bool print_start_from{};
|
||||||
|
bool progress{};
|
||||||
|
unsigned int thread_count{};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This enum represents possible exit states of the command line parser.
|
* This enum represents possible exit states of the command line parser.
|
||||||
*/
|
*/
|
||||||
@@ -132,6 +145,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool ensure_output_directory_exists(const std::string &dir);
|
bool ensure_output_directory_exists(const std::string &dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Combines runtime configuration parameters into a single structure
|
||||||
|
*
|
||||||
|
* @return Runtime config instance
|
||||||
|
*/
|
||||||
|
runtime_config get_runtime_config() const;
|
||||||
|
|
||||||
std::string config_path{".clang-uml"};
|
std::string config_path{".clang-uml"};
|
||||||
std::optional<std::string> compilation_database_dir{};
|
std::optional<std::string> compilation_database_dir{};
|
||||||
std::vector<std::string> diagram_names{};
|
std::vector<std::string> diagram_names{};
|
||||||
@@ -155,6 +175,7 @@ public:
|
|||||||
std::optional<std::string> add_include_diagram;
|
std::optional<std::string> add_include_diagram;
|
||||||
std::optional<std::string> add_diagram_from_template;
|
std::optional<std::string> add_diagram_from_template;
|
||||||
bool dump_config{false};
|
bool dump_config{false};
|
||||||
|
bool print_start_from{false};
|
||||||
std::optional<bool> paths_relative_to_pwd{};
|
std::optional<bool> paths_relative_to_pwd{};
|
||||||
std::vector<std::string> template_variables{};
|
std::vector<std::string> template_variables{};
|
||||||
bool list_templates{false};
|
bool list_templates{false};
|
||||||
|
|||||||
@@ -83,8 +83,7 @@ void generate_diagram_impl(const std::string &od, const std::string &name,
|
|||||||
std::shared_ptr<clanguml::config::diagram> diagram,
|
std::shared_ptr<clanguml::config::diagram> diagram,
|
||||||
const common::compilation_database &db,
|
const common::compilation_database &db,
|
||||||
const std::vector<std::string> &translation_units,
|
const std::vector<std::string> &translation_units,
|
||||||
const std::vector<clanguml::common::generator_type_t> &generators,
|
const cli::runtime_config &rc, std::function<void()> &&progress)
|
||||||
bool verbose, std::function<void()> &&progress)
|
|
||||||
{
|
{
|
||||||
using diagram_config = DiagramConfig;
|
using diagram_config = DiagramConfig;
|
||||||
using diagram_model = typename diagram_model_t<DiagramConfig>::type;
|
using diagram_model = typename diagram_model_t<DiagramConfig>::type;
|
||||||
@@ -92,10 +91,22 @@ void generate_diagram_impl(const std::string &od, const std::string &name,
|
|||||||
|
|
||||||
auto model = clanguml::common::generators::generate<diagram_model,
|
auto model = clanguml::common::generators::generate<diagram_model,
|
||||||
diagram_config, diagram_visitor>(db, diagram->name,
|
diagram_config, diagram_visitor>(db, diagram->name,
|
||||||
dynamic_cast<diagram_config &>(*diagram), translation_units, verbose,
|
dynamic_cast<diagram_config &>(*diagram), translation_units, rc.verbose,
|
||||||
std::move(progress));
|
std::move(progress));
|
||||||
|
|
||||||
for (const auto generator_type : generators) {
|
if constexpr (std::is_same_v<DiagramConfig, config::sequence_diagram>) {
|
||||||
|
if (rc.print_start_from) {
|
||||||
|
auto start_from_values = model->list_start_from_values();
|
||||||
|
|
||||||
|
for (const auto &start_from : start_from_values) {
|
||||||
|
std::cout << start_from << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto generator_type : rc.generators) {
|
||||||
if (generator_type == generator_type_t::plantuml) {
|
if (generator_type == generator_type_t::plantuml) {
|
||||||
generate_diagram_select_generator<diagram_config,
|
generate_diagram_select_generator<diagram_config,
|
||||||
plantuml_generator_tag>(od, name, diagram, model);
|
plantuml_generator_tag>(od, name, diagram, model);
|
||||||
@@ -112,8 +123,7 @@ void generate_diagram(const std::string &od, const std::string &name,
|
|||||||
std::shared_ptr<clanguml::config::diagram> diagram,
|
std::shared_ptr<clanguml::config::diagram> diagram,
|
||||||
const common::compilation_database &db,
|
const common::compilation_database &db,
|
||||||
const std::vector<std::string> &translation_units,
|
const std::vector<std::string> &translation_units,
|
||||||
const std::vector<clanguml::common::generator_type_t> &generators,
|
const cli::runtime_config &runtime_config, std::function<void()> &&progress)
|
||||||
bool verbose, std::function<void()> &&progress)
|
|
||||||
{
|
{
|
||||||
using clanguml::common::generator_type_t;
|
using clanguml::common::generator_type_t;
|
||||||
using clanguml::common::model::diagram_t;
|
using clanguml::common::model::diagram_t;
|
||||||
@@ -125,36 +135,35 @@ void generate_diagram(const std::string &od, const std::string &name,
|
|||||||
|
|
||||||
if (diagram->type() == diagram_t::kClass) {
|
if (diagram->type() == diagram_t::kClass) {
|
||||||
detail::generate_diagram_impl<class_diagram>(od, name, diagram, db,
|
detail::generate_diagram_impl<class_diagram>(od, name, diagram, db,
|
||||||
translation_units, generators, verbose, std::move(progress));
|
translation_units, runtime_config, std::move(progress));
|
||||||
}
|
}
|
||||||
else if (diagram->type() == diagram_t::kSequence) {
|
else if (diagram->type() == diagram_t::kSequence) {
|
||||||
detail::generate_diagram_impl<sequence_diagram>(od, name, diagram, db,
|
detail::generate_diagram_impl<sequence_diagram>(od, name, diagram, db,
|
||||||
translation_units, generators, verbose, std::move(progress));
|
translation_units, runtime_config, std::move(progress));
|
||||||
}
|
}
|
||||||
else if (diagram->type() == diagram_t::kPackage) {
|
else if (diagram->type() == diagram_t::kPackage) {
|
||||||
detail::generate_diagram_impl<package_diagram>(od, name, diagram, db,
|
detail::generate_diagram_impl<package_diagram>(od, name, diagram, db,
|
||||||
translation_units, generators, verbose, std::move(progress));
|
translation_units, runtime_config, std::move(progress));
|
||||||
}
|
}
|
||||||
else if (diagram->type() == diagram_t::kInclude) {
|
else if (diagram->type() == diagram_t::kInclude) {
|
||||||
detail::generate_diagram_impl<include_diagram>(od, name, diagram, db,
|
detail::generate_diagram_impl<include_diagram>(od, name, diagram, db,
|
||||||
translation_units, generators, verbose, std::move(progress));
|
translation_units, runtime_config, std::move(progress));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_diagrams(const std::vector<std::string> &diagram_names,
|
void generate_diagrams(const std::vector<std::string> &diagram_names,
|
||||||
config::config &config, const std::string &od,
|
config::config &config, const std::string &od,
|
||||||
const common::compilation_database_ptr &db, const int verbose,
|
const common::compilation_database_ptr &db,
|
||||||
const unsigned int thread_count, bool progress,
|
const cli::runtime_config &runtime_config,
|
||||||
const std::vector<clanguml::common::generator_type_t> &generators,
|
|
||||||
const std::map<std::string, std::vector<std::string>>
|
const std::map<std::string, std::vector<std::string>>
|
||||||
&translation_units_map)
|
&translation_units_map)
|
||||||
{
|
{
|
||||||
util::thread_pool_executor generator_executor{thread_count};
|
util::thread_pool_executor generator_executor{runtime_config.thread_count};
|
||||||
std::vector<std::future<void>> futs;
|
std::vector<std::future<void>> futs;
|
||||||
|
|
||||||
std::unique_ptr<progress_indicator> indicator;
|
std::unique_ptr<progress_indicator> indicator;
|
||||||
|
|
||||||
if (progress) {
|
if (runtime_config.progress) {
|
||||||
std::cout << termcolor::white
|
std::cout << termcolor::white
|
||||||
<< "Processing translation units and generating diagrams:\n";
|
<< "Processing translation units and generating diagrams:\n";
|
||||||
indicator = std::make_unique<progress_indicator>();
|
indicator = std::make_unique<progress_indicator>();
|
||||||
@@ -184,17 +193,17 @@ void generate_diagrams(const std::vector<std::string> &diagram_names,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto generator = [&od, &generators, &name = name, &diagram = diagram,
|
auto generator = [&od, &name = name, &diagram = diagram, &indicator,
|
||||||
&indicator, db = std::ref(*db),
|
db = std::ref(*db),
|
||||||
translation_units = valid_translation_units,
|
translation_units = valid_translation_units,
|
||||||
verbose]() mutable {
|
runtime_config]() mutable {
|
||||||
try {
|
try {
|
||||||
if (indicator)
|
if (indicator)
|
||||||
indicator->add_progress_bar(name, translation_units.size(),
|
indicator->add_progress_bar(name, translation_units.size(),
|
||||||
diagram_type_to_color(diagram->type()));
|
diagram_type_to_color(diagram->type()));
|
||||||
|
|
||||||
generate_diagram(od, name, diagram, db, translation_units,
|
generate_diagram(od, name, diagram, db, translation_units,
|
||||||
generators, verbose != 0, [&indicator, &name]() {
|
runtime_config, [&indicator, &name]() {
|
||||||
if (indicator)
|
if (indicator)
|
||||||
indicator->increment(name);
|
indicator->increment(name);
|
||||||
});
|
});
|
||||||
@@ -217,7 +226,7 @@ void generate_diagrams(const std::vector<std::string> &diagram_names,
|
|||||||
fut.get();
|
fut.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress) {
|
if (runtime_config.progress) {
|
||||||
indicator->stop();
|
indicator->stop();
|
||||||
std::cout << termcolor::white << "Done\n";
|
std::cout << termcolor::white << "Done\n";
|
||||||
std::cout << termcolor::reset;
|
std::cout << termcolor::reset;
|
||||||
|
|||||||
@@ -374,13 +374,14 @@ std::unique_ptr<DiagramModel> generate(const common::compilation_database &db,
|
|||||||
* @param translation_units List of translation units for the diagram
|
* @param translation_units List of translation units for the diagram
|
||||||
* @param generators List of generator types to be used for the diagram
|
* @param generators List of generator types to be used for the diagram
|
||||||
* @param verbose Log level
|
* @param verbose Log level
|
||||||
|
* @param progress Function to report translation unit progress
|
||||||
*/
|
*/
|
||||||
void generate_diagram(const std::string &od, const std::string &name,
|
void generate_diagram(const std::string &od, const std::string &name,
|
||||||
std::shared_ptr<clanguml::config::diagram> diagram,
|
std::shared_ptr<clanguml::config::diagram> diagram,
|
||||||
const common::compilation_database &db,
|
const common::compilation_database &db,
|
||||||
const std::vector<std::string> &translation_units,
|
const std::vector<std::string> &translation_units,
|
||||||
const std::vector<clanguml::common::generator_type_t> &generators,
|
const cli::runtime_config &runtime_config,
|
||||||
bool verbose);
|
std::function<void()> &&progress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate diagrams
|
* @brief Generate diagrams
|
||||||
@@ -397,9 +398,8 @@ void generate_diagram(const std::string &od, const std::string &name,
|
|||||||
*/
|
*/
|
||||||
void generate_diagrams(const std::vector<std::string> &diagram_names,
|
void generate_diagrams(const std::vector<std::string> &diagram_names,
|
||||||
clanguml::config::config &config, const std::string &od,
|
clanguml::config::config &config, const std::string &od,
|
||||||
const common::compilation_database_ptr &db, int verbose,
|
const common::compilation_database_ptr &db,
|
||||||
unsigned int thread_count, bool progress,
|
const cli::runtime_config &runtime_config,
|
||||||
const std::vector<clanguml::common::generator_type_t> &generators,
|
|
||||||
const std::map<std::string, std::vector<std::string>>
|
const std::map<std::string, std::vector<std::string>>
|
||||||
&translation_units_map);
|
&translation_units_map);
|
||||||
|
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ int main(int argc, const char *argv[])
|
|||||||
translation_units_map);
|
translation_units_map);
|
||||||
|
|
||||||
common::generators::generate_diagrams(cli.diagram_names, cli.config,
|
common::generators::generate_diagrams(cli.diagram_names, cli.config,
|
||||||
cli.effective_output_directory, db, cli.verbose, cli.thread_count,
|
cli.effective_output_directory, db, cli.get_runtime_config(),
|
||||||
cli.progress, cli.generators, translation_units_map);
|
translation_units_map);
|
||||||
}
|
}
|
||||||
catch (error::compilation_database_error &e) {
|
catch (error::compilation_database_error &e) {
|
||||||
LOG_ERROR("Failed to load compilation database from {} due to: {}",
|
LOG_ERROR("Failed to load compilation database from {} due to: {}",
|
||||||
|
|||||||
@@ -179,15 +179,15 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
|||||||
else if (m.type() == message_t::kIf) {
|
else if (m.type() == message_t::kIf) {
|
||||||
print_debug(m, ostr);
|
print_debug(m, ostr);
|
||||||
ostr << "alt";
|
ostr << "alt";
|
||||||
if (m.condition_text())
|
if (const auto &text = m.condition_text(); text.has_value())
|
||||||
ostr << " " << m.condition_text().value();
|
ostr << " " << text.value();
|
||||||
ostr << '\n';
|
ostr << '\n';
|
||||||
}
|
}
|
||||||
else if (m.type() == message_t::kElseIf) {
|
else if (m.type() == message_t::kElseIf) {
|
||||||
print_debug(m, ostr);
|
print_debug(m, ostr);
|
||||||
ostr << "else";
|
ostr << "else";
|
||||||
if (m.condition_text())
|
if (const auto &text = m.condition_text(); text.has_value())
|
||||||
ostr << " " << m.condition_text().value();
|
ostr << " " << text.value();
|
||||||
ostr << '\n';
|
ostr << '\n';
|
||||||
}
|
}
|
||||||
else if (m.type() == message_t::kElse) {
|
else if (m.type() == message_t::kElse) {
|
||||||
@@ -200,8 +200,8 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
|||||||
else if (m.type() == message_t::kWhile) {
|
else if (m.type() == message_t::kWhile) {
|
||||||
print_debug(m, ostr);
|
print_debug(m, ostr);
|
||||||
ostr << "loop";
|
ostr << "loop";
|
||||||
if (m.condition_text())
|
if (const auto &text = m.condition_text(); text.has_value())
|
||||||
ostr << " " << m.condition_text().value();
|
ostr << " " << text.value();
|
||||||
ostr << '\n';
|
ostr << '\n';
|
||||||
}
|
}
|
||||||
else if (m.type() == message_t::kWhileEnd) {
|
else if (m.type() == message_t::kWhileEnd) {
|
||||||
@@ -210,8 +210,8 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
|||||||
else if (m.type() == message_t::kFor) {
|
else if (m.type() == message_t::kFor) {
|
||||||
print_debug(m, ostr);
|
print_debug(m, ostr);
|
||||||
ostr << "loop";
|
ostr << "loop";
|
||||||
if (m.condition_text())
|
if (const auto &text = m.condition_text(); text.has_value())
|
||||||
ostr << " " << m.condition_text().value();
|
ostr << " " << text.value();
|
||||||
ostr << '\n';
|
ostr << '\n';
|
||||||
}
|
}
|
||||||
else if (m.type() == message_t::kForEnd) {
|
else if (m.type() == message_t::kForEnd) {
|
||||||
@@ -220,8 +220,8 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
|||||||
else if (m.type() == message_t::kDo) {
|
else if (m.type() == message_t::kDo) {
|
||||||
print_debug(m, ostr);
|
print_debug(m, ostr);
|
||||||
ostr << "loop";
|
ostr << "loop";
|
||||||
if (m.condition_text())
|
if (const auto &text = m.condition_text(); text.has_value())
|
||||||
ostr << " " << m.condition_text().value();
|
ostr << " " << text.value();
|
||||||
ostr << '\n';
|
ostr << '\n';
|
||||||
}
|
}
|
||||||
else if (m.type() == message_t::kDoEnd) {
|
else if (m.type() == message_t::kDoEnd) {
|
||||||
@@ -253,8 +253,8 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
|||||||
else if (m.type() == message_t::kConditional) {
|
else if (m.type() == message_t::kConditional) {
|
||||||
print_debug(m, ostr);
|
print_debug(m, ostr);
|
||||||
ostr << "alt";
|
ostr << "alt";
|
||||||
if (m.condition_text())
|
if (const auto &text = m.condition_text(); text.has_value())
|
||||||
ostr << " " << m.condition_text().value();
|
ostr << " " << text.value();
|
||||||
ostr << '\n';
|
ostr << '\n';
|
||||||
}
|
}
|
||||||
else if (m.type() == message_t::kConditionalElse) {
|
else if (m.type() == message_t::kConditionalElse) {
|
||||||
|
|||||||
@@ -181,6 +181,22 @@ bool diagram::should_include(
|
|||||||
dynamic_cast<const common::model::source_location &>(p));
|
dynamic_cast<const common::model::source_location &>(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> diagram::list_start_from_values() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
for (const auto &[from_id, act] : sequences_) {
|
||||||
|
|
||||||
|
const auto &from_activity = *(participants_.at(from_id));
|
||||||
|
|
||||||
|
result.push_back(from_activity.full_name(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(result.begin(), result.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void diagram::print() const
|
void diagram::print() const
|
||||||
{
|
{
|
||||||
LOG_TRACE(" --- Participants ---");
|
LOG_TRACE(" --- Participants ---");
|
||||||
|
|||||||
@@ -212,6 +212,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool should_include(const sequence_diagram::model::participant &p) const;
|
bool should_include(const sequence_diagram::model::participant &p) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get list of all possible 'start_from' values in the model
|
||||||
|
*
|
||||||
|
* @return List of all possible 'start_from' values
|
||||||
|
*/
|
||||||
|
std::vector<std::string> list_start_from_values() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Once the diagram is complete, run any final processing.
|
* @brief Once the diagram is complete, run any final processing.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user