clang-uml
— это автоматический генератор классов, последовательностей, пакетов и диаграмм включения C++ в UML, управляемый файлами конфигурации YAML. Основная идея проекта — легко поддерживать актуальные диаграммы в базе кода или документировать устаревший код. Файл или файлы конфигурации clang-uml
определяют типы и содержимое каждой сгенерированной диаграммы. Диаграммы могут быть созданы в форматах PlantUML, MermaidJS и JSON.
clang-uml
в настоящее время поддерживает C++ до версии 20, а также C и Objective-C.
Полную документацию можно найти на clang-uml.github.io.
Чтобы узнать, на что способен clang-uml
, посмотрите диаграммы, созданные для случаев модульного тестирования, здесь или примеры в репозитории clang-uml-examples.
Основные поддерживаемые на данный момент функции включают в себя:
Более подробную документацию можно найти на clang-uml.github.io.
Инструкции по установке для Linux
, macos
и Windows
можно найти здесь.
clang-uml
требует актуального файла compile_commands.json, содержащего список команд, используемых для компиляции исходного кода.
Инструкции по созданию compile_commands.json
с использованием некоторых существующих систем сборки C++ см. здесь.
По умолчанию clang-uml
предполагает, что файл конфигурации .clang-uml
и файлы базы данных компиляции compile_commands.json
находятся в текущем каталоге, поэтому, если они находятся в каталоге верхнего уровня проекта, просто запустите:
clang-uml
Путь вывода диаграмм, а также альтернативное расположение базы данных компиляции можно указать в файле конфигурации .clang-uml
или через параметры командной строки.
Другие варианты см. в справке:
clang-uml --help
Файлы конфигурации написаны в формате YAML и содержат определения диаграмм, которые должны быть созданы с помощью clang-uml
. Базовый пример выглядит следующим образом:
compilation_database_dir : .
output_directory : diagrams
diagrams :
myproject_class :
type : class
glob :
- src/*.cc
using_namespace : myproject
include :
namespaces :
- myproject
exclude :
namespaces :
- myproject::detail
plantuml :
after :
- ' note left of {{ alias("MyProjectMain") }}: Main class of myproject library. '
Подробное справочное руководство по файлам конфигурации см. здесь.
Чтобы узнать, на что способен clang-uml
, просмотрите документацию по тестовым примерам здесь.
Чтобы увидеть диаграммы для самого clang-uml
на основе его собственной конфигурации, выполните следующее:
make clanguml_diagrams
и откройте диаграммы SVG в папке docs/diagrams
.
Следующий код C++:
template < typename T, typename P> struct A {
T t;
P p;
};
struct B {
std::string value;
};
template < typename T> using AString = A<T, std::string>;
template < typename T> using AStringPtr = A<T, std::unique_ptr<std::string>>;
template < typename T>
using PairPairBA = std::pair<std::pair<B, A< long , T>>, long >;
template < class T > using VectorPtr = std::unique_ptr<std::vector<T>>;
template < class T > using APtr = std::unique_ptr<A< double , T>>;
template < class T > using ASharedPtr = std::shared_ptr<A< double , T>>;
template < class T , class U >
using AAPtr = std::unique_ptr<std::pair<A< double , T>, A< long , U>>>;
template < typename T> using SimpleCallback = std::function< void (T, int )>;
template < typename ... T> using GenericCallback = std::function< void (T..., int )>;
using VoidCallback = GenericCallback< void *>;
using BVector = std::vector<B>;
using BVector2 = BVector;
using AIntString = AString< int >;
using ACharString = AString< char >;
using AStringString = AString<std::string>;
using BStringString = AStringString;
template < typename T> class R {
using AWCharString = AString< wchar_t >;
PairPairBA< bool > bapair;
APtr< bool > abool;
AAPtr< bool , float > aboolfloat;
ASharedPtr< float > afloat;
A< bool , std::string> boolstring;
AStringPtr< float > floatstring;
AIntString intstring;
AStringString stringstring;
BStringString bstringstring;
AAPtr<T, float > atfloat;
protected:
BVector bs;
public:
BVector2 bs2;
SimpleCallback<ACharString> cb;
GenericCallback<AWCharString> gcb;
VoidCallback vcb;
VectorPtr<B> vps;
};
результаты показаны на следующей диаграмме (через PlantUML):
Откройте здесь необработанное изображение и проверьте всплывающие подсказки при наведении и гиперссылки на классы и методы.
Следующий код C++:
# include < atomic >
# include < functional >
# include < iostream >
# include < memory >
# include < string >
namespace clanguml {
namespace t20029 {
std::string encode_b64 (std::string &&content) { return std::move (content); }
template < typename T> class Encoder : public T {
public:
bool send (std::string &&msg)
{
return T::send ( std::move (
// Encode the message using Base64 encoding and pass it to the next
// layer
encode ( std::move (msg))));
}
protected:
std::string encode (std::string &&msg) { return encode_b64 ( std::move (msg)); }
};
template < typename T> class Retrier : public T {
public:
bool send (std::string &&msg)
{
std::string buffer{ std::move (msg)};
int retryCount = 5 ;
// Repeat until send() succeeds or retry count is exceeded
while (retryCount--) {
if ( T::send (buffer))
return true ;
}
return false ;
}
};
class ConnectionPool {
public:
void connect ()
{
if (!is_connected_. load ())
connect_impl ();
}
bool send ( const std::string &msg) { return true ; }
private:
void connect_impl () { is_connected_ = true ; }
std::atomic< bool > is_connected_;
};
int tmain ()
{
auto pool = std::make_shared<Encoder<Retrier<ConnectionPool>>>();
// Establish connection to the remote server synchronously
pool-> connect ();
// Repeat for each line in the input stream
for (std::string line; std::getline (std::cin, line);) {
if (!pool-> send ( std::move (line)))
break ;
}
return 0 ;
}
}
}
результаты показаны на следующей диаграмме (через PlantUML):
Следующий код C++:
namespace clanguml {
namespace t30003 {
namespace ns1 {
namespace ns2_v1_0_0 {
class A {
};
}
namespace [ [deprecated]] ns2_v0_9_0 {
class A {
};
}
namespace {
class Anon final {
};
}
}
namespace [ [deprecated]] ns3 {
namespace ns1 ::ns2 {
class Anon : public t30003 ::ns1::ns2_v1_0_0::A {
};
}
class B : public ns1 ::ns2::Anon {
};
}
}
}
результаты показаны на следующей диаграмме (через PlantUML):
Если вы ищете более простой инструмент для визуализации и анализа графиков включения, воспользуйтесь другим моим инструментом — clang-include-graph.
Следующая структура кода C++:
tests/t40001
├── include
│ ├── lib1
│ │ └── lib1.h
│ └── t40001_include1.h
└── src
└── t40001.cc
приводит к следующей диаграмме (через PlantUML) на основе директив включения в код:
UML | ПлантУМЛ | РусалкаJS |
---|---|---|
Наследование | ||
Ассоциация | ||
Зависимость | ||
Агрегация | ||
Состав | ||
Специализация/создание шаблона | ||
Вложенность (внутренний класс/перечисление) | ||
Включить (локальный) | ||
Включить (систему) |
Для типичных баз кода одна диаграмма, созданная на основе всего кода или даже одного пространства имен, может быть слишком большой, чтобы ее можно было использовать, например, как часть документации. clang-uml
позволяет указать контент, который будет включаться и исключаться из каждой диаграммы, используя простую конфигурацию YAML:
include :
# Include only elements from these namespaces
namespaces :
- clanguml::common
- clanguml::config
# Include all subclasses of ClassA (including ClassA)
subclasses :
- clanguml::common::ClassA
# and specializations of template Class<T> (including Class<T>)
specializations :
- clanguml::common::ClassT<T>
# and all classes depending on Class D
dependants :
- clanguml::common::ClassD
# and all dependencies of ClassE
dependencies :
- clanguml::common::ClassE
# and classes in direct relation to ClassB (including ClassB)
context :
- clanguml::common::ClassB
# Include only inheritance relationships
relationships :
- inheritance
exclude :
# Exclude all elements from detail namespace
namespaces :
- clanguml::common::detail
# and also exclude ClassF
elements :
- clanguml::common::ClassF
Более подробную информацию об этом можно найти в разделе документации по фильтрам диаграмм.
Встроенные тестовые примеры, используемые для модульного тестирования clang-uml
, можно просмотреть здесь.
Этот проект опирается на следующие замечательные инструменты:
Если вы хотите внести свой вклад в проект, пожалуйста, ознакомьтесь с правилами участия.
Copyright 2021-present Bartek Kryza <[email protected]>
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.