summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2014-07-29 17:22:45 -0700
committerMark Spruiell <mes@zeroc.com>2014-07-29 17:22:45 -0700
commit1ae29aa042323c6ea5b776eda3d14003e17bdbb1 (patch)
tree64d76ec048ece9271753d026f1607f867ffdcab6 /cpp/src
parentadding -n option for PHP tests to eliminate warnings (diff)
downloadice-1ae29aa042323c6ea5b776eda3d14003e17bdbb1.tar.bz2
ice-1ae29aa042323c6ea5b776eda3d14003e17bdbb1.tar.xz
ice-1ae29aa042323c6ea5b776eda3d14003e17bdbb1.zip
ICE-2600 - serialization support for C# exceptions
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Slice/CsUtil.cpp271
-rw-r--r--cpp/src/slice2cs/Gen.cpp87
2 files changed, 330 insertions, 28 deletions
diff --git a/cpp/src/Slice/CsUtil.cpp b/cpp/src/Slice/CsUtil.cpp
index 6c064e5a6c0..3a330819f57 100644
--- a/cpp/src/Slice/CsUtil.cpp
+++ b/cpp/src/Slice/CsUtil.cpp
@@ -404,6 +404,34 @@ Slice::CsGenerator::isValueType(const TypePtr& type)
return false;
}
+bool
+Slice::CsGenerator::isSerializable(const TypePtr& type)
+{
+ //
+ // A proxy cannot be serialized because a communicator is required during deserialization.
+ //
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ if((builtin && builtin->kind() == Builtin::KindObjectProxy) || proxy)
+ {
+ return false;
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ return isSerializable(seq->type());
+ }
+
+ DictionaryPtr d = DictionaryPtr::dynamicCast(type);
+ if(d)
+ {
+ return isSerializable(d->keyType()) && isSerializable(d->valueType());
+ }
+
+ return true;
+}
+
void
Slice::CsGenerator::writeMarshalUnmarshalCode(Output &out,
const TypePtr& type,
@@ -2063,6 +2091,249 @@ Slice::CsGenerator::writeOptionalSequenceMarshalUnmarshalCode(Output& out,
}
}
+void
+Slice::CsGenerator::writeSerializeDeserializeCode(Output &out,
+ const TypePtr& type,
+ const string& param,
+ bool optional,
+ int tag,
+ bool serialize)
+{
+ if(!isSerializable(type))
+ {
+ return;
+ }
+
+ if(optional)
+ {
+ const string typeName = typeToString(type, true);
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ", typeof(" << typeName << "));";
+ }
+ else
+ {
+ out << nl << param << " = (" << typeName << ")info__.GetValue(\"" << param << "\", typeof(" << typeName
+ << "));";
+ }
+ return;
+ }
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Builtin::KindByte:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetByte(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindBool:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetBoolean(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindShort:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetInt16(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindInt:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetInt32(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindLong:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetInt64(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindFloat:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetSingle(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindDouble:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetDouble(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindString:
+ {
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << " == null ? \"\" : " << param
+ << ");";
+ }
+ else
+ {
+ out << nl << param << " = " << "info__.GetString(\"" << param << "\");";
+ }
+ break;
+ }
+ case Builtin::KindObject:
+ case Builtin::KindLocalObject:
+ {
+ const string typeName = typeToString(type, false);
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ", typeof(" << typeName << "));";
+ }
+ else
+ {
+ out << nl << param << " = (" << typeName << ")info__.GetValue(\"" << param << "\", typeof("
+ << typeName << "));";
+ }
+ break;
+ }
+ case Builtin::KindObjectProxy:
+ {
+ //
+ // Proxies cannot be serialized.
+ //
+ break;
+ }
+ }
+ return;
+ }
+
+ ProxyPtr prx = ProxyPtr::dynamicCast(type);
+ if(prx)
+ {
+ //
+ // Proxies cannot be serialized.
+ //
+ return;
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ const string typeName = typeToString(type, false);
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ", typeof(" << typeName << "));";
+ }
+ else
+ {
+ out << nl << param << " = (" << typeName << ")info__.GetValue(\"" << param << "\", typeof(" << typeName
+ << "));";
+ }
+ return;
+ }
+
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ const string typeName = typeToString(type, false);
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ", typeof(" << typeName << "));";
+ }
+ else
+ {
+ out << nl << param << " = (" << typeName << ")info__.GetValue(\"" << param << "\", typeof(" << typeName
+ << "));";
+ }
+ return;
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ const string typeName = typeToString(type, false);
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ", typeof(" << typeName << "));";
+ }
+ else
+ {
+ out << nl << param << " = (" << typeName << ")info__.GetValue(\"" << param << "\", typeof(" << typeName
+ << "));";
+ }
+ return;
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ const string typeName = typeToString(type, false);
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ", typeof(" << typeName << "));";
+ }
+ else
+ {
+ out << nl << param << " = (" << typeName << ")info__.GetValue(\"" << param << "\", typeof(" << typeName
+ << "));";
+ }
+ return;
+ }
+
+ DictionaryPtr d = DictionaryPtr::dynamicCast(type);
+ assert(d);
+ const string typeName = typeToString(type, false);
+ if(serialize)
+ {
+ out << nl << "info__.AddValue(\"" << param << "\", " << param << ", typeof(" << typeName << "));";
+ }
+ else
+ {
+ out << nl << param << " = (" << typeName << ")info__.GetValue(\"" << param << "\", typeof(" << typeName
+ << "));";
+ }
+}
+
string
Slice::CsGenerator::toArrayAlloc(const string& decl, const string& sz)
{
diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp
index adaeb38b502..dd1020042f7 100644
--- a/cpp/src/slice2cs/Gen.cpp
+++ b/cpp/src/slice2cs/Gen.cpp
@@ -3018,6 +3018,7 @@ Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
{
emitComVisibleAttribute();
emitPartialTypeAttributes();
+ _out << nl << "[_System.Serializable]";
if(p->allOperations().size() > 0) // See bug 4747
{
_out << nl << "[_System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Design\", \"CA1012\")]";
@@ -3029,56 +3030,43 @@ Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
}
_out << "partial class " << fixId(name);
- bool baseWritten = false;
-
+ StringList baseNames;
if(!hasBaseClass)
{
if(!p->isLocal())
{
- _out << " : Ice.Object";
- baseWritten = true;
+ baseNames.push_back("Ice.Object");
}
}
else
{
- _out << " : " << fixId(bases.front()->scoped());
- baseWritten = true;
+ baseNames.push_back(fixId(bases.front()->scoped()));
bases.pop_front();
}
if(p->isAbstract() && !p->isLocal())
{
- if(baseWritten)
- {
- _out << ", ";
- }
- else
- {
- _out << " : ";
- baseWritten = true;
- }
+ baseNames.push_back(name + "Operations_");
+ baseNames.push_back(name + "OperationsNC_");
+ }
- if(!p->isLocal())
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q)
+ {
+ if((*q)->isAbstract())
{
- _out << name << "Operations_, ";
- _out << name << "OperationsNC_";
+ baseNames.push_back(fixId((*q)->scoped()));
}
}
- for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q)
+ if(!baseNames.empty())
{
- if((*q)->isAbstract())
+ _out << " : ";
+ for(StringList::iterator q = baseNames.begin(); q != baseNames.end(); ++q)
{
- if(baseWritten)
+ if(q != baseNames.begin())
{
_out << ", ";
}
- else
- {
- _out << " : ";
- baseWritten = true;
- }
-
- _out << fixId((*q)->scoped());
+ _out << *q;
}
}
}
@@ -3381,6 +3369,10 @@ Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
emitAttributes(p);
emitComVisibleAttribute();
emitGeneratedCodeAttribute();
+ if(isSerializable(p->type()))
+ {
+ _out << nl << "[_System.Serializable]";
+ }
_out << nl << "public class " << name
<< " : Ice.CollectionBase<" << s << ">, _System.ICloneable";
_out << sb;
@@ -3462,6 +3454,7 @@ Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
// Suppress FxCop diagnostic about a missing constructor MyException(String).
//
_out << nl << "[_System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Design\", \"CA1032\")]";
+ _out << nl << "[_System.Serializable]";
emitPartialTypeAttributes();
_out << nl << "public partial class " << name << " : ";
if(base)
@@ -3561,6 +3554,18 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
}
_out << eb;
+ _out << sp;
+ emitGeneratedCodeAttribute();
+ _out << nl << "public " << name << "(_System.Runtime.Serialization.SerializationInfo info__, "
+ << "_System.Runtime.Serialization.StreamingContext context__) : base(info__, context__)";
+ _out << sb;
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ string name = fixId((*q)->name(), DotNet::Exception, false);
+ writeSerializeDeserializeCode(_out, (*q)->type(), name, (*q)->optional(), (*q)->tag(), false);
+ }
+ _out << eb;
+
if(!allDataMembers.empty())
{
if(!dataMembers.empty())
@@ -3665,6 +3670,22 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
_out << nl << "return true;";
_out << eb;
+ if(!dataMembers.empty())
+ {
+ _out << sp;
+ emitGeneratedCodeAttribute();
+ _out << nl << "public override void GetObjectData(_System.Runtime.Serialization.SerializationInfo info__, "
+ << "_System.Runtime.Serialization.StreamingContext context__)";
+ _out << sb;
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ string name = fixId((*q)->name(), DotNet::Exception, false);
+ writeSerializeDeserializeCode(_out, (*q)->type(), name, (*q)->optional(), (*q)->tag(), true);
+ }
+ _out << sp << nl << "base.GetObjectData(info__, context__);";
+ _out << eb;
+ }
+
_out << sp << nl << "#endregion"; // Object members
_out << sp << nl << "#region Comparison members";
@@ -3962,6 +3983,7 @@ Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p)
emitAttributes(p);
emitPartialTypeAttributes();
+ _out << nl << "[_System.Serializable]";
if(isValueType(p))
{
_out << nl << "public partial struct " << name;
@@ -4268,6 +4290,10 @@ Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p)
emitAttributes(p);
emitComVisibleAttribute();
emitGeneratedCodeAttribute();
+ if(isSerializable(p->keyType()) && isSerializable(p->valueType()))
+ {
+ _out << nl << "[_System.Serializable]";
+ }
_out << nl << "public class " << name
<< " : Ice.DictionaryBase<" << ks << ", " << vs << ">, _System.ICloneable";
_out << sb;
@@ -4433,6 +4459,11 @@ Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p)
dataMemberName = propertyName;
}
+ if(!isSerializable(p->type()))
+ {
+ _out << nl << "[_System.NonSerialized]";
+ }
+
if(isProperty)
{
_out << nl << "private";