summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamroot.jam1
-rw-r--r--slicer/json/serializer.cpp1
-rw-r--r--slicer/slicer/common.ice4
-rw-r--r--slicer/slicer/modelPartsTypes.impl.h7
-rw-r--r--slicer/slicer/slicer.cpp7
-rw-r--r--slicer/test/Jamfile.jam1
-rw-r--r--slicer/test/functions.ice19
-rw-r--r--slicer/test/functionsImpl.cpp6
-rw-r--r--slicer/test/functionsImpl.h13
-rw-r--r--slicer/test/serializers.cpp54
-rw-r--r--slicer/tool/parser.cpp7
11 files changed, 118 insertions, 2 deletions
diff --git a/Jamroot.jam b/Jamroot.jam
index b350916..b878832 100644
--- a/Jamroot.jam
+++ b/Jamroot.jam
@@ -38,6 +38,7 @@ project
<toolset>tidy:<exclude>test/bin/tidy/debug/checker-none/cxxstd-17-iso/classtype.h
<toolset>tidy:<exclude>test/bin/tidy/debug/checker-none/cxxstd-17-iso/collections.h
<toolset>tidy:<exclude>test/bin/tidy/debug/checker-none/cxxstd-17-iso/enums.h
+ <toolset>tidy:<exclude>test/bin/tidy/debug/checker-none/cxxstd-17-iso/functions.h
<toolset>tidy:<exclude>test/bin/tidy/debug/checker-none/cxxstd-17-iso/inheritance.h
<toolset>tidy:<exclude>test/bin/tidy/debug/checker-none/cxxstd-17-iso/interfaces.h
<toolset>tidy:<exclude>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<T>::Create()
{
BOOST_ASSERT(this->Model);
- *this->Model = std::make_shared<T>();
+ if constexpr (std::is_abstract_v<T>) {
+ throw AbstractClassException(ModelPartForComplexBase::demangle(typeid(T).name()));
+ }
+ else {
+ *this->Model = std::make_shared<T>();
+ }
}
template<typename T>
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
:
<toolset>gcc:<dependency>../tool//slicer/<toolset>gcc
<toolset>clang:<dependency>../tool//slicer/<toolset>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 <functions.h>
+
+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 <definedDirs.h>
#include <fstream>
#include <functional>
+#include <functionsImpl.h>
#include <json.h>
#include <json/serializer.h>
#include <libxml2/libxml/parser.h>
@@ -660,6 +661,59 @@ BOOST_AUTO_TEST_CASE(conversion)
BOOST_REQUIRE_EQUAL("2016-06-30 12:34:56", std::get<json::String>(std::get<json::Object>(v)["conv"]));
}
+BOOST_AUTO_TEST_CASE(DeserializeJsonAbstractEmpty)
+{
+ auto in = json::parseValue(R"J({ "obj": null })J");
+ auto obj = Slicer::DeserializeAny<Slicer::JsonValueDeserializer, Functions::SFuncs>(in);
+ BOOST_REQUIRE(!obj.obj);
+}
+
+BOOST_AUTO_TEST_CASE(DeserializeJsonAbstractDefault)
+{
+ auto in = json::parseValue(R"J({ "obj": {} })J");
+ BOOST_CHECK_THROW((Slicer::DeserializeAny<Slicer::JsonValueDeserializer, Functions::SFuncs>(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<Slicer::JsonValueDeserializer, Functions::SFuncs>(in);
+ BOOST_REQUIRE(obj.obj);
+ auto impl = std::dynamic_pointer_cast<Functions::FuncsSub>(obj.obj);
+ BOOST_REQUIRE(impl);
+ BOOST_CHECK_EQUAL("value", impl->testVal);
+}
+
+BOOST_AUTO_TEST_CASE(DeserializeXmlAbstractEmpty)
+{
+ std::stringstream in("<SFuncs/>");
+ auto obj = Slicer::DeserializeAny<Slicer::XmlStreamDeserializer, Functions::SFuncs>(in);
+ BOOST_REQUIRE(!obj.obj);
+}
+
+BOOST_AUTO_TEST_CASE(DeserializeXmlAbstractDefault)
+{
+ std::stringstream in("<SFuncs><obj/></SFuncs>");
+ BOOST_CHECK_THROW((Slicer::DeserializeAny<Slicer::XmlStreamDeserializer, Functions::SFuncs>(in)),
+ Slicer::AbstractClassException);
+}
+
+BOOST_AUTO_TEST_CASE(DeserializeXmlAbstractImpl)
+{
+ std::stringstream in(R"X(
+ <SFuncs>
+ <obj slicer-typeid="::Functions::FuncsSub">
+ <testVal>value</testVal>
+ </obj>
+ </SFuncs>)X");
+ auto obj = Slicer::DeserializeAny<Slicer::XmlStreamDeserializer, Functions::SFuncs>(in);
+ BOOST_REQUIRE(obj.obj);
+ auto impl = std::dynamic_pointer_cast<Functions::FuncsSub>(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, ".", "::"));