clang-uml
é um gerador automático de classe, sequência, pacote e diagrama de inclusão de C++ para UML, conduzido por arquivos de configuração YAML. A ideia principal por trás do projeto é manter facilmente diagramas atualizados dentro de uma base de código ou código legado de documento. O arquivo ou arquivos de configuração do clang-uml
definem os tipos e conteúdos de cada diagrama gerado. Os diagramas podem ser gerados nos formatos PlantUML, MermaidJS e JSON.
clang-uml
atualmente suporta C++ até a versão 20, bem como C e Objective-C.
A documentação completa pode ser encontrada em clang-uml.github.io.
Para ver o que clang-uml
pode fazer, verifique os diagramas gerados para casos de teste de unidade aqui ou exemplos no repositório clang-uml-examples.
Os principais recursos suportados até agora incluem:
Documentação mais abrangente pode estar em clang-uml.github.io.
Instruções de instalação para Linux
, macos
e Windows
podem ser encontradas aqui.
clang-uml
requer um arquivo compile_commands.json atualizado, contendo a lista de comandos usados para compilar o código-fonte.
Veja aqui instruções sobre como gerar compile_commands.json
usando alguns dos sistemas de compilação C++ existentes.
Por padrão, clang-uml
assumirá que o arquivo de configuração .clang-uml
e os arquivos compile_commands.json
do banco de dados de compilação estão no diretório atual, portanto, se eles estiverem no diretório de nível superior de um projeto, simplesmente execute:
clang-uml
O caminho de saída para diagramas, bem como o local alternativo do banco de dados de compilação podem ser especificados no arquivo de configuração .clang-uml
ou através de parâmetros de linha de comando.
Para outras opções, consulte a ajuda:
clang-uml --help
Os arquivos de configuração são escritos em YAML e fornecem definição de diagramas que devem ser gerados por clang-uml
. O exemplo básico é o seguinte:
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. '
Veja aqui o guia detalhado de referência do arquivo de configuração.
Para ver o que clang-uml
pode fazer, consulte a documentação dos casos de teste aqui.
Para ver os diagramas do próprio clang-uml
, com base em sua própria configuração, execute o seguinte:
make clanguml_diagrams
e abra os diagramas SVG na pasta docs/diagrams
.
O seguinte código 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;
};
resulta no seguinte diagrama (via PlantUML):
Abra a imagem bruta aqui e confira as dicas de ferramentas instantâneas e hiperlinks para classes e métodos.
O seguinte código 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 ;
}
}
}
resulta no seguinte diagrama (via PlantUML):
O seguinte código 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 {
};
}
}
}
resulta no seguinte diagrama (via PlantUML):
Caso você esteja procurando uma ferramenta mais simples para visualizar e analisar gráficos de inclusão, confira minha outra ferramenta - clang-include-graph
A seguinte estrutura de código C++:
tests/t40001
├── include
│ ├── lib1
│ │ └── lib1.h
│ └── t40001_include1.h
└── src
└── t40001.cc
resulta no diagrama a seguir (via PlantUML) com base nas diretivas include no código:
UML | PlantaUML | SereiaJS |
---|---|---|
Herança | ||
Associação | ||
Dependência | ||
Agregação | ||
Composição | ||
Especialização/instanciação de modelo | ||
Aninhamento (classe interna/enum) | ||
Incluir (local) | ||
Incluir (sistema) |
Para bases de código típicas, um único diagrama gerado a partir de um código inteiro ou mesmo de um único namespace pode ser grande demais para ser útil, por exemplo, como parte da documentação. clang-uml
permite especificar o conteúdo a ser incluído e excluído de cada diagrama usando uma configuração YAML simples:
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
Mais detalhes sobre isso podem ser encontrados na seção de documentação dos filtros de diagrama.
Os casos de teste integrados usados para teste de unidade do clang-uml
podem ser navegados aqui.
Este projeto conta com as seguintes ótimas ferramentas:
Se você gostaria de contribuir com o projeto, verifique as diretrizes de contribuição.
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.