diff --git a/Makefile b/Makefile index 002f4201..cc053baa 100644 --- a/Makefile +++ b/Makefile @@ -62,4 +62,4 @@ init_compile_commands: debug .PHONY: clang-format clang-format: - docker run --rm -v $(CURDIR):/root/sources bkryza/clang-format-check:1.2 + docker run --rm -v $(CURDIR):/root/sources bkryza/clang-format-check:1.3 diff --git a/README.md b/README.md index 9e78e252..e253dd24 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,17 @@ The following decorators are currently supported: - [aggregation](docs/test_cases/t00030.md) - document the property as aggregation - [style](docs/test_cases/t00031.md) - add PlantUML style to a C++ entity +##### Doxygen integration +`clang-uml` can be omitted completed in ![Doxygen](https://www.doxygen.nl/index.html), by adding the following +lines to the Doxygen config file: + +``` +ALIASES += clanguml="" +ALIASES += clanguml{1}="" +ALIASES += clanguml{2}="" +ALIASES += clanguml{3}="" +``` + ### Sequence diagrams #### Example diff --git a/docs/test_cases.md b/docs/test_cases.md index 8f06dcc2..19d605fa 100644 --- a/docs/test_cases.md +++ b/docs/test_cases.md @@ -30,6 +30,7 @@ * [t00029](./test_cases/t00029.md) - PlantUML skip decorator test case * [t00030](./test_cases/t00030.md) - PlantUML relationship decorators test case * [t00031](./test_cases/t00031.md) - PlantUML style decorator test case + * [t00032](./test_cases/t00032.md) - Class template with template base classes test case ## Sequence diagrams * [t20001](./test_cases/t20001.md) - Basic sequence diagram ## Configuration diagrams diff --git a/docs/test_cases/t00002.md b/docs/test_cases/t00002.md index 5adadd4d..1e3b2ca5 100644 --- a/docs/test_cases/t00002.md +++ b/docs/test_cases/t00002.md @@ -34,12 +34,12 @@ public: class B : public A { public: - virtual void foo_a() override {} + virtual void foo_a() override { } }; class C : public A { public: - virtual void foo_c() override {} + virtual void foo_c() override { } }; class D : public B, public C { diff --git a/docs/test_cases/t00003.md b/docs/test_cases/t00003.md index 2b0e8783..299fb8b1 100644 --- a/docs/test_cases/t00003.md +++ b/docs/test_cases/t00003.md @@ -35,9 +35,9 @@ public: A(const A &) = default; virtual ~A() = default; - void basic_method() {} + void basic_method() { } static int static_method() { return 0; } - void const_method() const {} + void const_method() const { } auto auto_method() { return 1; } auto double_int(const int i) { return 2 * i; } @@ -57,7 +57,7 @@ public: static const auto auto_member{10UL}; protected: - void protected_method() {} + void protected_method() { } int protected_member; @@ -66,7 +66,7 @@ protected: }; private: - void private_method() {} + void private_method() { } int private_member; int a, b, c; diff --git a/docs/test_cases/t00004.md b/docs/test_cases/t00004.md index 2a8bf99d..a6f84008 100644 --- a/docs/test_cases/t00004.md +++ b/docs/test_cases/t00004.md @@ -25,7 +25,7 @@ namespace t00004 { class A { public: - void foo() const {} + void foo() const { } class AA { public: @@ -35,7 +35,7 @@ public: }; }; - void foo2() const {} + void foo2() const { } }; } } diff --git a/docs/test_cases/t00011.md b/docs/test_cases/t00011.md index ea0560e4..35ce8de0 100644 --- a/docs/test_cases/t00011.md +++ b/docs/test_cases/t00011.md @@ -34,7 +34,7 @@ template class D { class A { private: - void foo() {} + void foo() { } friend class B; friend class external::C; // TODO diff --git a/docs/test_cases/t00013.md b/docs/test_cases/t00013.md index b374935c..c3bc0857 100644 --- a/docs/test_cases/t00013.md +++ b/docs/test_cases/t00013.md @@ -48,7 +48,7 @@ class R; struct D { int d; - void print(R *r) {} + void print(R *r) { } }; template struct E { diff --git a/docs/test_cases/t00015.md b/docs/test_cases/t00015.md index 8c33c9ba..47c773ba 100644 --- a/docs/test_cases/t00015.md +++ b/docs/test_cases/t00015.md @@ -28,7 +28,8 @@ class A { } namespace ns2_v0_9_0 { -class [[deprecated]] A {}; +class [[deprecated]] A { +}; } namespace { diff --git a/docs/test_cases/t00021.md b/docs/test_cases/t00021.md index 32390628..2218a661 100644 --- a/docs/test_cases/t00021.md +++ b/docs/test_cases/t00021.md @@ -35,20 +35,20 @@ public: class Visitor1 : public Visitor { public: - void visit_A(const A &item) const override {} - void visit_B(const B &item) const override {} + 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 {} + 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 {} + void visit_A(const A &item) const override { } + void visit_B(const B &item) const override { } }; class Item { @@ -59,12 +59,12 @@ public: class A : public Item { public: - void accept(const Visitor &visitor) const override {} + void accept(const Visitor &visitor) const override { } }; class B : public Item { public: - void accept(const Visitor &visitor) const override {} + void accept(const Visitor &visitor) const override { } }; } } diff --git a/docs/test_cases/t00022.md b/docs/test_cases/t00022.md index b8b9e1b9..15da0671 100644 --- a/docs/test_cases/t00022.md +++ b/docs/test_cases/t00022.md @@ -38,14 +38,14 @@ protected: class A1 : public A { protected: - void method1() override {} - void method2() override {} + void method1() override { } + void method2() override { } }; class A2 : public A { protected: - void method1() override {} - void method2() override {} + void method1() override { } + void method2() override { } }; } } diff --git a/docs/test_cases/t00023.md b/docs/test_cases/t00023.md index f8bef705..606e7aa5 100644 --- a/docs/test_cases/t00023.md +++ b/docs/test_cases/t00023.md @@ -31,17 +31,17 @@ public: class StrategyA : public Strategy { public: - void algorithm() override {} + void algorithm() override { } }; class StrategyB : public Strategy { public: - void algorithm() override {} + void algorithm() override { } }; class StrategyC : public Strategy { public: - void algorithm() override {} + void algorithm() override { } }; class Context { diff --git a/docs/test_cases/t00024.md b/docs/test_cases/t00024.md index f4266f2e..9d2b1248 100644 --- a/docs/test_cases/t00024.md +++ b/docs/test_cases/t00024.md @@ -33,14 +33,14 @@ public: class Target1 : public Target { public: - void m1() override {} - void m2() override {} + void m1() override { } + void m2() override { } }; class Target2 : public Target { public: - void m1() override {} - void m2() override {} + void m1() override { } + void m2() override { } }; class Proxy : public Target { diff --git a/docs/test_cases/t00025.md b/docs/test_cases/t00025.md index d9cf06dd..de475cf1 100644 --- a/docs/test_cases/t00025.md +++ b/docs/test_cases/t00025.md @@ -25,14 +25,14 @@ namespace t00025 { class Target1 { public: - void m1() {} - void m2() {} + void m1() { } + void m2() { } }; class Target2 { public: - void m1() {} - void m2() {} + void m1() { } + void m2() { } }; template class Proxy { diff --git a/docs/test_cases/t00027.md b/docs/test_cases/t00027.md index b794cfe3..7b9c36a9 100644 --- a/docs/test_cases/t00027.md +++ b/docs/test_cases/t00027.md @@ -36,7 +36,7 @@ class Line : public Shape, public T>... { public: void display() override { - std::apply([](auto &&... x) { (x.display(), ...); }, + std::apply([](auto &&...x) { (x.display(), ...); }, std::forward_as_tuple(T>()...)); } }; @@ -46,7 +46,7 @@ class Text : public Shape, public T>... { public: void display() override { - std::apply([](auto &&... x) { (x.display(), ...); }, + std::apply([](auto &&...x) { (x.display(), ...); }, std::forward_as_tuple(T>()...)); } }; @@ -57,12 +57,12 @@ struct ShapeDecorator { template class Color : public ShapeDecorator { public: - void display() override {} + void display() override { } }; template class Weight : public ShapeDecorator { public: - void display() override {} + void display() override { } }; struct Window { diff --git a/docs/test_cases/t00032.md b/docs/test_cases/t00032.md new file mode 100644 index 00000000..839b10c7 --- /dev/null +++ b/docs/test_cases/t00032.md @@ -0,0 +1,62 @@ +# t00032 - Class template with template base classes test case +## Config +```yaml +compilation_database_dir: .. +output_directory: puml +diagrams: + t00032_class: + type: class + glob: + - ../../tests/t00032/t00032.cc + using_namespace: + - clanguml::t00032 + include: + namespaces: + - clanguml::t00032 + +``` +## Source code +File t00032.cc +```cpp +#include +#include + +namespace clanguml { +namespace t00032 { + +struct Base { +}; + +struct TBase { +}; + +struct A { + void operator()() { } +}; + +struct B { + void operator()() { } +}; + +struct C { + void operator()() { } +}; + +template +struct Overload : public Base, public T, public Ts... { + using Ts::operator()...; + L counter; +}; + +template Overload(Ts...) -> Overload; + +struct R { + Overload overload; +}; + +} // namespace t00032 +} // namespace clanguml + +``` +## Generated UML diagrams +![t00032_class](./t00032_class.png "Class template with template base classes test case") diff --git a/docs/test_cases/t00032_class.png b/docs/test_cases/t00032_class.png new file mode 100644 index 00000000..a8dd3edb Binary files /dev/null and b/docs/test_cases/t00032_class.png differ diff --git a/docs/test_cases/t20001.md b/docs/test_cases/t20001.md index d24a578a..18bf4669 100644 --- a/docs/test_cases/t20001.md +++ b/docs/test_cases/t20001.md @@ -43,7 +43,7 @@ struct C { class A { public: - A() {} + A() { } int add(int x, int y) { return m_c.add(x, y); } @@ -58,7 +58,7 @@ public: return res; } - void log_result(int r) {} + void log_result(int r) { } private: detail::C m_c{}; diff --git a/src/uml/class_diagram_visitor.cc b/src/uml/class_diagram_visitor.cc index 30c9fea8..3282cbea 100644 --- a/src/uml/class_diagram_visitor.cc +++ b/src/uml/class_diagram_visitor.cc @@ -31,6 +31,8 @@ #include #include +#include + namespace clanguml { namespace visitor { namespace class_diagram { @@ -1185,6 +1187,8 @@ class_ tu_visitor::build_template_instantiation( class_ tinst; std::string full_template_name; + std::deque> template_base_params{}; + if (t.primary_template().get(ctx.entity_index).size()) { const auto &primary_template_ref = static_cast( @@ -1201,6 +1205,54 @@ class_ tu_visitor::build_template_instantiation( if (full_template_name.back() == ':') tinst.name = full_template_name + tinst.name; + std::vector> template_parameter_names{}; + if (primary_template_ref.scope_name().has_value()) { + for (const auto &tp : primary_template_ref.scope_name() + .value() + .template_parameters()) { + template_parameter_names.emplace_back( + tp.name(), tp.is_variadic()); + } + } + + // Check if the primary template has any base classes + int base_index = 0; + for (const auto &base : primary_template_ref.bases()) { + if (base.kind() == cppast::cpp_entity_kind::base_class_t) { + const auto &base_class = + static_cast(base); + + const auto base_class_name = + cppast::to_string(base_class.type()); + + LOG_DBG("Found template instantiation base: {}, {}, {}", + cppast::to_string(base.kind()), base_class_name, + base_index); + + // Check if any of the primary template arguments has a + // parameter equal to this type + auto it = std::find_if(template_parameter_names.begin(), + template_parameter_names.end(), + [&base_class_name]( + const auto &p) { return p.first == base_class_name; }); + + if (it != template_parameter_names.end()) { + // Found base class which is a template parameter + LOG_DBG("Found base class which is a template parameter " + "{}, {}, {}", + it->first, it->second, + std::distance(template_parameter_names.begin(), it)); + template_base_params.emplace_back(it->first, it->second, + std::distance(template_parameter_names.begin(), it)); + } + else { + // This is a regular base class - it is handled by + // process_template + } + } + base_index++; + } + if (primary_template_ref.user_data()) { tinst.base_template_usr = static_cast(primary_template_ref.user_data()); @@ -1232,7 +1284,11 @@ class_ tu_visitor::build_template_instantiation( tinst.is_template_instantiation = true; + // Process template argumetns + int arg_index{0}; + bool variadic_params{false}; for (const auto &targ : t.arguments().value()) { + bool add_template_argument_as_base_class{false}; class_template ct; if (targ.type()) { ct.type = cppast::to_string(targ.type().value()); @@ -1250,6 +1306,31 @@ class_ tu_visitor::build_template_instantiation( .as_string(); } + // In case any of the template arguments are base classes, add + // them as parents of the current template instantiation class + if (template_base_params.size() > 0) { + auto [arg_name, is_variadic, index] = template_base_params.front(); + if (variadic_params) + add_template_argument_as_base_class = true; + else { + variadic_params = is_variadic; + if (arg_index == index) { + add_template_argument_as_base_class = true; + template_base_params.pop_front(); + } + } + + if (add_template_argument_as_base_class) { + LOG_DBG("Adding template argument '{}' as base class", ct.type); + + class_parent cp; + cp.access = class_parent::access_t::kPublic; + cp.name = ct.type; + + tinst.bases.emplace_back(std::move(cp)); + } + } + LOG_DBG("Adding template argument '{}'", ct.type); tinst.templates.emplace_back(std::move(ct)); diff --git a/src/uml/sequence_diagram_model.h b/src/uml/sequence_diagram_model.h index 504e3778..395a3714 100644 --- a/src/uml/sequence_diagram_model.h +++ b/src/uml/sequence_diagram_model.h @@ -55,7 +55,7 @@ struct diagram { std::map sequences; - void sort() {} + void sort() { } }; } } diff --git a/tests/catch.h b/tests/catch.h index 9a6a49f9..f531df86 100644 --- a/tests/catch.h +++ b/tests/catch.h @@ -853,8 +853,9 @@ constexpr auto operator"" _catch_sr( INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) #else #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ - INTERNAL_CATCH_EXPAND_VARGS(decltype( \ - get_wrapper())) + INTERNAL_CATCH_EXPAND_VARGS( \ + decltype(get_wrapper())) #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2( \ INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) @@ -1277,8 +1278,8 @@ template struct true_given : std::true_type { }; struct is_callable_tester { template - true_given()(std::declval()...))> static test(int); + true_given()( + std::declval()...))> static test(int); template std::false_type static test(...); }; @@ -1634,8 +1635,8 @@ struct AutoReg : NonCopyable { }; \ static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ using TestInit = typename create()), \ + decltype(get_wrapper()), \ TypeList>::type; \ TestInit t; \ @@ -1851,8 +1852,8 @@ struct AutoReg : NonCopyable { }; \ static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ using TestInit = typename create()), \ + decltype(get_wrapper()), \ TypeList>::type; \ TestInit t; \ @@ -2152,7 +2153,7 @@ inline id performOptionalSelector(id obj, SEL sel) #define CATCH_UNSAFE_UNRETAINED #define CATCH_ARC_STRONG #else -inline void arcSafeRelease(NSObject *) {} +inline void arcSafeRelease(NSObject *) { } inline id performOptionalSelector(id obj, SEL sel) { #ifdef __clang__ @@ -2194,8 +2195,9 @@ template std::string rawMemoryToString(const T &object) template class IsStreamInsertable { template - static auto test(int) -> decltype( - std::declval() << std::declval(), std::true_type()); + static auto test(int) + -> decltype(std::declval() << std::declval(), + std::true_type()); template static auto test(...) -> std::false_type; @@ -2549,7 +2551,7 @@ struct TupleElementPrinter { template struct TupleElementPrinter { - static void print(const Tuple &, std::ostream &) {} + static void print(const Tuple &, std::ostream &) { } }; } @@ -3318,7 +3320,7 @@ public: } template - void captureValues(size_t index, T const &value, Ts const &... values) + void captureValues(size_t index, T const &value, Ts const &...values) { captureValue(index, Catch::Detail::stringify(value)); captureValues(index + 1, values...); @@ -4698,13 +4700,15 @@ struct IGeneratorTracker { namespace Catch { #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -template -[[noreturn]] void throw_exception(Ex const &e) { throw e; } +template [[noreturn]] void throw_exception(Ex const &e) +{ + throw e; +} #else // ^^ Exceptions are enabled // Exceptions are disabled vv [[noreturn]] void throw_exception(std::exception const &e); #endif - [[noreturn]] void throw_logic_error(std::string const &msg); +[[noreturn]] void throw_logic_error(std::string const &msg); [[noreturn]] void throw_domain_error(std::string const &msg); [[noreturn]] void throw_runtime_error(std::string const &msg); @@ -4754,7 +4758,7 @@ namespace Generators { // !TBD move this into its own location? namespace pf { template -std::unique_ptr make_unique(Args &&... args) +std::unique_ptr make_unique(Args &&...args) { return std::unique_ptr(new T(std::forward(args)...)); } @@ -4847,14 +4851,14 @@ template class Generators : public IGenerator { populate(T(std::forward(val))); } template - void populate(U &&valueOrGenerator, Gs &&... moreGenerators) + void populate(U &&valueOrGenerator, Gs &&...moreGenerators) { populate(std::forward(valueOrGenerator)); populate(std::forward(moreGenerators)...); } public: - template Generators(Gs &&... moreGenerators) + template Generators(Gs &&...moreGenerators) { m_generators.reserve(sizeof...(Gs)); populate(std::forward(moreGenerators)...); @@ -4888,7 +4892,7 @@ template struct as { }; template -auto makeGenerators(GeneratorWrapper &&generator, Gs &&... moreGenerators) +auto makeGenerators(GeneratorWrapper &&generator, Gs &&...moreGenerators) -> Generators { return Generators( @@ -4900,13 +4904,13 @@ auto makeGenerators(GeneratorWrapper &&generator) -> Generators return Generators(std::move(generator)); } template -auto makeGenerators(T &&val, Gs &&... moreGenerators) -> Generators +auto makeGenerators(T &&val, Gs &&...moreGenerators) -> Generators { return makeGenerators( value(std::forward(val)), std::forward(moreGenerators)...); } template -auto makeGenerators(as, U &&val, Gs &&... moreGenerators) -> Generators +auto makeGenerators(as, U &&val, Gs &&...moreGenerators) -> Generators { return makeGenerators( value(T(std::forward(val))), std::forward(moreGenerators)...); @@ -5749,7 +5753,7 @@ public: } private: - virtual ~OcMethod() {} + virtual ~OcMethod() { } Class m_cls; SEL m_sel; @@ -6557,7 +6561,7 @@ struct IStreamingReporter { virtual void noMatchingTestCases(std::string const &spec) = 0; - virtual void reportInvalidArguments(std::string const &) {} + virtual void reportInvalidArguments(std::string const &) { } virtual void testRunStarting(TestRunInfo const &testRunInfo) = 0; virtual void testGroupStarting(GroupInfo const &groupInfo) = 0; @@ -6566,10 +6570,10 @@ struct IStreamingReporter { virtual void sectionStarting(SectionInfo const §ionInfo) = 0; #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - virtual void benchmarkPreparing(std::string const &) {} - virtual void benchmarkStarting(BenchmarkInfo const &) {} - virtual void benchmarkEnded(BenchmarkStats<> const &) {} - virtual void benchmarkFailed(std::string const &) {} + virtual void benchmarkPreparing(std::string const &) { } + virtual void benchmarkStarting(BenchmarkInfo const &) { } + virtual void benchmarkEnded(BenchmarkStats<> const &) { } + virtual void benchmarkFailed(std::string const &) { } #endif // CATCH_CONFIG_ENABLE_BENCHMARKING virtual void assertionStarting(AssertionInfo const &assertionInfo) = 0; @@ -6652,9 +6656,9 @@ template struct StreamingReporterBase : IStreamingReporter { ~StreamingReporterBase() override = default; - void noMatchingTestCases(std::string const &) override {} + void noMatchingTestCases(std::string const &) override { } - void reportInvalidArguments(std::string const &) override {} + void reportInvalidArguments(std::string const &) override { } void testRunStarting(TestRunInfo const &_testRunInfo) override { @@ -6718,7 +6722,7 @@ struct CumulativeReporterBase : IStreamingReporter { : value(_value) { } - virtual ~Node() {} + virtual ~Node() { } using ChildNodes = std::vector>; T value; @@ -6794,10 +6798,10 @@ struct CumulativeReporterBase : IStreamingReporter { return {Verbosity::Normal}; } - void testRunStarting(TestRunInfo const &) override {} - void testGroupStarting(GroupInfo const &) override {} + void testRunStarting(TestRunInfo const &) override { } + void testGroupStarting(GroupInfo const &) override { } - void testCaseStarting(TestCaseInfo const &) override {} + void testCaseStarting(TestCaseInfo const &) override { } void sectionStarting(SectionInfo const §ionInfo) override { @@ -6823,7 +6827,7 @@ struct CumulativeReporterBase : IStreamingReporter { m_deepestSection = std::move(node); } - void assertionStarting(AssertionInfo const &) override {} + void assertionStarting(AssertionInfo const &) override { } bool assertionEnded(AssertionStats const &assertionStats) override { @@ -6873,7 +6877,7 @@ struct CumulativeReporterBase : IStreamingReporter { } virtual void testRunEndedCumulative() = 0; - void skipTest(TestCaseInfo const &) override {} + void skipTest(TestCaseInfo const &) override { } IConfigPtr m_config; std::ostream &stream; @@ -7458,7 +7462,7 @@ inline void optimizer_barrier() template inline void deoptimize_value(T &&x) { keep_memory(&x); } template -inline auto invoke_deoptimized(Fn &&fn, Args &&... args) -> +inline auto invoke_deoptimized(Fn &&fn, Args &&...args) -> typename std::enable_if< !std::is_same::value>::type { @@ -7466,7 +7470,7 @@ inline auto invoke_deoptimized(Fn &&fn, Args &&... args) -> } template -inline auto invoke_deoptimized(Fn &&fn, Args &&... args) -> +inline auto invoke_deoptimized(Fn &&fn, Args &&...args) -> typename std::enable_if< std::is_same::value>::type { @@ -7498,14 +7502,14 @@ template using CompleteType_t = typename CompleteType::type; template struct CompleteInvoker { template - static Result invoke(Fun &&fun, Args &&... args) + static Result invoke(Fun &&fun, Args &&...args) { return std::forward(fun)(std::forward(args)...); } }; template <> struct CompleteInvoker { template - static CompleteType_t invoke(Fun &&fun, Args &&... args) + static CompleteType_t invoke(Fun &&fun, Args &&...args) { std::forward(fun)(std::forward(args)...); return {}; @@ -7516,7 +7520,7 @@ template using ResultOf_t = typename std::result_of::type; // invoke and not return void :( template CompleteType_t> complete_invoke( - Fun &&fun, Args &&... args) + Fun &&fun, Args &&...args) { return CompleteInvoker>::invoke( std::forward(fun), std::forward(args)...); @@ -7683,7 +7687,7 @@ private: }; struct do_nothing { - void operator()() const {} + void operator()() const { } }; template @@ -7802,7 +7806,7 @@ namespace Catch { namespace Benchmark { namespace Detail { template -TimingOf measure(Fun &&fun, Args &&... args) +TimingOf measure(Fun &&fun, Args &&...args) { auto start = Clock::now(); auto &&r = Detail::complete_invoke(fun, std::forward(args)...); @@ -8153,8 +8157,7 @@ EnvironmentEstimate> estimate_clock_cost( volatile auto ignored = Clock::now(); (void)ignored; } - }) - .elapsed; + }).elapsed; }; time_clock(1); int iters = clock_cost_estimation_iterations; @@ -8442,7 +8445,7 @@ template struct ObjectStorage { ~ObjectStorage() { destruct_on_exit(); } - template void construct(Args &&... args) + template void construct(Args &&...args) { new (&data) T(std::forward(args)...); } @@ -10082,7 +10085,7 @@ public: return m_tokenBuffer.front(); } - auto operator-> () const -> Token const * + auto operator->() const -> Token const * { assert(!m_tokenBuffer.empty()); return &m_tokenBuffer.front(); @@ -11380,7 +11383,7 @@ struct IColourImpl { }; struct NoColourImpl : IColourImpl { - void use(Colour::Code) override {} + void use(Colour::Code) override { } static IColourImpl *instance() { @@ -11868,7 +11871,8 @@ void formatReconstructedExpression(std::ostream &os, std::string const &lhs, namespace Catch { #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && \ !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) -[[noreturn]] void throw_exception(std::exception const &e) { +[[noreturn]] void throw_exception(std::exception const &e) +{ Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n" << "The message was: " << e.what() << '\n'; @@ -11881,8 +11885,10 @@ namespace Catch { throw_exception(std::logic_error(msg)); } -[[noreturn]] void throw_domain_error( - std::string const &msg) { throw_exception(std::domain_error(msg)); } +[[noreturn]] void throw_domain_error(std::string const &msg) +{ + throw_exception(std::domain_error(msg)); +} [[noreturn]] void throw_runtime_error(std::string const &msg) { @@ -11925,7 +11931,7 @@ std::vector parseEnums(StringRef enums); namespace Catch { -IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {} +IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() { } namespace Detail { @@ -11954,7 +11960,7 @@ std::vector parseEnums(StringRef enums) return parsed; } -EnumInfo::~EnumInfo() {} +EnumInfo::~EnumInfo() { } StringRef EnumInfo::lookup(int value) const { @@ -12033,7 +12039,7 @@ private: namespace Catch { -ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {} +ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { } void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator *translator) @@ -12278,7 +12284,7 @@ char FatalConditionHandler::altStackMem[sigStackSize] = {}; #else namespace Catch { -void FatalConditionHandler::reset() {} +void FatalConditionHandler::reset() { } } #endif // signals/SEH handling @@ -12294,13 +12300,13 @@ void FatalConditionHandler::reset() {} namespace Catch { -IGeneratorTracker::~IGeneratorTracker() {} +IGeneratorTracker::~IGeneratorTracker() { } const char *GeneratorException::what() const noexcept { return m_msg; } namespace Generators { -GeneratorUntypedBase::~GeneratorUntypedBase() {} +GeneratorUntypedBase::~GeneratorUntypedBase() { } auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker & @@ -12496,7 +12502,7 @@ TestRunStats::TestRunStats( TestRunStats::~TestRunStats() = default; -void IStreamingReporter::fatalErrorEncountered(StringRef) {} +void IStreamingReporter::fatalErrorEncountered(StringRef) { } bool IStreamingReporter::isMulti() const { return false; } IReporterFactory::~IReporterFactory() = default; @@ -12539,7 +12545,7 @@ LeakDetector::LeakDetector() #else -Catch::LeakDetector::LeakDetector() {} +Catch::LeakDetector::LeakDetector() { } #endif @@ -14145,7 +14151,7 @@ struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { m_generator = std::move(generator); } }; -GeneratorTracker::~GeneratorTracker() {} +GeneratorTracker::~GeneratorTracker() { } } RunContext::RunContext( @@ -15056,8 +15062,8 @@ int Session::runInternal() // the return value to 255 prevents false negative when some multiple // of 256 tests has failed return (std::min)(MaxExitCode, - (std::max)( - totals.error, static_cast(totals.assertions.failed))); + (std::max)(totals.error, + static_cast(totals.assertions.failed))); } #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) catch (std::exception &ex) @@ -15086,7 +15092,7 @@ static auto getSingletons() -> std::vector *& } } -ISingleton::~ISingleton() {} +ISingleton::~ISingleton() { } void addSingleton(ISingleton *singleton) { @@ -15519,7 +15525,7 @@ RegistrarForTagAliases::RegistrarForTagAliases( namespace Catch { -TagAliasRegistry::~TagAliasRegistry() {} +TagAliasRegistry::~TagAliasRegistry() { } TagAlias const *TagAliasRegistry::find(std::string const &alias) const { @@ -15562,7 +15568,7 @@ void TagAliasRegistry::add(std::string const &alias, std::string const &tag, << "\tRedefined at: " << lineInfo); } -ITagAliasRegistry::~ITagAliasRegistry() {} +ITagAliasRegistry::~ITagAliasRegistry() { } ITagAliasRegistry const &ITagAliasRegistry::get() { @@ -17428,7 +17434,7 @@ std::set TestEventListenerBase::getSupportedVerbosities() return {Verbosity::Quiet, Verbosity::Normal, Verbosity::High}; } -void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} +void TestEventListenerBase::assertionStarting(AssertionInfo const &) { } bool TestEventListenerBase::assertionEnded(AssertionStats const &) { @@ -17702,7 +17708,7 @@ void CompactReporter::noMatchingTestCases(std::string const &spec) stream << "No test cases matched '" << spec << '\'' << std::endl; } -void CompactReporter::assertionStarting(AssertionInfo const &) {} +void CompactReporter::assertionStarting(AssertionInfo const &) { } bool CompactReporter::assertionEnded(AssertionStats const &_assertionStats) { @@ -17739,7 +17745,7 @@ void CompactReporter::testRunEnded(TestRunStats const &_testRunStats) StreamingReporterBase::testRunEnded(_testRunStats); } -CompactReporter::~CompactReporter() {} +CompactReporter::~CompactReporter() { } CATCH_REGISTER_REPORTER("compact", CompactReporter) @@ -18156,7 +18162,7 @@ void ConsoleReporter::reportInvalidArguments(std::string const &arg) stream << "Invalid Filter: " << arg << std::endl; } -void ConsoleReporter::assertionStarting(AssertionInfo const &) {} +void ConsoleReporter::assertionStarting(AssertionInfo const &) { } bool ConsoleReporter::assertionEnded(AssertionStats const &_assertionStats) { @@ -18571,7 +18577,7 @@ JunitReporter::JunitReporter(ReporterConfig const &_config) m_reporterPrefs.shouldReportAllAssertions = true; } -JunitReporter::~JunitReporter() {} +JunitReporter::~JunitReporter() { } std::string JunitReporter::getDescription() { @@ -18579,7 +18585,7 @@ std::string JunitReporter::getDescription() "junitreport target"; } -void JunitReporter::noMatchingTestCases(std::string const & /*spec*/) {} +void JunitReporter::noMatchingTestCases(std::string const & /*spec*/) { } void JunitReporter::testRunStarting(TestRunInfo const &runInfo) { @@ -19063,7 +19069,7 @@ void XmlReporter::sectionStarting(SectionInfo const §ionInfo) } } -void XmlReporter::assertionStarting(AssertionInfo const &) {} +void XmlReporter::assertionStarting(AssertionInfo const &) { } bool XmlReporter::assertionEnded(AssertionStats const &assertionStats) { diff --git a/tests/t00002/t00002.cc b/tests/t00002/t00002.cc index 6a8b92dd..6eb8a5de 100644 --- a/tests/t00002/t00002.cc +++ b/tests/t00002/t00002.cc @@ -11,12 +11,12 @@ public: class B : public A { public: - virtual void foo_a() override {} + virtual void foo_a() override { } }; class C : public A { public: - virtual void foo_c() override {} + virtual void foo_c() override { } }; class D : public B, public C { diff --git a/tests/t00003/t00003.cc b/tests/t00003/t00003.cc index b63fd7bb..1820dc1c 100644 --- a/tests/t00003/t00003.cc +++ b/tests/t00003/t00003.cc @@ -15,9 +15,9 @@ public: A(const A &) = default; virtual ~A() = default; - void basic_method() {} + void basic_method() { } static int static_method() { return 0; } - void const_method() const {} + void const_method() const { } auto auto_method() { return 1; } auto double_int(const int i) { return 2 * i; } @@ -37,7 +37,7 @@ public: static const auto auto_member{10UL}; protected: - void protected_method() {} + void protected_method() { } int protected_member; @@ -46,7 +46,7 @@ protected: }; private: - void private_method() {} + void private_method() { } int private_member; int a, b, c; diff --git a/tests/t00004/t00004.cc b/tests/t00004/t00004.cc index 22be0004..3216ba7a 100644 --- a/tests/t00004/t00004.cc +++ b/tests/t00004/t00004.cc @@ -3,7 +3,7 @@ namespace t00004 { class A { public: - void foo() const {} + void foo() const { } class AA { public: @@ -13,7 +13,7 @@ public: }; }; - void foo2() const {} + void foo2() const { } }; } } diff --git a/tests/t00011/t00011.cc b/tests/t00011/t00011.cc index 20f9de5a..ea9bcb2d 100644 --- a/tests/t00011/t00011.cc +++ b/tests/t00011/t00011.cc @@ -14,7 +14,7 @@ template class D { class A { private: - void foo() {} + void foo() { } friend class B; friend class external::C; // TODO diff --git a/tests/t00013/t00013.cc b/tests/t00013/t00013.cc index dc8ca465..d96d0e84 100644 --- a/tests/t00013/t00013.cc +++ b/tests/t00013/t00013.cc @@ -27,7 +27,7 @@ class R; struct D { int d; - void print(R *r) {} + void print(R *r) { } }; template struct E { diff --git a/tests/t00015/t00015.cc b/tests/t00015/t00015.cc index a7762cac..736eb9ff 100644 --- a/tests/t00015/t00015.cc +++ b/tests/t00015/t00015.cc @@ -8,7 +8,8 @@ class A { } namespace ns2_v0_9_0 { -class [[deprecated]] A {}; +class [[deprecated]] A { +}; } namespace { diff --git a/tests/t00021/t00021.cc b/tests/t00021/t00021.cc index c3aaa1c4..0a338a12 100644 --- a/tests/t00021/t00021.cc +++ b/tests/t00021/t00021.cc @@ -15,20 +15,20 @@ public: class Visitor1 : public Visitor { public: - void visit_A(const A &item) const override {} - void visit_B(const B &item) const override {} + 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 {} + 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 {} + void visit_A(const A &item) const override { } + void visit_B(const B &item) const override { } }; class Item { @@ -39,12 +39,12 @@ public: class A : public Item { public: - void accept(const Visitor &visitor) const override {} + void accept(const Visitor &visitor) const override { } }; class B : public Item { public: - void accept(const Visitor &visitor) const override {} + void accept(const Visitor &visitor) const override { } }; } } diff --git a/tests/t00022/t00022.cc b/tests/t00022/t00022.cc index 2e26ace2..d226c4db 100644 --- a/tests/t00022/t00022.cc +++ b/tests/t00022/t00022.cc @@ -18,14 +18,14 @@ protected: class A1 : public A { protected: - void method1() override {} - void method2() override {} + void method1() override { } + void method2() override { } }; class A2 : public A { protected: - void method1() override {} - void method2() override {} + void method1() override { } + void method2() override { } }; } } diff --git a/tests/t00023/t00023.cc b/tests/t00023/t00023.cc index ac990ba5..3d3cdd94 100644 --- a/tests/t00023/t00023.cc +++ b/tests/t00023/t00023.cc @@ -11,17 +11,17 @@ public: class StrategyA : public Strategy { public: - void algorithm() override {} + void algorithm() override { } }; class StrategyB : public Strategy { public: - void algorithm() override {} + void algorithm() override { } }; class StrategyC : public Strategy { public: - void algorithm() override {} + void algorithm() override { } }; class Context { diff --git a/tests/t00024/t00024.cc b/tests/t00024/t00024.cc index b22bb5c9..d082aee8 100644 --- a/tests/t00024/t00024.cc +++ b/tests/t00024/t00024.cc @@ -13,14 +13,14 @@ public: class Target1 : public Target { public: - void m1() override {} - void m2() override {} + void m1() override { } + void m2() override { } }; class Target2 : public Target { public: - void m1() override {} - void m2() override {} + void m1() override { } + void m2() override { } }; class Proxy : public Target { diff --git a/tests/t00025/t00025.cc b/tests/t00025/t00025.cc index c31ee5a8..091b8185 100644 --- a/tests/t00025/t00025.cc +++ b/tests/t00025/t00025.cc @@ -5,14 +5,14 @@ namespace t00025 { class Target1 { public: - void m1() {} - void m2() {} + void m1() { } + void m2() { } }; class Target2 { public: - void m1() {} - void m2() {} + void m1() { } + void m2() { } }; template class Proxy { diff --git a/tests/t00027/t00027.cc b/tests/t00027/t00027.cc index 379a100d..7f0ea89c 100644 --- a/tests/t00027/t00027.cc +++ b/tests/t00027/t00027.cc @@ -16,7 +16,7 @@ class Line : public Shape, public T>... { public: void display() override { - std::apply([](auto &&... x) { (x.display(), ...); }, + std::apply([](auto &&...x) { (x.display(), ...); }, std::forward_as_tuple(T>()...)); } }; @@ -26,7 +26,7 @@ class Text : public Shape, public T>... { public: void display() override { - std::apply([](auto &&... x) { (x.display(), ...); }, + std::apply([](auto &&...x) { (x.display(), ...); }, std::forward_as_tuple(T>()...)); } }; @@ -37,12 +37,12 @@ struct ShapeDecorator { template class Color : public ShapeDecorator { public: - void display() override {} + void display() override { } }; template class Weight : public ShapeDecorator { public: - void display() override {} + void display() override { } }; struct Window { diff --git a/tests/t00032/.clang-uml b/tests/t00032/.clang-uml new file mode 100644 index 00000000..58018aa0 --- /dev/null +++ b/tests/t00032/.clang-uml @@ -0,0 +1,12 @@ +compilation_database_dir: .. +output_directory: puml +diagrams: + t00032_class: + type: class + glob: + - ../../tests/t00032/t00032.cc + using_namespace: + - clanguml::t00032 + include: + namespaces: + - clanguml::t00032 diff --git a/tests/t00032/t00032.cc b/tests/t00032/t00032.cc new file mode 100644 index 00000000..c080048e --- /dev/null +++ b/tests/t00032/t00032.cc @@ -0,0 +1,38 @@ +#include +#include + +namespace clanguml { +namespace t00032 { + +struct Base { +}; + +struct TBase { +}; + +struct A { + void operator()() { } +}; + +struct B { + void operator()() { } +}; + +struct C { + void operator()() { } +}; + +template +struct Overload : public Base, public T, public Ts... { + using Ts::operator()...; + L counter; +}; + +template Overload(Ts...) -> Overload; + +struct R { + Overload overload; +}; + +} // namespace t00032 +} // namespace clanguml diff --git a/tests/t00032/test_case.h b/tests/t00032/test_case.h new file mode 100644 index 00000000..d8effc23 --- /dev/null +++ b/tests/t00032/test_case.h @@ -0,0 +1,63 @@ +/** + * tests/t00032/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("t00032", "[test-case][class]") +{ + auto [config, db] = load_config("t00032"); + + auto diagram = config.diagrams["t00032_class"]; + + REQUIRE(diagram->name == "t00032_class"); + + REQUIRE(diagram->include.namespaces.size() == 1); + REQUIRE_THAT(diagram->include.namespaces, + VectorContains(std::string{"clanguml::t00032"})); + + REQUIRE(diagram->exclude.namespaces.size() == 0); + + REQUIRE(diagram->should_include("clanguml::t00032::A")); + + auto model = generate_class_diagram(db, diagram); + + REQUIRE(model.name == "t00032_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("Base"))); + REQUIRE_THAT(puml, IsClass(_A("TBase"))); + REQUIRE_THAT(puml, IsClass(_A("A"))); + REQUIRE_THAT(puml, IsClass(_A("B"))); + REQUIRE_THAT(puml, IsClass(_A("C"))); + REQUIRE_THAT(puml, IsClass(_A("R"))); + + REQUIRE_THAT(puml, IsClassTemplate("Overload", "T,L,Ts...")); + + REQUIRE_THAT(puml, IsBaseClass(_A("Base"), _A("Overload"))); + REQUIRE_THAT( + puml, IsBaseClass(_A("TBase"), _A("Overload"))); + REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("Overload"))); + REQUIRE_THAT(puml, IsBaseClass(_A("B"), _A("Overload"))); + REQUIRE_THAT(puml, IsBaseClass(_A("C"), _A("Overload"))); + + save_puml( + "./" + config.output_directory + "/" + diagram->name + ".puml", puml); +} diff --git a/tests/t20001/t20001.cc b/tests/t20001/t20001.cc index 2523199b..18878c11 100644 --- a/tests/t20001/t20001.cc +++ b/tests/t20001/t20001.cc @@ -13,7 +13,7 @@ struct C { class A { public: - A() {} + A() { } int add(int x, int y) { return m_c.add(x, y); } @@ -28,7 +28,7 @@ public: return res; } - void log_result(int r) {} + void log_result(int r) { } private: detail::C m_c{}; diff --git a/tests/test_cases.cc b/tests/test_cases.cc index a3f2fe62..d410f137 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -135,6 +135,7 @@ using namespace clanguml::test::matchers; #include "t00029/test_case.h" #include "t00030/test_case.h" #include "t00031/test_case.h" +#include "t00032/test_case.h" // // Sequence diagram tests diff --git a/tests/test_cases.yaml b/tests/test_cases.yaml index a34689f6..160c327b 100644 --- a/tests/test_cases.yaml +++ b/tests/test_cases.yaml @@ -90,6 +90,9 @@ test_cases: - name: t00031 title: PlantUML style decorator test case description: + - name: t00032 + title: Class template with template base classes test case + description: Sequence diagrams: - name: t20001 title: Basic sequence diagram