From 4e9fcf61c3251129f7d36d00a2de88af6cedb465 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 30 Aug 2020 13:19:23 +0100 Subject: Support model parts that are abstract classes with functions --- Jamroot.jam | 1 + slicer/json/serializer.cpp | 1 - slicer/slicer/common.ice | 4 +++ slicer/slicer/modelPartsTypes.impl.h | 7 ++++- slicer/slicer/slicer.cpp | 7 +++++ slicer/test/Jamfile.jam | 1 + slicer/test/functions.ice | 19 +++++++++++++ slicer/test/functionsImpl.cpp | 6 ++++ slicer/test/functionsImpl.h | 13 +++++++++ slicer/test/serializers.cpp | 54 ++++++++++++++++++++++++++++++++++++ slicer/tool/parser.cpp | 7 +++++ 11 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 slicer/test/functions.ice create mode 100644 slicer/test/functionsImpl.cpp create mode 100644 slicer/test/functionsImpl.h diff --git a/Jamroot.jam b/Jamroot.jam index b350916..b878832 100644 --- a/Jamroot.jam +++ b/Jamroot.jam @@ -38,6 +38,7 @@ project tidy:test/bin/tidy/debug/checker-none/cxxstd-17-iso/classtype.h tidy:test/bin/tidy/debug/checker-none/cxxstd-17-iso/collections.h tidy:test/bin/tidy/debug/checker-none/cxxstd-17-iso/enums.h + tidy:test/bin/tidy/debug/checker-none/cxxstd-17-iso/functions.h tidy:test/bin/tidy/debug/checker-none/cxxstd-17-iso/inheritance.h tidy:test/bin/tidy/debug/checker-none/cxxstd-17-iso/interfaces.h tidy:test/bin/tidy/debug/checker-none/cxxstd-17-iso/json.h diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index b94ae2e..0fa736c 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -181,7 +181,6 @@ namespace Slicer { for (const auto & element : o) { auto emp = modelPart->GetChild(element.first); if (emp) { - emp->Create(); std::visit(DocumentTreeIterate(emp), element.second); emp->Complete(); } diff --git a/slicer/slicer/common.ice b/slicer/slicer/common.ice index 9198aaa..60a4f92 100644 --- a/slicer/slicer/common.ice +++ b/slicer/slicer/common.ice @@ -42,6 +42,10 @@ module Slicer { exception InvalidStreamOperation extends SerializerError { string method; }; + ["cpp:ice_print"] + exception AbstractClassException extends DeserializerError { + string type; + }; }; #endif diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index b821d06..7efc02d 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -544,7 +544,12 @@ namespace Slicer { ModelPartForClass::Create() { BOOST_ASSERT(this->Model); - *this->Model = std::make_shared(); + if constexpr (std::is_abstract_v) { + throw AbstractClassException(ModelPartForComplexBase::demangle(typeid(T).name())); + } + else { + *this->Model = std::make_shared(); + } } template diff --git a/slicer/slicer/slicer.cpp b/slicer/slicer/slicer.cpp index af55977..f6d6fa6 100644 --- a/slicer/slicer/slicer.cpp +++ b/slicer/slicer/slicer.cpp @@ -104,4 +104,11 @@ namespace Slicer { { InvalidStreamOperationMsg::write(s, method); } + + AdHocFormatter(AbstractClassExceptionMsg, "%? is an abstract class"); + void + AbstractClassException::ice_print(std::ostream & s) const + { + AbstractClassExceptionMsg::write(s, type); + } } diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam index d0eecdb..6801a77 100644 --- a/slicer/test/Jamfile.jam +++ b/slicer/test/Jamfile.jam @@ -20,6 +20,7 @@ lib icetypes : lib types : [ glob *.ice ] conversions.cpp + functionsImpl.cpp : gcc:../tool//slicer/gcc clang:../tool//slicer/clang diff --git a/slicer/test/functions.ice b/slicer/test/functions.ice new file mode 100644 index 0000000..baedc6d --- /dev/null +++ b/slicer/test/functions.ice @@ -0,0 +1,19 @@ +#ifndef SLICER_TEST_FUNCTIONS +#define SLICER_TEST_FUNCTIONS + +["slicer:include:functionsImpl.h"] +module Functions { + local class Funcs { + void func(); + }; + ["slicer:implementation:Functions.FuncsSubImpl"] + local class FuncsSub extends Funcs { + string testVal; + }; + local struct SFuncs { + Funcs obj; + }; +}; + +#endif + diff --git a/slicer/test/functionsImpl.cpp b/slicer/test/functionsImpl.cpp new file mode 100644 index 0000000..f57211d --- /dev/null +++ b/slicer/test/functionsImpl.cpp @@ -0,0 +1,6 @@ +#include "functionsImpl.h" + +void +Functions::FuncsSubImpl::func() +{ +} diff --git a/slicer/test/functionsImpl.h b/slicer/test/functionsImpl.h new file mode 100644 index 0000000..e46f28e --- /dev/null +++ b/slicer/test/functionsImpl.h @@ -0,0 +1,13 @@ +#ifndef SLICER_TEST_FUNCITONSIMPL_H +#define SLICER_TEST_FUNCITONSIMPL_H + +#include + +namespace Functions { + class FuncsSubImpl : public FuncsSub { + public: + void func() override; + }; +} + +#endif diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index d63651d..6b4393b 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -660,6 +661,59 @@ BOOST_AUTO_TEST_CASE(conversion) BOOST_REQUIRE_EQUAL("2016-06-30 12:34:56", std::get(std::get(v)["conv"])); } +BOOST_AUTO_TEST_CASE(DeserializeJsonAbstractEmpty) +{ + auto in = json::parseValue(R"J({ "obj": null })J"); + auto obj = Slicer::DeserializeAny(in); + BOOST_REQUIRE(!obj.obj); +} + +BOOST_AUTO_TEST_CASE(DeserializeJsonAbstractDefault) +{ + auto in = json::parseValue(R"J({ "obj": {} })J"); + BOOST_CHECK_THROW((Slicer::DeserializeAny(in)), + Slicer::AbstractClassException); +} + +BOOST_AUTO_TEST_CASE(DeserializeJsonAbstractImpl) +{ + auto in = json::parseValue(R"J({ "obj": {"slicer-typeid": "::Functions::FuncsSub", "testVal": "value"} })J"); + auto obj = Slicer::DeserializeAny(in); + BOOST_REQUIRE(obj.obj); + auto impl = std::dynamic_pointer_cast(obj.obj); + BOOST_REQUIRE(impl); + BOOST_CHECK_EQUAL("value", impl->testVal); +} + +BOOST_AUTO_TEST_CASE(DeserializeXmlAbstractEmpty) +{ + std::stringstream in(""); + auto obj = Slicer::DeserializeAny(in); + BOOST_REQUIRE(!obj.obj); +} + +BOOST_AUTO_TEST_CASE(DeserializeXmlAbstractDefault) +{ + std::stringstream in(""); + BOOST_CHECK_THROW((Slicer::DeserializeAny(in)), + Slicer::AbstractClassException); +} + +BOOST_AUTO_TEST_CASE(DeserializeXmlAbstractImpl) +{ + std::stringstream in(R"X( + + + value + + )X"); + auto obj = Slicer::DeserializeAny(in); + BOOST_REQUIRE(obj.obj); + auto impl = std::dynamic_pointer_cast(obj.obj); + BOOST_REQUIRE(impl); + BOOST_CHECK_EQUAL("value", impl->testVal); +} + BOOST_AUTO_TEST_CASE(customerModelPartCounters) { BOOST_REQUIRE_EQUAL(21, TestModule::completions); diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index 33f003b..5a1d626 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -309,6 +309,13 @@ namespace Slicer { copyMetadata(c->getMetaData()); fprintbf(cpp, ";\n\n"); + if (auto implementation = metaDataValue("slicer:implementation:", c->getMetaData())) { + fprintbf(cpp, "\ttemplate<> void ModelPartForClass<%s>::Create() {\n", c->scoped()); + fprintf(cpp, "\t\tBOOST_ASSERT(this->Model);\n"); + fprintbf(cpp, "\t\t*this->Model = std::make_shared<%s>();\n}\n\n", + boost::algorithm::replace_all_copy(*implementation, ".", "::")); + } + if (auto cmp = metaDataValue("slicer:custommodelpart:", c->getMetaData())) { fprintbf(cpp, "CUSTOMMODELPARTFOR(%s, %s< %s >, %s);\n\n", Slice::typeToString(decl), getBasicModelPart(decl), c->scoped(), boost::algorithm::replace_all_copy(*cmp, ".", "::")); -- cgit v1.2.3