/** * src/config/config.cc * * Copyright (c) 2021 Bartek Kryza * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" namespace clanguml { namespace config { config load(const std::string &config_file) { YAML::Node doc = YAML::LoadFile(config_file); return doc.as(); } bool diagram::should_include_entities(const std::string &ent) { for (const auto &ex : exclude.entity_types) { if (ent == ex) return false; } if (include.entity_types.empty()) return true; for (const auto &in : include.entity_types) { if (ent == in) return true; } return false; } bool diagram::should_include_relationship(const std::string &rel) { for (const auto &ex : exclude.relationships) { if (rel == ex) return false; } if (include.relationships.empty()) return true; for (const auto &in : include.relationships) { if (rel == in) return true; } return false; } bool diagram::should_include(const std::string &name_) const { auto name = clanguml::util::unqualify(name_); for (const auto &ex : exclude.namespaces) { if (name.find(ex) == 0) { spdlog::debug("Skipping from diagram: {}", name); return false; } } // If no inclusive namespaces are provided, // allow all if (include.namespaces.empty()) return true; for (const auto &in : include.namespaces) { if (name.find(in) == 0) return true; } spdlog::debug("Skipping from diagram: {}", name); return false; } bool diagram::should_include(const model::class_diagram::scope_t scope) const { for (const auto &s : exclude.scopes) { if (s == scope) return false; } if (include.scopes.empty()) return true; for (const auto &s : include.scopes) { if (s == scope) return true; } return false; } bool class_diagram::has_class(std::string clazz) { for (const auto &c : classes) { for (const auto &ns : using_namespace) { std::string prefix{}; if (!ns.empty()) { prefix = ns + "::"; } if (prefix + c == clazz) return true; } } return false; } } } namespace YAML { using clanguml::config::class_diagram; using clanguml::config::config; using clanguml::config::filter; using clanguml::config::plantuml; using clanguml::config::sequence_diagram; using clanguml::config::source_location; using clanguml::model::class_diagram::scope_t; template <> struct convert { static bool decode(const Node &node, scope_t &rhs) { if (node.as() == "public") rhs = scope_t::kPublic; else if (node.as() == "protected") rhs = scope_t::kProtected; else if (node.as() == "private") rhs = scope_t::kPrivate; else return false; return true; } }; template <> struct convert> { static bool decode( const Node &node, std::vector &rhs) { for (auto it = node.begin(); it != node.end(); ++it) { const YAML::Node &n = *it; if (n["usr"]) { rhs.emplace_back(n["usr"].as()); } else if (n["marker"]) { rhs.emplace_back(n["marker"].as()); } else if (n["file"] && n["line"]) { rhs.emplace_back(std::make_pair( n["file"].as(), n["line"].as())); } else { return false; } } return true; } }; template <> struct convert { static bool decode(const Node &node, plantuml &rhs) { if (node["before"]) rhs.before = node["before"].as(); if (node["after"]) rhs.after = node["after"].as(); return true; } }; // // filter Yaml decoder // template <> struct convert { static bool decode(const Node &node, filter &rhs) { if (node["namespaces"]) rhs.namespaces = node["namespaces"].as(); if (node["relationships"]) rhs.relationships = node["relationships"].as(); if (node["entity_types"]) rhs.entity_types = node["entity_types"].as(); if (node["scopes"]) rhs.scopes = node["scopes"].as(); return true; } }; template bool decode_diagram(const Node &node, T &rhs) { if (node["using_namespace"]) rhs.using_namespace = node["using_namespace"].as>(); if (node["glob"]) rhs.glob = node["glob"].as>(); if (node["include"]) rhs.include = node["include"].as(); if (node["exclude"]) rhs.exclude = node["exclude"].as(); if (node["plantuml"]) rhs.puml = node["plantuml"].as(); return true; } // // class_diagram Yaml decoder // template <> struct convert { static bool decode(const Node &node, class_diagram &rhs) { if (!decode_diagram(node, rhs)) return false; if (node["include_relations_also_as_members"]) rhs.include_relations_also_as_members = node["include_relations_also_as_members"] .as(); return true; } }; // // sequence_diagram Yaml decoder // template <> struct convert { static bool decode(const Node &node, sequence_diagram &rhs) { if (!decode_diagram(node, rhs)) return false; if (node["start_from"]) rhs.start_from = node["start_from"].as(); return true; } }; // // config Yaml decoder // template <> struct convert { static bool decode(const Node &node, config &rhs) { if (node["glob"]) rhs.glob = node["glob"].as>(); if (node["output_directory"]) rhs.output_directory = node["output_directory"].as(); if (node["compilation_database_dir"]) rhs.compilation_database_dir = node["compilation_database_dir"].as(); auto diagrams = node["diagrams"]; assert(diagrams.Type() == NodeType::Map); for (const auto &d : diagrams) { const auto diagram_type = d.second["type"].as(); auto name = d.first.as(); if (diagram_type == "class") { rhs.diagrams[name] = std::make_shared( d.second.as()); } else if (diagram_type == "sequence") { rhs.diagrams[name] = std::make_shared( d.second.as()); } else { spdlog::warn( "Diagrams of type {} are not supported at the moment... ", diagram_type); } rhs.diagrams[name]->name = name; } return true; } }; }