clang-uml
est un générateur automatique de classes, de séquences, de packages et d'inclusions C++ vers UML, piloté par des fichiers de configuration YAML. L'idée principale derrière le projet est de maintenir facilement des diagrammes à jour dans une base de code ou un document existant. Le ou les fichiers de configuration pour clang-uml
définissent les types et le contenu de chaque diagramme généré. Les diagrammes peuvent être générés aux formats PlantUML, MermaidJS et JSON.
clang-uml
prend actuellement en charge C++ jusqu'à la version 20, ainsi que C et Objective-C.
La documentation complète peut être trouvée sur clang-uml.github.io.
Pour voir ce que clang-uml
peut faire, consultez les diagrammes générés pour les cas de tests unitaires ici ou les exemples dans le référentiel clang-uml-examples.
Les principales fonctionnalités prises en charge jusqu'à présent incluent :
Une documentation plus complète peut être consultée sur clang-uml.github.io.
Les instructions d'installation pour Linux
, macos
et Windows
peuvent être trouvées ici.
clang-uml
nécessite un fichier compile_commands.json à jour, contenant la liste des commandes utilisées pour compiler le code source.
Voir ici pour obtenir des instructions sur la façon de générer compile_commands.json
à l'aide de certains des systèmes de construction C++ existants.
Par défaut, clang-uml
supposera que le fichier de configuration .clang-uml
et les fichiers de la base de données de compilation compile_commands.json
se trouvent dans le répertoire actuel, donc s'ils se trouvent dans le répertoire de niveau supérieur d'un projet, exécutez simplement :
clang-uml
Le chemin de sortie des diagrammes, ainsi qu'un emplacement alternatif de la base de données de compilation peuvent être spécifiés dans le fichier de configuration .clang-uml
ou via des paramètres de ligne de commande.
Pour d'autres options, consultez l'aide :
clang-uml --help
Les fichiers de configuration sont écrits en YAML et fournissent la définition des diagrammes qui doivent être générés par clang-uml
. L'exemple de base est le suivant :
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. '
Voir ici pour le guide de référence détaillé des fichiers de configuration.
Pour voir ce que clang-uml
peut faire, parcourez la documentation des cas de test ici.
Afin de voir les diagrammes du clang-uml
lui-même, en fonction de sa propre configuration, exécutez ce qui suit :
make clanguml_diagrams
et ouvrez les diagrammes SVG dans le dossier docs/diagrams
.
Le code C++ suivant :
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;
};
donne le diagramme suivant (via PlantUML) :
Ouvrez l'image brute ici et consultez les info-bulles de survol et les hyperliens vers les classes et les méthodes.
Le code C++ suivant :
# 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 ;
}
}
}
donne le diagramme suivant (via PlantUML) :
Le code C++ suivant :
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 {
};
}
}
}
donne le diagramme suivant (via PlantUML) :
Si vous recherchez un outil plus simple pour visualiser et analyser les graphiques d'inclusion, consultez mon autre outil - clang-include-graph
La structure de code C++ suivante :
tests/t40001
├── include
│ ├── lib1
│ │ └── lib1.h
│ └── t40001_include1.h
└── src
└── t40001.cc
donne le diagramme suivant (via PlantUML) basé sur les directives d'inclusion dans le code :
UML | PlanteUML | SirèneJS |
---|---|---|
Héritage | ||
Association | ||
Dépendance | ||
Agrégation | ||
Composition | ||
Spécialisation/instanciation de modèles | ||
Imbrication (classe interne/énumération) | ||
Inclure (local) | ||
Inclure (système) |
Pour les bases de code typiques, un seul diagramme généré à partir d'un code entier ou même d'un seul espace de noms peut être trop volumineux pour être utile, par exemple dans le cadre d'une documentation. clang-uml
permet de spécifier le contenu à inclure et à exclure de chaque diagramme à l'aide d'une configuration YAML simple :
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
Plus de détails à ce sujet peuvent être trouvés dans la section de documentation des filtres de diagramme.
Les cas de test intégrés utilisés pour les tests unitaires du clang-uml
peuvent être consultés ici.
Ce projet s'appuie sur les excellents outils suivants :
Si vous souhaitez contribuer au projet, veuillez consulter les directives de contribution.
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.