Compare commits
10 Commits
add-title-
...
llvm-17-su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7b4efa80e | ||
|
|
e7d6c94a14 | ||
|
|
f339c34dd8 | ||
|
|
26abb71b4c | ||
|
|
8865a42ff0 | ||
|
|
13a1012e96 | ||
|
|
92422624cb | ||
|
|
9d43281bdd | ||
|
|
c398c6ffda | ||
|
|
1983a609a0 |
@@ -1,6 +1,8 @@
|
||||
compilation_database_dir: debug
|
||||
output_directory: docs/diagrams
|
||||
comment_parser: clang
|
||||
remove_compile_flags:
|
||||
- -Wno-class-memaccess
|
||||
generate_links:
|
||||
link: "{% if existsIn(element, \"doxygen_link\") %}{{ element.doxygen_link }}{% endif %}"
|
||||
tooltip: "{% if existsIn(element, \"comment\") and existsIn(element.comment, \"brief\") %}{{ abbrv(trim(replace(element.comment.brief.0, \"\\n+\", \" \")), 256) }}{% else %}{{ element.name }}{% endif %}"
|
||||
@@ -72,4 +74,4 @@ diagrams:
|
||||
include!: uml/package/architecture_package.yml
|
||||
# Include diagrams
|
||||
include_graph:
|
||||
include!: uml/include/include.yml
|
||||
include!: uml/include/include.yml
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# CHANGELOG
|
||||
|
||||
* Excluded package diagram relationships to rejected packages (#185)
|
||||
* Added 'title' diagram property (#184)
|
||||
* Make sure sequence diagram messages generated during static variable
|
||||
initialization are rendered only once (#183)
|
||||
|
||||
### 0.4.0
|
||||
* Added MermaidJS diagram generators (#27)
|
||||
|
||||
|
||||
@@ -132,6 +132,20 @@ if(APPLE OR (LLVM_VERSION_MAJOR GREATER_EQUAL 16))
|
||||
${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
|
||||
endif()
|
||||
|
||||
#
|
||||
# Setup custom compile options depending on various compiler
|
||||
# and environment quirks
|
||||
#
|
||||
if(LLVM_VERSION_MAJOR GREATER_EQUAL 17)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CUSTOM_COMPILE_OPTIONS "-Wno-class-memaccess")
|
||||
endif()
|
||||
endif()
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(CUSTOM_COMPILE_OPTIONS
|
||||
"${CUSTOM_COMPILE_OPTIONS} -Wno-unused-private-field")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Setup threads library
|
||||
#
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[](https://github.com/bkryza/clang-uml/actions)
|
||||
[](https://codecov.io/gh/bkryza/clang-uml)
|
||||
[](https://github.com/bkryza/clang-uml/releases)
|
||||
[](https://github.com/bkryza/clang-uml/releases)
|
||||
[](https://github.com/bkryza/clang-uml/releases)
|
||||
[](https://clang-uml.github.io)
|
||||
|
||||
`clang-uml` is an automatic C++ to UML class, sequence, package and include diagram generator, driven by
|
||||
@@ -80,6 +80,7 @@ Nowadays, this file can be generated rather easily using multiple methods:
|
||||
* For Boost-based projects
|
||||
try [commands_to_compilation_database](https://github.com/tee3/commands_to_compilation_database)
|
||||
* For SCons, invoke `compilation_db` tool (requires SCons > 4.0.0)
|
||||
* For Bazel, try [bazel-compile-commands-extractor](https://github.com/hedronvision/bazel-compile-commands-extractor)
|
||||
* For Microsoft Visual Studio projects try [Clang Power Tools](https://www.clangpowertools.com)
|
||||
|
||||
### Invocation
|
||||
|
||||
@@ -25,8 +25,8 @@ endif(MSVC)
|
||||
target_compile_features(clang-umllib INTERFACE cxx_std_17)
|
||||
target_compile_options(clang-umllib PRIVATE
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>>:
|
||||
-Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-private-field
|
||||
-Wno-deprecated-declarations>
|
||||
-Werror -Wall -Wextra -Wno-unused-parameter
|
||||
-Wno-deprecated-declarations ${CUSTOM_COMPILE_OPTIONS}>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/MP /W1 /bigobj /wd4291 /wd4624 /wd4244>)
|
||||
target_compile_definitions(clang-umllib PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:
|
||||
@@ -40,8 +40,8 @@ add_executable(clang-uml ${MAIN_SOURCE_FILE})
|
||||
target_compile_features(clang-uml PUBLIC cxx_std_17)
|
||||
target_compile_options(clang-uml PRIVATE
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>>:
|
||||
-Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-private-field
|
||||
-Wno-deprecated-declarations>
|
||||
-Werror -Wall -Wextra -Wno-unused-parameter
|
||||
-Wno-deprecated-declarations ${CUSTOM_COMPILE_OPTIONS}>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/MP /W1 /bigobj /wd4291 /wd4624 /wd4244>)
|
||||
target_compile_definitions(clang-uml PRIVATE
|
||||
${ENABLE_BACKWARD_CPP})
|
||||
|
||||
@@ -30,6 +30,16 @@ diagram_element::id_t diagram_element::id() const { return id_; }
|
||||
|
||||
void diagram_element::set_id(diagram_element::id_t id) { id_ = id; }
|
||||
|
||||
std::optional<id_t> diagram_element::parent_element_id() const
|
||||
{
|
||||
return parent_element_id_;
|
||||
}
|
||||
|
||||
void diagram_element::set_parent_element_id(diagram_element::id_t id)
|
||||
{
|
||||
parent_element_id_ = id;
|
||||
}
|
||||
|
||||
std::string diagram_element::alias() const
|
||||
{
|
||||
assert(id_ >= 0);
|
||||
|
||||
@@ -64,6 +64,20 @@ public:
|
||||
*/
|
||||
void set_id(id_t id);
|
||||
|
||||
/**
|
||||
* Get elements parent package id.
|
||||
*
|
||||
* @return Parent package id if element is nested.
|
||||
*/
|
||||
std::optional<id_t> parent_element_id() const;
|
||||
|
||||
/**
|
||||
* Set elements parent package id.
|
||||
*
|
||||
* @param id Id of parent package.
|
||||
*/
|
||||
void set_parent_element_id(diagram_element::id_t id);
|
||||
|
||||
/**
|
||||
* @brief Return elements' diagram alias.
|
||||
*
|
||||
@@ -174,6 +188,7 @@ public:
|
||||
|
||||
private:
|
||||
id_t id_{0};
|
||||
std::optional<id_t> parent_element_id_{0};
|
||||
std::string name_;
|
||||
std::vector<relationship> relationships_;
|
||||
bool nested_{false};
|
||||
|
||||
@@ -248,10 +248,6 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const
|
||||
e.full_name(false);
|
||||
});
|
||||
|
||||
if (tvl::is_false(result))
|
||||
LOG_DBG("Element {} rejected by namespace_filter 1",
|
||||
e.full_name(false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -273,10 +269,6 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const
|
||||
e.full_name(false);
|
||||
});
|
||||
|
||||
if (tvl::is_false(result))
|
||||
LOG_DBG("Element {} rejected by namespace_filter (package diagram)",
|
||||
e.full_name(false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -290,9 +282,6 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const
|
||||
return std::get<common::regex>(nsit.value()) %= e.full_name(false);
|
||||
});
|
||||
|
||||
if (tvl::is_false(result))
|
||||
LOG_DBG("Element {} rejected by namespace_filter", e.full_name(false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,9 +94,11 @@ public:
|
||||
|
||||
auto parent = get_element(path);
|
||||
|
||||
if (parent && dynamic_cast<nested_trait<T, Path> *>(&parent.value()))
|
||||
if (parent && dynamic_cast<nested_trait<T, Path> *>(&parent.value())) {
|
||||
p->set_parent_element_id(parent.value().id());
|
||||
return dynamic_cast<nested_trait<T, Path> &>(parent.value())
|
||||
.template add_element<V>(std::move(p));
|
||||
}
|
||||
|
||||
LOG_INFO("No parent element found at: {}", path.to_string());
|
||||
|
||||
|
||||
@@ -504,8 +504,6 @@ private:
|
||||
/*! Whether template argument is ellipsis (...) */
|
||||
bool is_ellipsis_{false};
|
||||
|
||||
bool is_noexcept_{false};
|
||||
|
||||
/*! Whether the template parameter is variadic */
|
||||
bool is_variadic_{false};
|
||||
|
||||
|
||||
@@ -123,6 +123,12 @@ void translation_unit_visitor::set_source_location(
|
||||
}
|
||||
}
|
||||
|
||||
if (std::filesystem::path file_path{file}; !file_path.is_absolute()) {
|
||||
file_path =
|
||||
std::filesystem::canonical(std::filesystem::absolute(file_path));
|
||||
file = file_path.string();
|
||||
}
|
||||
|
||||
element.set_file(file);
|
||||
element.set_file_relative(util::path_to_url(
|
||||
std::filesystem::relative(element.file(), relative_to_path_).string()));
|
||||
|
||||
@@ -36,6 +36,14 @@ void generator::generate_relationships(
|
||||
if (model().should_include(relationship_t::kDependency)) {
|
||||
for (const auto &r : p.relationships()) {
|
||||
nlohmann::json rel = r;
|
||||
|
||||
auto destination_package = model().get(r.destination());
|
||||
|
||||
if (!destination_package ||
|
||||
!model().should_include(
|
||||
dynamic_cast<const package &>(*destination_package)))
|
||||
continue;
|
||||
|
||||
rel["source"] = std::to_string(p.id());
|
||||
parent["relationships"].push_back(std::move(rel));
|
||||
}
|
||||
|
||||
@@ -45,9 +45,17 @@ void generator::generate_relationships(
|
||||
for (const auto &r : p.relationships()) {
|
||||
std::stringstream relstr;
|
||||
try {
|
||||
auto destination = model().to_alias(r.destination());
|
||||
if (!destination.empty()) {
|
||||
relstr << p.alias() << " -.-> " << destination << '\n';
|
||||
auto destination_package = model().get(r.destination());
|
||||
|
||||
if (!destination_package ||
|
||||
!model().should_include(
|
||||
dynamic_cast<const package &>(*destination_package)))
|
||||
continue;
|
||||
|
||||
auto destination_alias = model().to_alias(r.destination());
|
||||
if (!destination_alias.empty()) {
|
||||
relstr << p.alias() << " -.-> " << destination_alias
|
||||
<< '\n';
|
||||
ostr << indent(1) << relstr.str();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,9 +38,17 @@ void generator::generate_relationships(
|
||||
for (const auto &r : p.relationships()) {
|
||||
std::stringstream relstr;
|
||||
try {
|
||||
auto destination = model().to_alias(r.destination());
|
||||
if (!destination.empty()) {
|
||||
relstr << p.alias() << " ..> " << destination << '\n';
|
||||
auto destination_package = model().get(r.destination());
|
||||
|
||||
if (!destination_package ||
|
||||
!model().should_include(
|
||||
dynamic_cast<const package &>(*destination_package)))
|
||||
continue;
|
||||
|
||||
auto destination_alias = model().to_alias(r.destination());
|
||||
|
||||
if (!destination_alias.empty()) {
|
||||
relstr << p.alias() << " ..> " << destination_alias << '\n';
|
||||
ostr << relstr.str();
|
||||
}
|
||||
}
|
||||
@@ -54,8 +62,9 @@ void generator::generate_relationships(
|
||||
|
||||
// Process it's subpackages relationships
|
||||
for (const auto &subpackage : p) {
|
||||
generate_relationships(
|
||||
dynamic_cast<const package &>(*subpackage), ostr);
|
||||
if (model().should_include(dynamic_cast<const package &>(*subpackage)))
|
||||
generate_relationships(
|
||||
dynamic_cast<const package &>(*subpackage), ostr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,12 +76,12 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
|
||||
p->set_name(name);
|
||||
p->set_namespace(package_parent);
|
||||
p->set_id(common::to_id(*ns));
|
||||
set_source_location(*ns, *p);
|
||||
|
||||
assert(p->id() > 0);
|
||||
|
||||
if (diagram().should_include(*p) && !diagram().get(p->id())) {
|
||||
process_comment(*ns, *p);
|
||||
set_source_location(*ns, *p);
|
||||
|
||||
p->set_style(p->style_spec());
|
||||
|
||||
@@ -232,8 +232,10 @@ void translation_unit_visitor::add_relationships(
|
||||
|
||||
pkg->set_name(pkg_name);
|
||||
pkg->set_id(get_package_id(cls));
|
||||
set_source_location(*cls, *pkg);
|
||||
|
||||
diagram().add(parent_path, std::move(pkg));
|
||||
if (diagram().should_include(*pkg))
|
||||
diagram().add(parent_path, std::move(pkg));
|
||||
}
|
||||
|
||||
auto current_package_id = get_package_id(cls);
|
||||
@@ -246,8 +248,21 @@ void translation_unit_visitor::add_relationships(
|
||||
auto current_package = diagram().get(current_package_id);
|
||||
|
||||
if (current_package) {
|
||||
std::vector<common::model::diagram_element::id_t> parent_ids =
|
||||
get_parent_package_ids(current_package_id);
|
||||
|
||||
for (const auto &dependency : relationships) {
|
||||
const auto destination_id = std::get<0>(dependency);
|
||||
|
||||
// Skip dependency relationships to parent packages
|
||||
if (util::contains(parent_ids, destination_id))
|
||||
continue;
|
||||
|
||||
// Skip dependency relationship to child packages
|
||||
if (util::contains(
|
||||
get_parent_package_ids(destination_id), current_package_id))
|
||||
continue;
|
||||
|
||||
relationship r{relationship_t::kDependency, destination_id,
|
||||
common::model::access_t::kNone};
|
||||
if (destination_id != current_package_id)
|
||||
@@ -605,4 +620,23 @@ translation_unit_visitor::config() const
|
||||
|
||||
void translation_unit_visitor::finalize() { }
|
||||
|
||||
std::vector<common::model::diagram_element::id_t>
|
||||
translation_unit_visitor::get_parent_package_ids(
|
||||
common::model::diagram_element::id_t id)
|
||||
{
|
||||
std::vector<common::model::diagram_element::id_t> parent_ids;
|
||||
std::optional<common::model::diagram_element::id_t> parent_id = id;
|
||||
|
||||
while (parent_id.has_value()) {
|
||||
parent_ids.push_back(parent_id.value());
|
||||
auto parent = this->diagram().get(parent_id.value());
|
||||
if (parent)
|
||||
parent_id = parent.value().parent_element_id();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return parent_ids;
|
||||
}
|
||||
|
||||
} // namespace clanguml::package_diagram::visitor
|
||||
|
||||
@@ -214,6 +214,9 @@ private:
|
||||
void add_relationships(
|
||||
clang::Decl *cls, found_relationships_t &relationships);
|
||||
|
||||
std::vector<common::model::diagram_element::id_t> get_parent_package_ids(
|
||||
common::model::diagram_element::id_t id);
|
||||
|
||||
// Reference to the output diagram model
|
||||
clanguml::package_diagram::model::diagram &diagram_;
|
||||
|
||||
|
||||
@@ -328,8 +328,6 @@ private:
|
||||
return block_end_types.count(mt) > 0;
|
||||
};
|
||||
|
||||
bool started_{false};
|
||||
|
||||
std::map<common::model::diagram_element::id_t, activity> sequences_;
|
||||
|
||||
std::map<common::model::diagram_element::id_t, std::unique_ptr<participant>>
|
||||
|
||||
@@ -58,8 +58,9 @@ foreach(TEST_NAME ${TEST_CASES})
|
||||
target_compile_options(${TEST_NAME} PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CXX>:
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>>:
|
||||
-Wno-unused-parameter -Wno-unused-private-field -Wno-unused-variable
|
||||
-Wno-attributes -Wno-nonnull -Wno-deprecated-enum-enum-conversion>
|
||||
-Wno-unused-parameter -Wno-unused-variable
|
||||
-Wno-attributes -Wno-nonnull -Wno-deprecated-enum-enum-conversion
|
||||
${CUSTOM_COMPILE_OPTIONS}>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/W1 /bigobj /wd4624>>)
|
||||
target_link_libraries(${TEST_NAME} PRIVATE ${CLANG_UML_TEST_LIBRARIES})
|
||||
endforeach()
|
||||
|
||||
@@ -13301,9 +13301,6 @@ bool RegexMatcher::match(std::string const &matchee) const
|
||||
{
|
||||
auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax
|
||||
// option anyway
|
||||
#if !defined(_WIN32)
|
||||
flags |= std::regex::multiline;
|
||||
#endif
|
||||
|
||||
if (m_caseSensitivity == CaseSensitive::Choice::No) {
|
||||
flags |= std::regex::icase;
|
||||
|
||||
@@ -263,12 +263,12 @@ template <typename T>
|
||||
void save_diagram(const std::filesystem::path &path, const T &diagram)
|
||||
{
|
||||
static_assert(
|
||||
std::same_as<T, std::string> || std::same_as<T, nlohmann::json>);
|
||||
std::is_same_v<T, std::string> || std::is_same_v<T, nlohmann::json>);
|
||||
|
||||
std::filesystem::create_directories(path.parent_path());
|
||||
std::ofstream ofs;
|
||||
ofs.open(path, std::ofstream::out | std::ofstream::trunc);
|
||||
if constexpr (std::same_as<T, nlohmann::json>) {
|
||||
if constexpr (std::is_same_v<T, nlohmann::json>) {
|
||||
ofs << std::setw(2) << diagram;
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user