diff --git a/Makefile b/Makefile
index fa43cc4f..1eebfe73 100644
--- a/Makefile
+++ b/Makefile
@@ -61,6 +61,7 @@ clanguml_diagrams: debug
mkdir -p docs/diagrams
debug/clang-uml
plantuml -tsvg docs/diagrams/*.puml
+ python3 util/format_svg.py docs/diagrams/*.svg
.PHONY: submodules
submodules:
diff --git a/docs/configuration_file.md b/docs/configuration_file.md
index ddd9dc82..d8c1914a 100644
--- a/docs/configuration_file.md
+++ b/docs/configuration_file.md
@@ -11,17 +11,21 @@
* `glob` - list of glob patterns to match source code files for analysis
* `include_relations_also_as_members` - when set to `false`, class members for relationships are rendered in UML are skipped from class definition (default: `true`)
* `generate_method_arguments` - determines whether the class diagrams methods contain full arguments (`full`), are abbreviated (`abbreviated`) or skipped (`none`)
-* `using_namespace` - similar to C++ `using namespace`, a `A::B` value here will render a class `A::B::C::MyClass` in the diagram as `C::MyClass`
+* `using_namespace` - similar to C++ `using namespace`, a `A::B` value here will render a class `A::B::C::MyClass` in the diagram as `C::MyClass`, at most 1 value is supported
* `include` - definition of inclusion patterns:
* `namespaces` - list of namespaces to include
* `relationships` - list of relationships to include
- * `entity_types` - list of entity types to include (e.g. `class`, `enum`)
- * `scopes` - list of visibility scopes to include (e.g. `private`)
+ * `elements` - list of elements, i.e. specific classes, enums, templates to include
+ * `access` - list of visibility scopes to include (e.g. `private`)
+ * `subclasses` - include only subclasses of specified classes (and themselves)
+ * `context` - include only entities in direct relationship with specified classes
* `exclude` - definition of excqlusion patterns:
* `namespaces` - list of namespaces to exclude
* `relationships` - list of relationships to exclude
- * `entity_types` - list of entity types to exclude (e.g. `class`, `enum`)
- * `scopes` - list of visibility scopes to exclude (e.g. `private`)
+ * `elements` - list of elements, i.e. specific classes, enums, templates to exclude
+ * `access` - list of visibility scopes to exclude (e.g. `private`)
+ * `subclasses` - exclude subclasses of specified classes (and themselves)
+ * `context` - exclude only entities in direct relationship with specified classes
* `layout` - add layout hints for entities (classes, packages)
* `plantuml` - verbatim PlantUML directives which should be added to a diagram
* `before` - list of directives which will be added before the generated diagram
@@ -79,9 +83,12 @@ diagrams:
namespaces:
- clanguml::common::model
- clanguml::class_diagram::model
+ # Only include elements in direct relationship with ClassA
+ context:
+ - ClassA
exclude:
# Do not include private members and methods in the diagram
- scopes:
+ access:
- private
layout:
# Add layout hints for PlantUML
diff --git a/docs/test_cases.md b/docs/test_cases.md
index 9b5a3647..50a10212 100644
--- a/docs/test_cases.md
+++ b/docs/test_cases.md
@@ -37,6 +37,9 @@
* [t00036](./test_cases/t00036.md) - Class diagram with namespaces generated as packages
* [t00037](./test_cases/t00037.md) - Anonymous nested struct test case
* [t00038](./test_cases/t00038.md) - Template instantiation with unexposed nested templates
+ * [t00039](./test_cases/t00039.md) - Subclass class diagram filter test
+ * [t00040](./test_cases/t00040.md) - Relationship and access filter test
+ * [t00041](./test_cases/t00041.md) - Context diagram filter test
## Sequence diagrams
* [t20001](./test_cases/t20001.md) - Basic sequence diagram test case
* [t20002](./test_cases/t20002.md) - Free function sequence diagram test case
diff --git a/docs/test_cases/t00002_class.svg b/docs/test_cases/t00002_class.svg
index f727a875..82e7b14d 100644
--- a/docs/test_cases/t00002_class.svg
+++ b/docs/test_cases/t00002_class.svg
@@ -1,145 +1,146 @@
-
+
+
-
-
+
+
A
-
+
-
+
foo_a() = 0 : void
-
+
-
+
foo_c() = 0 : void
-
-
+
+
B
-
+
-
+
foo_a() : void
-
-
+
+
C
-
+
-
+
foo_c() : void
-
-
+
+
D
-
+
-
+
as : std::vector<A*>
-
+
-
+
foo_a() : void
-
+
-
+
foo_c() : void
-
-
+
+
E
-
+
-
+
as : std::vector<A*>
-
+
-
+
foo_a() : void
-
+
-
+
foo_c() : void
-
+
Base abstract interface.
-
+
-
+
-
+
as
-
+
-
+
-
+
as
-
+
-
+
diff --git a/docs/test_cases/t00003_class.svg b/docs/test_cases/t00003_class.svg
index 65531da2..8b07705b 100644
--- a/docs/test_cases/t00003_class.svg
+++ b/docs/test_cases/t00003_class.svg
@@ -1,201 +1,202 @@
-
+
+
-
-
+
+
A
-
+
-
+
public_member : int
-
+
-
+
static_int : int
-
+
-
+
static_const_int : int const
-
+
-
+
auto_member : unsigned long const
-
+
-
+
protected_member : int
-
+
-
+
private_member : int
-
+
-
+
a : int
-
+
-
+
b : int
-
+
-
+
c : int
-
+
-
+
A() : void
-
+
-
+
A(int i) : void
-
+
-
+
A(A&& ) : void
-
+
-
+
A(A const& ) : void
-
+
-
+
~A() : void
-
+
-
+
basic_method() : void
-
+
-
+
static_method() : int
-
+
-
+
const_method() const : void
-
+
-
+
auto_method() : int
-
+
-
+
double_int(int const i) : int
-
+
-
+
sum(double const a, double const b) : double
-
+
-
+
default_int(int i = 12) : int
-
+
-
+
default_string(int i, std::string s = "abc") : std::string
-
+
-
+
create_from_int(int i) : A
-
+
-
+
protected_method() : void
-
+
-
+
private_method() : void
-
+
-
+
compare : std::function<bool(int const)>
diff --git a/docs/test_cases/t00004_class.svg b/docs/test_cases/t00004_class.svg
index 744ab16c..f8195895 100644
--- a/docs/test_cases/t00004_class.svg
+++ b/docs/test_cases/t00004_class.svg
@@ -1,45 +1,46 @@
-
+
+
-
-
+
+
A
-
+
-
+
foo() const : void
-
+
-
+
foo2() const : void
-
-
+
+
AA
-
-
+
+
Lights
@@ -49,23 +50,23 @@
Red
-
-
+
+
AAA
-
+
-
+
-
+
diff --git a/docs/test_cases/t00005_class.svg b/docs/test_cases/t00005_class.svg
index c7645dbe..0f3ddaeb 100644
--- a/docs/test_cases/t00005_class.svg
+++ b/docs/test_cases/t00005_class.svg
@@ -1,245 +1,246 @@
-
+
+
-
-
+
+
A
-
-
+
+
B
-
-
+
+
C
-
-
+
+
D
-
-
+
+
E
-
-
+
+
F
-
-
+
+
G
-
-
+
+
H
-
-
+
+
I
-
-
+
+
J
-
-
+
+
K
-
-
+
+
R
-
+
-
+
some_int : int
-
+
-
+
some_int_pointer : int*
-
+
-
+
some_int_pointer_pointer : int**
-
+
-
+
some_int_reference : int&
-
+
-
+
a : A
-
+
-
+
b : B*
-
+
-
+
c : C&
-
+
-
+
d : D const*
-
+
-
+
e : E const&
-
+
-
+
f : F&&
-
+
-
+
g : G**
-
+
-
+
h : H***
-
+
-
+
i : I*&
-
+
-
+
j : J volatile*
-
+
-
+
k : K*
-
+
+a
-
+
+b
-
+
+c
-
+
+d
-
+
+e
-
+
+f
-
+
+g
-
+
+h
-
+
+i
-
+
+j
-
+
+k
diff --git a/docs/test_cases/t00006_class.svg b/docs/test_cases/t00006_class.svg
index 17a9940c..6d655087 100644
--- a/docs/test_cases/t00006_class.svg
+++ b/docs/test_cases/t00006_class.svg
@@ -1,143 +1,144 @@
-
+
+
-
-
+
+
A
-
-
+
+
B
-
-
+
+
C
-
-
+
+
D
-
-
+
+
E
-
-
+
+
F
-
-
+
+
G
-
-
+
+
H
-
-
+
+
I
-
-
+
+
J
-
-
+
+
K
-
-
+
+
L
-
-
+
+
M
-
-
+
+
N
-
-
+
+
NN
-
-
+
+
NNN
-
-
+
+
custom_container
@@ -145,15 +146,15 @@
T
-
+
-
+
data : std::vector<T>
-
+
custom_container
@@ -161,159 +162,159 @@
E
-
-
+
+
R
-
+
-
+
a : std::vector<A>
-
+
-
+
b : std::vector<B*>
-
+
-
+
c : std::map<int,C>
-
+
-
+
d : std::map<int,D*>
-
+
-
+
e : custom_container<E>
-
+
-
+
f : std::vector<std::vector<F>>
-
+
-
+
g : std::map<int,std::vector<G*>>
-
+
-
+
h : std::array<H,10>
-
+
-
+
i : std::array<I*,5>
-
+
-
+
j : J[10]
-
+
-
+
k : K*[20]
-
+
-
+
lm : std::vector<std::pair<L,M>>
-
+
-
+
ns : std::tuple<N,NN,NNN>
-
+
-
+
-
+
+a
-
+
+b
-
+
+c
-
+
+d
-
+
+e
-
+
+f
-
+
+g
-
+
+h
-
+
+i
-
+
+j
-
+
+k
-
+
lm
-
+
lm
-
+
ns
-
+
ns
-
+
ns
diff --git a/docs/test_cases/t00007_class.svg b/docs/test_cases/t00007_class.svg
index cd8df63d..f6fa6e5d 100644
--- a/docs/test_cases/t00007_class.svg
+++ b/docs/test_cases/t00007_class.svg
@@ -1,73 +1,74 @@
-
+
+
-
-
+
+
A
-
-
+
+
B
-
-
+
+
C
-
-
+
+
R
-
+
-
+
a : std::unique_ptr<A>
-
+
-
+
b : std::shared_ptr<B>
-
+
-
+
c : std::weak_ptr<C>
-
+
+a
-
+
+b
-
+
+c
diff --git a/docs/test_cases/t00008_class.svg b/docs/test_cases/t00008_class.svg
index 15d5c562..32db5eb7 100644
--- a/docs/test_cases/t00008_class.svg
+++ b/docs/test_cases/t00008_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
A
@@ -17,51 +18,51 @@
T,P,CMP,int N
-
+
-
+
value : T
-
+
-
+
pointer : T*
-
+
-
+
reference : T&
-
+
-
+
values : std::vector<P>
-
+
-
+
ints : std::array<int,N>
-
+
-
+
comparator : CMP
-
-
+
+
Vector
@@ -69,16 +70,16 @@
T
-
+
-
+
values : std::vector<T>
-
-
+
+
B
@@ -86,15 +87,15 @@
T,C<>
-
+
-
+
template_template : C<T>
-
+
B
@@ -102,31 +103,31 @@
int,Vector
-
-
+
+
D
-
+
-
+
ints : B<int,Vector>
-
+
-
+
add(int i) : void
-
+
-
+
ints
diff --git a/docs/test_cases/t00009_class.svg b/docs/test_cases/t00009_class.svg
index 1e144c92..13d224e2 100644
--- a/docs/test_cases/t00009_class.svg
+++ b/docs/test_cases/t00009_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
A
@@ -17,15 +18,15 @@
T
-
+
-
+
value : T
-
+
A
@@ -33,7 +34,7 @@
int
-
+
A
@@ -41,7 +42,7 @@
std::string
-
+
A
@@ -49,50 +50,50 @@
std::vector<std::string>
-
-
+
+
B
-
+
-
+
aint : A<int>
-
+
-
+
astring : A<std::string>*
-
+
-
+
avector : A<std::vector<std::string>>&
-
+
-
+
-
+
-
+
aint
-
+
astring
-
+
avector
diff --git a/docs/test_cases/t00010_class.svg b/docs/test_cases/t00010_class.svg
index 356995e2..bbc31508 100644
--- a/docs/test_cases/t00010_class.svg
+++ b/docs/test_cases/t00010_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
A
@@ -17,22 +18,22 @@
T,P
-
+
-
+
first : T
-
+
-
+
second : P
-
+
A
@@ -40,8 +41,8 @@
T,std::string
-
-
+
+
B
@@ -49,15 +50,15 @@
T
-
+
-
+
astring : A<T,std::string>
-
+
B
@@ -65,30 +66,30 @@
int
-
-
+
+
C
-
+
-
+
aintstring : B<int>
-
+
-
+
astring
-
+
-
+
aintstring
diff --git a/docs/test_cases/t00011_class.svg b/docs/test_cases/t00011_class.svg
index 2872ba64..78537d30 100644
--- a/docs/test_cases/t00011_class.svg
+++ b/docs/test_cases/t00011_class.svg
@@ -1,15 +1,16 @@
-
+
-
+
+
-
-
+
+
D
@@ -17,57 +18,58 @@
T
-
+
-
+
value : T
-
-
+
+
A
-
+
-
+
foo() : void
-
-
+
+
B
-
+
-
+
m_a : A*
-
+
-
+
foo() : void
-
-
- «friend»
-
-
-
- m_a
+
+
+
+ «friend»
+
+
+
+ m_a
diff --git a/docs/test_cases/t00012_class.svg b/docs/test_cases/t00012_class.svg
index c28eecbc..fcd8a4c2 100644
--- a/docs/test_cases/t00012_class.svg
+++ b/docs/test_cases/t00012_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
A
@@ -17,23 +18,23 @@
T,Ts...
-
+
-
+
value : T
-
+
-
+
values : int
-
-
+
+
B
@@ -42,15 +43,15 @@
-
+
-
+
ints : std::array<int,sizeof...(Is)>
-
-
+
+
C
@@ -59,14 +60,14 @@
-
+
-
+
ints : std::array<T,sizeof...(Is)>
-
+
A
@@ -74,7 +75,7 @@
int,std::string,float
-
+
A
@@ -82,7 +83,7 @@
int,std::string,bool
-
+
B
@@ -90,7 +91,7 @@
3,2,1
-
+
B
@@ -98,7 +99,7 @@
1,1,1,1
-
+
C
@@ -106,79 +107,79 @@
std::map<int,std::vector<std::vector<std::vector<std::string>>>>,3,3,3
-
-
+
+
R
-
+
-
+
a1 : A<int,std::string,float>
-
+
-
+
a2 : A<int,std::string,bool>
-
+
-
+
b1 : B<3,2,1>
-
+
-
+
b2 : B<1,1,1,1>
-
+
-
+
c1 : C<std::map<int,std::vector<std::vector<std::vector<std::string>>>>,3,3,3>
-
+
Long template annotation
-
+
-
+
-
+
-
+
-
+
-
+
a1
-
+
a2
-
+
b1
-
+
b2
-
+
c1
diff --git a/docs/test_cases/t00013_class.svg b/docs/test_cases/t00013_class.svg
index e74b8e62..00d045e5 100644
--- a/docs/test_cases/t00013_class.svg
+++ b/docs/test_cases/t00013_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
ABCD::F
@@ -17,83 +18,83 @@
T
-
+
-
+
f : T
-
-
+
+
A
-
+
-
+
a : int
-
-
+
+
B
-
+
-
+
b : int
-
-
+
+
C
-
+
-
+
c : int
-
-
+
+
D
-
+
-
+
d : int
-
+
-
+
print(R* r) : void
-
-
+
+
E
@@ -101,15 +102,15 @@
T
-
+
-
+
e : T
-
+
E
@@ -117,7 +118,7 @@
int
-
+
F
@@ -125,7 +126,7 @@
int
-
+
E
@@ -133,123 +134,123 @@
std::string
-
-
+
+
R
-
+
-
+
estring : E<std::string>
-
+
-
+
get_a(A* a) : int
-
+
-
+
get_b(B& b) : int
-
+
-
+
get_const_b(B const& b) : int
-
+
-
+
get_c(C c) : int
-
+
-
+
get_d(D&& d) : int
-
+
-
+
get_d2(D&& d) : int
-
+
-
+
get_e(E<T> e) : T
-
+
-
+
get_int_e(E<int> const& e) : int
-
+
-
+
get_int_e2(E<int>& e) : int
-
+
-
+
get_f(F<T> const& f) : T
-
+
-
+
get_int_f(F<int> const& f) : int
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
estring
diff --git a/docs/test_cases/t00014_class.svg b/docs/test_cases/t00014_class.svg
index 6efb1c97..d07ffa4b 100644
--- a/docs/test_cases/t00014_class.svg
+++ b/docs/test_cases/t00014_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
A
@@ -17,22 +18,22 @@
T,P
-
+
-
+
t : T
-
+
-
+
p : P
-
+
A
@@ -40,22 +41,22 @@
T,std::string
-
-
+
+
B
-
+
-
+
value : std::string
-
+
A
@@ -63,7 +64,7 @@
bool,std::string
-
+
AString
@@ -71,7 +72,7 @@
float
-
+
AString
@@ -79,7 +80,7 @@
int
-
+
AString
@@ -87,7 +88,7 @@
std::string
-
+
GeneralCallback
@@ -95,115 +96,115 @@
AIntString
-
+
GeneralCallback
-
-
+
+
R
-
+
-
+
boolstring : A<bool,std::string>
-
+
-
+
floatstring : AString<float>
-
+
-
+
intstring : AIntString
-
+
-
+
stringstring : AStringString
-
+
-
+
bs : BVector
-
+
-
+
bs2 : BVector2
-
+
-
+
cb : GeneralCallback<AIntString>
-
+
-
+
vcb : VoidCallback
-
+
-
+
-
+
-
+
-
+
-
+
boolstring
-
+
floatstring
-
+
intstring
-
+
stringstring
-
+
bs
-
+
bs2
-
+
cb
-
+
vcb
diff --git a/docs/test_cases/t00015_class.svg b/docs/test_cases/t00015_class.svg
index fe9eda6d..832850d6 100644
--- a/docs/test_cases/t00015_class.svg
+++ b/docs/test_cases/t00015_class.svg
@@ -1,58 +1,59 @@
-
+
+
-
-
+
+
ns1::A
-
-
+
+
ns1::ns2_v0_9_0::A
-
-
+
+
ns1::Anon
-
-
+
+
ns3::ns1::ns2::Anon
-
-
+
+
ns3::B
-
+
-
+
-
+
diff --git a/docs/test_cases/t00016_class.svg b/docs/test_cases/t00016_class.svg
index 9c6d4fc5..9e19bcdd 100644
--- a/docs/test_cases/t00016_class.svg
+++ b/docs/test_cases/t00016_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
is_numeric<>
@@ -18,8 +19,8 @@
value : enum
-
-
+
+
is_numeric
@@ -30,8 +31,8 @@
value : enum
-
-
+
+
is_numeric
@@ -42,8 +43,8 @@
value : enum
-
-
+
+
is_numeric
@@ -54,8 +55,8 @@
value : enum
-
-
+
+
is_numeric
@@ -66,13 +67,13 @@
value : enum
-
+
-
+
-
+
-
+
diff --git a/docs/test_cases/t00017_class.svg b/docs/test_cases/t00017_class.svg
index 9c736dbd..dbd3e31f 100644
--- a/docs/test_cases/t00017_class.svg
+++ b/docs/test_cases/t00017_class.svg
@@ -1,183 +1,184 @@
-
+
+
-
-
+
+
A
-
-
+
+
B
-
-
+
+
C
-
-
+
+
D
-
-
+
+
E
-
-
+
+
F
-
-
+
+
G
-
-
+
+
H
-
-
+
+
I
-
-
+
+
J
-
-
+
+
K
-
-
+
+
R
-
+
-
+
some_int : int
-
+
-
+
some_int_pointer : int*
-
+
-
+
some_int_pointer_pointer : int**
-
+
-
+
some_int_reference : int&
-
+
-
+
R(int& some_int, C& cc, E const& ee, F&& ff, I*& ii) : void
-
+
-
+
-c
-
+
-
+
-e
-
+
-
+
-f
-
+
-
+
-i
-
+
-a
-
+
-b
-
+
-d
-
+
-g
-
+
-h
-
+
-j
-
+
-k
diff --git a/docs/test_cases/t00018_class.svg b/docs/test_cases/t00018_class.svg
index 0026b519..cf056069 100644
--- a/docs/test_cases/t00018_class.svg
+++ b/docs/test_cases/t00018_class.svg
@@ -1,130 +1,131 @@
-
+
+
-
-
+
+
impl::widget
-
+
-
+
n : int
-
+
-
+
draw(widget const& w) const : void
-
+
-
+
draw(widget const& w) : void
-
+
-
+
widget(int n) : void
-
-
+
+
widget
-
+
-
+
pImpl : std::unique_ptr<impl::widget>
-
+
-
+
draw() const : void
-
+
-
+
draw() : void
-
+
-
+
shown() const : bool
-
+
-
+
widget(int ) : void
-
+
-
+
~widget() : void
-
+
-
+
widget(widget&& ) : void
-
+
-
+
widget(widget const& ) : void
-
+
-
+
operator=(widget&& ) : widget&
-
+
-
+
operator=(widget const& ) : widget&
-
+
-
+
pImpl
diff --git a/docs/test_cases/t00019_class.svg b/docs/test_cases/t00019_class.svg
index 7f0a608c..d2ec0e29 100644
--- a/docs/test_cases/t00019_class.svg
+++ b/docs/test_cases/t00019_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
Layer2
@@ -18,51 +19,51 @@
-
+
-
+
all_calls_count() const : int
-
-
+
+
Base
-
+
-
+
Base() : void
-
+
-
+
~Base() : void
-
+
-
+
m1() : int
-
+
-
+
m2() : std::string
-
-
+
+
Layer1
@@ -71,22 +72,22 @@
-
+
-
+
m1() : int
-
+
-
+
m2() : std::string
-
-
+
+
Layer3
@@ -94,50 +95,50 @@
LowerLayer
-
+
-
+
m_m1_calls : int
-
+
-
+
m_m2_calls : int
-
+
-
+
m1() : int
-
+
-
+
m2() : std::string
-
+
-
+
m1_calls() const : int
-
+
-
+
m2_calls() const : int
-
+
Layer3
@@ -145,7 +146,7 @@
Base
-
+
Layer2
@@ -153,7 +154,7 @@
Layer3<Base>
-
+
Layer1
@@ -161,40 +162,40 @@
Layer2<Layer3<Base>>
-
-
+
+
A
-
+
-
+
layers : std::unique_ptr<Layer1<Layer2<Layer3<Base>>>>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
layers
diff --git a/docs/test_cases/t00020_class.svg b/docs/test_cases/t00020_class.svg
index 53d028cb..23d91945 100644
--- a/docs/test_cases/t00020_class.svg
+++ b/docs/test_cases/t00020_class.svg
@@ -1,202 +1,203 @@
-
+
+
-
-
+
+
ProductA
-
+
-
+
~ProductA() : void
-
+
-
+
sell(int price) const = 0 : bool
-
-
+
+
ProductA1
-
+
-
+
sell(int price) const : bool
-
-
+
+
ProductA2
-
+
-
+
sell(int price) const : bool
-
-
+
+
ProductB
-
+
-
+
~ProductB() : void
-
+
-
+
buy(int price) const = 0 : bool
-
-
+
+
ProductB1
-
+
-
+
buy(int price) const : bool
-
-
+
+
ProductB2
-
+
-
+
buy(int price) const : bool
-
-
+
+
AbstractFactory
-
+
-
+
make_a() const = 0 : std::unique_ptr<ProductA>
-
+
-
+
make_b() const = 0 : std::unique_ptr<ProductB>
-
-
+
+
Factory1
-
+
-
+
make_a() const : std::unique_ptr<ProductA>
-
+
-
+
make_b() const : std::unique_ptr<ProductB>
-
-
+
+
Factory2
-
+
-
+
make_a() const : std::unique_ptr<ProductA>
-
+
-
+
make_b() const : std::unique_ptr<ProductB>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/docs/test_cases/t00021_class.svg b/docs/test_cases/t00021_class.svg
index 4f9e4d1f..38801577 100644
--- a/docs/test_cases/t00021_class.svg
+++ b/docs/test_cases/t00021_class.svg
@@ -1,191 +1,192 @@
-
+
+
-
-
+
+
Visitor
-
+
-
+
~Visitor() : void
-
+
-
+
visit_A(A const& item) const = 0 : void
-
+
-
+
visit_B(B const& item) const = 0 : void
-
-
+
+
Visitor1
-
+
-
+
visit_A(A const& item) const : void
-
+
-
+
visit_B(B const& item) const : void
-
-
+
+
Visitor2
-
+
-
+
visit_A(A const& item) const : void
-
+
-
+
visit_B(B const& item) const : void
-
-
+
+
Visitor3
-
+
-
+
visit_A(A const& item) const : void
-
+
-
+
visit_B(B const& item) const : void
-
-
+
+
Item
-
+
-
+
~Item() : void
-
+
-
+
accept(Visitor const& visitor) const = 0 : void
-
-
+
+
A
-
+
-
+
accept(Visitor const& visitor) const : void
-
-
+
+
B
-
+
-
+
accept(Visitor const& visitor) const : void
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/docs/test_cases/t00022_class.svg b/docs/test_cases/t00022_class.svg
index fe0c156b..451e4c6e 100644
--- a/docs/test_cases/t00022_class.svg
+++ b/docs/test_cases/t00022_class.svg
@@ -1,89 +1,90 @@
-
+
+
-
-
+
+
A
-
+
-
+
template_method() : void
-
+
-
+
method1() = 0 : void
-
+
-
+
method2() = 0 : void
-
-
+
+
A1
-
+
-
+
method1() : void
-
+
-
+
method2() : void
-
-
+
+
A2
-
+
-
+
method1() : void
-
+
-
+
method2() : void
-
+
-
+
diff --git a/docs/test_cases/t00023_class.svg b/docs/test_cases/t00023_class.svg
index e0f74bce..7c837b84 100644
--- a/docs/test_cases/t00023_class.svg
+++ b/docs/test_cases/t00023_class.svg
@@ -1,118 +1,119 @@
-
+
+
-
-
+
+
Strategy
-
+
-
+
~Strategy() : void
-
+
-
+
algorithm() = 0 : void
-
-
+
+
StrategyA
-
+
-
+
algorithm() : void
-
-
+
+
StrategyB
-
+
-
+
algorithm() : void
-
-
+
+
StrategyC
-
+
-
+
algorithm() : void
-
-
+
+
Context
-
+
-
+
m_strategy : std::unique_ptr<Strategy>
-
+
-
+
Context(std::unique_ptr<Strategy> strategy) : void
-
+
-
+
apply() : void
-
+
-
+
-
+
-
+
-
+
m_strategy
diff --git a/docs/test_cases/t00024_class.svg b/docs/test_cases/t00024_class.svg
index 530eddfa..8c7101a2 100644
--- a/docs/test_cases/t00024_class.svg
+++ b/docs/test_cases/t00024_class.svg
@@ -1,133 +1,134 @@
-
+
+
-
-
+
+
Target
-
+
-
+
~Target() : void
-
+
-
+
m1() = 0 : void
-
+
-
+
m2() = 0 : void
-
-
+
+
Target1
-
+
-
+
m1() : void
-
+
-
+
m2() : void
-
-
+
+
Target2
-
+
-
+
m1() : void
-
+
-
+
m2() : void
-
-
+
+
Proxy
-
+
-
+
m_target : std::shared_ptr<Target>
-
+
-
+
Proxy(std::shared_ptr<Target> target) : void
-
+
-
+
m1() : void
-
+
-
+
m2() : void
-
+
-
+
-
+
-
+
m_target
-
+
diff --git a/docs/test_cases/t00025_class.svg b/docs/test_cases/t00025_class.svg
index 8ec44b8d..9731d133 100644
--- a/docs/test_cases/t00025_class.svg
+++ b/docs/test_cases/t00025_class.svg
@@ -1,59 +1,60 @@
-
+
+
-
-
+
+
Target1
-
+
-
+
m1() : void
-
+
-
+
m2() : void
-
-
+
+
Target2
-
+
-
+
m1() : void
-
+
-
+
m2() : void
-
-
+
+
Proxy
@@ -61,36 +62,36 @@
T
-
+
-
+
m_target : std::shared_ptr<T>
-
+
-
+
Proxy(std::shared_ptr<T> target) : void
-
+
-
+
m1() : void
-
+
-
+
m2() : void
-
+
Proxy
@@ -98,7 +99,7 @@
Target1
-
+
Proxy
@@ -106,41 +107,41 @@
Target2
-
-
+
+
ProxyHolder
-
+
-
+
proxy1 : Proxy<Target1>
-
+
-
+
proxy2 : Proxy<Target2>
-
+
-
+
-
+
-
+
-
+
proxy1
-
+
proxy2
diff --git a/docs/test_cases/t00026_class.svg b/docs/test_cases/t00026_class.svg
index f21f1cbb..4107e405 100644
--- a/docs/test_cases/t00026_class.svg
+++ b/docs/test_cases/t00026_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
Memento
@@ -17,30 +18,30 @@
T
-
+
-
+
m_value : T
-
+
-
+
Memento(T&& v) : void
-
+
-
+
value() const : T
-
-
+
+
Originator
@@ -48,51 +49,51 @@
T
-
+
-
+
m_value : T
-
+
-
+
Originator(T&& v) : void
-
+
-
+
memoize_value() const : Memento<T>
-
+
-
+
load(Memento<T> const& m) : void
-
+
-
+
print() const : void
-
+
-
+
set(T&& v) : void
-
-
+
+
Caretaker
@@ -100,29 +101,29 @@
T
-
+
-
+
m_mementos : std::unordered_map<std::string,Memento<T>>
-
+
-
+
state(std::string const& n) : Memento<T>&
-
+
-
+
set_state(std::string const& s, Memento<T>&& m) : void
-
+
Caretaker
@@ -130,7 +131,7 @@
std::string
-
+
Originator
@@ -138,45 +139,45 @@
std::string
-
-
+
+
StringMemento
-
+
-
+
caretaker : Caretaker<std::string>
-
+
-
+
originator : Originator<std::string>
-
+
-
+
-
+
m_mementos
-
+
-
+
-
+
caretaker
-
+
originator
diff --git a/docs/test_cases/t00027_class.svg b/docs/test_cases/t00027_class.svg
index 0bdc0f16..825c00ac 100644
--- a/docs/test_cases/t00027_class.svg
+++ b/docs/test_cases/t00027_class.svg
@@ -1,37 +1,38 @@
-
+
+
-
-
+
+
Shape
-
+
-
+
display() = 0 : void
-
+
-
+
~Shape() : void
-
-
+
+
Line
@@ -40,15 +41,15 @@
-
+
-
+
display() : void
-
-
+
+
Text
@@ -57,30 +58,30 @@
-
+
-
+
display() : void
-
-
+
+
ShapeDecorator
-
+
-
+
display() = 0 : void
-
-
+
+
Color
@@ -89,15 +90,15 @@
-
+
-
+
display() : void
-
-
+
+
Weight
@@ -106,14 +107,14 @@
-
+
-
+
display() : void
-
+
Line
@@ -121,7 +122,7 @@
Color,Weight
-
+
Line
@@ -129,7 +130,7 @@
Color
-
+
Text
@@ -137,7 +138,7 @@
Color,Weight
-
+
Text
@@ -145,71 +146,71 @@
Color
-
-
+
+
Window
-
+
-
+
border : Line<Color,Weight>
-
+
-
+
divider : Line<Color>
-
+
-
+
title : Text<Color,Weight>
-
+
-
+
description : Text<Color>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
border
-
+
divider
-
+
title
-
+
description
diff --git a/docs/test_cases/t00028_class.svg b/docs/test_cases/t00028_class.svg
index a46c146e..e6ba4850 100644
--- a/docs/test_cases/t00028_class.svg
+++ b/docs/test_cases/t00028_class.svg
@@ -1,75 +1,76 @@
-
+
+
-
-
+
+
A
-
+
A class note.
-
+
A class note.
-
-
+
+
B
-
+
B class note.
-
+
B class note.
-
-
+
+
C
-
+
C class note.
-
+
C class note.
-
-
+
+
D
-
+
D
class
note.
-
+
D
class
note.
-
-
+
+
E
@@ -77,27 +78,27 @@
T
-
+
-
+
param : T
-
+
E template class note.
-
-
+
+
G
-
-
+
+
F
@@ -107,13 +108,13 @@
three
-
+
F enum note.
-
+
F enum note.
-
+
E
@@ -121,97 +122,97 @@
int
-
-
+
+
R
-
+
-
+
aaa : A
-
+
-
+
bbb : B*
-
+
-
+
ccc : C&
-
+
-
+
ddd : std::vector<std::shared_ptr<D>>
-
+
-
+
eee : E<int>
-
+
-
+
ggg : G**
-
+
-
+
R(C& c) : void
-
+
R class note.
-
+
R class note.
-
-
-
-
+
+
+
+
-
+
-
+
ccc
-
+
aaa
-
+
bbb
-
+
ddd
-
+
eee
-
+
ggg
diff --git a/docs/test_cases/t00029_class.svg b/docs/test_cases/t00029_class.svg
index 4cd06884..cb589208 100644
--- a/docs/test_cases/t00029_class.svg
+++ b/docs/test_cases/t00029_class.svg
@@ -1,23 +1,24 @@
-
+
+
-
-
+
+
A
-
-
+
+
C
@@ -25,16 +26,16 @@
T
-
+
-
+
param : T
-
-
+
+
E
@@ -44,72 +45,72 @@
three
-
-
+
+
G1
-
-
+
+
G2
-
-
+
+
G3
-
-
+
+
G4
-
-
+
+
R
-
+
-
+
g1 : G1
-
+
-
+
g3 : G3&
-
+
-
+
g4 : std::shared_ptr<G4>
-
+
g1
-
+
g4
diff --git a/docs/test_cases/t00030_class.svg b/docs/test_cases/t00030_class.svg
index cb4b0d2e..59a90a82 100644
--- a/docs/test_cases/t00030_class.svg
+++ b/docs/test_cases/t00030_class.svg
@@ -1,98 +1,99 @@
-
+
+
-
-
+
+
A
-
-
+
+
B
-
-
+
+
C
-
-
+
+
D
-
-
+
+
R
-
+
-
+
aaa : A
-
+
-
+
bbb : std::vector<B>
-
+
-
+
ccc : std::vector<C>
-
+
-
+
ddd : D
-
+
aaa
-
+
bbb
0..1
1..*
-
+
ccc
0..1
1..5
-
+
ddd
diff --git a/docs/test_cases/t00031_class.svg b/docs/test_cases/t00031_class.svg
index ceba61a7..0dba7e6b 100644
--- a/docs/test_cases/t00031_class.svg
+++ b/docs/test_cases/t00031_class.svg
@@ -1,32 +1,33 @@
-
+
-
+
-
+
+
-
-
-
+
+
+
A
-
-
+
+
B
@@ -36,8 +37,8 @@
three
-
-
+
+
@@ -46,23 +47,23 @@
T
-
+
-
+
ttt : T
-
-
+
+
D
-
+
C
@@ -70,57 +71,57 @@
int
-
-
+
+
R
-
+
-
+
aaa : A*
-
+
-
+
bbb : std::vector<B>
-
+
-
+
ccc : C<int>
-
+
-
+
ddd : D*
-
+
-
+
aaa
-
+
bbb
-
+
ccc
-
+
ddd
diff --git a/docs/test_cases/t00032_class.svg b/docs/test_cases/t00032_class.svg
index 7f78d0c5..1a02ffed 100644
--- a/docs/test_cases/t00032_class.svg
+++ b/docs/test_cases/t00032_class.svg
@@ -1,76 +1,77 @@
-
+
+
-
-
+
+
Base
-
-
+
+
TBase
-
-
+
+
A
-
+
-
+
operator()() : void
-
-
+
+
B
-
+
-
+
operator()() : void
-
-
+
+
C
-
+
-
+
operator()() : void
-
-
+
+
Overload
@@ -78,15 +79,15 @@
T,L,Ts...
-
+
-
+
counter : L
-
+
Overload
@@ -94,42 +95,42 @@
TBase,int,A,B,C
-
-
+
+
R
-
+
-
+
overload : Overload<TBase,int,A,B,C>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
overload
diff --git a/docs/test_cases/t00033_class.svg b/docs/test_cases/t00033_class.svg
index 083403ba..1fc558ff 100644
--- a/docs/test_cases/t00033_class.svg
+++ b/docs/test_cases/t00033_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
A
@@ -17,16 +18,16 @@
T
-
+
-
+
aaa : T
-
-
+
+
B
@@ -34,16 +35,16 @@
T
-
+
-
+
bbb : T
-
-
+
+
C
@@ -51,30 +52,30 @@
T
-
+
-
+
ccc : T
-
-
+
+
D
-
+
-
+
ddd : int
-
+
C
@@ -82,7 +83,7 @@
D
-
+
B
@@ -90,7 +91,7 @@
std::unique_ptr<C<D>>
-
+
A
@@ -98,34 +99,34 @@
B<std::unique_ptr<C<D>>>
-
-
+
+
R
-
+
-
+
abc : A<B<std::unique_ptr<C<D>>>>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
abc
diff --git a/docs/test_cases/t00034_class.svg b/docs/test_cases/t00034_class.svg
index 5a126006..c30b7c8d 100644
--- a/docs/test_cases/t00034_class.svg
+++ b/docs/test_cases/t00034_class.svg
@@ -1,37 +1,38 @@
-
+
+
-
-
+
+
Void
-
+
-
+
operator==(Void const& ) const : bool
-
+
-
+
operator!=(Void const& ) const : bool
-
-
+
+
lift_void
@@ -40,8 +41,8 @@
-
-
+
+
lift_void
@@ -50,8 +51,8 @@
-
-
+
+
drop_void
@@ -60,8 +61,8 @@
-
-
+
+
drop_void
@@ -70,43 +71,43 @@
-
-
+
+
A
-
-
+
+
R
-
+
-
+
la : lift_void_t<A>*
-
+
-
+
lv : lift_void_t<void>*
-
+
-
+
-
+
-
+
la
diff --git a/docs/test_cases/t00035_class.svg b/docs/test_cases/t00035_class.svg
index f0937dde..69058bc7 100644
--- a/docs/test_cases/t00035_class.svg
+++ b/docs/test_cases/t00035_class.svg
@@ -1,47 +1,48 @@
-
+
+
-
-
+
+
Top
-
-
+
+
Left
-
-
+
+
Center
-
-
+
+
Bottom
-
-
+
+
Right
diff --git a/docs/test_cases/t00036_class.svg b/docs/test_cases/t00036_class.svg
index 57782899..56a28096 100644
--- a/docs/test_cases/t00036_class.svg
+++ b/docs/test_cases/t00036_class.svg
@@ -1,30 +1,31 @@
-
+
+
-
+
ns1
-
+
ns11
-
+
ns111
-
+
ns2
-
+
ns22
-
-
+
+
E
@@ -33,8 +34,8 @@
yellow
-
-
+
+
A
@@ -42,15 +43,15 @@
T
-
+
-
+
a : T
-
+
A
@@ -58,32 +59,32 @@
int
-
-
+
+
B
-
+
-
+
a_int : A<int>
-
-
+
+
C
-
+
-
+
a_int
diff --git a/docs/test_cases/t00037_class.svg b/docs/test_cases/t00037_class.svg
index d2dddc84..167ee043 100644
--- a/docs/test_cases/t00037_class.svg
+++ b/docs/test_cases/t00037_class.svg
@@ -1,91 +1,92 @@
-
+
+
-
-
+
+
ST
-
+
-
+
dimensions : «anonymous»
-
-
+
+
<<anonymous>>
-
+
-
+
t : double
-
+
-
+
x : double
-
+
-
+
y : double
-
+
-
+
z : double
-
-
+
+
A
-
+
-
+
st : ST
-
+
-
+
A() : void
-
+
-
+
st
diff --git a/docs/test_cases/t00038_class.svg b/docs/test_cases/t00038_class.svg
index ed083346..ed262556 100644
--- a/docs/test_cases/t00038_class.svg
+++ b/docs/test_cases/t00038_class.svg
@@ -1,15 +1,16 @@
-
+
+
-
-
+
+
thirdparty::ns1::color_t
@@ -19,16 +20,16 @@
blue
-
-
+
+
thirdparty::ns1::E
-
-
+
+
property_t
@@ -38,47 +39,47 @@
property_c
-
-
+
+
A
-
-
+
+
B
-
-
+
+
C
-
-
+
+
key_t
-
+
-
+
key : std::string
-
-
+
+
map
@@ -87,8 +88,8 @@
-
-
+
+
map
@@ -97,8 +98,8 @@
-
-
+
+
map
@@ -107,8 +108,8 @@
-
-
+
+
map
@@ -117,8 +118,8 @@
-
-
+
+
map
@@ -127,31 +128,31 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/docs/test_cases/t00039.md b/docs/test_cases/t00039.md
new file mode 100644
index 00000000..40948b07
--- /dev/null
+++ b/docs/test_cases/t00039.md
@@ -0,0 +1,72 @@
+# t00039 - Subclass class diagram filter test
+## Config
+```yaml
+compilation_database_dir: ..
+output_directory: puml
+diagrams:
+ t00039_class:
+ type: class
+ generate_packages: false
+ glob:
+ - ../../tests/t00039/t00039.cc
+ using_namespace:
+ - clanguml::t00039
+ include:
+ subclasses:
+ - clanguml::t00039::A
+ - clanguml::t00039::ns3::F
+ relationships:
+ - inheritance
+```
+## Source code
+File t00039.cc
+```cpp
+#include
+
+namespace clanguml::t00039 {
+struct B {
+};
+
+namespace ns1 {
+struct BB : public B {
+};
+} // namespace ns1
+
+struct A {
+};
+
+struct AA : public A {
+};
+
+struct AAA : public AA {
+ B *b;
+};
+
+namespace ns2 {
+struct AAAA : public AAA {
+};
+} // namespace ns2
+
+namespace ns3 {
+template struct F {
+ T *t;
+};
+
+template struct FF : public F {
+ M *m;
+};
+
+template struct FE : public F {
+ M *m;
+};
+
+template struct FFF : public FF {
+ N *n;
+};
+
+} // namespace ns3
+} // namespace clanguml::t00039
+
+```
+## Generated UML diagrams
+
diff --git a/docs/test_cases/t00039_class.svg b/docs/test_cases/t00039_class.svg
new file mode 100644
index 00000000..8117f628
--- /dev/null
+++ b/docs/test_cases/t00039_class.svg
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+
+
+
+
+
+
+
+ AA
+
+
+
+
+
+
+
+ AAA
+
+
+
+
+
+
+
+ b : B*
+
+
+
+
+
+
+ ns2::AAAA
+
+
+
+
+
+
+
+ ns3::F
+
+ T
+
+
+
+
+
+
+
+ t : T*
+
+
+
+
+
+
+ ns3::FF
+
+ T,M
+
+
+
+
+
+
+
+ m : M*
+
+
+
+
+
+
+ ns3::FE
+
+ T,M
+
+
+
+
+
+
+
+ m : M*
+
+
+
+
+
+
+ ns3::FFF
+
+ T,M,N
+
+
+
+
+
+
+
+ n : N*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/test_cases/t00040.md b/docs/test_cases/t00040.md
new file mode 100644
index 00000000..fd62d589
--- /dev/null
+++ b/docs/test_cases/t00040.md
@@ -0,0 +1,68 @@
+# t00040 - Relationship and access filter test
+## Config
+```yaml
+compilation_database_dir: ..
+output_directory: puml
+diagrams:
+ t00040_class:
+ type: class
+ generate_packages: false
+ glob:
+ - ../../tests/t00040/t00040.cc
+ using_namespace:
+ - clanguml::t00040
+ include:
+ namespaces:
+ - clanguml::t00040
+ access:
+ - public
+ - protected
+ exclude:
+ relationships:
+ - dependency
+ elements:
+ - clanguml::t00040::B
+```
+## Source code
+File t00040.cc
+```cpp
+namespace clanguml::t00040 {
+
+struct B {
+};
+
+struct A {
+public:
+ int get_a() { return hidden_a_; }
+
+protected:
+ int ii_;
+
+private:
+ void foo() { }
+
+ int hidden_a_;
+};
+
+class AA : public A {
+public:
+};
+
+class AAA : public AA {
+public:
+ int get_aaa() { return hidden_aaa_; }
+ B *b;
+
+private:
+ int hidden_aaa_;
+};
+
+struct R {
+ void foo(A *a) { }
+};
+
+} // namespace clanguml::t00040
+
+```
+## Generated UML diagrams
+
diff --git a/docs/test_cases/t00040_class.svg b/docs/test_cases/t00040_class.svg
new file mode 100644
index 00000000..f2f2460c
--- /dev/null
+++ b/docs/test_cases/t00040_class.svg
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+
+
+
+
+
+
+
+ ii_ : int
+
+
+
+
+
+
+
+ get_a() : int
+
+
+
+
+
+ AA
+
+
+
+
+
+
+
+ AAA
+
+
+
+
+
+
+
+ b : B*
+
+
+
+
+
+
+
+ get_aaa() : int
+
+
+
+
+
+ R
+
+
+
+
+
+
+
+
+ foo(A* a) : void
+
+
+
+
+
+
+
diff --git a/docs/test_cases/t00041.md b/docs/test_cases/t00041.md
new file mode 100644
index 00000000..ab17251e
--- /dev/null
+++ b/docs/test_cases/t00041.md
@@ -0,0 +1,74 @@
+# t00041 - Context diagram filter test
+## Config
+```yaml
+compilation_database_dir: ..
+output_directory: puml
+diagrams:
+ t00041_class:
+ type: class
+ generate_packages: false
+ glob:
+ - ../../tests/t00041/t00041.cc
+ using_namespace:
+ - clanguml::t00041
+ include:
+ namespaces:
+ - clanguml::t00041
+ context:
+ - clanguml::t00041::RR
+ subclasses:
+ - clanguml::t00041::ns1::N
+```
+## Source code
+File t00041.cc
+```cpp
+namespace clanguml::t00041 {
+
+struct B {
+};
+
+struct A {
+};
+
+class AA : public A {
+};
+
+struct R {
+};
+
+struct RR;
+
+struct D {
+ RR *rr;
+};
+
+struct E {
+};
+
+struct F {
+};
+
+struct RR : public R {
+ E *e;
+ F *f;
+};
+
+struct RRR : public RR {
+};
+
+namespace ns1 {
+struct N {
+};
+
+struct NN : public N {
+};
+
+struct NM : public N {
+};
+}
+
+} // namespace clanguml::t00041
+
+```
+## Generated UML diagrams
+
diff --git a/docs/test_cases/t00041_class.svg b/docs/test_cases/t00041_class.svg
new file mode 100644
index 00000000..e00c3a92
--- /dev/null
+++ b/docs/test_cases/t00041_class.svg
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ R
+
+
+
+
+
+
+
+ D
+
+
+
+
+
+
+
+ rr : RR*
+
+
+
+
+
+
+ E
+
+
+
+
+
+
+
+ F
+
+
+
+
+
+
+
+ RR
+
+
+
+
+
+
+
+ e : E*
+
+
+
+
+
+
+ f : F*
+
+
+
+
+
+
+ RRR
+
+
+
+
+
+
+
+ ns1::N
+
+
+
+
+
+
+
+ ns1::NN
+
+
+
+
+
+
+
+ ns1::NM
+
+
+
+
+
+
+ rr
+
+
+ +e
+
+
+ +f
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/test_cases/t20001_sequence.svg b/docs/test_cases/t20001_sequence.svg
index bbbcbdff..470e2953 100644
--- a/docs/test_cases/t20001_sequence.svg
+++ b/docs/test_cases/t20001_sequence.svg
@@ -6,6 +6,7 @@
+
diff --git a/docs/test_cases/t20002_sequence.svg b/docs/test_cases/t20002_sequence.svg
index d8e94f30..568a2b80 100644
--- a/docs/test_cases/t20002_sequence.svg
+++ b/docs/test_cases/t20002_sequence.svg
@@ -6,6 +6,7 @@
+
diff --git a/docs/test_cases/t30001_package.svg b/docs/test_cases/t30001_package.svg
index 94383a86..19cfccfc 100644
--- a/docs/test_cases/t30001_package.svg
+++ b/docs/test_cases/t30001_package.svg
@@ -1,66 +1,67 @@
-
+
+
-
-
+
+
A
-
-
+
+
AA
-
-
+
+
B
-
-
+
+
AA
-
-
+
+
AAA
-
-
+
+
BBB
-
-
+
+
BB
-
-
+
+
AAA
-
-
+
+
BBB
-
-
+
+
BB
-
+
A AAA note...
-
+
diff --git a/docs/test_cases/t30002_package.svg b/docs/test_cases/t30002_package.svg
index ae5fa916..2f90ac61 100644
--- a/docs/test_cases/t30002_package.svg
+++ b/docs/test_cases/t30002_package.svg
@@ -1,128 +1,129 @@
-
+
+
-
-
+
+
A
-
-
+
+
AA
-
-
+
+
B
-
-
+
+
BB
-
-
+
+
A1
-
-
+
+
A2
-
-
+
+
A3
-
-
+
+
A4
-
-
+
+
A5
-
-
+
+
A6
-
-
+
+
A7
-
-
+
+
A8
-
-
+
+
A9
-
-
+
+
A10
-
-
+
+
A11
-
-
+
+
A12
-
-
+
+
A13
-
-
+
+
BBB
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/docs/test_cases/t30003_package.svg b/docs/test_cases/t30003_package.svg
index 5997775a..abfcdeaa 100644
--- a/docs/test_cases/t30003_package.svg
+++ b/docs/test_cases/t30003_package.svg
@@ -1,46 +1,47 @@
-
+
+
-
-
+
+
ns1
-
-
+
+
ns3
«deprecated»
-
-
+
+
ns1
-
-
+
+
ns2_v1_0_0
-
-
+
+
ns2_v0_9_0
«deprecated»
-
-
+
+
ns2
-
+
diff --git a/docs/test_cases/t30004_package.svg b/docs/test_cases/t30004_package.svg
index 8fe51741..0a766e61 100644
--- a/docs/test_cases/t30004_package.svg
+++ b/docs/test_cases/t30004_package.svg
@@ -1,57 +1,58 @@
-
+
+
-
-
+
+
A
-
+
Package AAA.
-
+
Package BBB.
-
+
CCCC package note.
-
+
Another CCC note.
-
+
We skipped DDD.
-
-
+
+
AAA
-
-
+
+
BBB
-
-
+
+
CCC
-
-
+
+
EEE
-
-
-
-
-
+
+
+
+
+
diff --git a/docs/test_cases/t30005_package.svg b/docs/test_cases/t30005_package.svg
index 21c5dacd..aefc641c 100644
--- a/docs/test_cases/t30005_package.svg
+++ b/docs/test_cases/t30005_package.svg
@@ -1,61 +1,62 @@
-
+
+
-
-
+
+
A
-
-
+
+
AA
-
-
+
+
B
-
-
+
+
BB
-
-
+
+
C
-
-
+
+
CC
-
-
+
+
AAA
-
-
+
+
BBB
-
-
+
+
CCC
-
+
-
+
diff --git a/docs/test_cases/t30006_package.svg b/docs/test_cases/t30006_package.svg
index b0b5cd09..7eced5db 100644
--- a/docs/test_cases/t30006_package.svg
+++ b/docs/test_cases/t30006_package.svg
@@ -1,39 +1,40 @@
-
+
+
-
-
+
+
B
-
-
+
+
A
-
-
+
+
C
-
+
Top A note.
-
+
Bottom A note.
-
-
-
+
+
+
-
+
diff --git a/docs/test_cases/t30007_package.svg b/docs/test_cases/t30007_package.svg
index 29f44063..59f9ad5b 100644
--- a/docs/test_cases/t30007_package.svg
+++ b/docs/test_cases/t30007_package.svg
@@ -1,44 +1,45 @@
-
+
+
-
-
+
+
A
-
-
+
+
B
-
-
+
+
AA
-
-
+
+
C
-
+
Compare layout with t30006.
-
+
Bottom A note.
-
-
-
+
+
+
-
+
diff --git a/docs/test_cases/t90000_class.svg b/docs/test_cases/t90000_class.svg
index 37c80296..64b6d962 100644
--- a/docs/test_cases/t90000_class.svg
+++ b/docs/test_cases/t90000_class.svg
@@ -6,6 +6,7 @@
+
diff --git a/examples/cppast/.clang-uml b/examples/cppast/.clang-uml
index 92e51154..63cb2b0f 100644
--- a/examples/cppast/.clang-uml
+++ b/examples/cppast/.clang-uml
@@ -25,7 +25,7 @@ diagrams:
exclude:
namespaces:
- cppast::detail
- scopes:
+ access:
- public
- protected
- private
@@ -73,7 +73,7 @@ diagrams:
- cppast::detail
entity_types:
- enums
- scopes:
+ access:
- public
- protected
- private
@@ -93,7 +93,7 @@ diagrams:
exclude:
namespaces:
- cppast::detail
- scopes:
+ access:
- public
- protected
- private
diff --git a/src/class_diagram/generators/plantuml/class_diagram_generator.cc b/src/class_diagram/generators/plantuml/class_diagram_generator.cc
index b90601fb..9b458fdb 100644
--- a/src/class_diagram/generators/plantuml/class_diagram_generator.cc
+++ b/src/class_diagram/generators/plantuml/class_diagram_generator.cc
@@ -110,7 +110,7 @@ void generator::generate(
// Process methods
//
for (const auto &m : c.methods()) {
- if (!m_config.should_include(m.scope()))
+ if (!m_model.should_include(m.access()))
continue;
if (m.is_pure_virtual())
@@ -121,7 +121,7 @@ void generator::generate(
std::string type{m.type()};
- ostr << plantuml_common::to_plantuml(m.scope()) << m.name();
+ ostr << plantuml_common::to_plantuml(m.access()) << m.name();
ostr << "(";
if (m_config.generate_method_arguments() !=
@@ -168,8 +168,7 @@ void generator::generate(
std::stringstream all_relations_str;
std::set unique_relations;
for (const auto &r : c.relationships()) {
- if (!m_config.should_include_relationship(
- common::model::to_string(r.type())))
+ if (!m_model.should_include(r.type()))
continue;
LOG_DBG("== Processing relationship {}",
@@ -196,7 +195,7 @@ void generator::generate(
<< m_model.to_alias(uns.relative(destination));
if (!r.label().empty()) {
- relstr << " : " << plantuml_common::to_plantuml(r.scope())
+ relstr << " : " << plantuml_common::to_plantuml(r.access())
<< r.label();
rendered_relations.emplace(r.label());
}
@@ -223,7 +222,7 @@ void generator::generate(
// Process members
//
for (const auto &m : c.members()) {
- if (!m_config.should_include(m.scope()))
+ if (!m_model.should_include(m.access()))
continue;
if (!m_config.include_relations_also_as_members() &&
@@ -233,7 +232,7 @@ void generator::generate(
if (m.is_static())
ostr << "{static} ";
- ostr << plantuml_common::to_plantuml(m.scope()) << m.name() << " : "
+ ostr << plantuml_common::to_plantuml(m.access()) << m.name() << " : "
<< uns.relative(m.type());
if (m_config.generate_links) {
@@ -245,7 +244,7 @@ void generator::generate(
ostr << "}" << '\n';
- if (m_config.should_include_relationship("inheritance")) {
+ if (m_model.should_include(relationship_t::kExtension)) {
for (const auto &b : c.parents()) {
std::stringstream relstr;
try {
@@ -288,8 +287,7 @@ void generator::generate(
ostr << "}" << '\n';
for (const auto &r : e.relationships()) {
- if (!m_config.should_include_relationship(
- common::model::to_string(r.type())))
+ if (!m_model.should_include(r.type()))
continue;
std::string destination;
@@ -357,14 +355,18 @@ void generator::generate(const package &p, std::ostream &ostr,
generate(sp, ostr, relationships_ostr);
}
else if (dynamic_cast(subpackage.get())) {
- generate_alias(dynamic_cast(*subpackage), ostr);
- generate(
- dynamic_cast(*subpackage), ostr, relationships_ostr);
+ if (m_model.should_include(*subpackage)) {
+ generate_alias(dynamic_cast(*subpackage), ostr);
+ generate(dynamic_cast(*subpackage), ostr,
+ relationships_ostr);
+ }
}
else if (dynamic_cast(subpackage.get())) {
- generate_alias(dynamic_cast(*subpackage), ostr);
- generate(
- dynamic_cast(*subpackage), ostr, relationships_ostr);
+ if (m_model.should_include(*subpackage)) {
+ generate_alias(dynamic_cast(*subpackage), ostr);
+ generate(dynamic_cast(*subpackage), ostr,
+ relationships_ostr);
+ }
}
}
@@ -394,12 +396,16 @@ void generator::generate(std::ostream &ostr) const
generate(sp, ostr, relationships_ostr);
}
else if (dynamic_cast(p.get())) {
- generate_alias(dynamic_cast(*p), ostr);
- generate(dynamic_cast(*p), ostr, relationships_ostr);
+ if (m_model.should_include(*p)) {
+ generate_alias(dynamic_cast(*p), ostr);
+ generate(dynamic_cast(*p), ostr, relationships_ostr);
+ }
}
else if (dynamic_cast(p.get())) {
- generate_alias(dynamic_cast(*p), ostr);
- generate(dynamic_cast(*p), ostr, relationships_ostr);
+ if (m_model.should_include(*p)) {
+ generate_alias(dynamic_cast(*p), ostr);
+ generate(dynamic_cast(*p), ostr, relationships_ostr);
+ }
}
ostr << '\n';
}
diff --git a/src/class_diagram/generators/plantuml/class_diagram_generator.h b/src/class_diagram/generators/plantuml/class_diagram_generator.h
index 74119724..9b8ec30d 100644
--- a/src/class_diagram/generators/plantuml/class_diagram_generator.h
+++ b/src/class_diagram/generators/plantuml/class_diagram_generator.h
@@ -49,9 +49,9 @@ using common_generator =
using clanguml::class_diagram::model::class_;
using clanguml::class_diagram::model::enum_;
+using clanguml::common::model::access_t;
using clanguml::common::model::package;
using clanguml::common::model::relationship_t;
-using clanguml::common::model::scope_t;
using namespace clanguml::util;
diff --git a/src/class_diagram/model/class_element.cc b/src/class_diagram/model/class_element.cc
index 65688e14..8c21456f 100644
--- a/src/class_diagram/model/class_element.cc
+++ b/src/class_diagram/model/class_element.cc
@@ -20,15 +20,15 @@
namespace clanguml::class_diagram::model {
-class_element::class_element(common::model::scope_t scope,
+class_element::class_element(common::model::access_t access,
const std::string &name, const std::string &type)
- : scope_{scope}
+ : access_{access}
, name_{name}
, type_{type}
{
}
-common::model::scope_t class_element::scope() const { return scope_; }
+common::model::access_t class_element::access() const { return access_; }
std::string class_element::name() const { return name_; }
@@ -39,7 +39,7 @@ inja::json class_element::context() const
inja::json ctx;
ctx["name"] = name();
ctx["type"] = type();
- ctx["scope"] = to_string(scope());
+ ctx["access"] = to_string(access());
return ctx;
}
}
diff --git a/src/class_diagram/model/class_element.h b/src/class_diagram/model/class_element.h
index 765fce87..441c26c9 100644
--- a/src/class_diagram/model/class_element.h
+++ b/src/class_diagram/model/class_element.h
@@ -29,17 +29,17 @@ namespace clanguml::class_diagram::model {
class class_element : public common::model::decorated_element,
public common::model::source_location {
public:
- class_element(common::model::scope_t scope, const std::string &name,
+ class_element(common::model::access_t scope, const std::string &name,
const std::string &type);
- common::model::scope_t scope() const;
+ common::model::access_t access() const;
std::string name() const;
std::string type() const;
virtual inja::json context() const;
private:
- common::model::scope_t scope_;
+ common::model::access_t access_;
std::string name_;
std::string type_;
};
diff --git a/src/class_diagram/model/class_member.cc b/src/class_diagram/model/class_member.cc
index 360f76b0..8bf041e6 100644
--- a/src/class_diagram/model/class_member.cc
+++ b/src/class_diagram/model/class_member.cc
@@ -20,9 +20,9 @@
namespace clanguml::class_diagram::model {
-class_member::class_member(common::model::scope_t scope,
+class_member::class_member(common::model::access_t access,
const std::string &name, const std::string &type)
- : class_element{scope, name, type}
+ : class_element{access, name, type}
{
}
diff --git a/src/class_diagram/model/class_member.h b/src/class_diagram/model/class_member.h
index f339d4cb..39b29983 100644
--- a/src/class_diagram/model/class_member.h
+++ b/src/class_diagram/model/class_member.h
@@ -25,7 +25,7 @@ namespace clanguml::class_diagram::model {
class class_member : public class_element {
public:
- class_member(common::model::scope_t scope, const std::string &name,
+ class_member(common::model::access_t access, const std::string &name,
const std::string &type);
bool is_relationship() const;
diff --git a/src/class_diagram/model/class_method.cc b/src/class_diagram/model/class_method.cc
index 38f44bfe..cef773cd 100644
--- a/src/class_diagram/model/class_method.cc
+++ b/src/class_diagram/model/class_method.cc
@@ -20,9 +20,9 @@
namespace clanguml::class_diagram::model {
-class_method::class_method(common::model::scope_t scope,
+class_method::class_method(common::model::access_t access,
const std::string &name, const std::string &type)
- : class_element{scope, name, type}
+ : class_element{access, name, type}
{
}
diff --git a/src/class_diagram/model/class_method.h b/src/class_diagram/model/class_method.h
index 024fbac7..f35ad492 100644
--- a/src/class_diagram/model/class_method.h
+++ b/src/class_diagram/model/class_method.h
@@ -27,7 +27,7 @@ namespace clanguml::class_diagram::model {
class class_method : public class_element {
public:
- class_method(common::model::scope_t scope, const std::string &name,
+ class_method(common::model::access_t access, const std::string &name,
const std::string &type);
bool is_pure_virtual() const;
diff --git a/src/class_diagram/model/diagram.cc b/src/class_diagram/model/diagram.cc
index 1200e889..26ba79e8 100644
--- a/src/class_diagram/model/diagram.cc
+++ b/src/class_diagram/model/diagram.cc
@@ -36,6 +36,11 @@ const std::vector> diagram::enums() const
return enums_;
}
+common::model::diagram_t diagram::type() const
+{
+ return common::model::diagram_t::kClass;
+}
+
bool diagram::has_class(const class_ &c) const
{
return std::any_of(classes_.cbegin(), classes_.cend(),
@@ -48,6 +53,18 @@ bool diagram::has_enum(const enum_ &e) const
[&e](const auto &ee) { return ee.get().full_name() == e.full_name(); });
}
+type_safe::optional_ref diagram::get_class(
+ const std::string &name) const
+{
+ for (const auto &c : classes_) {
+ if (c.get().full_name(false) == name) {
+ return {c};
+ }
+ }
+
+ return type_safe::nullopt;
+}
+
void diagram::add_type_alias(std::unique_ptr &&ta)
{
LOG_DBG(
@@ -107,6 +124,26 @@ void diagram::add_enum(std::unique_ptr &&e)
LOG_DBG("Enum {} already in the model", e->name());
}
+void diagram::get_parents(
+ std::unordered_set> &parents) const
+{
+ bool found_new = false;
+ for (const auto &parent : parents) {
+ for (const auto &pp : parent.get().parents()) {
+ const auto p = get_class(pp.name());
+ if (p.has_value()) {
+ auto [it, found] = parents.emplace(p.value());
+ if (found)
+ found_new = true;
+ }
+ }
+ }
+
+ if (found_new) {
+ get_parents(parents);
+ }
+}
+
std::string diagram::to_alias(const std::string &full_name) const
{
LOG_DBG("Looking for alias for {}", full_name);
diff --git a/src/class_diagram/model/diagram.h b/src/class_diagram/model/diagram.h
index 86f8acd7..cf372240 100644
--- a/src/class_diagram/model/diagram.h
+++ b/src/class_diagram/model/diagram.h
@@ -25,6 +25,7 @@
#include "type_alias.h"
#include
+#include
#include
namespace clanguml::class_diagram::model {
@@ -40,6 +41,8 @@ public:
diagram &operator=(const diagram &) = delete;
diagram &operator=(diagram &&) = default;
+ common::model::diagram_t type() const override;
+
const std::vector> classes() const;
const std::vector> enums() const;
@@ -48,6 +51,9 @@ public:
bool has_enum(const enum_ &e) const;
+ type_safe::optional_ref get_class(
+ const std::string &name) const;
+
void add_type_alias(std::unique_ptr &&ta);
void add_class(std::unique_ptr &&c);
@@ -58,6 +64,9 @@ public:
std::string to_alias(const std::string &full_name) const;
+ void get_parents(
+ std::unordered_set> &parents) const;
+
friend void print_diagram_tree(const diagram &d, const int level);
private:
@@ -66,3 +75,18 @@ private:
std::map> type_aliases_;
};
}
+
+namespace std {
+
+template <>
+struct hash<
+ type_safe::object_ref> {
+ std::size_t operator()(const type_safe::object_ref<
+ const clanguml::class_diagram::model::class_> &key) const
+ {
+ using clanguml::class_diagram::model::class_;
+
+ return std::hash{}(key.get().full_name(false));
+ }
+};
+}
diff --git a/src/class_diagram/visitor/translation_unit_context.cc b/src/class_diagram/visitor/translation_unit_context.cc
index 0031d010..83655608 100644
--- a/src/class_diagram/visitor/translation_unit_context.cc
+++ b/src/class_diagram/visitor/translation_unit_context.cc
@@ -184,6 +184,12 @@ clanguml::class_diagram::model::diagram &translation_unit_context::diagram()
return diagram_;
}
+clanguml::class_diagram::model::diagram &
+translation_unit_context::diagram() const
+{
+ return diagram_;
+}
+
void translation_unit_context::set_current_package(
type_safe::optional_ref p)
{
diff --git a/src/class_diagram/visitor/translation_unit_context.h b/src/class_diagram/visitor/translation_unit_context.h
index 714f7eae..62cb7293 100644
--- a/src/class_diagram/visitor/translation_unit_context.h
+++ b/src/class_diagram/visitor/translation_unit_context.h
@@ -74,6 +74,8 @@ public:
clanguml::class_diagram::model::diagram &diagram();
+ clanguml::class_diagram::model::diagram &diagram() const;
+
void set_current_package(type_safe::optional_ref p);
type_safe::optional_ref get_current_package() const;
diff --git a/src/class_diagram/visitor/translation_unit_visitor.cc b/src/class_diagram/visitor/translation_unit_visitor.cc
index aea10efe..9320c680 100644
--- a/src/class_diagram/visitor/translation_unit_visitor.cc
+++ b/src/class_diagram/visitor/translation_unit_visitor.cc
@@ -46,28 +46,27 @@ using clanguml::class_diagram::model::type_alias;
using clanguml::common::model::access_t;
using clanguml::common::model::relationship;
using clanguml::common::model::relationship_t;
-using clanguml::common::model::scope_t;
namespace detail {
-scope_t cpp_access_specifier_to_scope(
+access_t cpp_access_specifier_to_access(
cppast::cpp_access_specifier_kind access_specifier)
{
- scope_t scope = scope_t::kPublic;
+ auto access = access_t::kPublic;
switch (access_specifier) {
case cppast::cpp_access_specifier_kind::cpp_public:
- scope = scope_t::kPublic;
+ access = access_t::kPublic;
break;
case cppast::cpp_access_specifier_kind::cpp_private:
- scope = scope_t::kPrivate;
+ access = access_t::kPrivate;
break;
case cppast::cpp_access_specifier_kind::cpp_protected:
- scope = scope_t::kProtected;
+ access = access_t::kProtected;
break;
default:
break;
}
- return scope;
+ return access;
}
}
@@ -146,7 +145,7 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
}
}
- if (ctx.config().should_include(
+ if (ctx.diagram().should_include(
ctx.get_namespace(), cls.name()))
process_class_declaration(cls);
}
@@ -157,7 +156,7 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
auto &enm = static_cast(e);
- if (ctx.config().should_include(
+ if (ctx.diagram().should_include(
ctx.get_namespace(), enm.name()))
process_enum_declaration(enm);
}
@@ -214,7 +213,7 @@ void translation_unit_visitor::process_type_alias_template(
cx::util::full_name(ctx.get_namespace(), at),
type_safe::ref(at.type_alias().underlying_type()));
- if (ctx.config().should_include(tinst->get_namespace() | tinst->name()))
+ if (ctx.diagram().should_include(tinst->get_namespace(), tinst->name()))
ctx.diagram().add_class(std::move(tinst));
}
}
@@ -241,13 +240,13 @@ void translation_unit_visitor::process_namespace(
auto usn = ctx.config().using_namespace();
- if (ctx.config().should_include_package(package_path)) {
- auto p = std::make_unique(usn);
- package_path = package_path.relative_to(usn);
+ auto p = std::make_unique(usn);
+ package_path = package_path.relative_to(usn);
- p->set_name(e.name());
- p->set_namespace(package_parent);
+ p->set_name(e.name());
+ p->set_namespace(package_parent);
+ if (ctx.diagram().should_include(*p)) {
if (e.comment().has_value())
p->set_comment(e.comment().value());
@@ -397,7 +396,8 @@ void translation_unit_visitor::process_class_declaration(
fmt::ptr(reinterpret_cast(&cls)));
assert(c_ptr);
- if (ctx.config().should_include(c.full_name(false)))
+
+ if (ctx.diagram().should_include(c))
ctx.diagram().add_class(std::move(c_ptr));
}
@@ -579,7 +579,8 @@ void translation_unit_visitor::process_class_bases(
cx::util::ns(base.type(), ctx.entity_index())};
base_ns = base_ns | common::model::namespace_{base.name()}.name();
cp.set_name(
- base_ns.relative_to(ctx.config().using_namespace()).to_string());
+ // base_ns.relative_to(ctx.config().using_namespace()).to_string());
+ base_ns.to_string());
cp.is_virtual(base.is_virtual());
switch (base.access_specifier()) {
@@ -660,7 +661,7 @@ void translation_unit_visitor::process_class_children(
child.scope_name() ? child.scope_name().value().name()
: "");
- process_friend(fr, c);
+ process_friend(fr, c, last_access_specifier);
}
else if (cppast::is_friended(child)) {
auto &fr =
@@ -668,7 +669,7 @@ void translation_unit_visitor::process_class_children(
LOG_DBG("Found friend template: {}", child.name());
- process_friend(fr, c);
+ process_friend(fr, c, last_access_specifier);
}
else {
LOG_DBG("Found some other class child: {} ({})", child.name(),
@@ -715,7 +716,7 @@ bool translation_unit_visitor::process_field_with_template_instantiation(
relationship_type = relationship_t::kAggregation;
relationship rr{relationship_type, tinst.full_name(),
- detail::cpp_access_specifier_to_scope(as), mv.name()};
+ detail::cpp_access_specifier_to_access(as), mv.name()};
rr.set_style(m.style_spec());
// Process field decorators
@@ -729,7 +730,7 @@ bool translation_unit_visitor::process_field_with_template_instantiation(
}
}
- if (ctx.config().should_include(tinst.get_namespace(), tinst.name())) {
+ if (ctx.diagram().should_include(tinst.get_namespace(), tinst.name())) {
LOG_DBG("Adding field instantiation relationship {} {} {} : {}",
rr.destination(), clanguml::common::model::to_string(rr.type()),
c.full_name(), rr.label());
@@ -763,7 +764,7 @@ void translation_unit_visitor::process_field(
type_name = "<>";
class_member m{
- detail::cpp_access_specifier_to_scope(as), mv.name(), type_name};
+ detail::cpp_access_specifier_to_access(as), mv.name(), type_name};
if (mv.location().has_value()) {
m.set_file(mv.location().value().file);
@@ -814,7 +815,7 @@ void translation_unit_visitor::process_field(
for (const auto &[type, relationship_type] : relationships) {
if (relationship_type != relationship_t::kNone) {
- relationship r{relationship_type, type, m.scope(), m.name()};
+ relationship r{relationship_type, type, m.access(), m.name()};
r.set_style(m.style_spec());
auto [decorator_rtype, decorator_rmult] = m.get_relationship();
@@ -846,7 +847,7 @@ void translation_unit_visitor::process_anonymous_enum(
for (const auto &ev : en) {
if (ev.kind() == cppast::cpp_entity_kind::enum_value_t) {
class_member m{
- detail::cpp_access_specifier_to_scope(as), ev.name(), "enum"};
+ detail::cpp_access_specifier_to_access(as), ev.name(), "enum"};
c.add_member(std::move(m));
}
}
@@ -856,7 +857,7 @@ void translation_unit_visitor::process_static_field(
const cppast::cpp_variable &mv, class_ &c,
cppast::cpp_access_specifier_kind as)
{
- class_member m{detail::cpp_access_specifier_to_scope(as), mv.name(),
+ class_member m{detail::cpp_access_specifier_to_access(as), mv.name(),
cppast::to_string(mv.type())};
if (mv.location().has_value()) {
@@ -879,7 +880,7 @@ void translation_unit_visitor::process_method(
const cppast::cpp_member_function &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
- class_method m{detail::cpp_access_specifier_to_scope(as),
+ class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), cppast::to_string(mf.return_type())};
m.is_pure_virtual(cppast::is_pure(mf.virtual_info()));
m.is_virtual(cppast::is_virtual(mf.virtual_info()));
@@ -921,8 +922,8 @@ void translation_unit_visitor::process_template_method(
static_cast(mf.function())
.return_type());
- class_method m{
- detail::cpp_access_specifier_to_scope(as), util::trim(mf.name()), type};
+ class_method m{detail::cpp_access_specifier_to_access(as),
+ util::trim(mf.name()), type};
m.is_pure_virtual(false);
m.is_virtual(false);
m.is_const(cppast::is_const(
@@ -962,7 +963,7 @@ void translation_unit_visitor::process_static_method(
const cppast::cpp_function &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
- class_method m{detail::cpp_access_specifier_to_scope(as),
+ class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), cppast::to_string(mf.return_type())};
m.is_pure_virtual(false);
m.is_virtual(false);
@@ -996,7 +997,7 @@ void translation_unit_visitor::process_constructor(
const cppast::cpp_constructor &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
- class_method m{detail::cpp_access_specifier_to_scope(as),
+ class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), "void"};
m.is_pure_virtual(false);
m.is_virtual(false);
@@ -1028,7 +1029,7 @@ void translation_unit_visitor::process_destructor(
const cppast::cpp_destructor &mf, class_ &c,
cppast::cpp_access_specifier_kind as)
{
- class_method m{detail::cpp_access_specifier_to_scope(as),
+ class_method m{detail::cpp_access_specifier_to_access(as),
util::trim(mf.name()), "void"};
m.is_pure_virtual(false);
m.is_virtual(cppast::is_virtual(mf.virtual_info()));
@@ -1100,7 +1101,8 @@ void translation_unit_visitor::process_function_parameter(
relationship_t::kDependency);
for (const auto &[type, relationship_type] : relationships) {
- if (ctx.config().should_include(cx::util::split_ns(type)) &&
+ auto [type_ns, type_name] = cx::util::split_ns(type);
+ if (ctx.diagram().should_include(type_ns, type_name) &&
(relationship_type != relationship_t::kNone) &&
(type != c.name_and_ns())) {
relationship r{relationship_t::kDependency, type};
@@ -1165,7 +1167,7 @@ void translation_unit_visitor::
// arguments string
}
- if (!ctx.config().should_include(ctx.get_namespace(),
+ if (!ctx.diagram().should_include(ctx.get_namespace(),
template_instantiation_type.primary_template()
.get(ctx.entity_index())[0]
.get()
@@ -1202,7 +1204,7 @@ void translation_unit_visitor::
c.add_relationship(std::move(rr));
- if (ctx.config().should_include(c.full_name(false)))
+ if (ctx.diagram().should_include(c))
ctx.diagram().add_class(std::move(tinst_ptr));
}
}
@@ -1227,8 +1229,8 @@ void translation_unit_visitor::process_template_template_parameter(
parent.add_template({"", t.name() + "<>"});
}
-void translation_unit_visitor::process_friend(
- const cppast::cpp_friend &f, class_ &parent)
+void translation_unit_visitor::process_friend(const cppast::cpp_friend &f,
+ class_ &parent, cppast::cpp_access_specifier_kind as)
{
// Only process friends to other classes or class templates
if (!f.entity() ||
@@ -1237,8 +1239,8 @@ void translation_unit_visitor::process_friend(
cppast::cpp_entity_kind::class_template_t))
return;
- relationship r{
- relationship_t::kFriendship, "", scope_t::kNone, "<>"};
+ relationship r{relationship_t::kFriendship, "",
+ detail::cpp_access_specifier_to_access(as), "<>"};
if (f.comment().has_value())
r.add_decorators(decorators::parse(f.comment().value()));
@@ -1249,7 +1251,7 @@ void translation_unit_visitor::process_friend(
if (f.type()) {
const auto [name_with_ns, name] =
cx::util::split_ns(cppast::to_string(f.type().value()));
- if (!ctx.config().should_include(name_with_ns, name))
+ if (!ctx.diagram().should_include(name_with_ns, name))
return;
LOG_DBG("Type friend declaration {}", name);
@@ -1288,7 +1290,7 @@ void translation_unit_visitor::process_friend(
name = cx::util::full_name(ctx.get_namespace(), f.entity().value());
}
- if (!ctx.config().should_include(ctx.get_namespace(), name))
+ if (!ctx.diagram().should_include(ctx.get_namespace(), name))
return;
r.set_destination(name);
@@ -1398,7 +1400,7 @@ bool translation_unit_visitor::find_relationships_in_template_instantiation(
LOG_DBG("Failed to process template argument of std::vector at: {}",
fn);
}
- else if (ctx.config().should_include(ns, name)) {
+ else if (ctx.diagram().should_include(ns, name)) {
LOG_DBG("User defined template instantiation: {} | {}",
cppast::to_string(t_), cppast::to_string(t_.canonical()));
@@ -1509,7 +1511,7 @@ bool translation_unit_visitor::find_relationships_in_unexposed_template_params(
type_with_namespace = common::model::namespace_{ct.type()};
}
- if (ctx.config().should_include(type_with_namespace.value())) {
+ if (ctx.diagram().should_include(type_with_namespace.value().to_string())) {
relationships.emplace_back(type_with_namespace.value().to_string(),
relationship_t::kDependency);
found = true;
@@ -1704,7 +1706,7 @@ void translation_unit_visitor::
auto nested_tinst =
build_template_instantiation(nested_template_parameter,
- ctx.config().should_include(tinst_ns, tinst_name)
+ ctx.diagram().should_include(tinst_ns, tinst_name)
? std::make_optional(&tinst)
: parent);
@@ -1713,11 +1715,11 @@ void translation_unit_visitor::
auto nested_tinst_full_name = nested_tinst->full_name();
- if (ctx.config().should_include(fn_ns, fn_name)) {
+ if (ctx.diagram().should_include(fn_ns, fn_name)) {
ctx.diagram().add_class(std::move(nested_tinst));
}
- if (ctx.config().should_include(tinst_ns, tinst_name)
+ if (ctx.diagram().should_include(tinst_ns, tinst_name)
// TODO: check why this breaks t00033:
// && ctx.config().should_include(
// cx::util::split_ns(tinst_dependency.destination()))
@@ -1753,7 +1755,7 @@ void translation_unit_visitor::
"type {} -> {}",
tinst.full_name(), tinst_dependency.destination());
- if (ctx.config().should_include(fn_ns, fn_name)) {
+ if (ctx.diagram().should_include(fn_ns, fn_name)) {
tinst.add_relationship(std::move(tinst_dependency));
}
else if (parent) {
diff --git a/src/class_diagram/visitor/translation_unit_visitor.h b/src/class_diagram/visitor/translation_unit_visitor.h
index 07bcc5e5..0a611b5b 100644
--- a/src/class_diagram/visitor/translation_unit_visitor.h
+++ b/src/class_diagram/visitor/translation_unit_visitor.h
@@ -124,7 +124,8 @@ public:
clanguml::class_diagram::model::class_ &parent);
void process_friend(const cppast::cpp_friend &t,
- clanguml::class_diagram::model::class_ &parent);
+ clanguml::class_diagram::model::class_ &parent,
+ cppast::cpp_access_specifier_kind as);
void process_namespace(const cppast::cpp_entity &e,
const cppast::cpp_namespace &ns_declaration);
diff --git a/src/common/generators/plantuml/generator.cc b/src/common/generators/plantuml/generator.cc
index 139a04b8..eea26a9c 100644
--- a/src/common/generators/plantuml/generator.cc
+++ b/src/common/generators/plantuml/generator.cc
@@ -42,14 +42,14 @@ std::string to_plantuml(relationship_t r, std::string style)
}
}
-std::string to_plantuml(scope_t scope)
+std::string to_plantuml(access_t scope)
{
switch (scope) {
- case scope_t::kPublic:
+ case access_t::kPublic:
return "+";
- case scope_t::kProtected:
+ case access_t::kProtected:
return "#";
- case scope_t::kPrivate:
+ case access_t::kPrivate:
return "-";
default:
return "";
diff --git a/src/common/generators/plantuml/generator.h b/src/common/generators/plantuml/generator.h
index 29aebf4e..4d40604f 100644
--- a/src/common/generators/plantuml/generator.h
+++ b/src/common/generators/plantuml/generator.h
@@ -17,6 +17,7 @@
*/
#pragma once
+#include "common/model/diagram_filter.h"
#include "config/config.h"
#include "util/error.h"
#include "util/util.h"
@@ -29,13 +30,13 @@
namespace clanguml::common::generators::plantuml {
+using clanguml::common::model::access_t;
using clanguml::common::model::element;
using clanguml::common::model::message_t;
using clanguml::common::model::relationship_t;
-using clanguml::common::model::scope_t;
std::string to_plantuml(relationship_t r, std::string style);
-std::string to_plantuml(scope_t scope);
+std::string to_plantuml(access_t scope);
std::string to_plantuml(message_t r);
template class generator {
@@ -224,17 +225,20 @@ void generator::generate_link(
template
-DiagramModel generate(const cppast::libclang_compilation_database &db,
- const std::string &name, DiagramConfig &diagram, bool verbose = false)
+std::unique_ptr generate(
+ const cppast::libclang_compilation_database &db, const std::string &name,
+ DiagramConfig &config, bool verbose = false)
{
LOG_INFO("Generating diagram {}.puml", name);
- DiagramModel d;
- d.set_name(name);
+ auto diagram = std::make_unique();
+ diagram->set_name(name);
+ diagram->set_filter(
+ std::make_unique(*diagram, config));
// Get all translation units matching the glob from diagram
// configuration
std::vector translation_units{};
- for (const auto &g : diagram.glob()) {
+ for (const auto &g : config.glob()) {
LOG_DBG("Processing glob: {}", g);
const auto matches = glob::rglob(g);
std::copy(matches.begin(), matches.end(),
@@ -248,12 +252,14 @@ DiagramModel generate(const cppast::libclang_compilation_database &db,
type_safe::ref(idx), std::move(logger)};
// Process all matching translation units
- DiagramVisitor ctx(idx, d, diagram);
+ DiagramVisitor ctx(idx, *diagram, config);
cppast::parse_files(parser, translation_units, db);
for (auto &file : parser.files())
ctx(file);
- return std::move(d);
+ diagram->set_complete(true);
+
+ return std::move(diagram);
}
template void generator::init_context()
diff --git a/src/common/model/diagram.cc b/src/common/model/diagram.cc
index 1f4263f5..7330236c 100644
--- a/src/common/model/diagram.cc
+++ b/src/common/model/diagram.cc
@@ -18,10 +18,71 @@
#include "diagram.h"
+#include "diagram_filter.h"
+#include "namespace.h"
+
namespace clanguml::common::model {
+diagram::diagram() = default;
+
+diagram::~diagram() = default;
+
+diagram::diagram(diagram &&) = default;
+
+diagram &diagram::operator=(diagram &&) = default;
+
std::string diagram::name() const { return name_; }
void diagram::set_name(const std::string &name) { name_ = name; }
+void diagram::set_filter(std::unique_ptr filter)
+{
+ filter_ = std::move(filter);
+}
+
+void diagram::set_complete(bool complete) { complete_ = complete; }
+
+bool diagram::complete() const { return complete_; }
+
+bool diagram::should_include(const element &e) const
+{
+ if (filter_.get() == nullptr)
+ return true;
+
+ return filter_->should_include(e);
+}
+
+bool diagram::should_include(const std::string &name) const
+{
+ if (filter_.get() == nullptr)
+ return true;
+
+ return filter_->should_include(name);
+}
+
+bool diagram::should_include(const relationship_t r) const
+{
+ if (filter_.get() == nullptr)
+ return true;
+
+ return filter_->should_include(r);
+}
+
+bool diagram::should_include(const access_t s) const
+{
+ if (filter_.get() == nullptr)
+ return true;
+
+ return filter_->should_include(s);
+}
+
+bool diagram::should_include(
+ const namespace_ &ns, const std::string &name) const
+{
+ if (filter_.get() == nullptr)
+ return true;
+
+ return filter_->should_include(ns, name);
+}
+
}
\ No newline at end of file
diff --git a/src/common/model/diagram.h b/src/common/model/diagram.h
index 3e4f95b0..71483f4d 100644
--- a/src/common/model/diagram.h
+++ b/src/common/model/diagram.h
@@ -17,18 +17,50 @@
*/
#pragma once
+#include "enums.h"
+
+#include
#include
namespace clanguml::common::model {
+class diagram_filter;
+class namespace_;
+class element;
+class relationship;
+
class diagram {
public:
- std::string name() const;
+ diagram();
+ virtual ~diagram();
+
+ virtual diagram_t type() const = 0;
+
+ diagram(const diagram &) = delete;
+ diagram(diagram &&);
+ diagram &operator=(const diagram &) = delete;
+ diagram &operator=(diagram &&);
void set_name(const std::string &name);
+ std::string name() const;
+
+ void set_filter(std::unique_ptr filter);
+
+ void set_complete(bool complete);
+ bool complete() const;
+
+ // TODO: refactor to a template method
+ bool should_include(const element &e) const;
+ bool should_include(const std::string &e) const;
+ bool should_include(const relationship r) const;
+ bool should_include(const relationship_t r) const;
+ bool should_include(const access_t s) const;
+ bool should_include(const namespace_ &ns, const std::string &name) const;
private:
std::string name_;
+ std::unique_ptr filter_;
+ bool complete_{false};
};
}
diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc
new file mode 100644
index 00000000..0d3d0d50
--- /dev/null
+++ b/src/common/model/diagram_filter.cc
@@ -0,0 +1,337 @@
+/**
+ * src/common/model/diagram_filter.cc
+ *
+ * Copyright (c) 2021-2022 Bartek Kryza
+ *
+ * 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.
+ */
+
+#include "diagram_filter.h"
+
+namespace clanguml::common::model {
+
+filter_visitor::filter_visitor(filter_t type)
+ : type_{type}
+{
+}
+
+tvl::value_t filter_visitor::match(
+ const diagram &d, const common::model::element &e) const
+{
+ return {};
+}
+
+tvl::value_t filter_visitor::match(
+ const diagram &d, const common::model::relationship_t &r) const
+{
+ return {};
+}
+
+tvl::value_t filter_visitor::match(
+ const diagram &d, const common::model::access_t &a) const
+{
+ return {};
+}
+
+tvl::value_t filter_visitor::match(
+ const diagram &d, const common::model::namespace_ &ns) const
+{
+ return {};
+}
+
+bool filter_visitor::is_inclusive() const
+{
+ return type_ == filter_t::kInclusive;
+}
+
+bool filter_visitor::is_exclusive() const
+{
+ return type_ == filter_t::kExclusive;
+}
+
+filter_t filter_visitor::type() const { return type_; }
+
+anyof_filter::anyof_filter(
+ filter_t type, std::vector> filters)
+ : filter_visitor{type}
+ , filters_{std::move(filters)}
+{
+}
+
+tvl::value_t anyof_filter::match(
+ const diagram &d, const common::model::element &e) const
+{
+ return tvl::any_of(filters_.begin(), filters_.end(),
+ [&d, &e](const auto &f) { return f->match(d, e); });
+}
+
+namespace_filter::namespace_filter(
+ filter_t type, std::vector namespaces)
+ : filter_visitor{type}
+ , namespaces_{namespaces}
+{
+}
+
+tvl::value_t namespace_filter::match(
+ const diagram &d, const namespace_ &ns) const
+{
+ if (ns.is_empty())
+ return {};
+
+ return tvl::any_of(namespaces_.begin(), namespaces_.end(),
+ [&ns](const auto &nsit) { return ns.starts_with(nsit) || ns == nsit; });
+}
+
+tvl::value_t namespace_filter::match(const diagram &d, const element &e) const
+{
+ if (dynamic_cast(&e) != nullptr) {
+ return tvl::any_of(
+ namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) {
+ return (e.get_namespace() | e.name()).starts_with(nsit) ||
+ nsit.starts_with(e.get_namespace() | e.name()) ||
+ (e.get_namespace() | e.name()) == nsit;
+ });
+ }
+ else {
+ return tvl::any_of(
+ namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) {
+ return e.get_namespace().starts_with(nsit);
+ });
+ }
+}
+
+element_filter::element_filter(filter_t type, std::vector elements)
+ : filter_visitor{type}
+ , elements_{elements}
+{
+}
+
+tvl::value_t element_filter::match(const diagram &d, const element &e) const
+{
+ return tvl::any_of(elements_.begin(), elements_.end(),
+ [&e](const auto &el) { return e.full_name(false) == el; });
+}
+
+subclass_filter::subclass_filter(filter_t type, std::vector roots)
+ : filter_visitor{type}
+ , roots_{roots}
+{
+}
+
+tvl::value_t subclass_filter::match(const diagram &d, const element &e) const
+{
+ if (d.type() != diagram_t::kClass)
+ return {};
+
+ if (roots_.empty())
+ return {};
+
+ if (!d.complete())
+ return {};
+
+ const auto &cd = dynamic_cast(d);
+
+ // First get all parents of element e
+ std::unordered_set<
+ type_safe::object_ref>
+ parents;
+
+ const auto &fn = e.full_name(false);
+ auto class_ref = cd.get_class(fn);
+
+ if (!class_ref.has_value())
+ return false;
+
+ parents.emplace(class_ref.value());
+
+ cd.get_parents(parents);
+
+ // Now check if any of the parents matches the roots specified in the
+ // filter config
+ for (const auto &root : roots_) {
+ for (const auto &parent : parents) {
+ if (root == parent.get().full_name(false))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+relationship_filter::relationship_filter(
+ filter_t type, std::vector relationships)
+ : filter_visitor{type}
+ , relationships_{relationships}
+{
+}
+
+tvl::value_t relationship_filter::match(
+ const diagram &d, const relationship_t &r) const
+{
+ return tvl::any_of(relationships_.begin(), relationships_.end(),
+ [&r](const auto &rel) { return r == rel; });
+}
+
+access_filter::access_filter(filter_t type, std::vector access)
+ : filter_visitor{type}
+ , access_{access}
+{
+}
+
+tvl::value_t access_filter::match(const diagram &d, const access_t &a) const
+{
+ return tvl::any_of(access_.begin(), access_.end(),
+ [&a](const auto &access) { return a == access; });
+}
+
+context_filter::context_filter(filter_t type, std::vector context)
+ : filter_visitor{type}
+ , context_{context}
+{
+}
+
+tvl::value_t context_filter::match(const diagram &d, const element &e) const
+{
+ if (d.type() != diagram_t::kClass)
+ return {};
+
+ if (!d.complete())
+ return {};
+
+ return tvl::any_of(context_.begin(), context_.end(),
+ [&e, &d](const auto &context_root_name) {
+ const auto &context_root =
+ static_cast(d).get_class(
+ context_root_name);
+
+ if (context_root.has_value()) {
+ // This is a direct match to the context root
+ if (context_root.value().full_name(false) == e.full_name(false))
+ return true;
+
+ // Return a positive match if the element e is in a direct
+ // relationship with any of the context_root's
+ for (const relationship &rel :
+ context_root.value().relationships()) {
+ if (rel.destination() == e.full_name(false))
+ return true;
+ }
+ for (const relationship &rel : e.relationships()) {
+ if (rel.destination() ==
+ context_root.value().full_name(false))
+ return true;
+ }
+
+ // Return a positive match if the context_root is a parent
+ // of the element
+ for (const class_diagram::model::class_parent &p :
+ context_root.value().parents()) {
+ if (p.name() == e.full_name(false))
+ return true;
+ }
+ if (dynamic_cast(&e) !=
+ nullptr) {
+ for (const class_diagram::model::class_parent &p :
+ static_cast(e)
+ .parents()) {
+ if (p.name() == context_root.value().full_name(false))
+ return true;
+ }
+ }
+ }
+
+ return false;
+ });
+}
+
+diagram_filter::diagram_filter(
+ const common::model::diagram &d, const config::diagram &c)
+ : diagram_{d}
+{
+ init_filters(c);
+}
+
+void diagram_filter::add_inclusive_filter(std::unique_ptr fv)
+{
+ inclusive_.emplace_back(std::move(fv));
+}
+
+void diagram_filter::add_exclusive_filter(std::unique_ptr fv)
+{
+ exclusive_.emplace_back(std::move(fv));
+}
+
+bool diagram_filter::should_include(
+ namespace_ ns, const std::string &name) const
+{
+ if (should_include(ns)) {
+ element e{namespace_{}};
+ e.set_name(name);
+ e.set_namespace(ns);
+
+ return should_include(e);
+ }
+
+ return false;
+}
+
+void diagram_filter::init_filters(const config::diagram &c)
+{
+ // Process inclusive filters
+ if (c.include) {
+ inclusive_.emplace_back(std::make_unique(
+ filter_t::kInclusive, c.include().namespaces));
+ inclusive_.emplace_back(std::make_unique(
+ filter_t::kInclusive, c.include().relationships));
+ inclusive_.emplace_back(std::make_unique(
+ filter_t::kInclusive, c.include().access));
+
+ // Include any of these matches even if one them does not match
+ std::vector> element_filters;
+ element_filters.emplace_back(std::make_unique(
+ filter_t::kInclusive, c.include().elements));
+ element_filters.emplace_back(std::make_unique(
+ filter_t::kInclusive, c.include().subclasses));
+ element_filters.emplace_back(std::make_unique(
+ filter_t::kInclusive, c.include().context));
+
+ inclusive_.emplace_back(std::make_unique(
+ filter_t::kInclusive, std::move(element_filters)));
+ }
+
+ // Process exclusive filters
+ if (c.exclude) {
+ exclusive_.emplace_back(std::make_unique(
+ filter_t::kExclusive, c.exclude().namespaces));
+ exclusive_.emplace_back(std::make_unique(
+ filter_t::kExclusive, c.exclude().elements));
+ exclusive_.emplace_back(std::make_unique(
+ filter_t::kExclusive, c.exclude().relationships));
+ exclusive_.emplace_back(std::make_unique(
+ filter_t::kExclusive, c.exclude().access));
+ exclusive_.emplace_back(std::make_unique(
+ filter_t::kExclusive, c.exclude().subclasses));
+ exclusive_.emplace_back(std::make_unique(
+ filter_t::kExclusive, c.exclude().context));
+ }
+}
+
+template <>
+bool diagram_filter::should_include(const std::string &name) const
+{
+ auto [ns, n] = cx::util::split_ns(name);
+
+ return should_include(ns, n);
+}
+
+}
diff --git a/src/common/model/diagram_filter.h b/src/common/model/diagram_filter.h
new file mode 100644
index 00000000..dfbc8886
--- /dev/null
+++ b/src/common/model/diagram_filter.h
@@ -0,0 +1,166 @@
+/**
+ * src/common/model/diagram_filter.h
+ *
+ * Copyright (c) 2021-2022 Bartek Kryza
+ *
+ * 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.
+ */
+#pragma once
+
+#include "class_diagram/model/diagram.h"
+#include "common/model/diagram.h"
+#include "common/model/element.h"
+#include "common/model/enums.h"
+#include "common/model/namespace.h"
+#include "config/config.h"
+#include "cx/util.h"
+#include "diagram.h"
+#include "tvl.h"
+
+namespace clanguml::common::model {
+
+enum filter_t { kInclusive, kExclusive };
+
+class filter_visitor {
+public:
+ filter_visitor(filter_t type);
+
+ virtual tvl::value_t match(
+ const diagram &d, const common::model::element &e) const;
+
+ virtual tvl::value_t match(
+ const diagram &d, const common::model::relationship_t &r) const;
+
+ virtual tvl::value_t match(
+ const diagram &d, const common::model::access_t &a) const;
+
+ virtual tvl::value_t match(
+ const diagram &d, const common::model::namespace_ &ns) const;
+
+ bool is_inclusive() const;
+ bool is_exclusive() const;
+
+ filter_t type() const;
+
+private:
+ filter_t type_;
+};
+
+struct anyof_filter : public filter_visitor {
+ anyof_filter(
+ filter_t type, std::vector> filters);
+
+ tvl::value_t match(
+ const diagram &d, const common::model::element &e) const override;
+
+private:
+ std::vector> filters_;
+};
+
+struct namespace_filter : public filter_visitor {
+ namespace_filter(filter_t type, std::vector namespaces);
+
+ tvl::value_t match(const diagram &d, const namespace_ &ns) const override;
+
+ tvl::value_t match(const diagram &d, const element &e) const override;
+
+private:
+ std::vector namespaces_;
+};
+
+struct element_filter : public filter_visitor {
+ element_filter(filter_t type, std::vector elements);
+
+ tvl::value_t match(const diagram &d, const element &e) const override;
+
+private:
+ std::vector elements_;
+};
+
+struct subclass_filter : public filter_visitor {
+ subclass_filter(filter_t type, std::vector roots);
+
+ tvl::value_t match(const diagram &d, const element &e) const override;
+
+private:
+ std::vector roots_;
+};
+
+struct relationship_filter : public filter_visitor {
+ relationship_filter(
+ filter_t type, std::vector relationships);
+
+ tvl::value_t match(
+ const diagram &d, const relationship_t &r) const override;
+
+private:
+ std::vector relationships_;
+};
+
+struct access_filter : public filter_visitor {
+ access_filter(filter_t type, std::vector access);
+
+ tvl::value_t match(const diagram &d, const access_t &a) const override;
+
+private:
+ std::vector access_;
+};
+
+struct context_filter : public filter_visitor {
+ context_filter(filter_t type, std::vector context);
+
+ tvl::value_t match(const diagram &d, const element &r) const override;
+
+private:
+ std::vector context_;
+};
+
+class diagram_filter {
+public:
+ diagram_filter(const common::model::diagram &d, const config::diagram &c);
+
+ void add_inclusive_filter(std::unique_ptr fv);
+
+ void add_exclusive_filter(std::unique_ptr fv);
+
+ bool should_include(namespace_ ns, const std::string &name) const;
+
+ template bool should_include(const T &e) const
+ {
+ auto exc = tvl::any_of(exclusive_.begin(), exclusive_.end(),
+ [this, &e](const auto &ex) { return ex->match(diagram_, e); });
+
+ if (tvl::is_true(exc))
+ return false;
+
+ auto inc = tvl::all_of(inclusive_.begin(), inclusive_.end(),
+ [this, &e](const auto &in) { return in->match(diagram_, e); });
+
+ if (tvl::is_undefined(inc) || tvl::is_true(inc))
+ return true;
+
+ return false;
+ }
+
+private:
+ void init_filters(const config::diagram &c);
+
+ std::vector> inclusive_;
+ std::vector> exclusive_;
+
+ const common::model::diagram &diagram_;
+};
+
+template <>
+bool diagram_filter::should_include(const std::string &name) const;
+}
\ No newline at end of file
diff --git a/src/common/model/element.h b/src/common/model/element.h
index 3adeec0b..74173a89 100644
--- a/src/common/model/element.h
+++ b/src/common/model/element.h
@@ -59,7 +59,7 @@ public:
return ns_.relative_to(using_namespace_);
}
- virtual std::string full_name(bool relative) const { return name(); }
+ virtual std::string full_name(bool relative) const { return name_and_ns(); }
void set_using_namespaces(const namespace_ &un);
diff --git a/src/common/model/enums.cc b/src/common/model/enums.cc
index df734e6d..f1336fa6 100644
--- a/src/common/model/enums.cc
+++ b/src/common/model/enums.cc
@@ -49,22 +49,6 @@ std::string to_string(relationship_t r)
}
}
-std::string to_string(scope_t s)
-{
- switch (s) {
- case scope_t::kPublic:
- return "public";
- case scope_t::kProtected:
- return "protected";
- case scope_t::kPrivate:
- return "private";
- case scope_t::kNone:
- return "none";
- default:
- assert(false);
- }
-}
-
std::string to_string(access_t a)
{
switch (a) {
diff --git a/src/common/model/enums.h b/src/common/model/enums.h
index 2b553562..e102a67c 100644
--- a/src/common/model/enums.h
+++ b/src/common/model/enums.h
@@ -21,9 +21,9 @@
namespace clanguml::common::model {
-enum class access_t { kPublic, kProtected, kPrivate };
+enum class diagram_t { kClass, kSequence, kPackage };
-enum class scope_t { kPublic, kProtected, kPrivate, kNone };
+enum class access_t { kPublic, kProtected, kPrivate };
enum class relationship_t {
kNone,
@@ -42,8 +42,6 @@ enum class message_t { kCall, kReturn };
std::string to_string(relationship_t r);
-std::string to_string(scope_t r);
-
std::string to_string(access_t r);
std::string to_string(message_t r);
diff --git a/src/common/model/namespace.cc b/src/common/model/namespace.cc
index ed25e50a..2e6c6012 100644
--- a/src/common/model/namespace.cc
+++ b/src/common/model/namespace.cc
@@ -140,7 +140,6 @@ const std::string &namespace_::operator[](const int index) const
bool namespace_::starts_with(const namespace_ &right) const
{
-
return util::starts_with(namespace_path_, right.namespace_path_);
}
diff --git a/src/common/model/relationship.cc b/src/common/model/relationship.cc
index f384e40a..28b0d961 100644
--- a/src/common/model/relationship.cc
+++ b/src/common/model/relationship.cc
@@ -21,12 +21,12 @@
namespace clanguml::common::model {
relationship::relationship(relationship_t type, const std::string &destination,
- scope_t scope, const std::string &label,
+ access_t access, const std::string &label,
const std::string &multiplicity_source,
const std::string &multiplicity_destination)
: type_{type}
, destination_{destination}
- , scope_{scope}
+ , access_{access}
, label_{label}
, multiplicity_source_{multiplicity_source}
, multiplicity_destination_{multiplicity_destination}
@@ -70,9 +70,9 @@ void relationship::set_label(const std::string &label) { label_ = label; }
std::string relationship::label() const { return label_; }
-void relationship::set_scope(scope_t scope) noexcept { scope_ = scope; }
+void relationship::set_access(access_t access) noexcept { access_ = access; }
-scope_t relationship::scope() const noexcept { return scope_; }
+access_t relationship::access() const noexcept { return access_; }
bool operator==(const relationship &l, const relationship &r)
{
diff --git a/src/common/model/relationship.h b/src/common/model/relationship.h
index d75addf8..6a695528 100644
--- a/src/common/model/relationship.h
+++ b/src/common/model/relationship.h
@@ -28,7 +28,7 @@ class relationship : public common::model::decorated_element,
public common::model::stylable_element {
public:
relationship(relationship_t type, const std::string &destination,
- scope_t scope = scope_t::kNone, const std::string &label = "",
+ access_t access = access_t::kPublic, const std::string &label = "",
const std::string &multiplicity_source = "",
const std::string &multiplicity_destination = "");
@@ -50,8 +50,8 @@ public:
void set_label(const std::string &label);
std::string label() const;
- void set_scope(scope_t scope) noexcept;
- scope_t scope() const noexcept;
+ void set_access(access_t scope) noexcept;
+ access_t access() const noexcept;
friend bool operator==(const relationship &l, const relationship &r);
@@ -61,6 +61,6 @@ private:
std::string multiplicity_source_;
std::string multiplicity_destination_;
std::string label_;
- scope_t scope_{scope_t::kNone};
+ access_t access_{access_t::kPublic};
};
}
diff --git a/src/common/model/tvl.h b/src/common/model/tvl.h
new file mode 100644
index 00000000..7889c789
--- /dev/null
+++ b/src/common/model/tvl.h
@@ -0,0 +1,74 @@
+/**
+ * src/class_diagram/model/tvl.h
+ *
+ * Copyright (c) 2021-2022 Bartek Kryza
+ *
+ * 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.
+ */
+#pragma once
+
+#include
+#include
+
+namespace clanguml::common::model::tvl {
+
+using value_t = std::optional;
+
+inline bool is_true(const value_t &v) { return v.has_value() && v.value(); }
+
+inline bool is_false(const value_t &v) { return v.has_value() && !v.value(); }
+
+inline bool is_undefined(const value_t &v) { return !v.has_value(); }
+
+template
+inline value_t all_of(InputIterator first, InputIterator last, Predicate pred)
+{
+ value_t res{};
+
+ for (InputIterator it = first; it != last; it++) {
+ value_t m = pred(*it);
+ if (m.has_value()) {
+ if (m.value() == true) {
+ res = true;
+ }
+ else {
+ res = false;
+ break;
+ }
+ }
+ }
+
+ return res;
+}
+
+template
+inline value_t any_of(InputIterator first, InputIterator last, Predicate pred)
+{
+ value_t res{};
+
+ for (InputIterator it = first; it != last; it++) {
+ value_t m = pred(*it);
+ if (m.has_value()) {
+ if (m.value() == true) {
+ res = true;
+ break;
+ }
+ else {
+ res = false;
+ }
+ }
+ }
+
+ return res;
+}
+};
\ No newline at end of file
diff --git a/src/config/config.cc b/src/config/config.cc
index 9e7d00dd..6084be63 100644
--- a/src/config/config.cc
+++ b/src/config/config.cc
@@ -108,134 +108,6 @@ void inheritable_diagram_options::inherit(
git.override(parent.git);
}
-bool diagram::should_include_entities(const std::string &ent)
-{
- for (const auto &ex : exclude().entity_types) {
- if (ent == ex)
- return false;
- }
-
- if (include().entity_types.empty())
- return true;
-
- for (const auto &in : include().entity_types) {
- if (ent == in)
- return true;
- }
-
- return false;
-}
-
-bool diagram::should_include_relationship(const std::string &rel)
-{
- for (const auto &ex : exclude().relationships) {
- if (rel == ex)
- return false;
- }
-
- if (include().relationships.empty())
- return true;
-
- for (const auto &in : include().relationships) {
- if (rel == in)
- return true;
- }
-
- return false;
-}
-
-bool diagram::should_include(
- const std::pair &name) const
-{
- return should_include(std::get<0>(name), std::get<1>(name));
-}
-
-bool diagram::should_include(
- const common::model::namespace_ &ns, const std::string &name) const
-{
- return should_include(ns | name);
-}
-
-bool diagram::should_include(const std::string &name_) const
-{
- auto name = clanguml::util::unqualify(name_);
-
- for (const auto &ex : exclude().namespaces) {
- if (name.find(ex.to_string()) == 0) {
- LOG_DBG("Skipping from diagram: {}", name);
- return false;
- }
- }
-
- // If no inclusive namespaces are provided,
- // allow all
- if (include().namespaces.empty())
- return true;
-
- for (const auto &in : include().namespaces) {
- if (name.find(in.to_string()) == 0)
- return true;
- }
-
- LOG_DBG("Skipping from diagram: {}", name);
-
- return false;
-}
-
-bool diagram::should_include(const common::model::namespace_ &path) const
-{
- return should_include(path.to_string());
-}
-
-bool diagram::should_include_package(
- const common::model::namespace_ &path) const
-{
- return should_include_package(path.to_string());
-}
-
-bool diagram::should_include_package(const std::string &name) const
-{
-
- for (const auto &ex : exclude().namespaces) {
- if (name.find(ex.to_string()) == 0) {
- LOG_DBG("Skipping from diagram: {}", name);
- return false;
- }
- }
-
- // If no inclusive namespaces are provided,
- // allow all
- if (include().namespaces.empty())
- return true;
-
- for (const auto &in : include().namespaces) {
- if (in.to_string().find(name) == 0 || name.find(in.to_string()) == 0)
- return true;
- }
-
- LOG_DBG("Skipping from diagram: {}", name);
-
- return false;
-}
-
-bool diagram::should_include(const clanguml::common::model::scope_t scope) const
-{
- for (const auto &s : exclude().scopes) {
- if (s == scope)
- return false;
- }
-
- if (include().scopes.empty())
- return true;
-
- for (const auto &s : include().scopes) {
- if (s == scope)
- return true;
- }
-
- return false;
-}
-
diagram_type class_diagram::type() const { return diagram_type::class_diagram; }
bool class_diagram::has_class(std::string clazz)
@@ -279,7 +151,8 @@ template <> void append_value(plantuml &l, const plantuml &r)
}
namespace YAML {
-using clanguml::common::model::scope_t;
+using clanguml::common::model::access_t;
+using clanguml::common::model::relationship_t;
using clanguml::config::class_diagram;
using clanguml::config::config;
using clanguml::config::filter;
@@ -361,15 +234,65 @@ std::shared_ptr parse_diagram_config(const Node &d)
return {};
}
-template <> struct convert {
- static bool decode(const Node &node, scope_t &rhs)
+//
+// config access_t decoder
+//
+template <> struct convert {
+ static bool decode(const Node &node, access_t &rhs)
{
if (node.as() == "public")
- rhs = scope_t::kPublic;
+ rhs = access_t::kPublic;
else if (node.as() == "protected")
- rhs = scope_t::kProtected;
+ rhs = access_t::kProtected;
else if (node.as() == "private")
- rhs = scope_t::kPrivate;
+ rhs = access_t::kPrivate;
+ else
+ return false;
+
+ return true;
+ }
+};
+
+//
+// config relationship_t decoder
+//
+template <> struct convert {
+ static bool decode(const Node &node, relationship_t &rhs)
+ {
+ assert(node.Type() == NodeType::Scalar);
+
+ auto relationship_name = node.as();
+ if (relationship_name == "extension" ||
+ relationship_name == "inheritance") {
+ rhs = relationship_t::kExtension;
+ }
+ else if (relationship_name == "composition") {
+ rhs = relationship_t::kComposition;
+ }
+ else if (relationship_name == "aggregation") {
+ rhs = relationship_t::kAggregation;
+ }
+ else if (relationship_name == "containment") {
+ rhs = relationship_t::kContainment;
+ }
+ else if (relationship_name == "ownership") {
+ rhs = relationship_t::kOwnership;
+ }
+ else if (relationship_name == "association") {
+ rhs = relationship_t::kAssociation;
+ }
+ else if (relationship_name == "instantiation") {
+ rhs = relationship_t::kInstantiation;
+ }
+ else if (relationship_name == "friendship") {
+ rhs = relationship_t::kFriendship;
+ }
+ else if (relationship_name == "dependency") {
+ rhs = relationship_t::kDependency;
+ }
+ else if (relationship_name == "none") {
+ rhs = relationship_t::kNone;
+ }
else
return false;
@@ -445,12 +368,17 @@ template <> struct convert {
rhs.relationships =
node["relationships"].as();
- if (node["entity_types"])
- rhs.entity_types =
- node["entity_types"].as();
+ if (node["elements"])
+ rhs.elements = node["elements"].as();
- if (node["scopes"])
- rhs.scopes = node["scopes"].as();
+ if (node["access"])
+ rhs.access = node["access"].as();
+
+ if (node["subclasses"])
+ rhs.subclasses = node["subclasses"].as();
+
+ if (node["context"])
+ rhs.context = node["context"].as();
return true;
}
diff --git a/src/config/config.h b/src/config/config.h
index 3ebabf55..11db75fe 100644
--- a/src/config/config.h
+++ b/src/config/config.h
@@ -48,21 +48,23 @@ struct plantuml {
struct filter {
std::vector namespaces;
- // Valid values are:
- // - inheritance
- // - dependency
- // - instantiation
- std::vector relationships;
+ std::vector elements;
// E.g.:
- // - classes
- // - enums
- std::vector entity_types;
+ // - inheritance/extension
+ // - dependency
+ // - instantiation
+ std::vector relationships;
// E.g.:
// - public
+ // - protected
// - private
- std::vector scopes;
+ std::vector access;
+
+ std::vector subclasses;
+
+ std::vector context;
};
enum class hint_t { up, down, left, right };
@@ -111,26 +113,6 @@ struct diagram : public inheritable_diagram_options {
virtual diagram_type type() const = 0;
- bool should_include_entities(const std::string &ent);
-
- bool should_include_relationship(const std::string &rel);
-
- bool should_include_package(const std::string &name) const;
-
- bool should_include_package(const common::model::namespace_ &path) const;
-
- bool should_include(
- const std::pair &name) const;
-
- bool should_include(
- const common::model::namespace_ &ns, const std::string &name) const;
-
- bool should_include(const common::model::scope_t scope) const;
-
- bool should_include(const std::string &name_) const;
-
- bool should_include(const common::model::namespace_ &path) const;
-
std::string name;
};
diff --git a/src/cx/util.cc b/src/cx/util.cc
index f43859a0..77520069 100644
--- a/src/cx/util.cc
+++ b/src/cx/util.cc
@@ -236,7 +236,7 @@ std::string ns(const cppast::cpp_type &t, const cppast::cpp_entity_index &idx)
static_cast(t)
.primary_template();
if (!primary_template.is_overloaded()) {
- LOG_WARN(
+ LOG_DBG(
"Cannot establish namespace for ", cppast::to_string(t));
return "";
}
diff --git a/src/main.cc b/src/main.cc
index b1ca2acc..d7a4d1c8 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -152,7 +152,7 @@ void generate_diagram(const std::string &od, const std::string &name,
dynamic_cast(*diagram), verbose);
ofs << clanguml::class_diagram::generators::plantuml::generator(
- dynamic_cast(*diagram), model);
+ dynamic_cast(*diagram), *model);
}
else if (diagram->type() == diagram_type::sequence_diagram) {
using diagram_config = sequence_diagram;
@@ -167,7 +167,7 @@ void generate_diagram(const std::string &od, const std::string &name,
ofs << clanguml::sequence_diagram::generators::plantuml::generator(
dynamic_cast(*diagram),
- model);
+ *model);
}
else if (diagram->type() == diagram_type::package_diagram) {
using diagram_config = package_diagram;
@@ -181,7 +181,7 @@ void generate_diagram(const std::string &od, const std::string &name,
dynamic_cast(*diagram), verbose);
ofs << clanguml::package_diagram::generators::plantuml::generator(
- dynamic_cast(*diagram), model);
+ dynamic_cast(*diagram), *model);
}
LOG_INFO("Written {} diagram to {}", name, path.string());
diff --git a/src/package_diagram/generators/plantuml/package_diagram_generator.cc b/src/package_diagram/generators/plantuml/package_diagram_generator.cc
index cebe62d4..f03a5be7 100644
--- a/src/package_diagram/generators/plantuml/package_diagram_generator.cc
+++ b/src/package_diagram/generators/plantuml/package_diagram_generator.cc
@@ -35,7 +35,7 @@ void generator::generate_relationships(
const auto &uns = m_config.using_namespace();
// Generate this packages relationship
- if (m_config.should_include_relationship("dependency")) {
+ if (m_model.should_include(relationship_t::kDependency)) {
for (const auto &r : p.relationships()) {
std::stringstream relstr;
try {
diff --git a/src/package_diagram/generators/plantuml/package_diagram_generator.h b/src/package_diagram/generators/plantuml/package_diagram_generator.h
index 075bcef0..bc416afa 100644
--- a/src/package_diagram/generators/plantuml/package_diagram_generator.h
+++ b/src/package_diagram/generators/plantuml/package_diagram_generator.h
@@ -46,9 +46,9 @@ template
using common_generator =
clanguml::common::generators::plantuml::generator;
+using clanguml::common::model::access_t;
using clanguml::common::model::package;
using clanguml::common::model::relationship_t;
-using clanguml::common::model::scope_t;
using namespace clanguml::util;
class generator : public common_generator {
diff --git a/src/package_diagram/model/diagram.cc b/src/package_diagram/model/diagram.cc
index 1fb2c1c6..f8835711 100644
--- a/src/package_diagram/model/diagram.cc
+++ b/src/package_diagram/model/diagram.cc
@@ -23,6 +23,11 @@
namespace clanguml::package_diagram::model {
+common::model::diagram_t diagram::type() const
+{
+ return common::model::diagram_t::kPackage;
+}
+
std::string diagram::to_alias(const std::string &full_name) const
{
LOG_DBG("Looking for alias for {}", full_name);
diff --git a/src/package_diagram/model/diagram.h b/src/package_diagram/model/diagram.h
index ba092552..f84fd1ad 100644
--- a/src/package_diagram/model/diagram.h
+++ b/src/package_diagram/model/diagram.h
@@ -38,6 +38,8 @@ public:
diagram &operator=(const diagram &) = delete;
diagram &operator=(diagram &&) = default;
+ common::model::diagram_t type() const override;
+
std::string to_alias(const std::string &full_name) const;
};
}
diff --git a/src/package_diagram/visitor/translation_unit_visitor.cc b/src/package_diagram/visitor/translation_unit_visitor.cc
index ee15c3b7..b0632fc9 100644
--- a/src/package_diagram/visitor/translation_unit_visitor.cc
+++ b/src/package_diagram/visitor/translation_unit_visitor.cc
@@ -42,29 +42,28 @@ using clanguml::common::model::access_t;
using clanguml::common::model::package;
using clanguml::common::model::relationship;
using clanguml::common::model::relationship_t;
-using clanguml::common::model::scope_t;
using clanguml::package_diagram::model::diagram;
namespace detail {
-scope_t cpp_access_specifier_to_scope(
+access_t cpp_access_specifier_to_access(
cppast::cpp_access_specifier_kind access_specifier)
{
- scope_t scope = scope_t::kPublic;
+ access_t access = access_t::kPublic;
switch (access_specifier) {
case cppast::cpp_access_specifier_kind::cpp_public:
- scope = scope_t::kPublic;
+ access = access_t::kPublic;
break;
case cppast::cpp_access_specifier_kind::cpp_private:
- scope = scope_t::kPrivate;
+ access = access_t::kPrivate;
break;
case cppast::cpp_access_specifier_kind::cpp_protected:
- scope = scope_t::kProtected;
+ access = access_t::kProtected;
break;
default:
break;
}
- return scope;
+ return access;
}
}
@@ -95,18 +94,18 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
auto package_path = package_parent | e.name();
auto usn = ctx.config().using_namespace();
- if (ctx.config().should_include_package(package_path)) {
- auto p = std::make_unique(usn);
- package_path = package_path.relative_to(usn);
+ auto p = std::make_unique(usn);
+ package_path = package_path.relative_to(usn);
- if (e.location().has_value()) {
- p->set_file(e.location().value().file);
- p->set_line(e.location().value().line);
- }
+ if (e.location().has_value()) {
+ p->set_file(e.location().value().file);
+ p->set_line(e.location().value().line);
+ }
- p->set_name(e.name());
- p->set_namespace(package_parent);
+ p->set_name(e.name());
+ p->set_namespace(package_parent);
+ if (ctx.diagram().should_include(*p)) {
if (ns_declaration.comment().has_value())
p->add_decorators(decorators::parse(
ns_declaration.comment().value()));
@@ -465,7 +464,7 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
found = find_relationships(args[0u].type().value(), relationships,
relationship_t::kDependency);
}
- else if (ctx.config().should_include(t_ns, t_name)) {
+ else if (ctx.diagram().should_include(t_ns, t_name)) {
LOG_DBG("User defined template instantiation: {} | {}",
cppast::to_string(t_), cppast::to_string(t_.canonical()));
diff --git a/src/sequence_diagram/model/diagram.cc b/src/sequence_diagram/model/diagram.cc
index b83869ce..779322ae 100644
--- a/src/sequence_diagram/model/diagram.cc
+++ b/src/sequence_diagram/model/diagram.cc
@@ -18,17 +18,16 @@
#include "diagram.h"
-#include
-#include
-#include
-
#include
#include
-#include
-#include
namespace clanguml::sequence_diagram::model {
+common::model::diagram_t diagram::type() const
+{
+ return common::model::diagram_t::kSequence;
+}
+
std::string diagram::to_alias(const std::string &full_name) const
{
return full_name;
diff --git a/src/sequence_diagram/model/diagram.h b/src/sequence_diagram/model/diagram.h
index 50b4eede..c846fdd2 100644
--- a/src/sequence_diagram/model/diagram.h
+++ b/src/sequence_diagram/model/diagram.h
@@ -34,6 +34,8 @@ public:
diagram &operator=(const diagram &) = delete;
diagram &operator=(diagram &&) = default;
+ common::model::diagram_t type() const override;
+
std::string to_alias(const std::string &full_name) const;
bool started{false};
diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.cc b/src/sequence_diagram/visitor/translation_unit_visitor.cc
index e999fdd4..001de746 100644
--- a/src/sequence_diagram/visitor/translation_unit_visitor.cc
+++ b/src/sequence_diagram/visitor/translation_unit_visitor.cc
@@ -81,7 +81,7 @@ void translation_unit_visitor::process_activities(const cppast::cpp_function &e)
.value();
m.from = cx::util::ns(caller) + "::" + caller.name();
- if (!ctx.config().should_include(
+ if (!ctx.diagram().should_include(
common::model::namespace_{cx::util::ns(caller)}, caller.name()))
continue;
@@ -98,7 +98,7 @@ void translation_unit_visitor::process_activities(const cppast::cpp_function &e)
if (callee.kind() == cpp_entity_kind::function_t)
m.to += "()";
- if (!ctx.config().should_include(
+ if (!ctx.diagram().should_include(
common::model::namespace_{cx::util::ns(callee)}, callee.name()))
continue;
diff --git a/tests/t00002/test_case.h b/tests/t00002/test_case.h
index 2b7856bf..fd3995bb 100644
--- a/tests/t00002/test_case.h
+++ b/tests/t00002/test_case.h
@@ -31,14 +31,14 @@ TEST_CASE("t00002", "[test-case][class]")
REQUIRE(diagram->exclude().namespaces.size() == 0);
- REQUIRE(diagram->should_include({"clanguml", "t00002"}, "A"));
- REQUIRE(!diagram->should_include({"std"}, "vector"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00002_class");
+ REQUIRE(model->name() == "t00002_class");
- auto puml = generate_class_puml(diagram, model);
+ REQUIRE(model->should_include({"clanguml", "t00002"}, "A"));
+ REQUIRE(!model->should_include({"std"}, "vector"));
+
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00003/test_case.h b/tests/t00003/test_case.h
index d5309310..23ad9731 100644
--- a/tests/t00003/test_case.h
+++ b/tests/t00003/test_case.h
@@ -28,13 +28,12 @@ TEST_CASE("t00003", "[test-case][class]")
REQUIRE(diagram->exclude().namespaces.size() == 0);
- REQUIRE(diagram->should_include("clanguml::t00003::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00003_class");
+ REQUIRE(model->name() == "t00003_class");
+ REQUIRE(model->should_include(std::string("clanguml::t00003::A")));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00004/test_case.h b/tests/t00004/test_case.h
index daafd155..6f224ebf 100644
--- a/tests/t00004/test_case.h
+++ b/tests/t00004/test_case.h
@@ -27,15 +27,15 @@ TEST_CASE("t00004", "[test-case][class]")
REQUIRE(diagram->include().namespaces.size() == 1);
REQUIRE(diagram->exclude().namespaces.size() == 0);
- REQUIRE(diagram->should_include("clanguml::t00004::A"));
- REQUIRE(diagram->should_include("clanguml::t00004::A::AA"));
- REQUIRE(diagram->should_include("clanguml::t00004::A:::AAA"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00004_class");
+ REQUIRE(model->name() == "t00004_class");
+ REQUIRE(!model->should_include("std::vector"));
+ REQUIRE(model->should_include("clanguml::t00004::A"));
+ REQUIRE(model->should_include("clanguml::t00004::A::AA"));
+ REQUIRE(model->should_include("clanguml::t00004::A:::AAA"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00005/test_case.h b/tests/t00005/test_case.h
index b1b9a6da..aa4f1753 100644
--- a/tests/t00005/test_case.h
+++ b/tests/t00005/test_case.h
@@ -24,16 +24,15 @@ TEST_CASE("t00005", "[test-case][class]")
REQUIRE(diagram->name == "t00005_class");
- REQUIRE(diagram->should_include("clanguml::t00005::A"));
- REQUIRE(diagram->should_include("clanguml::t00005::B"));
- REQUIRE(diagram->should_include("clanguml::t00005::C"));
- REQUIRE(diagram->should_include("clanguml::t00005::D"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00005_class");
+ REQUIRE(model->name() == "t00005_class");
+ REQUIRE(model->should_include("clanguml::t00005::A"));
+ REQUIRE(model->should_include("clanguml::t00005::B"));
+ REQUIRE(model->should_include("clanguml::t00005::C"));
+ REQUIRE(model->should_include("clanguml::t00005::D"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00006/test_case.h b/tests/t00006/test_case.h
index fa6d7b4d..9037f669 100644
--- a/tests/t00006/test_case.h
+++ b/tests/t00006/test_case.h
@@ -24,17 +24,17 @@ TEST_CASE("t00006", "[test-case][class]")
REQUIRE(diagram->name == "t00006_class");
- REQUIRE(diagram->should_include("clanguml::t00006::A"));
- REQUIRE(diagram->should_include("clanguml::t00006::B"));
- REQUIRE(diagram->should_include("clanguml::t00006::C"));
- REQUIRE(diagram->should_include("clanguml::t00006::D"));
- REQUIRE(diagram->should_include("clanguml::t00006::E"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00006_class");
+ REQUIRE(model->name() == "t00006_class");
- auto puml = generate_class_puml(diagram, model);
+ REQUIRE(model->should_include("clanguml::t00006::A"));
+ REQUIRE(model->should_include("clanguml::t00006::B"));
+ REQUIRE(model->should_include("clanguml::t00006::C"));
+ REQUIRE(model->should_include("clanguml::t00006::D"));
+ REQUIRE(model->should_include("clanguml::t00006::E"));
+
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00007/test_case.h b/tests/t00007/test_case.h
index e3f8ce87..af0c02a0 100644
--- a/tests/t00007/test_case.h
+++ b/tests/t00007/test_case.h
@@ -24,17 +24,11 @@ TEST_CASE("t00007", "[test-case][class]")
REQUIRE(diagram->name == "t00007_class");
- REQUIRE(diagram->should_include("clanguml::t00007::A"));
- REQUIRE(diagram->should_include("clanguml::t00007::B"));
- REQUIRE(diagram->should_include("clanguml::t00007::C"));
- REQUIRE(diagram->should_include("clanguml::t00007::D"));
- REQUIRE(diagram->should_include("clanguml::t00007::E"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00007_class");
+ REQUIRE(model->name() == "t00007_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00008/test_case.h b/tests/t00008/test_case.h
index b2361adc..ce30cc75 100644
--- a/tests/t00008/test_case.h
+++ b/tests/t00008/test_case.h
@@ -24,14 +24,11 @@ TEST_CASE("t00008", "[test-case][class]")
REQUIRE(diagram->name == "t00008_class");
- REQUIRE(diagram->should_include("clanguml::t00008::A"));
- REQUIRE(diagram->should_include("clanguml::t00008::B"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00008_class");
+ REQUIRE(model->name() == "t00008_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00009/test_case.h b/tests/t00009/test_case.h
index b63c7e87..4faedca7 100644
--- a/tests/t00009/test_case.h
+++ b/tests/t00009/test_case.h
@@ -24,14 +24,11 @@ TEST_CASE("t00009", "[test-case][class]")
REQUIRE(diagram->name == "t00009_class");
- REQUIRE(diagram->should_include("clanguml::t00009::A"));
- REQUIRE(diagram->should_include("clanguml::t00009::B"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00009_class");
+ REQUIRE(model->name() == "t00009_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00010/test_case.h b/tests/t00010/test_case.h
index 22754c08..19dc49f1 100644
--- a/tests/t00010/test_case.h
+++ b/tests/t00010/test_case.h
@@ -24,14 +24,11 @@ TEST_CASE("t00010", "[test-case][class]")
REQUIRE(diagram->name == "t00010_class");
- REQUIRE(diagram->should_include("clanguml::t00010::A"));
- REQUIRE(diagram->should_include("clanguml::t00010::B"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00010_class");
+ REQUIRE(model->name() == "t00010_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00011/test_case.h b/tests/t00011/test_case.h
index 8fb39319..da15bf51 100644
--- a/tests/t00011/test_case.h
+++ b/tests/t00011/test_case.h
@@ -24,14 +24,11 @@ TEST_CASE("t00011", "[test-case][class]")
REQUIRE(diagram->name == "t00011_class");
- REQUIRE(diagram->should_include("clanguml::t00011::A"));
- REQUIRE(diagram->should_include("clanguml::t00011::B"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00011_class");
+ REQUIRE(model->name() == "t00011_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
@@ -40,7 +37,7 @@ TEST_CASE("t00011", "[test-case][class]")
REQUIRE_THAT(puml, IsClass(_A("B")));
REQUIRE_THAT(puml, IsClass(_A("D")));
- REQUIRE_THAT(puml, IsFriend(_A("A"), _A("B")));
+ REQUIRE_THAT(puml, IsFriend(_A("A"), _A("B")));
// REQUIRE_THAT(puml, IsFriend(_A("A"), _A("D")));
save_puml(
diff --git a/tests/t00012/test_case.h b/tests/t00012/test_case.h
index 2f8e2057..1a8dd1cd 100644
--- a/tests/t00012/test_case.h
+++ b/tests/t00012/test_case.h
@@ -24,14 +24,11 @@ TEST_CASE("t00012", "[test-case][class]")
REQUIRE(diagram->name == "t00012_class");
- REQUIRE(diagram->should_include("clanguml::t00012::A"));
- REQUIRE(diagram->should_include("clanguml::t00012::B"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00012_class");
+ REQUIRE(model->name() == "t00012_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00013/test_case.h b/tests/t00013/test_case.h
index ca91b368..5bcf89c4 100644
--- a/tests/t00013/test_case.h
+++ b/tests/t00013/test_case.h
@@ -24,15 +24,14 @@ TEST_CASE("t00013", "[test-case][class]")
REQUIRE(diagram->name == "t00013_class");
- REQUIRE(diagram->should_include("clanguml::t00013::A"));
- REQUIRE(diagram->should_include("clanguml::t00013::B"));
- REQUIRE(diagram->should_include("ABCD::F"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00013_class");
+ REQUIRE(model->name() == "t00013_class");
+ REQUIRE(model->should_include("clanguml::t00013::A"));
+ REQUIRE(model->should_include("clanguml::t00013::B"));
+ REQUIRE(model->should_include("ABCD::F"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00014/test_case.h b/tests/t00014/test_case.h
index ec4e5cd7..70a414af 100644
--- a/tests/t00014/test_case.h
+++ b/tests/t00014/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00014", "[test-case][class]")
REQUIRE(diagram->name == "t00014_class");
- REQUIRE(diagram->should_include("clanguml::t00014::S"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00014_class");
+ REQUIRE(model->name() == "t00014_class");
+ REQUIRE(model->should_include("clanguml::t00014::B"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00015/test_case.h b/tests/t00015/test_case.h
index 5ac0dbd3..91a9d094 100644
--- a/tests/t00015/test_case.h
+++ b/tests/t00015/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00015", "[test-case][class]")
REQUIRE(diagram->name == "t00015_class");
- REQUIRE(diagram->should_include("clanguml::t00015::ns1::ns2::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00015_class");
+ REQUIRE(model->name() == "t00015_class");
+ REQUIRE(model->should_include("clanguml::t00015::ns1::ns2::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00016/test_case.h b/tests/t00016/test_case.h
index 21232329..7efc05d8 100644
--- a/tests/t00016/test_case.h
+++ b/tests/t00016/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00016", "[test-case][class]")
REQUIRE(diagram->name == "t00016_class");
- REQUIRE(diagram->should_include("clanguml::t00016::is_numeric"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00016_class");
+ REQUIRE(model->name() == "t00016_class");
+ REQUIRE(model->should_include("clanguml::t00016::is_numeric"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00017/test_case.h b/tests/t00017/test_case.h
index 2d5ecb47..147bae53 100644
--- a/tests/t00017/test_case.h
+++ b/tests/t00017/test_case.h
@@ -24,16 +24,11 @@ TEST_CASE("t00017", "[test-case][class]")
REQUIRE(diagram->name == "t00017_class");
- REQUIRE(diagram->should_include("clanguml::t00017::A"));
- REQUIRE(diagram->should_include("clanguml::t00017::B"));
- REQUIRE(diagram->should_include("clanguml::t00017::C"));
- REQUIRE(diagram->should_include("clanguml::t00017::D"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00017_class");
+ REQUIRE(model->name() == "t00017_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00018/test_case.h b/tests/t00018/test_case.h
index 05e065d2..c1b54842 100644
--- a/tests/t00018/test_case.h
+++ b/tests/t00018/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00018", "[test-case][class]")
REQUIRE(diagram->name == "t00018_class");
- REQUIRE(diagram->should_include("clanguml::t00018::widget"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00018_class");
+ REQUIRE(model->name() == "t00018_class");
+ REQUIRE(model->should_include("clanguml::t00018::widget"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00019/test_case.h b/tests/t00019/test_case.h
index fc9328b0..cddbdb28 100644
--- a/tests/t00019/test_case.h
+++ b/tests/t00019/test_case.h
@@ -24,16 +24,11 @@ TEST_CASE("t00019", "[test-case][class]")
REQUIRE(diagram->name == "t00019_class");
- REQUIRE(diagram->should_include("clanguml::t00019::Layer1"));
- REQUIRE(diagram->should_include("clanguml::t00019::Layer2"));
- REQUIRE(diagram->should_include("clanguml::t00019::Layer3"));
- REQUIRE(diagram->should_include("clanguml::t00019::Base"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00019_class");
+ REQUIRE(model->name() == "t00019_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00020/test_case.h b/tests/t00020/test_case.h
index 8a15d02b..8ee87691 100644
--- a/tests/t00020/test_case.h
+++ b/tests/t00020/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00020", "[test-case][class]")
REQUIRE(diagram->name == "t00020_class");
- REQUIRE(diagram->should_include("clanguml::t00020::ProductA"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00020_class");
+ REQUIRE(model->name() == "t00020_class");
+ REQUIRE(model->should_include("clanguml::t00020::ProductA"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00021/test_case.h b/tests/t00021/test_case.h
index f956b6df..fafa3b82 100644
--- a/tests/t00021/test_case.h
+++ b/tests/t00021/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00021", "[test-case][class]")
REQUIRE(diagram->name == "t00021_class");
- REQUIRE(diagram->should_include("clanguml::t00021::Visitor"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00021_class");
+ REQUIRE(model->name() == "t00021_class");
+ REQUIRE(model->should_include("clanguml::t00021::Visitor"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00022/test_case.h b/tests/t00022/test_case.h
index 3585d0ea..426894fb 100644
--- a/tests/t00022/test_case.h
+++ b/tests/t00022/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00022", "[test-case][class]")
REQUIRE(diagram->name == "t00022_class");
- REQUIRE(diagram->should_include("clanguml::t00022::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00022_class");
+ REQUIRE(model->name() == "t00022_class");
+ REQUIRE(model->should_include("clanguml::t00022::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00023/test_case.h b/tests/t00023/test_case.h
index 90c381a5..dffcbcd9 100644
--- a/tests/t00023/test_case.h
+++ b/tests/t00023/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00023", "[test-case][class]")
REQUIRE(diagram->name == "t00023_class");
- REQUIRE(diagram->should_include("clanguml::t00023::Visitor"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00023_class");
+ REQUIRE(model->name() == "t00023_class");
+ REQUIRE(model->should_include("clanguml::t00023::Visitor"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00024/test_case.h b/tests/t00024/test_case.h
index 1a9b5fa7..3b1acd59 100644
--- a/tests/t00024/test_case.h
+++ b/tests/t00024/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00024", "[test-case][class]")
REQUIRE(diagram->name == "t00024_class");
- REQUIRE(diagram->should_include("clanguml::t00024::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00024_class");
+ REQUIRE(model->name() == "t00024_class");
+ REQUIRE(model->should_include("clanguml::t00024::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00025/test_case.h b/tests/t00025/test_case.h
index f37bf07b..078af9f2 100644
--- a/tests/t00025/test_case.h
+++ b/tests/t00025/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00025", "[test-case][class]")
REQUIRE(diagram->name == "t00025_class");
- REQUIRE(diagram->should_include("clanguml::t00025::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00025_class");
+ REQUIRE(model->name() == "t00025_class");
+ REQUIRE(model->should_include("clanguml::t00025::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00026/test_case.h b/tests/t00026/test_case.h
index d7509334..9e4ab933 100644
--- a/tests/t00026/test_case.h
+++ b/tests/t00026/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00026", "[test-case][class]")
REQUIRE(diagram->name == "t00026_class");
- REQUIRE(diagram->should_include("clanguml::t00026::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00026_class");
+ REQUIRE(model->name() == "t00026_class");
+ REQUIRE(model->should_include("clanguml::t00026::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00027/test_case.h b/tests/t00027/test_case.h
index c9fe40f5..f073b50b 100644
--- a/tests/t00027/test_case.h
+++ b/tests/t00027/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00027", "[test-case][class]")
REQUIRE(diagram->name == "t00027_class");
- REQUIRE(diagram->should_include("clanguml::t00027::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00027_class");
+ REQUIRE(model->name() == "t00027_class");
+ REQUIRE(model->should_include("clanguml::t00027::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00028/test_case.h b/tests/t00028/test_case.h
index 89ef3fbb..9cb64281 100644
--- a/tests/t00028/test_case.h
+++ b/tests/t00028/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00028", "[test-case][class]")
REQUIRE(diagram->name == "t00028_class");
- REQUIRE(diagram->should_include("clanguml::t00028::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00028_class");
+ REQUIRE(model->name() == "t00028_class");
+ REQUIRE(model->should_include("clanguml::t00028::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00029/test_case.h b/tests/t00029/test_case.h
index f4e02f56..7ba0d045 100644
--- a/tests/t00029/test_case.h
+++ b/tests/t00029/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00029", "[test-case][class]")
REQUIRE(diagram->name == "t00029_class");
- REQUIRE(diagram->should_include("clanguml::t00029::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00029_class");
+ REQUIRE(model->name() == "t00029_class");
+ REQUIRE(model->should_include("clanguml::t00029::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00030/test_case.h b/tests/t00030/test_case.h
index 87aacb9b..76f7b362 100644
--- a/tests/t00030/test_case.h
+++ b/tests/t00030/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00030", "[test-case][class]")
REQUIRE(diagram->name == "t00030_class");
- REQUIRE(diagram->should_include("clanguml::t00030::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00030_class");
+ REQUIRE(model->name() == "t00030_class");
+ REQUIRE(model->should_include("clanguml::t00030::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00031/test_case.h b/tests/t00031/test_case.h
index 25a6488e..338c1b90 100644
--- a/tests/t00031/test_case.h
+++ b/tests/t00031/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00031", "[test-case][class]")
REQUIRE(diagram->name == "t00031_class");
- REQUIRE(diagram->should_include("clanguml::t00031::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00031_class");
+ REQUIRE(model->name() == "t00031_class");
+ REQUIRE(model->should_include("clanguml::t00031::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00032/test_case.h b/tests/t00032/test_case.h
index fc6b3abc..28baa3de 100644
--- a/tests/t00032/test_case.h
+++ b/tests/t00032/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00032", "[test-case][class]")
REQUIRE(diagram->name == "t00032_class");
- REQUIRE(diagram->should_include("clanguml::t00032::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00032_class");
+ REQUIRE(model->name() == "t00032_class");
+ REQUIRE(model->should_include("clanguml::t00032::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00033/test_case.h b/tests/t00033/test_case.h
index 35025cc4..f65c1c8d 100644
--- a/tests/t00033/test_case.h
+++ b/tests/t00033/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00033", "[test-case][class]")
REQUIRE(diagram->name == "t00033_class");
- REQUIRE(diagram->should_include("clanguml::t00033::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00033_class");
+ REQUIRE(model->name() == "t00033_class");
+ REQUIRE(model->should_include("clanguml::t00033::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00034/test_case.h b/tests/t00034/test_case.h
index affcb3a8..44a64a88 100644
--- a/tests/t00034/test_case.h
+++ b/tests/t00034/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00034", "[test-case][class]")
REQUIRE(diagram->name == "t00034_class");
- REQUIRE(diagram->should_include("clanguml::t00034::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00034_class");
+ REQUIRE(model->name() == "t00034_class");
+ REQUIRE(model->should_include("clanguml::t00034::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00035/test_case.h b/tests/t00035/test_case.h
index 7cbf4163..8a0c3694 100644
--- a/tests/t00035/test_case.h
+++ b/tests/t00035/test_case.h
@@ -24,13 +24,12 @@ TEST_CASE("t00035", "[test-case][class]")
REQUIRE(diagram->name == "t00035_class");
- REQUIRE(diagram->should_include("clanguml::t00035::A"));
-
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00035_class");
+ REQUIRE(model->name() == "t00035_class");
+ REQUIRE(model->should_include("clanguml::t00035::A"));
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00036/test_case.h b/tests/t00036/test_case.h
index ee8a3ae4..30393389 100644
--- a/tests/t00036/test_case.h
+++ b/tests/t00036/test_case.h
@@ -27,9 +27,9 @@ TEST_CASE("t00036", "[test-case][class]")
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00036_class");
+ REQUIRE(model->name() == "t00036_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00037/test_case.h b/tests/t00037/test_case.h
index 87927d99..46b74998 100644
--- a/tests/t00037/test_case.h
+++ b/tests/t00037/test_case.h
@@ -27,9 +27,9 @@ TEST_CASE("t00037", "[test-case][class]")
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00037_class");
+ REQUIRE(model->name() == "t00037_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00038/test_case.h b/tests/t00038/test_case.h
index 8ca2b260..992d94b4 100644
--- a/tests/t00038/test_case.h
+++ b/tests/t00038/test_case.h
@@ -27,9 +27,9 @@ TEST_CASE("t00038", "[test-case][class]")
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t00038_class");
+ REQUIRE(model->name() == "t00038_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t00039/.clang-uml b/tests/t00039/.clang-uml
new file mode 100644
index 00000000..89ff7ef5
--- /dev/null
+++ b/tests/t00039/.clang-uml
@@ -0,0 +1,16 @@
+compilation_database_dir: ..
+output_directory: puml
+diagrams:
+ t00039_class:
+ type: class
+ generate_packages: false
+ glob:
+ - ../../tests/t00039/t00039.cc
+ using_namespace:
+ - clanguml::t00039
+ include:
+ subclasses:
+ - clanguml::t00039::A
+ - clanguml::t00039::ns3::F
+ relationships:
+ - inheritance
\ No newline at end of file
diff --git a/tests/t00039/t00039.cc b/tests/t00039/t00039.cc
new file mode 100644
index 00000000..2944ed5e
--- /dev/null
+++ b/tests/t00039/t00039.cc
@@ -0,0 +1,45 @@
+#include
+
+namespace clanguml::t00039 {
+struct B {
+};
+
+namespace ns1 {
+struct BB : public B {
+};
+} // namespace ns1
+
+struct A {
+};
+
+struct AA : public A {
+};
+
+struct AAA : public AA {
+ B *b;
+};
+
+namespace ns2 {
+struct AAAA : public AAA {
+};
+} // namespace ns2
+
+namespace ns3 {
+template struct F {
+ T *t;
+};
+
+template struct FF : public F {
+ M *m;
+};
+
+template struct FE : public F {
+ M *m;
+};
+
+template struct FFF : public FF {
+ N *n;
+};
+
+} // namespace ns3
+} // namespace clanguml::t00039
diff --git a/tests/t00039/test_case.h b/tests/t00039/test_case.h
new file mode 100644
index 00000000..6a2caf2c
--- /dev/null
+++ b/tests/t00039/test_case.h
@@ -0,0 +1,56 @@
+/**
+ * tests/t00039/test_case.cc
+ *
+ * Copyright (c) 2021-2022 Bartek Kryza
+ *
+ * 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.
+ */
+
+TEST_CASE("t00039", "[test-case][class]")
+{
+ auto [config, db] = load_config("t00039");
+
+ auto diagram = config.diagrams["t00039_class"];
+
+ REQUIRE(diagram->name == "t00039_class");
+ REQUIRE(diagram->generate_packages() == false);
+
+ auto model = generate_class_diagram(db, diagram);
+
+ REQUIRE(model->name() == "t00039_class");
+
+ auto puml = generate_class_puml(diagram, *model);
+ AliasMatcher _A(puml);
+
+ REQUIRE_THAT(puml, StartsWith("@startuml"));
+ REQUIRE_THAT(puml, EndsWith("@enduml\n"));
+
+ REQUIRE_THAT(puml, IsClass(_A("A")));
+ REQUIRE_THAT(puml, IsClass(_A("AA")));
+ REQUIRE_THAT(puml, IsClass(_A("AAA")));
+ REQUIRE_THAT(puml, IsClass(_A("ns2::AAAA")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("AA")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("AA"), _A("AAA")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("AAA"), _A("ns2::AAAA")));
+
+ REQUIRE_THAT(puml, !IsClass(_A("B")));
+ REQUIRE_THAT(puml, !IsClass(_A("ns1::BB")));
+
+ REQUIRE_THAT(puml, IsClassTemplate("ns3::F", "T"));
+ REQUIRE_THAT(puml, IsClassTemplate("ns3::FF", "T,M"));
+ REQUIRE_THAT(puml, IsClassTemplate("ns3::FE", "T,M"));
+ REQUIRE_THAT(puml, IsClassTemplate("ns3::FFF", "T,M,N"));
+
+ save_puml(
+ "./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
+}
diff --git a/tests/t00040/.clang-uml b/tests/t00040/.clang-uml
new file mode 100644
index 00000000..20744d33
--- /dev/null
+++ b/tests/t00040/.clang-uml
@@ -0,0 +1,21 @@
+compilation_database_dir: ..
+output_directory: puml
+diagrams:
+ t00040_class:
+ type: class
+ generate_packages: false
+ glob:
+ - ../../tests/t00040/t00040.cc
+ using_namespace:
+ - clanguml::t00040
+ include:
+ namespaces:
+ - clanguml::t00040
+ access:
+ - public
+ - protected
+ exclude:
+ relationships:
+ - dependency
+ elements:
+ - clanguml::t00040::B
\ No newline at end of file
diff --git a/tests/t00040/t00040.cc b/tests/t00040/t00040.cc
new file mode 100644
index 00000000..21b76dd2
--- /dev/null
+++ b/tests/t00040/t00040.cc
@@ -0,0 +1,36 @@
+namespace clanguml::t00040 {
+
+struct B {
+};
+
+struct A {
+public:
+ int get_a() { return hidden_a_; }
+
+protected:
+ int ii_;
+
+private:
+ void foo() { }
+
+ int hidden_a_;
+};
+
+class AA : public A {
+public:
+};
+
+class AAA : public AA {
+public:
+ int get_aaa() { return hidden_aaa_; }
+ B *b;
+
+private:
+ int hidden_aaa_;
+};
+
+struct R {
+ void foo(A *a) { }
+};
+
+} // namespace clanguml::t00040
diff --git a/tests/t00040/test_case.h b/tests/t00040/test_case.h
new file mode 100644
index 00000000..1019a385
--- /dev/null
+++ b/tests/t00040/test_case.h
@@ -0,0 +1,50 @@
+/**
+ * tests/t00040/test_case.cc
+ *
+ * Copyright (c) 2021-2022 Bartek Kryza
+ *
+ * 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.
+ */
+
+TEST_CASE("t00040", "[test-case][class]")
+{
+ auto [config, db] = load_config("t00040");
+
+ auto diagram = config.diagrams["t00040_class"];
+
+ REQUIRE(diagram->name == "t00040_class");
+ REQUIRE(diagram->generate_packages() == false);
+
+ auto model = generate_class_diagram(db, diagram);
+
+ REQUIRE(model->name() == "t00040_class");
+
+ auto puml = generate_class_puml(diagram, *model);
+ AliasMatcher _A(puml);
+
+ REQUIRE_THAT(puml, StartsWith("@startuml"));
+ REQUIRE_THAT(puml, EndsWith("@enduml\n"));
+
+ REQUIRE_THAT(puml, IsClass(_A("A")));
+ REQUIRE_THAT(puml, IsClass(_A("AA")));
+ REQUIRE_THAT(puml, IsClass(_A("AAA")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("AA")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("AA"), _A("AAA")));
+
+ REQUIRE_THAT(puml, !IsClass(_A("B")));
+
+ REQUIRE_THAT(puml, !IsDependency(_A("R"), _A("A")));
+
+ save_puml(
+ "./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
+}
diff --git a/tests/t00041/.clang-uml b/tests/t00041/.clang-uml
new file mode 100644
index 00000000..2ec91634
--- /dev/null
+++ b/tests/t00041/.clang-uml
@@ -0,0 +1,17 @@
+compilation_database_dir: ..
+output_directory: puml
+diagrams:
+ t00041_class:
+ type: class
+ generate_packages: false
+ glob:
+ - ../../tests/t00041/t00041.cc
+ using_namespace:
+ - clanguml::t00041
+ include:
+ namespaces:
+ - clanguml::t00041
+ context:
+ - clanguml::t00041::RR
+ subclasses:
+ - clanguml::t00041::ns1::N
\ No newline at end of file
diff --git a/tests/t00041/t00041.cc b/tests/t00041/t00041.cc
new file mode 100644
index 00000000..c6099308
--- /dev/null
+++ b/tests/t00041/t00041.cc
@@ -0,0 +1,46 @@
+namespace clanguml::t00041 {
+
+struct B {
+};
+
+struct A {
+};
+
+class AA : public A {
+};
+
+struct R {
+};
+
+struct RR;
+
+struct D {
+ RR *rr;
+};
+
+struct E {
+};
+
+struct F {
+};
+
+struct RR : public R {
+ E *e;
+ F *f;
+};
+
+struct RRR : public RR {
+};
+
+namespace ns1 {
+struct N {
+};
+
+struct NN : public N {
+};
+
+struct NM : public N {
+};
+}
+
+} // namespace clanguml::t00041
diff --git a/tests/t00041/test_case.h b/tests/t00041/test_case.h
new file mode 100644
index 00000000..a4fbb4b1
--- /dev/null
+++ b/tests/t00041/test_case.h
@@ -0,0 +1,66 @@
+/**
+ * tests/t00041/test_case.cc
+ *
+ * Copyright (c) 2021-2022 Bartek Kryza
+ *
+ * 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.
+ */
+
+TEST_CASE("t00041", "[test-case][class]")
+{
+ auto [config, db] = load_config("t00041");
+
+ auto diagram = config.diagrams["t00041_class"];
+
+ REQUIRE(diagram->name == "t00041_class");
+ REQUIRE(diagram->generate_packages() == false);
+
+ auto model = generate_class_diagram(db, diagram);
+
+ REQUIRE(model->name() == "t00041_class");
+
+ auto puml = generate_class_puml(diagram, *model);
+ AliasMatcher _A(puml);
+
+ REQUIRE_THAT(puml, StartsWith("@startuml"));
+ REQUIRE_THAT(puml, EndsWith("@enduml\n"));
+
+ REQUIRE_THAT(puml, !IsClass(_A("A")));
+ REQUIRE_THAT(puml, !IsClass(_A("AA")));
+ REQUIRE_THAT(puml, !IsClass(_A("AAA")));
+
+ REQUIRE_THAT(puml, !IsClass(_A("B")));
+
+ REQUIRE_THAT(puml, IsClass(_A("D")));
+ REQUIRE_THAT(puml, IsClass(_A("E")));
+ REQUIRE_THAT(puml, IsClass(_A("F")));
+ REQUIRE_THAT(puml, IsClass(_A("R")));
+ REQUIRE_THAT(puml, IsClass(_A("RR")));
+ REQUIRE_THAT(puml, IsClass(_A("RRR")));
+
+ REQUIRE_THAT(puml, IsBaseClass(_A("R"), _A("RR")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("RR"), _A("RRR")));
+
+ REQUIRE_THAT(puml, IsAssociation(_A("D"), _A("RR"), "+rr"));
+ REQUIRE_THAT(puml, IsAssociation(_A("RR"), _A("E"), "+e"));
+ REQUIRE_THAT(puml, IsAssociation(_A("RR"), _A("F"), "+f"));
+
+ REQUIRE_THAT(puml, IsClass(_A("ns1::N")));
+ REQUIRE_THAT(puml, IsClass(_A("ns1::NN")));
+ REQUIRE_THAT(puml, IsClass(_A("ns1::NM")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("ns1::N"), _A("ns1::NN")));
+ REQUIRE_THAT(puml, IsBaseClass(_A("ns1::N"), _A("ns1::NM")));
+
+ save_puml(
+ "./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
+}
diff --git a/tests/t20001/test_case.h b/tests/t20001/test_case.h
index 66319027..d330bfd9 100644
--- a/tests/t20001/test_case.h
+++ b/tests/t20001/test_case.h
@@ -22,17 +22,17 @@ TEST_CASE("t20001", "[test-case][sequence]")
auto diagram = config.diagrams["t20001_sequence"];
- REQUIRE(diagram->should_include("clanguml::t20001::A"));
- REQUIRE(!diagram->should_include("clanguml::t20001::detail::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t20001_sequence");
auto model = generate_sequence_diagram(db, diagram);
- REQUIRE(model.name() == "t20001_sequence");
+ REQUIRE(model->name() == "t20001_sequence");
- auto puml = generate_sequence_puml(diagram, model);
+ REQUIRE(model->should_include("clanguml::t20001::A"));
+ REQUIRE(!model->should_include("clanguml::t20001::detail::C"));
+ REQUIRE(!model->should_include("std::vector"));
+
+ auto puml = generate_sequence_puml(diagram, *model);
REQUIRE_THAT(puml, StartsWith("@startuml"));
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
diff --git a/tests/t20002/test_case.h b/tests/t20002/test_case.h
index 24cc8501..a5ab0472 100644
--- a/tests/t20002/test_case.h
+++ b/tests/t20002/test_case.h
@@ -26,9 +26,9 @@ TEST_CASE("t20002", "[test-case][sequence]")
auto model = generate_sequence_diagram(db, diagram);
- REQUIRE(model.name() == "t20002_sequence");
+ REQUIRE(model->name() == "t20002_sequence");
- auto puml = generate_sequence_puml(diagram, model);
+ auto puml = generate_sequence_puml(diagram, *model);
REQUIRE_THAT(puml, StartsWith("@startuml"));
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
diff --git a/tests/t30001/test_case.h b/tests/t30001/test_case.h
index 8ed7251f..15c6a261 100644
--- a/tests/t30001/test_case.h
+++ b/tests/t30001/test_case.h
@@ -22,17 +22,17 @@ TEST_CASE("t30001", "[test-case][package]")
auto diagram = config.diagrams["t30001_package"];
- REQUIRE(diagram->should_include("clanguml::t30001::A"));
- REQUIRE(!diagram->should_include("clanguml::t30001::detail::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t30001_package");
auto model = generate_package_diagram(db, diagram);
- REQUIRE(model.name() == "t30001_package");
+ REQUIRE(model->name() == "t30001_package");
- auto puml = generate_package_puml(diagram, model);
+ REQUIRE(model->should_include("clanguml::t30001::A"));
+ REQUIRE(!model->should_include("clanguml::t30001::detail::C"));
+ REQUIRE(!model->should_include("std::vector"));
+
+ auto puml = generate_package_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t30002/test_case.h b/tests/t30002/test_case.h
index 5cddd8ed..e77e7b05 100644
--- a/tests/t30002/test_case.h
+++ b/tests/t30002/test_case.h
@@ -22,17 +22,13 @@ TEST_CASE("t30002", "[test-case][package]")
auto diagram = config.diagrams["t30002_package"];
- REQUIRE(diagram->should_include("clanguml::t30002::A"));
- REQUIRE(!diagram->should_include("clanguml::t30002::detail::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t30002_package");
auto model = generate_package_diagram(db, diagram);
- REQUIRE(model.name() == "t30002_package");
+ REQUIRE(model->name() == "t30002_package");
- auto puml = generate_package_puml(diagram, model);
+ auto puml = generate_package_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t30003/test_case.h b/tests/t30003/test_case.h
index 5d508026..faa29614 100644
--- a/tests/t30003/test_case.h
+++ b/tests/t30003/test_case.h
@@ -22,17 +22,13 @@ TEST_CASE("t30003", "[test-case][package]")
auto diagram = config.diagrams["t30003_package"];
- REQUIRE(diagram->should_include("clanguml::t30003::A"));
- REQUIRE(diagram->should_include("clanguml::t30003::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t30003_package");
auto model = generate_package_diagram(db, diagram);
- REQUIRE(model.name() == "t30003_package");
+ REQUIRE(model->name() == "t30003_package");
- auto puml = generate_package_puml(diagram, model);
+ auto puml = generate_package_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t30004/test_case.h b/tests/t30004/test_case.h
index fbc2a03c..e850084b 100644
--- a/tests/t30004/test_case.h
+++ b/tests/t30004/test_case.h
@@ -22,17 +22,13 @@ TEST_CASE("t30004", "[test-case][package]")
auto diagram = config.diagrams["t30004_package"];
- REQUIRE(diagram->should_include("clanguml::t30004::A"));
- REQUIRE(diagram->should_include("clanguml::t30004::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t30004_package");
auto model = generate_package_diagram(db, diagram);
- REQUIRE(model.name() == "t30004_package");
+ REQUIRE(model->name() == "t30004_package");
- auto puml = generate_package_puml(diagram, model);
+ auto puml = generate_package_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t30005/test_case.h b/tests/t30005/test_case.h
index d1186ef5..30c181f3 100644
--- a/tests/t30005/test_case.h
+++ b/tests/t30005/test_case.h
@@ -22,17 +22,13 @@ TEST_CASE("t30005", "[test-case][package]")
auto diagram = config.diagrams["t30005_package"];
- REQUIRE(diagram->should_include("clanguml::t30005::A"));
- REQUIRE(diagram->should_include("clanguml::t30005::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t30005_package");
auto model = generate_package_diagram(db, diagram);
- REQUIRE(model.name() == "t30005_package");
+ REQUIRE(model->name() == "t30005_package");
- auto puml = generate_package_puml(diagram, model);
+ auto puml = generate_package_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t30006/test_case.h b/tests/t30006/test_case.h
index 174d2612..4991f12a 100644
--- a/tests/t30006/test_case.h
+++ b/tests/t30006/test_case.h
@@ -22,17 +22,13 @@ TEST_CASE("t30006", "[test-case][package]")
auto diagram = config.diagrams["t30006_package"];
- REQUIRE(diagram->should_include("clanguml::t30006::A"));
- REQUIRE(diagram->should_include("clanguml::t30006::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t30006_package");
auto model = generate_package_diagram(db, diagram);
- REQUIRE(model.name() == "t30006_package");
+ REQUIRE(model->name() == "t30006_package");
- auto puml = generate_package_puml(diagram, model);
+ auto puml = generate_package_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t30007/test_case.h b/tests/t30007/test_case.h
index 130f1e96..03850092 100644
--- a/tests/t30007/test_case.h
+++ b/tests/t30007/test_case.h
@@ -22,17 +22,13 @@ TEST_CASE("t30007", "[test-case][package]")
auto diagram = config.diagrams["t30007_package"];
- REQUIRE(diagram->should_include("clanguml::t30007::A"));
- REQUIRE(diagram->should_include("clanguml::t30007::C"));
- REQUIRE(!diagram->should_include("std::vector"));
-
REQUIRE(diagram->name == "t30007_package");
auto model = generate_package_diagram(db, diagram);
- REQUIRE(model.name() == "t30007_package");
+ REQUIRE(model->name() == "t30007_package");
- auto puml = generate_package_puml(diagram, model);
+ auto puml = generate_package_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/t90000/test_case.h b/tests/t90000/test_case.h
index 068416ce..425d5dc9 100644
--- a/tests/t90000/test_case.h
+++ b/tests/t90000/test_case.h
@@ -24,9 +24,9 @@ TEST_CASE("t90000", "[test-case][config]")
auto model = generate_class_diagram(db, diagram);
- REQUIRE(model.name() == "t90000_class");
+ REQUIRE(model->name() == "t90000_class");
- auto puml = generate_class_puml(diagram, model);
+ auto puml = generate_class_puml(diagram, *model);
AliasMatcher _A(puml);
REQUIRE_THAT(puml, StartsWith("@startuml"));
diff --git a/tests/test_cases.cc b/tests/test_cases.cc
index f8a0c6cf..3487f740 100644
--- a/tests/test_cases.cc
+++ b/tests/test_cases.cc
@@ -51,8 +51,8 @@ std::pair load_config2(
return std::make_pair(std::move(config), std::move(db));
}
-clanguml::sequence_diagram::model::diagram generate_sequence_diagram(
- cppast::libclang_compilation_database &db,
+std::unique_ptr
+generate_sequence_diagram(cppast::libclang_compilation_database &db,
std::shared_ptr diagram)
{
using diagram_config = clanguml::config::sequence_diagram;
@@ -66,10 +66,10 @@ clanguml::sequence_diagram::model::diagram generate_sequence_diagram(
diagram_config, diagram_visitor>(db, diagram->name,
dynamic_cast