diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 997e3b2e..cb1f75a2 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -200,6 +200,13 @@ the configuration file to `clang-uml` using `stdin`, e.g.: yq 'explode(.)' .clang-uml | clang-uml --config - ``` +## Schema validation error is thrown, but the configuration file is correct +Current version of `clang-uml` performs automatic configuration file +schema validation, and exits if the configuration file is invalid. + +In case there is a bug in the schema validation, the schema validation +step can be skipped by providing `--no-validate` command line option. + ## Class diagrams ### "fatal error: 'stddef.h' file not found" diff --git a/src/cli/cli_handler.cc b/src/cli/cli_handler.cc index 5812045a..85b20fc3 100644 --- a/src/cli/cli_handler.cc +++ b/src/cli/cli_handler.cc @@ -131,6 +131,10 @@ cli_flow_t cli_handler::parse(int argc, const char **argv) "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"); + app.add_flag("--no-validate", no_validate, + "Do not perform configuration file schema validation"); + app.add_flag("--validate-only", validate_only, + "Perform configuration file schema validation and exit"); try { app.parse(argc, argv); @@ -245,7 +249,13 @@ cli_flow_t cli_handler::load_config() { try { config = clanguml::config::load( - config_path, paths_relative_to_pwd, no_metadata); + config_path, paths_relative_to_pwd, no_metadata, !no_validate); + if (validate_only) { + LOG_INFO("Configuration file {} is valid.", config_path); + + return cli_flow_t::kExit; + } + return cli_flow_t::kContinue; } catch (std::runtime_error &e) { diff --git a/src/cli/cli_handler.h b/src/cli/cli_handler.h index b785b14a..a281b70f 100644 --- a/src/cli/cli_handler.h +++ b/src/cli/cli_handler.h @@ -183,6 +183,8 @@ public: std::optional show_template; std::vector generators{ clanguml::common::generator_type_t::plantuml}; + bool no_validate{false}; + bool validate_only{false}; clanguml::config::config config; diff --git a/src/config/config.h b/src/config/config.h index 46f470c2..2cb6a2ba 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -36,6 +36,10 @@ namespace clanguml { +namespace cli { +struct runtime_config; +} // namespace cli + /** * @brief Configuration file related classes * @@ -472,7 +476,7 @@ struct inheritable_diagram_options { * @embed{diagram_config_hierarchy_class.svg} */ struct diagram : public inheritable_diagram_options { - virtual ~diagram() = default; + ~diagram() override = default; virtual common::model::diagram_t type() const = 0; @@ -622,11 +626,12 @@ struct config : public inheritable_diagram_options { * the configuration file or to the current * directory (`$PWD`) * @param no_metadata Whether the diagram should skip metadata at the end + * @param validate If true, perform schema validation * @return Configuration instance */ config load(const std::string &config_file, std::optional paths_relative_to_pwd = {}, - std::optional no_metadata = {}); + std::optional no_metadata = {}, bool validate = true); } // namespace config diff --git a/src/config/schema.h b/src/config/schema.h index d1bda894..62f1c2b5 100644 --- a/src/config/schema.h +++ b/src/config/schema.h @@ -64,6 +64,10 @@ types: - class - enum - concept + - method + - function + - function_template + - lambda relationship_filter_t: !variant - extension - inheritance diff --git a/src/config/yaml_decoders.cc b/src/config/yaml_decoders.cc index 08541326..22fbf1b4 100644 --- a/src/config/yaml_decoders.cc +++ b/src/config/yaml_decoders.cc @@ -16,6 +16,7 @@ * limitations under the License. */ +#include "cli/cli_handler.h" #include "config.h" #include "diagram_templates.h" #include "schema.h" @@ -831,7 +832,8 @@ void resolve_option_path(YAML::Node &doc, const std::string &option) } // namespace config load(const std::string &config_file, - std::optional paths_relative_to_pwd, std::optional no_metadata) + std::optional paths_relative_to_pwd, std::optional no_metadata, + bool validate) { try { auto schema = YAML::Load(clanguml::config::schema_str); @@ -930,15 +932,17 @@ config load(const std::string &config_file, } } - auto schema_errors = schema_validator.validate(doc); + if (validate) { + auto schema_errors = schema_validator.validate(doc); - if (schema_errors.size() > 0) { - // print validation errors - for (const auto &err : schema_errors) { - LOG_ERROR("Schema error: {}", err.description()); + if (!schema_errors.empty()) { + // print validation errors + for (const auto &err : schema_errors) { + LOG_ERROR("Schema error: {}", err.description()); + } + + throw YAML::Exception({}, "Invalid configuration schema"); } - - throw YAML::Exception({}, "Invalid configuration schema"); } auto d = doc.as(); diff --git a/uml/class/diagram_element_hierarchy_class.yml b/uml/class/diagram_element_hierarchy_class.yml index 60d1792c..3a12c8b0 100644 --- a/uml/class/diagram_element_hierarchy_class.yml +++ b/uml/class/diagram_element_hierarchy_class.yml @@ -12,9 +12,8 @@ include: subclasses: - clanguml::common::model::decorated_element - clanguml::common::model::source_location - include: - relationships: - - inheritance + relationships: + - inheritance exclude: relationships: - dependency