diff --git a/docs/test_cases.md b/docs/test_cases.md index 04a004cc..963737db 100644 --- a/docs/test_cases.md +++ b/docs/test_cases.md @@ -19,6 +19,7 @@ * [t00018](./test_cases/t00018.md) - Pimpl pattern * [t00019](./test_cases/t00019.md) - Layercake pattern * [t00020](./test_cases/t00020.md) - Abstract factory pattern + * [t00021](./test_cases/t00021.md) - Visitor pattern ## Sequence diagrams * [t20001](./test_cases/t20001.md) - Basic sequence diagram ## Configuration diagrams diff --git a/docs/test_cases/t00002_class.png b/docs/test_cases/t00002_class.png index 3893723c..1afa8b14 100644 Binary files a/docs/test_cases/t00002_class.png and b/docs/test_cases/t00002_class.png differ diff --git a/docs/test_cases/t00003_class.png b/docs/test_cases/t00003_class.png index 5244f94c..1275a434 100644 Binary files a/docs/test_cases/t00003_class.png and b/docs/test_cases/t00003_class.png differ diff --git a/docs/test_cases/t00004_class.png b/docs/test_cases/t00004_class.png index d77cb040..ba383e17 100644 Binary files a/docs/test_cases/t00004_class.png and b/docs/test_cases/t00004_class.png differ diff --git a/docs/test_cases/t00005_class.png b/docs/test_cases/t00005_class.png index 7d28d2b9..0b418da6 100644 Binary files a/docs/test_cases/t00005_class.png and b/docs/test_cases/t00005_class.png differ diff --git a/docs/test_cases/t00006_class.png b/docs/test_cases/t00006_class.png index 2459105c..648d53ad 100644 Binary files a/docs/test_cases/t00006_class.png and b/docs/test_cases/t00006_class.png differ diff --git a/docs/test_cases/t00007_class.png b/docs/test_cases/t00007_class.png index c36315f3..f802af97 100644 Binary files a/docs/test_cases/t00007_class.png and b/docs/test_cases/t00007_class.png differ diff --git a/docs/test_cases/t00008_class.png b/docs/test_cases/t00008_class.png index 694d620c..70837f03 100644 Binary files a/docs/test_cases/t00008_class.png and b/docs/test_cases/t00008_class.png differ diff --git a/docs/test_cases/t00009_class.png b/docs/test_cases/t00009_class.png index e8be7a19..2e93ec78 100644 Binary files a/docs/test_cases/t00009_class.png and b/docs/test_cases/t00009_class.png differ diff --git a/docs/test_cases/t00010_class.png b/docs/test_cases/t00010_class.png index ce2b69ef..b3c96344 100644 Binary files a/docs/test_cases/t00010_class.png and b/docs/test_cases/t00010_class.png differ diff --git a/docs/test_cases/t00011_class.png b/docs/test_cases/t00011_class.png index ef329d4c..99bdb36c 100644 Binary files a/docs/test_cases/t00011_class.png and b/docs/test_cases/t00011_class.png differ diff --git a/docs/test_cases/t00012_class.png b/docs/test_cases/t00012_class.png index 223502dc..7ebd9577 100644 Binary files a/docs/test_cases/t00012_class.png and b/docs/test_cases/t00012_class.png differ diff --git a/docs/test_cases/t00013_class.png b/docs/test_cases/t00013_class.png index 5032ee20..f011be6a 100644 Binary files a/docs/test_cases/t00013_class.png and b/docs/test_cases/t00013_class.png differ diff --git a/docs/test_cases/t00014_class.png b/docs/test_cases/t00014_class.png index e6f8c223..c9f5390a 100644 Binary files a/docs/test_cases/t00014_class.png and b/docs/test_cases/t00014_class.png differ diff --git a/docs/test_cases/t00015_class.png b/docs/test_cases/t00015_class.png index bedf4146..24e8b4fb 100644 Binary files a/docs/test_cases/t00015_class.png and b/docs/test_cases/t00015_class.png differ diff --git a/docs/test_cases/t00016_class.png b/docs/test_cases/t00016_class.png index b8e20f56..82b5fc5b 100644 Binary files a/docs/test_cases/t00016_class.png and b/docs/test_cases/t00016_class.png differ diff --git a/docs/test_cases/t00017_class.png b/docs/test_cases/t00017_class.png index d7a0413d..249ecba5 100644 Binary files a/docs/test_cases/t00017_class.png and b/docs/test_cases/t00017_class.png differ diff --git a/docs/test_cases/t00018.md b/docs/test_cases/t00018.md index 760615a8..1b72af09 100644 --- a/docs/test_cases/t00018.md +++ b/docs/test_cases/t00018.md @@ -17,6 +17,36 @@ diagrams: ``` ## Source code +File t00018_impl.cc +```cpp +#include "t00018_impl.h" +#include "t00018.h" + +namespace clanguml { +namespace t00018 { +namespace impl { + +widget::widget(int n) + : n(n) +{ +} + +void widget::draw(const clanguml::t00018::widget &w) const +{ + if (w.shown()) + std::cout << "drawing a const widget " << n << '\n'; +} + +void widget::draw(const clanguml::t00018::widget &w) +{ + if (w.shown()) + std::cout << "drawing a non-const widget " << n << '\n'; +} +} +} +} + +``` File t00018_impl.h ```cpp #pragma once @@ -101,36 +131,6 @@ widget &widget::operator=(widget &&) = default; } } -``` -File t00018_impl.cc -```cpp -#include "t00018_impl.h" -#include "t00018.h" - -namespace clanguml { -namespace t00018 { -namespace impl { - -widget::widget(int n) - : n(n) -{ -} - -void widget::draw(const clanguml::t00018::widget &w) const -{ - if (w.shown()) - std::cout << "drawing a const widget " << n << '\n'; -} - -void widget::draw(const clanguml::t00018::widget &w) -{ - if (w.shown()) - std::cout << "drawing a non-const widget " << n << '\n'; -} -} -} -} - ``` ## Generated UML diagrams ![t00018_class](./t00018_class.png "Pimpl pattern") diff --git a/docs/test_cases/t00018_class.png b/docs/test_cases/t00018_class.png index a5911e01..4cd3f4cb 100644 Binary files a/docs/test_cases/t00018_class.png and b/docs/test_cases/t00018_class.png differ diff --git a/docs/test_cases/t00019.md b/docs/test_cases/t00019.md index 5d835bfc..6a7a8b01 100644 --- a/docs/test_cases/t00019.md +++ b/docs/test_cases/t00019.md @@ -22,25 +22,21 @@ diagrams: ``` ## Source code -File t00019_layer2.h +File t00019.cc ```cpp -#pragma once +#include "t00019_base.h" +#include "t00019_layer1.h" +#include "t00019_layer2.h" +#include "t00019_layer3.h" + +#include namespace clanguml { namespace t00019 { -template class Layer2 : public LowerLayer { - - using LowerLayer::LowerLayer; - - using LowerLayer::m1; - - using LowerLayer::m2; - - int all_calls_count() const - { - return LowerLayer::m1_calls() + LowerLayer::m2_calls(); - } +class A { +public: + std::unique_ptr>>> layers; }; } } @@ -98,26 +94,6 @@ template class Layer1 : public LowerLayer { } } -``` -File t00019.cc -```cpp -#include "t00019_base.h" -#include "t00019_layer1.h" -#include "t00019_layer2.h" -#include "t00019_layer3.h" - -#include - -namespace clanguml { -namespace t00019 { - -class A { -public: - std::unique_ptr>>> layers; -}; -} -} - ``` File t00019_layer3.h ```cpp @@ -155,6 +131,30 @@ private: } } +``` +File t00019_layer2.h +```cpp +#pragma once + +namespace clanguml { +namespace t00019 { + +template class Layer2 : public LowerLayer { + + using LowerLayer::LowerLayer; + + using LowerLayer::m1; + + using LowerLayer::m2; + + int all_calls_count() const + { + return LowerLayer::m1_calls() + LowerLayer::m2_calls(); + } +}; +} +} + ``` ## Generated UML diagrams ![t00019_class](./t00019_class.png "Layercake pattern") diff --git a/docs/test_cases/t00019_class.png b/docs/test_cases/t00019_class.png index c2eb10e4..f8ac04d4 100644 Binary files a/docs/test_cases/t00019_class.png and b/docs/test_cases/t00019_class.png differ diff --git a/docs/test_cases/t00020.md b/docs/test_cases/t00020.md new file mode 100644 index 00000000..7f0eb992 --- /dev/null +++ b/docs/test_cases/t00020.md @@ -0,0 +1,100 @@ +# t00020 - Abstract factory pattern +## Config +```yaml +compilation_database_dir: .. +output_directory: puml +diagrams: + t00020_class: + type: class + glob: + - ../../tests/t00020/t00020.cc + using_namespace: + - clanguml::t00020 + include: + namespaces: + - clanguml::t00020 + plantuml: + after: + - '@A(ProductA1) <.. @A(Factory1)' + - '@A(ProductB1) <.. @A(Factory1)' + - '@A(ProductA2) <.. @A(Factory2)' + - '@A(ProductB2) <.. @A(Factory2)' + +``` +## Source code +File t00020.cc +```cpp +#include + +namespace clanguml { +namespace t00020 { + +class ProductA { +public: + virtual ~ProductA() = default; + virtual bool sell(int price) const = 0; +}; + +class ProductA1 : public ProductA { +public: + bool sell(int price) const override { return price > 1000; } +}; + +class ProductA2 : public ProductA { +public: + bool sell(int price) const override { return price > 2000; } +}; + +class ProductB { +public: + virtual ~ProductB() = default; + virtual bool buy(int price) const = 0; +}; + +class ProductB1 : public ProductB { +public: + bool buy(int price) const override { return price < 1000; } +}; + +class ProductB2 : public ProductB { +public: + bool buy(int price) const override { return price < 2000; } +}; + +class AbstractFactory { +public: + virtual std::unique_ptr make_a() const = 0; + virtual std::unique_ptr make_b() const = 0; +}; + +class Factory1 : public AbstractFactory { +public: + std::unique_ptr make_a() const override + { + return std::make_unique(); + } + + std::unique_ptr make_b() const override + { + return std::make_unique(); + } +}; + +class Factory2 : public AbstractFactory { +public: + std::unique_ptr make_a() const override + { + return std::make_unique(); + } + + std::unique_ptr make_b() const override + { + return std::make_unique(); + } +}; +} +} + +``` +## Generated UML diagrams +![t00020_class](./t00020_class.png "Abstract factory pattern") diff --git a/docs/test_cases/t00020_class.png b/docs/test_cases/t00020_class.png new file mode 100644 index 00000000..5b15ac07 Binary files /dev/null and b/docs/test_cases/t00020_class.png differ diff --git a/docs/test_cases/t00021.md b/docs/test_cases/t00021.md new file mode 100644 index 00000000..2218a661 --- /dev/null +++ b/docs/test_cases/t00021.md @@ -0,0 +1,74 @@ +# t00021 - Visitor pattern +## Config +```yaml +compilation_database_dir: .. +output_directory: puml +diagrams: + t00021_class: + type: class + glob: + - ../../tests/t00021/t00021.cc + using_namespace: + - clanguml::t00021 + include: + namespaces: + - clanguml::t00021 + +``` +## Source code +File t00021.cc +```cpp +#include + +namespace clanguml { +namespace t00021 { + +class A; +class B; + +class Visitor { +public: + virtual ~Visitor() = default; + virtual void visit_A(const A &item) const = 0; + virtual void visit_B(const B &item) const = 0; +}; + +class Visitor1 : public Visitor { +public: + void visit_A(const A &item) const override { } + void visit_B(const B &item) const override { } +}; + +class Visitor2 : public Visitor { +public: + void visit_A(const A &item) const override { } + void visit_B(const B &item) const override { } +}; + +class Visitor3 : public Visitor { +public: + void visit_A(const A &item) const override { } + void visit_B(const B &item) const override { } +}; + +class Item { +public: + virtual ~Item() = default; + virtual void accept(const Visitor &visitor) const = 0; +}; + +class A : public Item { +public: + void accept(const Visitor &visitor) const override { } +}; + +class B : public Item { +public: + void accept(const Visitor &visitor) const override { } +}; +} +} + +``` +## Generated UML diagrams +![t00021_class](./t00021_class.png "Visitor pattern") diff --git a/docs/test_cases/t00021_class.png b/docs/test_cases/t00021_class.png new file mode 100644 index 00000000..ec18ba33 Binary files /dev/null and b/docs/test_cases/t00021_class.png differ diff --git a/docs/test_cases/t20001_sequence.png b/docs/test_cases/t20001_sequence.png index 8466db95..9042abe3 100644 Binary files a/docs/test_cases/t20001_sequence.png and b/docs/test_cases/t20001_sequence.png differ diff --git a/docs/test_cases/t90000_class.png b/docs/test_cases/t90000_class.png index 042201e5..3a38629b 100644 Binary files a/docs/test_cases/t90000_class.png and b/docs/test_cases/t90000_class.png differ diff --git a/tests/t00021/.clanguml b/tests/t00021/.clanguml new file mode 100644 index 00000000..0f7c063a --- /dev/null +++ b/tests/t00021/.clanguml @@ -0,0 +1,12 @@ +compilation_database_dir: .. +output_directory: puml +diagrams: + t00021_class: + type: class + glob: + - ../../tests/t00021/t00021.cc + using_namespace: + - clanguml::t00021 + include: + namespaces: + - clanguml::t00021 diff --git a/tests/t00021/t00021.cc b/tests/t00021/t00021.cc new file mode 100644 index 00000000..c3aaa1c4 --- /dev/null +++ b/tests/t00021/t00021.cc @@ -0,0 +1,50 @@ +#include + +namespace clanguml { +namespace t00021 { + +class A; +class B; + +class Visitor { +public: + virtual ~Visitor() = default; + virtual void visit_A(const A &item) const = 0; + virtual void visit_B(const B &item) const = 0; +}; + +class Visitor1 : public Visitor { +public: + void visit_A(const A &item) const override {} + void visit_B(const B &item) const override {} +}; + +class Visitor2 : public Visitor { +public: + void visit_A(const A &item) const override {} + void visit_B(const B &item) const override {} +}; + +class Visitor3 : public Visitor { +public: + void visit_A(const A &item) const override {} + void visit_B(const B &item) const override {} +}; + +class Item { +public: + virtual ~Item() = default; + virtual void accept(const Visitor &visitor) const = 0; +}; + +class A : public Item { +public: + void accept(const Visitor &visitor) const override {} +}; + +class B : public Item { +public: + void accept(const Visitor &visitor) const override {} +}; +} +} diff --git a/tests/t00021/test_case.h b/tests/t00021/test_case.h new file mode 100644 index 00000000..e6da5cbd --- /dev/null +++ b/tests/t00021/test_case.h @@ -0,0 +1,54 @@ +/** + * tests/t00021/test_case.cc + * + * Copyright (c) 2021 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("t00021", "[test-case][class]") +{ + auto [config, db] = load_config("t00021"); + + auto diagram = config.diagrams["t00021_class"]; + + REQUIRE(diagram->name == "t00021_class"); + + REQUIRE(diagram->include.namespaces.size() == 1); + REQUIRE_THAT(diagram->include.namespaces, + VectorContains(std::string{"clanguml::t00021"})); + + REQUIRE(diagram->exclude.namespaces.size() == 0); + + REQUIRE(diagram->should_include("clanguml::t00021::Visitor")); + + auto model = generate_class_diagram(db, diagram); + + REQUIRE(model.name == "t00021_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, IsAbstractClass(_A("Item"))); + REQUIRE_THAT(puml, IsAbstractClass(_A("Visitor"))); + REQUIRE_THAT(puml, IsClass(_A("A"))); + REQUIRE_THAT(puml, IsClass(_A("B"))); + REQUIRE_THAT(puml, IsClass(_A("Visitor1"))); + REQUIRE_THAT(puml, IsClass(_A("Visitor2"))); + REQUIRE_THAT(puml, IsClass(_A("Visitor3"))); + + save_puml( + "./" + config.output_directory + "/" + diagram->name + ".puml", puml); +} diff --git a/tests/test_cases.cc b/tests/test_cases.cc index ed18e6a8..c7c7ad47 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -124,6 +124,7 @@ using namespace clanguml::test::matchers; #include "t00018/test_case.h" #include "t00019/test_case.h" #include "t00020/test_case.h" +#include "t00021/test_case.h" // // Sequence diagram tests diff --git a/tests/test_cases.yaml b/tests/test_cases.yaml index 80411e8f..4deb7fa9 100644 --- a/tests/test_cases.yaml +++ b/tests/test_cases.yaml @@ -57,6 +57,9 @@ test_cases: - name: t00020 title: Abstract factory pattern description: + - name: t00021 + title: Visitor pattern + description: Sequence diagrams: - name: t20001 title: Basic sequence diagram