Compare commits
13 Commits
0.5.1
...
fix-codeco
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57d24da0df | ||
|
|
7317761670 | ||
|
|
87a1e876cc | ||
|
|
449729d54e | ||
|
|
a61d719a69 | ||
|
|
42c9fa4579 | ||
|
|
0da2585c3f | ||
|
|
8e24a2cb63 | ||
|
|
e3fd1382e9 | ||
|
|
31d8f4d773 | ||
|
|
0fac87c27a | ||
|
|
06ada3af55 | ||
|
|
97b094f77e |
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Update package database
|
||||
run: sudo apt -y update
|
||||
- name: Install deps
|
||||
@@ -51,5 +51,7 @@ jobs:
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: coverage-src.info
|
||||
disable_search: true
|
||||
name: clang-uml
|
||||
fail_ci_if_error: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: false
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -33,6 +33,10 @@ coverage*.info
|
||||
packaging/_BUILD
|
||||
packaging/conda/meta.yaml
|
||||
|
||||
#nix
|
||||
.direnv/
|
||||
result
|
||||
|
||||
# CLion
|
||||
|
||||
.idea/
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# CHANGELOG
|
||||
|
||||
* Fixed building with LLVM 18 (#251)
|
||||
|
||||
### 0.5.1
|
||||
|
||||
* Fixed elements filter in sequence diagrams (#248)
|
||||
|
||||
@@ -107,6 +107,7 @@ if(APPLE)
|
||||
set(YAML_CPP_LIBRARY_DIR ${HOMEBREW_PREFIX}/lib)
|
||||
endif(PKG_CONFIG_FOUND)
|
||||
elseif(MSVC)
|
||||
find_package(yaml-cpp REQUIRED)
|
||||
set(YAML_CPP_LIBRARIES "yaml-cpp")
|
||||
else()
|
||||
find_package(yaml-cpp REQUIRED)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
message(STATUS "Checking for LLVM and Clang...")
|
||||
|
||||
if(LLVM_VERSION STREQUAL "18")
|
||||
set(LLVM_VERSION "18.1")
|
||||
endif()
|
||||
|
||||
# If user provided a path to llvm-config executable use it to detect
|
||||
# LLVM Version and appropriate CMake module path
|
||||
if(NOT "${LLVM_CONFIG_PATH}" STREQUAL "")
|
||||
@@ -77,6 +81,11 @@ else(LINK_LLVM_SHARED)
|
||||
if(${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "16.0")
|
||||
list(APPEND LIBTOOLING_LIBS clangASTMatchers)
|
||||
endif()
|
||||
if(MSVC)
|
||||
if(${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "18.1")
|
||||
list(APPEND LIBTOOLING_LIBS clangAPINotes)
|
||||
endif()
|
||||
endif(MSVC)
|
||||
endif(LINK_LLVM_SHARED)
|
||||
|
||||
if("${LIBTOOLING_LIBS}" STREQUAL "")
|
||||
|
||||
@@ -53,6 +53,23 @@ conda config --set channel_priority strict
|
||||
conda install -c bkryza/label/clang-uml clang-uml
|
||||
```
|
||||
|
||||
#### nix
|
||||
|
||||
```bash
|
||||
git clone https://github.com/bkryza/clang-uml
|
||||
|
||||
# To build using nix flakes
|
||||
nix --extra-experimental-features 'nix-command flakes' build
|
||||
|
||||
# or without nix flakes
|
||||
nix-build -E 'with import <nixpkgs> { }; callPackage ./packaging/nix { }'
|
||||
```
|
||||
|
||||
Or if you have flake enabled, you can also directly run
|
||||
```bash
|
||||
nix run github:bkryza/clang-uml
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
Download and run the latest Windows installer from
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* [Diagram generation is very slow](#diagram-generation-is-very-slow)
|
||||
* [Diagram generated with PlantUML is cropped](#diagram-generated-with-plantuml-is-cropped)
|
||||
* [Clang produces several warnings during diagram generation](#clang-produces-several-warnings-during-diagram-generation)
|
||||
* [Errors with C++20 modules and LLVM 18](#errors-with-c20-modules-and-llvm-18)
|
||||
* [Cannot generate diagrams from header-only projects](#cannot-generate-diagrams-from-header-only-projects)
|
||||
* [YAML anchors and aliases are not fully supported](#yaml-anchors-and-aliases-are-not-fully-supported)
|
||||
* [Schema validation error is thrown, but the configuration file is correct](#schema-validation-error-is-thrown-but-the-configuration-file-is-correct)
|
||||
@@ -143,6 +144,21 @@ remove_compile_flags:
|
||||
- -Wshadow
|
||||
```
|
||||
|
||||
### Errors with C++20 modules and LLVM 18
|
||||
|
||||
When running `clang-uml` on code using C++20 modules, the LLVM version used to
|
||||
build the project must be compatible with the LLVM version linked to
|
||||
`clang-uml`, otherwise you'll get error like this:
|
||||
```
|
||||
fatal error: malformed or corrupted AST file: 'malformed block record in AST file'
|
||||
```
|
||||
or like this:
|
||||
```
|
||||
error: PCH file uses an older PCH format that is no longer supported
|
||||
```
|
||||
|
||||
In particular versions 17 and 18 of LLVM are not compatible in this regard.
|
||||
|
||||
### Cannot generate diagrams from header-only projects
|
||||
|
||||
Currently, in order to generate UML diagrams using `clang-uml` it is necessary
|
||||
|
||||
45
flake.lock
generated
Normal file
45
flake.lock
generated
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712014858,
|
||||
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1712163089,
|
||||
"narHash": "sha256-Um+8kTIrC19vD4/lUCN9/cU9kcOsD1O1m+axJqQPyMM=",
|
||||
"path": "/nix/store/n2g5cqwv8qf5p6vjxny6pg3blbdij12k-source",
|
||||
"rev": "fd281bd6b7d3e32ddfa399853946f782553163b5",
|
||||
"type": "path"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
34
flake.nix
Normal file
34
flake.nix
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
description = "C++ UML diagram generator based on Clang";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs";
|
||||
|
||||
flake-parts = {
|
||||
url = "github:hercules-ci/flake-parts";
|
||||
inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = {flake-parts, ...} @ inputs:
|
||||
flake-parts.lib.mkFlake {inherit inputs;} {
|
||||
systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
|
||||
|
||||
perSystem = {
|
||||
self',
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
packages = {
|
||||
default = self'.packages.clang-uml;
|
||||
clang-uml = pkgs.callPackage ./packaging/nix {};
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
inputsFrom = [self'.packages.clang-uml];
|
||||
};
|
||||
|
||||
formatter = pkgs.alejandra;
|
||||
};
|
||||
};
|
||||
}
|
||||
30
packaging/nix/default.nix
Normal file
30
packaging/nix/default.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
stdenv,
|
||||
cmake,
|
||||
pkg-config,
|
||||
installShellFiles,
|
||||
libclang,
|
||||
libllvm,
|
||||
yaml-cpp,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "clang-uml";
|
||||
src = ../..;
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
pkg-config
|
||||
installShellFiles
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
libclang
|
||||
libllvm
|
||||
yaml-cpp
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --bash $src/packaging/autocomplete/clang-uml
|
||||
installShellCompletion --zsh $src/packaging/autocomplete/_clang-uml
|
||||
'';
|
||||
}
|
||||
@@ -1280,7 +1280,11 @@ void translation_unit_visitor::process_method_properties(
|
||||
const bool is_constructor = c.name() == method_name;
|
||||
const bool is_destructor = fmt::format("~{}", c.name()) == method_name;
|
||||
|
||||
#if LLVM_VERSION_MAJOR > 17
|
||||
method.is_pure_virtual(mf.isPureVirtual());
|
||||
#else
|
||||
method.is_pure_virtual(mf.isPure());
|
||||
#endif
|
||||
method.is_virtual(mf.isVirtual());
|
||||
method.is_const(mf.isConst());
|
||||
method.is_defaulted(mf.isDefaulted());
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
|
||||
#include "clang_visitor.h"
|
||||
|
||||
#if LLVM_VERSION_MAJOR > 17
|
||||
#define CLANG_UML_LLVM_COMMENT_KIND(COMMENT_KIND) \
|
||||
clang::comments::CommentKind::COMMENT_KIND
|
||||
#else
|
||||
#define CLANG_UML_LLVM_COMMENT_KIND(COMMENT_KIND) \
|
||||
clang::comments::Comment::COMMENT_KIND##Kind
|
||||
#endif
|
||||
|
||||
namespace clanguml::common::visitor::comment {
|
||||
|
||||
clang_visitor::clang_visitor(clang::SourceManager &source_manager)
|
||||
@@ -45,7 +53,6 @@ void clang_visitor::visit(
|
||||
cmt["formatted"] = formatted_comment;
|
||||
|
||||
using clang::comments::BlockCommandComment;
|
||||
using clang::comments::Comment;
|
||||
using clang::comments::FullComment;
|
||||
using clang::comments::ParagraphComment;
|
||||
using clang::comments::ParamCommandComment;
|
||||
@@ -59,7 +66,7 @@ void clang_visitor::visit(
|
||||
|
||||
for (const auto *block : full_comment->getBlocks()) {
|
||||
const auto block_kind = block->getCommentKind();
|
||||
if (block_kind == Comment::ParagraphCommentKind) {
|
||||
if (block_kind == CLANG_UML_LLVM_COMMENT_KIND(ParagraphComment)) {
|
||||
std::string paragraph_text;
|
||||
|
||||
visit_paragraph(clang::dyn_cast<ParagraphComment>(block), traits,
|
||||
@@ -75,18 +82,21 @@ void clang_visitor::visit(
|
||||
|
||||
cmt["paragraph"].push_back(paragraph_text);
|
||||
}
|
||||
else if (block_kind == Comment::TextCommentKind) {
|
||||
else if (block_kind == CLANG_UML_LLVM_COMMENT_KIND(TextComment)) {
|
||||
// TODO
|
||||
}
|
||||
else if (block_kind == Comment::ParamCommandCommentKind) {
|
||||
else if (block_kind ==
|
||||
CLANG_UML_LLVM_COMMENT_KIND(ParamCommandComment)) {
|
||||
visit_param_command(
|
||||
clang::dyn_cast<ParamCommandComment>(block), traits, cmt);
|
||||
}
|
||||
else if (block_kind == Comment::TParamCommandCommentKind) {
|
||||
else if (block_kind ==
|
||||
CLANG_UML_LLVM_COMMENT_KIND(TParamCommandComment)) {
|
||||
visit_tparam_command(
|
||||
clang::dyn_cast<TParamCommandComment>(block), traits, cmt);
|
||||
}
|
||||
else if (block_kind == Comment::BlockCommandCommentKind) {
|
||||
else if (block_kind ==
|
||||
CLANG_UML_LLVM_COMMENT_KIND(BlockCommandComment)) {
|
||||
if (const auto *command =
|
||||
clang::dyn_cast<BlockCommandComment>(block);
|
||||
command != nullptr) {
|
||||
@@ -135,7 +145,7 @@ void clang_visitor::visit_block_command(
|
||||
paragraph_it != command->child_end(); ++paragraph_it) {
|
||||
|
||||
if ((*paragraph_it)->getCommentKind() ==
|
||||
Comment::ParagraphCommentKind) {
|
||||
CLANG_UML_LLVM_COMMENT_KIND(ParagraphComment)) {
|
||||
visit_paragraph(clang::dyn_cast<ParagraphComment>(*paragraph_it),
|
||||
traits, command_text);
|
||||
}
|
||||
@@ -168,7 +178,8 @@ void clang_visitor::visit_param_command(
|
||||
for (const auto *it = command->child_begin(); it != command->child_end();
|
||||
++it) {
|
||||
|
||||
if ((*it)->getCommentKind() == Comment::ParagraphCommentKind) {
|
||||
if ((*it)->getCommentKind() ==
|
||||
CLANG_UML_LLVM_COMMENT_KIND(ParagraphComment)) {
|
||||
visit_paragraph(
|
||||
clang::dyn_cast<ParagraphComment>(*it), traits, description);
|
||||
}
|
||||
@@ -202,7 +213,8 @@ void clang_visitor::visit_tparam_command(
|
||||
|
||||
for (const auto *it = command->child_begin(); it != command->child_end();
|
||||
++it) {
|
||||
if ((*it)->getCommentKind() == Comment::ParagraphCommentKind) {
|
||||
if ((*it)->getCommentKind() ==
|
||||
CLANG_UML_LLVM_COMMENT_KIND(ParagraphComment)) {
|
||||
visit_paragraph(
|
||||
clang::dyn_cast<ParagraphComment>(*it), traits, description);
|
||||
}
|
||||
@@ -232,7 +244,8 @@ void clang_visitor::visit_paragraph(
|
||||
for (const auto *text_it = paragraph->child_begin();
|
||||
text_it != paragraph->child_end(); ++text_it) {
|
||||
|
||||
if ((*text_it)->getCommentKind() == Comment::TextCommentKind &&
|
||||
if ((*text_it)->getCommentKind() ==
|
||||
CLANG_UML_LLVM_COMMENT_KIND(TextComment) &&
|
||||
clang::dyn_cast<TextComment>(*text_it) != nullptr) {
|
||||
// Merge paragraph lines into a single string
|
||||
text += clang::dyn_cast<TextComment>(*text_it)->getText();
|
||||
|
||||
@@ -217,6 +217,21 @@ public:
|
||||
template_parameter process_integral_argument(
|
||||
const clang::TemplateArgument &arg);
|
||||
|
||||
#if LLVM_VERSION_MAJOR > 17
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::StructuralValue`
|
||||
*
|
||||
* @note The template argument is a non-type template argument that can't be
|
||||
* represented by the special-case Declaration, NullPtr, or Integral
|
||||
* forms.
|
||||
*
|
||||
* @param arg Template argument
|
||||
* @return Return template argument model
|
||||
*/
|
||||
template_parameter process_structural_argument(
|
||||
const clang::TemplateArgument &arg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Process `clang::TemplateArgument::NullPtr`
|
||||
*
|
||||
@@ -1041,6 +1056,10 @@ void template_builder<VisitorT>::argument_process_dispatch(
|
||||
argument.push_back(a);
|
||||
}
|
||||
break;
|
||||
#if LLVM_VERSION_MAJOR > 17
|
||||
case clang::TemplateArgument::StructuralValue:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1213,6 +1232,21 @@ template_parameter template_builder<VisitorT>::process_integral_argument(
|
||||
return template_parameter::make_argument(result);
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MAJOR > 17
|
||||
template <typename VisitorT>
|
||||
template_parameter template_builder<VisitorT>::process_structural_argument(
|
||||
const clang::TemplateArgument &arg)
|
||||
{
|
||||
assert(arg.getKind() == clang::TemplateArgument::StructuralValue);
|
||||
|
||||
std::string result;
|
||||
llvm::raw_string_ostream ostream(result);
|
||||
arg.dump(ostream);
|
||||
|
||||
return template_parameter::make_argument(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename VisitorT>
|
||||
template_parameter template_builder<VisitorT>::process_null_argument(
|
||||
const clang::TemplateArgument &arg)
|
||||
|
||||
Reference in New Issue
Block a user