Added initial support for MermaidJS include diagrams
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
#include "common/model/diagram_filter.h"
|
#include "common/model/diagram_filter.h"
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "include_diagram/generators/json/include_diagram_generator.h"
|
#include "include_diagram/generators/json/include_diagram_generator.h"
|
||||||
|
#include "include_diagram/generators/mermaid/include_diagram_generator.h"
|
||||||
#include "include_diagram/generators/plantuml/include_diagram_generator.h"
|
#include "include_diagram/generators/plantuml/include_diagram_generator.h"
|
||||||
#include "indicators/indicators.hpp"
|
#include "indicators/indicators.hpp"
|
||||||
#include "package_diagram/generators/json/package_diagram_generator.h"
|
#include "package_diagram/generators/json/package_diagram_generator.h"
|
||||||
@@ -180,11 +181,11 @@ struct diagram_generator_t<clanguml::config::package_diagram,
|
|||||||
mermaid_generator_tag> {
|
mermaid_generator_tag> {
|
||||||
using type = clanguml::package_diagram::generators::mermaid::generator;
|
using type = clanguml::package_diagram::generators::mermaid::generator;
|
||||||
};
|
};
|
||||||
// template <>
|
template <>
|
||||||
// struct diagram_generator_t<clanguml::config::include_diagram,
|
struct diagram_generator_t<clanguml::config::include_diagram,
|
||||||
// mermaid_generator_tag> {
|
mermaid_generator_tag> {
|
||||||
// using type = clanguml::include_diagram::generators::mermaid::generator;
|
using type = clanguml::include_diagram::generators::mermaid::generator;
|
||||||
// };
|
};
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
/**
|
||||||
|
* @file src/include_diagram/generators/mermaid/include_diagram_generator.cc
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 "include_diagram_generator.h"
|
||||||
|
|
||||||
|
#include "util/error.h"
|
||||||
|
|
||||||
|
namespace clanguml::include_diagram::generators::mermaid {
|
||||||
|
|
||||||
|
using clanguml::common::generators::mermaid::indent;
|
||||||
|
|
||||||
|
generator::generator(diagram_config &config, diagram_model &model)
|
||||||
|
: common_generator<diagram_config, diagram_model>{config, model}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator::generate_relationships(
|
||||||
|
const source_file &f, std::ostream &ostr) const
|
||||||
|
{
|
||||||
|
if (!util::contains(m_generated_aliases, f.alias()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG_DBG("Generating relationships for file {}", f.full_name(true));
|
||||||
|
|
||||||
|
namespace mermaid_common = clanguml::common::generators::mermaid;
|
||||||
|
|
||||||
|
if (f.type() == common::model::source_file_t::kDirectory) {
|
||||||
|
util::for_each(f, [this, &ostr](const auto &file) {
|
||||||
|
generate_relationships(
|
||||||
|
dynamic_cast<const source_file &>(*file), ostr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
util::for_each_if(
|
||||||
|
f.relationships(),
|
||||||
|
[this](const auto &r) {
|
||||||
|
return model().should_include(r.type()) &&
|
||||||
|
util::contains(m_generated_aliases,
|
||||||
|
model().get(r.destination()).value().alias());
|
||||||
|
},
|
||||||
|
[&f, &ostr, this](const auto &r) {
|
||||||
|
ostr << indent(1) << f.alias() << " "
|
||||||
|
<< (r.type() == common::model::relationship_t::kDependency
|
||||||
|
? "-.->"
|
||||||
|
: "-->")
|
||||||
|
<< " " << model().get(r.destination()).value().alias()
|
||||||
|
<< '\n';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator::generate(const source_file &f, std::ostream &ostr) const
|
||||||
|
{
|
||||||
|
if (f.type() == common::model::source_file_t::kDirectory) {
|
||||||
|
LOG_DBG("Generating directory {}", f.name());
|
||||||
|
|
||||||
|
ostr << indent(1) << "subgraph " << f.alias() << "[" << f.name()
|
||||||
|
<< "]\n";
|
||||||
|
|
||||||
|
util::for_each(f, [this, &ostr](const auto &file) {
|
||||||
|
generate(dynamic_cast<const source_file &>(*file), ostr);
|
||||||
|
});
|
||||||
|
|
||||||
|
ostr << indent(1) << "end" << '\n';
|
||||||
|
|
||||||
|
m_generated_aliases.emplace(f.alias());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_DBG("Generating file {}", f.name());
|
||||||
|
|
||||||
|
if (model().should_include(f)) {
|
||||||
|
ostr << indent(1) << f.alias() << "[" << f.name() << "]\n";
|
||||||
|
|
||||||
|
m_generated_aliases.emplace(f.alias());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator::generate_notes(
|
||||||
|
std::ostream &ostr, const common::model::source_file &element) const
|
||||||
|
{
|
||||||
|
const auto &config =
|
||||||
|
common_generator<diagram_config, diagram_model>::config();
|
||||||
|
|
||||||
|
for (const auto &decorator : element.decorators()) {
|
||||||
|
auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
|
||||||
|
if (note && note->applies_to_diagram(config.name)) {
|
||||||
|
auto note_id_str = fmt::format("N_{}", note_id_++);
|
||||||
|
|
||||||
|
ostr << indent(1) << note_id_str << "(" << note->text << ")\n";
|
||||||
|
|
||||||
|
ostr << indent(1) << note_id_str << "-.-" << element.alias()
|
||||||
|
<< '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator::generate_diagram(std::ostream &ostr) const
|
||||||
|
{
|
||||||
|
ostr << "flowchart\n";
|
||||||
|
|
||||||
|
// Generate files and folders
|
||||||
|
util::for_each(model(), [this, &ostr](const auto &f) {
|
||||||
|
generate(dynamic_cast<source_file &>(*f), ostr);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Process file include relationships
|
||||||
|
util::for_each(model(), [this, &ostr](const auto &f) {
|
||||||
|
generate_relationships(dynamic_cast<source_file &>(*f), ostr);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Process file notes
|
||||||
|
util::for_each(model(), [this, &ostr](const auto &f) {
|
||||||
|
generate_notes(ostr, dynamic_cast<source_file &>(*f));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} // namespace clanguml::include_diagram::generators::plantuml
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* @file src/include_diagram/generators/mermaid/include_diagram_generator.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/generators/mermaid/generator.h"
|
||||||
|
#include "common/model/package.h"
|
||||||
|
#include "common/model/relationship.h"
|
||||||
|
#include "common/model/source_file.h"
|
||||||
|
#include "config/config.h"
|
||||||
|
#include "include_diagram/model/diagram.h"
|
||||||
|
#include "include_diagram/visitor/translation_unit_visitor.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace clanguml::include_diagram::generators::mermaid {
|
||||||
|
|
||||||
|
using diagram_config = clanguml::config::include_diagram;
|
||||||
|
using diagram_model = clanguml::include_diagram::model::diagram;
|
||||||
|
|
||||||
|
template <typename C, typename D>
|
||||||
|
using common_generator = clanguml::common::generators::mermaid::generator<C, D>;
|
||||||
|
|
||||||
|
using clanguml::common::model::access_t;
|
||||||
|
using clanguml::common::model::package;
|
||||||
|
using clanguml::common::model::relationship_t;
|
||||||
|
using clanguml::common::model::source_file;
|
||||||
|
using namespace clanguml::util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Include diagram MermaidJS generator
|
||||||
|
*/
|
||||||
|
class generator : public common_generator<diagram_config, diagram_model> {
|
||||||
|
public:
|
||||||
|
generator(diagram_config &config, diagram_model &model);
|
||||||
|
|
||||||
|
using common_generator<diagram_config, diagram_model>::generate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main generator method.
|
||||||
|
*
|
||||||
|
* This method is called first and coordinates the entire diagram
|
||||||
|
* generation.
|
||||||
|
*
|
||||||
|
* @param ostr Output stream.
|
||||||
|
*/
|
||||||
|
void generate_diagram(std::ostream &ostr) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate relationships originating from source_file `f`
|
||||||
|
*
|
||||||
|
* @param p Diagram element
|
||||||
|
* @param parent Output stream
|
||||||
|
*/
|
||||||
|
void generate_relationships(const source_file &p, std::ostream &ostr) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate notes attached to files
|
||||||
|
*
|
||||||
|
* @param ostr Output stream
|
||||||
|
* @param element Element with a note
|
||||||
|
*/
|
||||||
|
void generate_notes(
|
||||||
|
std::ostream &ostr, const common::model::source_file &element) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate diagram element
|
||||||
|
*
|
||||||
|
* @param e Source file diagram element
|
||||||
|
* @param parent Output stream
|
||||||
|
*/
|
||||||
|
void generate(const source_file &e, std::ostream &ostr) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable unsigned long note_id_{0UL};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace clanguml::include_diagram::generators::mermaid
|
||||||
@@ -21,3 +21,7 @@ diagrams:
|
|||||||
after:
|
after:
|
||||||
- 'note right of {{ alias("include/lib1") }}: This is a lib1 include dir'
|
- 'note right of {{ alias("include/lib1") }}: This is a lib1 include dir'
|
||||||
- 'note right of {{ alias("include/t40001_include1.h") }}: This is a t40001_include1.h include file'
|
- 'note right of {{ alias("include/t40001_include1.h") }}: This is a t40001_include1.h include file'
|
||||||
|
mermaid:
|
||||||
|
after:
|
||||||
|
- 'N_00001(This is a lib1 include dir)-.-{{ alias("include/lib1") }}'
|
||||||
|
- 'N_00002(This is a lib1 include dir)-.-{{ alias("include/t40001_include1.h") }}'
|
||||||
@@ -79,4 +79,10 @@ TEST_CASE("t40001", "[test-case][include]")
|
|||||||
|
|
||||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mmd = generate_include_mermaid(diagram, *model);
|
||||||
|
|
||||||
|
save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,4 +110,10 @@ TEST_CASE("t40002", "[test-case][include]")
|
|||||||
|
|
||||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mmd = generate_include_mermaid(diagram, *model);
|
||||||
|
|
||||||
|
save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,4 +74,10 @@ TEST_CASE("t40003", "[test-case][include]")
|
|||||||
|
|
||||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mmd = generate_include_mermaid(diagram, *model);
|
||||||
|
|
||||||
|
save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,6 +251,14 @@ std::string generate_package_mermaid(
|
|||||||
config, model);
|
config, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string generate_include_mermaid(
|
||||||
|
std::shared_ptr<clanguml::config::diagram> config,
|
||||||
|
clanguml::include_diagram::model::diagram &model)
|
||||||
|
{
|
||||||
|
return detail::generate_diagram_mermaid<clanguml::config::include_diagram>(
|
||||||
|
config, model);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void save_diagram(const std::filesystem::path &path, const T &diagram)
|
void save_diagram(const std::filesystem::path &path, const T &diagram)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user