summaryrefslogtreecommitdiff
path: root/cpp/src/slice2swift/SwiftUtil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/slice2swift/SwiftUtil.cpp')
-rw-r--r--cpp/src/slice2swift/SwiftUtil.cpp2815
1 files changed, 2815 insertions, 0 deletions
diff --git a/cpp/src/slice2swift/SwiftUtil.cpp b/cpp/src/slice2swift/SwiftUtil.cpp
new file mode 100644
index 00000000000..80e9d6469c2
--- /dev/null
+++ b/cpp/src/slice2swift/SwiftUtil.cpp
@@ -0,0 +1,2815 @@
+//
+// Copyright (c) ZeroC, Inc. All rights reserved.
+//
+//
+
+#include <IceUtil/OutputUtil.h>
+#include <IceUtil/StringUtil.h>
+
+#include <Slice/Util.h>
+
+#include <SwiftUtil.h>
+
+using namespace std;
+using namespace Slice;
+using namespace IceUtilInternal;
+
+namespace
+{
+
+static string
+lookupKwd(const string& name)
+{
+ //
+ // Keyword list. *Must* be kept in alphabetical order.
+ //
+ static const string keywordList[] =
+ {
+ "Any", "as", "associatedtype", "associativity", "break",
+ "case", "catch", "class", "continue", "convenience", "default", "defer", "deinit",
+ "didSet", "do", "dynamic", "else", "enum", "extension", "fallthrough", "false",
+ "fileprivate", "final", "for", "func", "get", "guard", "if", "import", "in", "indirect",
+ "infix", "init", "inout", "internal", "is", "lazy", "left", "let", "mutating", "nil",
+ "none", "nonmutating", "open", "operator", "optional", "override", "postfix", "precedence",
+ "prefix", "private", "protocol", "public", "repeat", "required", "rethrows", "return",
+ "right", "self", "set", "static", "struct", "subscript", "super", "switch", "throw", "throws",
+ "true", "try", "Type", "typealias", "unowned", "var", "weak", "where", "while", "willSet"
+ };
+ bool found = binary_search(&keywordList[0],
+ &keywordList[sizeof(keywordList) / sizeof(*keywordList)],
+ name,
+ Slice::CICompare());
+ if(found)
+ {
+ return "`" + name + "`";
+ }
+
+ return name;
+}
+
+string
+replace(string s, string patt, string val)
+{
+ string r = s;
+ string::size_type pos = r.find(patt);
+ while(pos != string::npos)
+ {
+ r.replace(pos, patt.size(), val);
+ pos += val.size();
+ pos = r.find(patt, pos);
+ }
+ return r;
+}
+
+string
+opFormatTypeToString(const OperationPtr& op )
+{
+ switch(op->format())
+ {
+ case DefaultFormat:
+ {
+ return ".DefaultFormat";
+ }
+ case CompactFormat:
+ {
+ return ".CompactFormat";
+ }
+ case SlicedFormat:
+ {
+ return ".SlicedFormat";
+ }
+ default:
+ {
+ assert(false);
+ }
+ }
+ return "???";
+}
+
+}
+
+//
+// Split a scoped name into its components and return the components as a list of (unscoped) identifiers.
+//
+StringList
+Slice::splitScopedName(const string& scoped)
+{
+ assert(scoped[0] == ':');
+ StringList ids;
+ string::size_type next = 0;
+ string::size_type pos;
+ while((pos = scoped.find("::", next)) != string::npos)
+ {
+ pos += 2;
+ if(pos != scoped.size())
+ {
+ string::size_type endpos = scoped.find("::", pos);
+ if(endpos != string::npos)
+ {
+ ids.push_back(scoped.substr(pos, endpos - pos));
+ }
+ }
+ next = pos;
+ }
+ if(next != scoped.size())
+ {
+ ids.push_back(scoped.substr(next));
+ }
+ else
+ {
+ ids.push_back("");
+ }
+
+ return ids;
+}
+
+//
+// Check the given identifier against Swift's list of reserved words. If it matches
+// a reserved word, then an escaped version is returned with a leading underscore.
+//
+string
+Slice::fixIdent(const string& ident)
+{
+ if(ident[0] != ':')
+ {
+ return lookupKwd(ident);
+ }
+ StringList ids = splitScopedName(ident);
+ transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd));
+ ostringstream result;
+ for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i)
+ {
+ result << "::" + *i;
+ }
+ return result.str();
+}
+
+string
+Slice::getSwiftModule(const ModulePtr& module, string& swiftPrefix)
+{
+ const string modulePrefix = "swift:module:";
+
+ string swiftModule;
+
+ if(module->findMetaData(modulePrefix, swiftModule))
+ {
+ swiftModule = swiftModule.substr(modulePrefix.size());
+
+ size_t pos = swiftModule.find(':');
+ if(pos != string::npos)
+ {
+ swiftPrefix = swiftModule.substr(pos + 1);
+ swiftModule = swiftModule.substr(0, pos);
+ }
+ }
+ else
+ {
+ swiftModule = module->name();
+ swiftPrefix = "";
+ }
+ return fixIdent(swiftModule);
+}
+
+string
+Slice::getSwiftModule(const ModulePtr& module)
+{
+ string prefix;
+ return getSwiftModule(module, prefix);
+}
+
+ModulePtr
+Slice::getTopLevelModule(const ContainedPtr& cont)
+{
+ //
+ // Traverse to the top-level module.
+ //
+ ModulePtr m;
+ ContainedPtr p = cont;
+ while(true)
+ {
+ if(ModulePtr::dynamicCast(p))
+ {
+ m = ModulePtr::dynamicCast(p);
+ }
+
+ ContainerPtr c = p->container();
+ p = ContainedPtr::dynamicCast(c); // This cast fails for Unit.
+ if(!p)
+ {
+ break;
+ }
+ }
+ return m;
+}
+
+ModulePtr
+Slice::getTopLevelModule(const TypePtr& type)
+{
+ assert(ProxyPtr::dynamicCast(type) || ContainedPtr::dynamicCast(type));
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ return getTopLevelModule(proxy ? ContainedPtr::dynamicCast(proxy->_class()->definition()) :
+ ContainedPtr::dynamicCast(type));
+}
+
+void
+SwiftGenerator::trimLines(StringList& l)
+{
+ //
+ // Remove empty trailing lines.
+ //
+ while(!l.empty() && l.back().empty())
+ {
+ l.pop_back();
+ }
+}
+
+StringList
+SwiftGenerator::splitComment(const string& c)
+{
+ string comment = c;
+
+ //
+ // Strip HTML markup and javadoc links -- MATLAB doesn't display them.
+ //
+ string::size_type pos = 0;
+ do
+ {
+ pos = comment.find('<', pos);
+ if(pos != string::npos)
+ {
+ string::size_type endpos = comment.find('>', pos);
+ if(endpos == string::npos)
+ {
+ break;
+ }
+ comment.erase(pos, endpos - pos + 1);
+ }
+ }
+ while(pos != string::npos);
+
+ const string link = "{@link";
+ pos = 0;
+ do
+ {
+ pos = comment.find(link, pos);
+ if(pos != string::npos)
+ {
+ comment.erase(pos, link.size() + 1); // Erase trailing white space too.
+ string::size_type endpos = comment.find('}', pos);
+ if(endpos != string::npos)
+ {
+ string ident = comment.substr(pos, endpos - pos);
+ comment.erase(pos, endpos - pos + 1);
+
+ //
+ // Check for links of the form {@link Type#member}.
+ //
+ string::size_type hash = ident.find('#');
+ string rest;
+ if(hash != string::npos)
+ {
+ rest = ident.substr(hash + 1);
+ ident = ident.substr(0, hash);
+ if(!ident.empty())
+ {
+ ident = fixIdent(ident);
+ if(!rest.empty())
+ {
+ ident += "." + fixIdent(rest);
+ }
+ }
+ else if(!rest.empty())
+ {
+ ident = fixIdent(rest);
+ }
+ }
+ else
+ {
+ ident = fixIdent(ident);
+ }
+
+ comment.insert(pos, ident);
+ }
+ }
+ }
+ while(pos != string::npos);
+
+ StringList result;
+
+ pos = 0;
+ string::size_type nextPos;
+ while((nextPos = comment.find_first_of('\n', pos)) != string::npos)
+ {
+ result.push_back(IceUtilInternal::trim(string(comment, pos, nextPos - pos)));
+ pos = nextPos + 1;
+ }
+ string lastLine = IceUtilInternal::trim(string(comment, pos));
+ if(!lastLine.empty())
+ {
+ result.push_back(lastLine);
+ }
+
+ trimLines(result);
+
+ return result;
+}
+
+bool
+SwiftGenerator::parseCommentLine(const string& l, const string& tag, bool namedTag, string& name, string& doc)
+{
+ doc.clear();
+
+ if(l.find(tag) == 0)
+ {
+ const string ws = " \t";
+
+ if(namedTag)
+ {
+ string::size_type n = l.find_first_not_of(ws, tag.size());
+ if(n == string::npos)
+ {
+ return false; // Malformed line, ignore it.
+ }
+ string::size_type end = l.find_first_of(ws, n);
+ if(end == string::npos)
+ {
+ return false; // Malformed line, ignore it.
+ }
+ name = l.substr(n, end - n);
+ n = l.find_first_not_of(ws, end);
+ if(n != string::npos)
+ {
+ doc = l.substr(n);
+ }
+ }
+ else
+ {
+ name.clear();
+
+ string::size_type n = l.find_first_not_of(ws, tag.size());
+ if(n == string::npos)
+ {
+ return false; // Malformed line, ignore it.
+ }
+ doc = l.substr(n);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+DocElements
+SwiftGenerator::parseComment(const ContainedPtr& p)
+{
+ DocElements doc;
+
+ doc.deprecated = false;
+
+ //
+ // First check metadata for a deprecated tag.
+ //
+ string deprecateMetadata;
+ if(p->findMetaData("deprecate", deprecateMetadata))
+ {
+ doc.deprecated = true;
+ if(deprecateMetadata.find("deprecate:") == 0 && deprecateMetadata.size() > 10)
+ {
+ doc.deprecateReason.push_back(IceUtilInternal::trim(deprecateMetadata.substr(10)));
+ }
+ }
+
+ //
+ // Split up the comment into lines.
+ //
+ StringList lines = splitComment(p->comment());
+
+ StringList::const_iterator i;
+ for(i = lines.begin(); i != lines.end(); ++i)
+ {
+ const string l = *i;
+ if(l[0] == '@')
+ {
+ break;
+ }
+ doc.overview.push_back(l);
+ }
+
+ enum State { StateMisc, StateParam, StateThrows, StateReturn, StateDeprecated };
+ State state = StateMisc;
+ string name;
+ const string ws = " \t";
+ const string paramTag = "@param";
+ const string throwsTag = "@throws";
+ const string exceptionTag = "@exception";
+ const string returnTag = "@return";
+ const string deprecatedTag = "@deprecated";
+ const string seeTag = "@see";
+ for(; i != lines.end(); ++i)
+ {
+ const string l = IceUtilInternal::trim(*i);
+ string line;
+ if(parseCommentLine(l, paramTag, true, name, line))
+ {
+ if(!line.empty())
+ {
+ state = StateParam;
+ StringList sl;
+ sl.push_back(line); // The first line of the description.
+ doc.params[name] = sl;
+ }
+ }
+ else if(parseCommentLine(l, throwsTag, true, name, line))
+ {
+ if(!line.empty())
+ {
+ state = StateThrows;
+ StringList sl;
+ sl.push_back(line); // The first line of the description.
+ doc.exceptions[name] = sl;
+ }
+ }
+ else if(parseCommentLine(l, exceptionTag, true, name, line))
+ {
+ if(!line.empty())
+ {
+ state = StateThrows;
+ StringList sl;
+ sl.push_back(line); // The first line of the description.
+ doc.exceptions[name] = sl;
+ }
+ }
+ else if(parseCommentLine(l, seeTag, false, name, line))
+ {
+ if(!line.empty())
+ {
+ doc.seeAlso.push_back(line);
+ }
+ }
+ else if(parseCommentLine(l, returnTag, false, name, line))
+ {
+ if(!line.empty())
+ {
+ state = StateReturn;
+ doc.returns.push_back(line); // The first line of the description.
+ }
+ }
+ else if(parseCommentLine(l, deprecatedTag, false, name, line))
+ {
+ doc.deprecated = true;
+ if(!line.empty())
+ {
+ state = StateDeprecated;
+ doc.deprecateReason.push_back(line); // The first line of the description.
+ }
+ }
+ else if(!l.empty())
+ {
+ if(l[0] == '@')
+ {
+ //
+ // Treat all other tags as miscellaneous comments.
+ //
+ state = StateMisc;
+ }
+
+ switch(state)
+ {
+ case StateMisc:
+ {
+ doc.misc.push_back(l);
+ break;
+ }
+ case StateParam:
+ {
+ assert(!name.empty());
+ StringList sl;
+ if(doc.params.find(name) != doc.params.end())
+ {
+ sl = doc.params[name];
+ }
+ sl.push_back(l);
+ doc.params[name] = sl;
+ break;
+ }
+ case StateThrows:
+ {
+ assert(!name.empty());
+ StringList sl;
+ if(doc.exceptions.find(name) != doc.exceptions.end())
+ {
+ sl = doc.exceptions[name];
+ }
+ sl.push_back(l);
+ doc.exceptions[name] = sl;
+ break;
+ }
+ case StateReturn:
+ {
+ doc.returns.push_back(l);
+ break;
+ }
+ case StateDeprecated:
+ {
+ doc.deprecateReason.push_back(l);
+ break;
+ }
+ }
+ }
+ }
+
+ trimLines(doc.overview);
+ trimLines(doc.deprecateReason);
+ trimLines(doc.misc);
+ trimLines(doc.returns);
+
+ return doc;
+}
+
+void
+SwiftGenerator::writeDocLines(IceUtilInternal::Output& out, const StringList& lines, bool commentFirst,
+ const string& space)
+{
+ StringList l = lines;
+ if(!commentFirst)
+ {
+ out << l.front();
+ l.pop_front();
+ }
+
+ for(StringList::const_iterator i = l.begin(); i != l.end(); ++i)
+ {
+ out << nl << "///";
+ if(!i->empty())
+ {
+ out << space << *i;
+ }
+ }
+}
+
+void
+SwiftGenerator::writeDocSentence(IceUtilInternal::Output& out, const StringList& lines)
+{
+ //
+ // Write the first sentence.
+ //
+ for(StringList::const_iterator i = lines.begin(); i != lines.end(); ++i)
+ {
+ const string ws = " \t";
+
+ if(i->empty())
+ {
+ break;
+ }
+ if(i != lines.begin() && i->find_first_not_of(ws) == 0)
+ {
+ out << " ";
+ }
+ string::size_type pos = i->find('.');
+ if(pos == string::npos)
+ {
+ out << *i;
+ }
+ else if(pos == i->size() - 1)
+ {
+ out << *i;
+ break;
+ }
+ else
+ {
+ //
+ // Assume a period followed by whitespace indicates the end of the sentence.
+ //
+ while(pos != string::npos)
+ {
+ if(ws.find((*i)[pos + 1]) != string::npos)
+ {
+ break;
+ }
+ pos = i->find('.', pos + 1);
+ }
+ if(pos != string::npos)
+ {
+ out << i->substr(0, pos + 1);
+ break;
+ }
+ else
+ {
+ out << *i;
+ }
+ }
+ }
+}
+
+void
+SwiftGenerator::writeDocSummary(IceUtilInternal::Output& out, const ContainedPtr& p)
+{
+ DocElements doc = parseComment(p);
+
+ string n = fixIdent(p->name());
+
+ //
+ // No leading newline.
+ //
+ if(!doc.overview.empty())
+ {
+ writeDocLines(out, doc.overview);
+ }
+
+ if(!doc.misc.empty())
+ {
+ out << "///" << nl;
+ writeDocLines(out, doc.misc);
+ }
+
+ if(doc.deprecated)
+ {
+ out << nl << "///";
+ out << nl << "/// ## Deprecated";
+ if(!doc.deprecateReason.empty())
+ {
+ writeDocLines(out, doc.deprecateReason);
+ }
+ }
+}
+
+void
+SwiftGenerator::writeOpDocSummary(IceUtilInternal::Output& out,
+ const OperationPtr& p,
+ bool async,
+ bool dispatch,
+ bool local)
+{
+ DocElements doc = parseComment(p);
+ if(!doc.overview.empty())
+ {
+ writeDocLines(out, doc.overview);
+ }
+
+ if(doc.deprecated)
+ {
+ out << nl << "///";
+ out << nl << "/// ## Deprecated";
+ if(!doc.deprecateReason.empty())
+ {
+ writeDocLines(out, doc.deprecateReason);
+ }
+ }
+
+ int typeCtx = TypeContextInParam;
+ if(local)
+ {
+ typeCtx |= TypeContextLocal;
+ }
+
+ const ParamInfoList allInParams = getAllInParams(p, typeCtx);
+ for(ParamInfoList::const_iterator q = allInParams.begin(); q != allInParams.end(); ++q)
+ {
+ out << nl << "///";
+ out << nl << "/// - parameter " << (!dispatch && allInParams.size() == 1 ? "_" : q->name)
+ << ": `" << q->typeStr << "`";
+ map<string, StringList>::const_iterator r = doc.params.find(q->name);
+ if(r != doc.params.end() && !r->second.empty())
+ {
+ out << " ";
+ writeDocLines(out, r->second, false);
+ }
+ }
+
+ if(!local)
+ {
+ out << nl << "///";
+ if(dispatch)
+ {
+ out << nl << "/// - parameter current: `Ice.Current` - The Current object for the dispatch.";
+ }
+ else
+ {
+ out << nl << "/// - parameter context: `Ice.Context` - Optional request context.";
+ }
+ }
+
+ typeCtx = local ? TypeContextLocal : 0;
+
+ if(async)
+ {
+ if(!dispatch)
+ {
+ out << nl << "///";
+ out << nl << "/// - parameter sentOn: `Dispatch.DispatchQueue?` - Optional dispatch queue used to";
+ out << nl << "/// dispatch sent callback, the default is to use `PromiseKit.conf.Q.return` queue.";
+ out << nl << "///";
+ out << nl << "/// - parameter sentFlags: `Dispatch.DispatchWorkItemFlags?` - Optional dispatch flags used";
+ out << nl << "/// to dispatch sent callback";
+ out << nl << "///";
+ out << nl << "/// - parameter sent: `((Swift.Bool) -> Swift.Void)` - Optional sent callback.";
+ }
+
+ out << nl << "///";
+ out << nl << "/// - returns: `PromiseKit.Promise<" << operationReturnType(p, typeCtx)
+ << ">` - The result of the operation";
+ }
+ else
+ {
+ const ParamInfoList allOutParams = getAllOutParams(p, typeCtx);
+ if(allOutParams.size() == 1)
+ {
+ ParamInfo ret = allOutParams.front();
+ out << nl << "///";
+ out << nl << "/// - returns: `" << ret.typeStr << "`";
+ if(p->returnType())
+ {
+ if(!doc.returns.empty())
+ {
+ out << " - ";
+ writeDocLines(out, doc.returns, false);
+ }
+ }
+ else
+ {
+ map<string, StringList>::const_iterator r = doc.params.find(ret.name);
+ if(r != doc.params.end() && !r->second.empty())
+ {
+ out << " - ";
+ writeDocLines(out, r->second, false);
+ }
+ }
+ }
+ else if(allOutParams.size() > 1)
+ {
+ out << nl << "///";
+ out << nl << "/// - returns: `" << operationReturnType(p, typeCtx) << "`:";
+ if(p->returnType())
+ {
+ ParamInfo ret = allOutParams.back();
+ out << nl << "///";
+ out << nl << "/// - " << ret.name << ": `" << ret.typeStr << "`";
+ if(!doc.returns.empty())
+ {
+ out << " - ";
+ writeDocLines(out, doc.returns, false);
+ }
+ }
+
+ for(ParamInfoList::const_iterator q = allOutParams.begin(); q != allOutParams.end(); ++q)
+ {
+ if(q->param != 0)
+ {
+ out << nl << "///";
+ out << nl << "/// - " << q->name << ": `" << q->typeStr << "`";
+ map<string, StringList>::const_iterator r = doc.params.find(q->name);
+ if(r != doc.params.end() && !r->second.empty())
+ {
+ out << " - ";
+ writeDocLines(out, r->second, false);
+ }
+ }
+ }
+ }
+ }
+
+ if(!doc.exceptions.empty() && !async)
+ {
+ out << nl << "///";
+ out << nl << "/// - throws:";
+ for(map<string, StringList>::const_iterator q = doc.exceptions.begin(); q != doc.exceptions.end(); ++q)
+ {
+ out << nl << "///";
+ out << nl << "/// - " << q->first;
+ if(!q->second.empty())
+ {
+ out << " - ";
+ writeDocLines(out, q->second, false, " ");
+ }
+ }
+ }
+
+ if(!doc.misc.empty())
+ {
+ out << nl;
+ writeDocLines(out, doc.misc, false);
+ }
+}
+
+void
+SwiftGenerator::writeProxyDocSummary(IceUtilInternal::Output& out, const ClassDefPtr& p, const string& swiftModule)
+{
+ DocElements doc = parseComment(p);
+
+ const string name = getUnqualified(getAbsolute(p), swiftModule);
+ const string prx = name + "Prx";
+
+ if(doc.overview.empty())
+ {
+ out << nl << "/// " << prx << " overview.";
+ }
+ else
+ {
+ writeDocLines(out, doc.overview);
+ }
+
+ const OperationList ops = p->operations();
+ if(!ops.empty())
+ {
+ out << nl << "///";
+ out << nl << "/// " << prx << " Methods:";
+ for(OperationList::const_iterator q = ops.begin(); q != ops.end(); ++q)
+ {
+ OperationPtr op = *q;
+ DocElements opdoc = parseComment(op);
+ out << nl << "///";
+ out << nl << "/// - " << fixIdent(op->name()) << ": ";
+ if(!opdoc.overview.empty())
+ {
+ writeDocSentence(out, opdoc.overview);
+ }
+
+ out << nl << "///";
+ out << nl << "/// - " << op->name() << "Async: ";
+ if(!opdoc.overview.empty())
+ {
+ writeDocSentence(out, opdoc.overview);
+ }
+ }
+ }
+
+ if(!doc.misc.empty())
+ {
+ writeDocLines(out, doc.misc, false);
+ }
+}
+
+void
+SwiftGenerator::writeServantDocSummary(IceUtilInternal::Output& out, const ClassDefPtr& p, const string& swiftModule)
+{
+ DocElements doc = parseComment(p);
+
+ const string name = getUnqualified(getAbsolute(p), swiftModule);
+
+ if(doc.overview.empty())
+ {
+ out << nl << "/// " << name << " overview.";
+ }
+ else
+ {
+ writeDocLines(out, doc.overview);
+ }
+
+ const OperationList ops = p->operations();
+ if(!ops.empty())
+ {
+ out << nl << "///";
+ out << nl << "/// " << name << " Methods:";
+ for(OperationList::const_iterator q = ops.begin(); q != ops.end(); ++q)
+ {
+ OperationPtr op = *q;
+ DocElements opdoc = parseComment(op);
+ out << nl << "///";
+ out << nl << "/// - " << fixIdent(op->name()) << ": ";
+ if(!opdoc.overview.empty())
+ {
+ writeDocSentence(out, opdoc.overview);
+ }
+ }
+ }
+
+ if(!doc.misc.empty())
+ {
+ writeDocLines(out, doc.misc, false);
+ }
+}
+
+void
+SwiftGenerator::writeMemberDoc(IceUtilInternal::Output& out, const DataMemberPtr& p)
+{
+ DocElements doc = parseComment(p);
+
+ //
+ // Skip if there are no doc comments.
+ //
+ if(doc.overview.empty() && doc.misc.empty() && doc.seeAlso.empty() && doc.deprecateReason.empty() &&
+ !doc.deprecated)
+ {
+ return;
+ }
+
+ if(doc.overview.empty())
+ {
+ out << nl << "/// " << fixIdent(p->name());
+ }
+ else
+ {
+ writeDocLines(out, doc.overview);
+ }
+
+ if(!doc.misc.empty())
+ {
+ writeDocLines(out, doc.misc);
+ }
+
+ if(doc.deprecated)
+ {
+ out << nl << "/// ##Deprecated";
+ if(!doc.deprecateReason.empty())
+ {
+ writeDocLines(out, doc.deprecateReason);
+ }
+ }
+}
+
+void
+SwiftGenerator::validateMetaData(const UnitPtr& u)
+{
+ MetaDataVisitor visitor;
+ u->visit(&visitor, true);
+}
+
+//
+// Get the fully-qualified name of the given definition. If a suffix is provided,
+// it is prepended to the definition's unqualified name. If the nameSuffix
+// is provided, it is appended to the container's name.
+//
+namespace
+{
+
+string
+getAbsoluteImpl(const ContainedPtr& cont, const string& prefix = "", const string& suffix = "")
+{
+ string swiftPrefix;
+ string swiftModule = getSwiftModule(getTopLevelModule(cont), swiftPrefix);
+
+ string str = cont->scope() + prefix + cont->name() + suffix;
+ if(str.find("::") == 0)
+ {
+ str.erase(0, 2);
+ }
+
+ size_t pos = str.find("::");
+ //
+ // Replace the definition top-level module by the corresponding Swift module
+ // and append the Swift prefix for the Slice module, then any remaining nested
+ // modules become a Swift prefix
+ //
+ if(pos != string::npos)
+ {
+ str = str.substr(pos + 2);
+ }
+ return swiftModule + "." + swiftPrefix + replace(str, "::", "");
+}
+
+}
+
+string
+SwiftGenerator::getValue(const string& swiftModule, const TypePtr& type)
+{
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Builtin::KindBool:
+ {
+ return "false";
+ }
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ {
+ return "0";
+ }
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ {
+ return "0.0";
+ }
+ case Builtin::KindString:
+ {
+ return "\"\"";
+ }
+ default:
+ {
+ return "nil";
+ }
+ }
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ return "." + fixIdent((*en->enumerators().begin())->name());
+ }
+
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ return getUnqualified(getAbsolute(type), swiftModule) + "()";
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ return getUnqualified(getAbsolute(type), swiftModule) + "()";
+ }
+
+ DictionaryPtr dict = DictionaryPtr::dynamicCast(type);
+ if(dict)
+ {
+ return getUnqualified(getAbsolute(type), swiftModule) + "()";
+ }
+
+ return "nil";
+}
+
+void
+SwiftGenerator::writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type,
+ const SyntaxTreeBasePtr& valueType, const string& value,
+ const StringList&, const string& swiftModule, bool optional)
+{
+ ConstPtr constant = ConstPtr::dynamicCast(valueType);
+ if(constant)
+ {
+ out << getUnqualified(getAbsolute(constant), swiftModule);
+ }
+ else
+ {
+ if(valueType)
+ {
+ BuiltinPtr bp = BuiltinPtr::dynamicCast(type);
+ EnumPtr ep = EnumPtr::dynamicCast(type);
+ if(bp && bp->kind() == Builtin::KindString)
+ {
+ out << "\"";
+ out << toStringLiteral(value, "\n\r\t", "", EC6UCN, 0);
+ out << "\"";
+ }
+ else if(ep)
+ {
+ assert(valueType);
+ EnumeratorPtr enumerator = EnumeratorPtr::dynamicCast(valueType);
+ assert(enumerator);
+ out << getUnqualified(getAbsolute(ep), swiftModule) << "." << enumerator->name();
+ }
+ else
+ {
+ out << value;
+ }
+ }
+ else if(optional)
+ {
+ out << "nil";
+ }
+ else
+ {
+ out << getValue(swiftModule, type);
+ }
+ }
+}
+
+string
+SwiftGenerator::typeToString(const TypePtr& type,
+ const ContainedPtr& toplevel,
+ const StringList& metadata,
+ bool optional,
+ int typeCtx)
+{
+ static const char* builtinTable[] =
+ {
+ "Swift.UInt8",
+ "Swift.Bool",
+ "Swift.Int16",
+ "Swift.Int32",
+ "Swift.Int64",
+ "Swift.Float",
+ "Swift.Double",
+ "Swift.String",
+ "Ice.Disp", // Object
+ "Ice.ObjectPrx", // ObjectPrx
+ "Swift.AnyObject", // LocalObject
+ "Ice.Value" // Value
+ };
+
+ if(!type)
+ {
+ return "";
+ }
+
+ bool local = (typeCtx & TypeContextLocal) != 0;
+ if(local)
+ {
+ for(StringList::const_iterator i = metadata.begin(); i != metadata.end(); ++i)
+ {
+ const string swiftType = "swift:type:";
+ const string meta = *i;
+ if(meta.find(swiftType) == 0)
+ {
+ return meta.substr(swiftType.size());
+ }
+ }
+ }
+
+ string t = "";
+ //
+ // The current module were the type is being used
+ //
+ string currentModule = getSwiftModule(getTopLevelModule(toplevel));
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ bool nonnull = find(metadata.begin(), metadata.end(), "swift:nonnull") != metadata.end();
+ bool inparam = typeCtx & TypeContextInParam;
+
+ if(builtin)
+ {
+ if(builtin->kind() == Builtin::KindObject && !(typeCtx & TypeContextLocal))
+ {
+ t = getUnqualified(builtinTable[Builtin::KindValue], currentModule);
+ }
+ else
+ {
+ t = getUnqualified(builtinTable[builtin->kind()], currentModule);
+ }
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ ProxyPtr prx = ProxyPtr::dynamicCast(type);
+ ContainedPtr cont = ContainedPtr::dynamicCast(type);
+
+ if(cl)
+ {
+ if(cl->isInterface() && !cl->isLocal())
+ {
+ t = fixIdent(getUnqualified(builtinTable[Builtin::KindValue], currentModule));
+ }
+ else
+ {
+ //
+ // Annotate nonnull closure as @escaping, Swift optional closure parameters are always
+ // @escaping see https://www.jessesquires.com/blog/why-optional-swift-closures-are-escaping/
+ //
+ if(cl->isLocal() && cl->definition() && cl->definition()->isDelegate() && inparam && nonnull)
+ {
+ t = "@escaping ";
+ }
+ t += fixIdent(getUnqualified(getAbsoluteImpl(cl), currentModule));
+ }
+ }
+ else if(prx)
+ {
+ ClassDefPtr def = prx->_class()->definition();
+ if(def->isInterface() || def->allOperations().size() > 0)
+ {
+ t = getUnqualified(getAbsoluteImpl(prx->_class(), "", "Prx"), currentModule);
+ }
+ else
+ {
+ t = getUnqualified("Ice.ObjectPrx", currentModule);
+ }
+ }
+ else if(cont)
+ {
+ t = fixIdent(getUnqualified(getAbsoluteImpl(cont), currentModule));
+ }
+
+ if(!nonnull && (optional || isNullableType(type)))
+ {
+ t += "?";
+ }
+ return t;
+}
+
+string
+SwiftGenerator::getAbsolute(const TypePtr& type)
+{
+ static const char* builtinTable[] =
+ {
+ "Swift.UInt8",
+ "Swift.Bool",
+ "Swift.Int16",
+ "Swift.Int32",
+ "Swift.Int64",
+ "Swift.Float",
+ "Swift.Double",
+ "Swift.String",
+ "Ice.Disp", // Object
+ "Ice.ObjectPrx", // ObjectPrx
+ "Swift.AnyObject", // LocalObject
+ "Ice.Value" // Value
+ };
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ return builtinTable[builtin->kind()];
+ }
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ if(proxy)
+ {
+ return getAbsoluteImpl(proxy->_class(), "", "Prx");
+ }
+
+ ContainedPtr cont = ContainedPtr::dynamicCast(type);
+ if(cont)
+ {
+ return getAbsoluteImpl(cont);
+ }
+
+ assert(false);
+ return "???";
+}
+
+string
+SwiftGenerator::getAbsolute(const ClassDeclPtr& cl)
+{
+ return getAbsoluteImpl(cl);
+}
+
+string
+SwiftGenerator::getAbsolute(const ClassDefPtr& cl)
+{
+ return getAbsoluteImpl(cl);
+}
+
+string
+SwiftGenerator::getAbsolute(const ProxyPtr& prx)
+{
+ return getAbsoluteImpl(prx->_class(), "", "Prx");
+}
+
+string
+SwiftGenerator::getAbsolute(const StructPtr& st)
+{
+ return getAbsoluteImpl(st);
+}
+
+string
+SwiftGenerator::getAbsolute(const ExceptionPtr& ex)
+{
+ return getAbsoluteImpl(ex);
+}
+
+string
+SwiftGenerator::getAbsolute(const EnumPtr& en)
+{
+ return getAbsoluteImpl(en);
+}
+
+string
+SwiftGenerator::getAbsolute(const ConstPtr& en)
+{
+ return getAbsoluteImpl(en);
+}
+
+string
+SwiftGenerator::getAbsolute(const SequencePtr& en)
+{
+ return getAbsoluteImpl(en);
+}
+
+string
+SwiftGenerator::getAbsolute(const DictionaryPtr& en)
+{
+ return getAbsoluteImpl(en);
+}
+
+string
+SwiftGenerator::getUnqualified(const string& type, const string& localModule)
+{
+ const string prefix = localModule + ".";
+ return type.find(prefix) == 0 ? type.substr(prefix.size()) : type;
+}
+
+string
+SwiftGenerator::modeToString(Operation::Mode opMode)
+{
+ string mode;
+ switch(opMode)
+ {
+ case Operation::Normal:
+ {
+ mode = ".Normal";
+ break;
+ }
+ case Operation::Nonmutating:
+ {
+ mode = ".Nonmutating";
+ break;
+ }
+ case Operation::Idempotent:
+ {
+ mode = ".Idempotent";
+ break;
+ }
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+ return mode;
+}
+
+string
+SwiftGenerator::getOptionalFormat(const TypePtr& type)
+{
+ BuiltinPtr bp = BuiltinPtr::dynamicCast(type);
+ if(bp)
+ {
+ switch(bp->kind())
+ {
+ case Builtin::KindByte:
+ case Builtin::KindBool:
+ {
+ return ".F1";
+ }
+ case Builtin::KindShort:
+ {
+ return ".F2";
+ }
+ case Builtin::KindInt:
+ case Builtin::KindFloat:
+ {
+ return ".F4";
+ }
+ case Builtin::KindLong:
+ case Builtin::KindDouble:
+ {
+ return ".F8";
+ }
+ case Builtin::KindString:
+ {
+ return ".VSize";
+ }
+ case Builtin::KindObject:
+ {
+ return ".Class";
+ }
+ case Builtin::KindObjectProxy:
+ {
+ return ".FSize";
+ }
+ case Builtin::KindLocalObject:
+ {
+ assert(false);
+ break;
+ }
+ case Builtin::KindValue:
+ {
+ return ".Class";
+ }
+ }
+ }
+
+ if(EnumPtr::dynamicCast(type))
+ {
+ return ".Size";
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ return seq->type()->isVariableLength() ? ".FSize" : ".VSize";
+ }
+
+ DictionaryPtr d = DictionaryPtr::dynamicCast(type);
+ if(d)
+ {
+ return (d->keyType()->isVariableLength() || d->valueType()->isVariableLength()) ?
+ ".FSize" : ".VSize";
+ }
+
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ return st->isVariableLength() ? ".FSize" : ".VSize";
+ }
+
+ if(ProxyPtr::dynamicCast(type))
+ {
+ return ".FSize";
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ assert(cl);
+ return ".Class";
+}
+
+bool
+SwiftGenerator::isNullableType(const TypePtr& type)
+{
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ case Builtin::KindValue:
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ return ClassDeclPtr::dynamicCast(type) || ProxyPtr::dynamicCast(type);
+}
+
+bool
+SwiftGenerator::isProxyType(const TypePtr& p)
+{
+ const BuiltinPtr builtin = BuiltinPtr::dynamicCast(p);
+ return (builtin && builtin->kind() == Builtin::KindObjectProxy) || ProxyPtr::dynamicCast(p);
+}
+
+bool
+SwiftGenerator::isClassType(const TypePtr& p)
+{
+ const BuiltinPtr builtin = BuiltinPtr::dynamicCast(p);
+ return (builtin && (builtin->kind() == Builtin::KindObject ||
+ builtin->kind() == Builtin::KindValue)) ||
+ ClassDeclPtr::dynamicCast(p);
+}
+
+bool
+SwiftGenerator::containsClassMembers(const StructPtr& s)
+{
+ DataMemberList dm = s->dataMembers();
+ for(DataMemberList::const_iterator i = dm.begin(); i != dm.end(); ++i)
+ {
+ if(isClassType((*i)->type()))
+ {
+ return true;
+ }
+
+ StructPtr st = StructPtr::dynamicCast((*i)->type());
+ if(st && containsClassMembers(st))
+ {
+ return true;
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast((*i)->type());
+ if(seq)
+ {
+ st = StructPtr::dynamicCast(seq->type());
+ if(isClassType(seq->type()) || (st && containsClassMembers(st)))
+ {
+ return true;
+ }
+ }
+
+ DictionaryPtr dict = DictionaryPtr::dynamicCast((*i)->type());
+ if(dict)
+ {
+ st = StructPtr::dynamicCast(dict->valueType());
+ if(isClassType(dict->valueType()) || (st && containsClassMembers(st)))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void
+SwiftGenerator::writeDefaultInitializer(IceUtilInternal::Output& out,
+ bool required,
+ bool rootClass)
+{
+ out << sp;
+ out << nl << "public ";
+ if(required)
+ {
+ out << "required ";
+ }
+ if(rootClass)
+ {
+ out << "init() {}";
+ }
+ else
+ {
+ assert(required);
+ out << "init()";
+ out << sb;
+ out << nl << "super.init()";
+ out << eb;
+ }
+}
+
+void
+SwiftGenerator::writeMemberwiseInitializer(IceUtilInternal::Output& out,
+ const DataMemberList& members,
+ const ContainedPtr& p)
+{
+ writeMemberwiseInitializer(out, members, DataMemberList(), members, p, false, true);
+}
+
+void
+SwiftGenerator::writeMemberwiseInitializer(IceUtilInternal::Output& out,
+ const DataMemberList& members,
+ const DataMemberList& baseMembers,
+ const DataMemberList& allMembers,
+ const ContainedPtr& p,
+ bool local,
+ bool rootClass,
+ const StringPairList& extraParams)
+{
+ if(!members.empty())
+ {
+ out << sp;
+ out << nl;
+ int typeCtx = TypeContextInParam;
+ if(local)
+ {
+ typeCtx |= TypeContextLocal;
+ }
+ out << "public init" << spar;
+ for(DataMemberList::const_iterator i = allMembers.begin(); i != allMembers.end(); ++i)
+ {
+ DataMemberPtr m = *i;
+ out << (fixIdent(m->name()) + ": " +
+ typeToString(m->type(), p, m->getMetaData(), m->optional(), TypeContextInParam));
+ }
+ for(StringPairList::const_iterator q = extraParams.begin(); q != extraParams.end(); ++q)
+ {
+ out << (q->first + ": " + q->second);
+ }
+ out << epar;
+ out << sb;
+ for(DataMemberList::const_iterator i = members.begin(); i != members.end(); ++i)
+ {
+ DataMemberPtr m = *i;
+ out << nl << "self." << fixIdent(m->name()) << " = " << fixIdent(m->name());
+ }
+
+ if(!rootClass)
+ {
+ out << nl << "super.init";
+ out << spar;
+ for(DataMemberList::const_iterator i = baseMembers.begin(); i != baseMembers.end(); ++i)
+ {
+ const string name = fixIdent((*i)->name());
+ out << (name + ": " + name);
+ }
+ for(StringPairList::const_iterator q = extraParams.begin(); q != extraParams.end(); ++q)
+ {
+ out << (q->first + ": " + q->first);
+ }
+ out << epar;
+ }
+ out << eb;
+ }
+}
+
+void
+SwiftGenerator::writeMembers(IceUtilInternal::Output& out,
+ const DataMemberList& members,
+ const ContainedPtr& p,
+ int typeCtx)
+{
+ string swiftModule = getSwiftModule(getTopLevelModule(p));
+ bool protocol = (typeCtx & TypeContextProtocol);
+ string access = protocol ? "" : "public ";
+ for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q)
+ {
+ DataMemberPtr member = *q;
+ TypePtr type = member->type();
+ string defaultValue = member->defaultValue();
+ writeMemberDoc(out, member);
+ out << nl << access << "var " << fixIdent(member->name()) << ": "
+ << typeToString(type, p, member->getMetaData(), member->optional(), typeCtx);
+ if(protocol)
+ {
+ out << " { get set }";
+ }
+ else
+ {
+ out << " = ";
+ writeConstantValue(out, type, member->defaultValueType(), defaultValue, p->getMetaData(), swiftModule,
+ member->optional());
+ }
+ }
+}
+
+bool
+SwiftGenerator::usesMarshalHelper(const TypePtr& type)
+{
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type());
+ if(builtin)
+ {
+ return builtin->kind() > Builtin::KindString;
+ }
+ return true;
+ }
+ return DictionaryPtr::dynamicCast(type);
+}
+
+void
+SwiftGenerator::writeMarshalUnmarshalCode(Output &out,
+ const TypePtr& type,
+ const ContainedPtr& p,
+ const string& param,
+ bool marshal,
+ int tag)
+{
+ string swiftModule = getSwiftModule(getTopLevelModule(p));
+ string stream = StructPtr::dynamicCast(p) ? "self" : marshal ? "ostr" : "istr";
+
+ string args;
+ if(tag >= 0)
+ {
+ args += "tag: " + int64ToString(tag);
+ if(marshal)
+ {
+ args += ", ";
+ }
+ }
+
+ if(marshal)
+ {
+ if(tag >= 0 || usesMarshalHelper(type))
+ {
+ args += "value: ";
+ }
+ args += param;
+ }
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Builtin::KindByte:
+ case Builtin::KindBool:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ case Builtin::KindString:
+ {
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ out << nl << param << " = try " << stream << ".read(" << args << ")";
+ }
+ break;
+ }
+ case Builtin::KindObjectProxy:
+ {
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ if(tag >= 0)
+ {
+ args += ", type: ";
+ }
+ args += getUnqualified(getAbsolute(type), swiftModule) + ".self";
+
+ out << nl << param << " = try " << stream << ".read(" << args << ")";
+ }
+ break;
+ }
+ case Builtin::KindObject:
+ case Builtin::KindValue:
+ {
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ out << nl << "try " << stream << ".read(" << args << ") { " << param << " = $0 }";
+ }
+ break;
+ }
+ case Builtin::KindLocalObject:
+ {
+ assert(false);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ if(ClassDeclPtr::dynamicCast(type))
+ {
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ if(cl->isInterface())
+ {
+ out << nl << "try " << stream << ".read(" << args << ") { " << param << " = $0 }";
+ }
+ else
+ {
+ if(tag >= 0)
+ {
+ args += ", value: ";
+ }
+ args += getUnqualified(getAbsolute(type), swiftModule) + ".self";
+ out << nl << "try " << stream << ".read(" << args << ") { " << param << " = $0 " << "}";
+ }
+ }
+ return;
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ out << nl << param << " = try " << stream << ".read(" << args << ")";
+ }
+ return;
+ }
+
+ ProxyPtr prx = ProxyPtr::dynamicCast(type);
+ if(prx)
+ {
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ if(tag >= 0)
+ {
+ args += ", type: ";
+ }
+
+ ClassDefPtr def = prx->_class()->definition();
+ if(def->isInterface() || def->allOperations().size() > 0)
+ {
+ args += getUnqualified(getAbsolute(type), swiftModule) + ".self";
+ }
+ else
+ {
+ args += getUnqualified("Ice.ObjectPrx", swiftModule) + ".self";
+ }
+ out << nl << param << " = try " << stream << ".read(" << args << ")";
+ }
+ return;
+ }
+
+ if(StructPtr::dynamicCast(type))
+ {
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ out << nl << param << " = try " << stream << ".read(" << args << ")";
+ }
+ return;
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ BuiltinPtr seqBuiltin = BuiltinPtr::dynamicCast(seq->type());
+ if(seqBuiltin && seqBuiltin->kind() <= Builtin::KindString)
+ {
+ if(marshal)
+ {
+ out << nl << stream << ".write(" << args << ")";
+ }
+ else
+ {
+ out << nl << param << " = try " << stream << ".read(" << args << ")";
+ }
+ }
+ else
+ {
+ string helper = getUnqualified(getAbsoluteImpl(ContainedPtr::dynamicCast(type)), swiftModule) + "Helper";
+ if(marshal)
+ {
+ out << nl << helper <<".write(to: " << stream << ", " << args << ")";
+ }
+ else
+ {
+ out << nl << param << " = try " << helper << ".read(from: " << stream;
+ if(!args.empty())
+ {
+ out << ", " << args;
+ }
+ out << ")";
+ }
+ }
+ return;
+ }
+
+ if(DictionaryPtr::dynamicCast(type))
+ {
+ string helper = getUnqualified(getAbsoluteImpl(ContainedPtr::dynamicCast(type)), swiftModule) + "Helper";
+ if(marshal)
+ {
+ out << nl << helper <<".write(to: " << stream << ", " << args << ")";
+ }
+ else
+ {
+ out << nl << param << " = try " << helper << ".read(from: " << stream;
+ if(!args.empty())
+ {
+ out << ", " << args;
+ }
+ out << ")";
+ }
+ return;
+ }
+}
+
+bool
+SwiftGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(UnitPtr::dynamicCast(p->container()))
+ {
+ const UnitPtr ut = p->unit();
+ const DefinitionContextPtr dc = ut->findDefinitionContext(p->file());
+ assert(dc);
+
+ // top-level module
+ ModulePtr m = ModulePtr::dynamicCast(p);
+ const string modulePrefix = "swift:module:";
+
+ string swiftModule;
+ string swiftPrefix;
+
+ if(m->findMetaData(modulePrefix, swiftModule))
+ {
+ swiftModule = swiftModule.substr(modulePrefix.size());
+
+ size_t pos = swiftModule.find(':');
+ if(pos != string::npos)
+ {
+ swiftPrefix = swiftModule.substr(pos + 1);
+ swiftModule = swiftModule.substr(0, pos);
+ }
+ }
+ else
+ {
+ swiftModule = m->name();
+ }
+
+ const string filename = m->definitionContext()->filename();
+ ModuleMap::const_iterator current = _modules.find(filename);
+
+ if(current == _modules.end())
+ {
+ _modules[filename] = swiftModule;
+ }
+ else if(current->second != swiftModule)
+ {
+ ostringstream os;
+ os << "invalid module mapping:\n Slice module `" << m->scoped() << "' should be map to Swift module `"
+ << current->second << "'" << endl;
+ dc->error(p->file(), p->line(), os.str());
+ }
+
+ ModulePrefix::iterator prefixes = _prefixes.find(swiftModule);
+ if(prefixes == _prefixes.end())
+ {
+ ModuleMap mappings;
+ mappings[p->name()] = swiftPrefix;
+ _prefixes[swiftModule] = mappings;
+ }
+ else
+ {
+ current = prefixes->second.find(p->name());
+ if(current == prefixes->second.end())
+ {
+ prefixes->second[p->name()] = swiftPrefix;
+ }
+ else if(current->second != swiftPrefix)
+ {
+ ostringstream os;
+ os << "invalid module prefix:\n Slice module `" << m->scoped() << "' is already using";
+ if(current->second.empty())
+ {
+ os << " no prefix " << endl;
+ }
+ else
+ {
+ os << " a different Swift module prefix `" << current->second << "'" << endl;
+ }
+ dc->error(p->file(), p->line(), os.str());
+ }
+ }
+ }
+ return true;
+}
+
+string
+SwiftGenerator::paramLabel(const string& param, const ParamDeclList& params)
+{
+ string s = param;
+ for(ParamDeclList::const_iterator q = params.begin(); q != params.end(); ++q)
+ {
+ if((*q)->name() == param)
+ {
+ s = "_" + s;
+ break;
+ }
+ }
+ return s;
+}
+
+bool
+SwiftGenerator::operationReturnIsTuple(const OperationPtr& op)
+{
+ ParamDeclList outParams = op->outParameters();
+ return (op->returnType() && outParams.size() > 0) || outParams.size() > 1;
+}
+
+string
+SwiftGenerator::operationReturnType(const OperationPtr& op, int typeCtx)
+{
+ ostringstream os;
+ bool returnIsTuple = operationReturnIsTuple(op);
+ if(returnIsTuple)
+ {
+ os << "(";
+ }
+
+ ParamDeclList outParams = op->outParameters();
+ TypePtr returnType = op->returnType();
+ if(returnType)
+ {
+ if(returnIsTuple)
+ {
+ os << paramLabel("returnValue", outParams) << ": ";
+ }
+ os << typeToString(returnType, op, op->getMetaData(), op->returnIsOptional(), typeCtx);
+ }
+
+ for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q)
+ {
+ if(returnType || q != outParams.begin())
+ {
+ os << ", ";
+ }
+
+ if(returnIsTuple)
+ {
+ os << (*q)->name() << ": ";
+ }
+
+ os << typeToString((*q)->type(), *q, (*q)->getMetaData(), (*q)->optional(), typeCtx);
+ }
+
+ if(returnIsTuple)
+ {
+ os << ")";
+ }
+
+ return os.str();
+}
+
+std::string
+SwiftGenerator::operationReturnDeclaration(const OperationPtr& op)
+{
+ ostringstream os;
+ ParamDeclList outParams = op->outParameters();
+ TypePtr returnType = op->returnType();
+ bool returnIsTuple = operationReturnIsTuple(op);
+
+ if(returnIsTuple)
+ {
+ os << "(";
+ }
+
+ if(returnType)
+ {
+ os << ("iceP_" + paramLabel("returnValue", outParams));
+ }
+
+ for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q)
+ {
+ if(returnType || q != outParams.begin())
+ {
+ os << ", ";
+ }
+
+ os << ("iceP_" + (*q)->name());
+ }
+
+ if(returnIsTuple)
+ {
+ os << ")";
+ }
+
+ return os.str();
+}
+
+string
+SwiftGenerator::operationInParamsDeclaration(const OperationPtr& op)
+{
+ ostringstream os;
+
+ ParamDeclList inParams = op->inParameters();
+ const bool isTuple = inParams.size() > 1;
+
+ if(!inParams.empty())
+ {
+ if(isTuple)
+ {
+ os << "(";
+ }
+ for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q)
+ {
+ if(q != inParams.begin())
+ {
+ os << ", ";
+ }
+
+ os << ("iceP_" + (*q)->name());
+ }
+ if(isTuple)
+ {
+ os << ")";
+ }
+
+ os << ": ";
+
+ if(isTuple)
+ {
+ os << "(";
+ }
+ for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q)
+ {
+ if(q != inParams.begin())
+ {
+ os << ", ";
+ }
+
+ os << typeToString((*q)->type(), *q, (*q)->getMetaData(), (*q)->optional());
+ }
+ if(isTuple)
+ {
+ os << ")";
+ }
+ }
+
+ return os.str();
+}
+
+bool
+SwiftGenerator::operationIsAmd(const OperationPtr& op)
+{
+ const ClassDefPtr cl = ClassDefPtr::dynamicCast(op->container());
+ return cl->hasMetaData("amd") || op->hasMetaData("amd");
+}
+
+ParamInfoList
+SwiftGenerator::getAllInParams(const OperationPtr& op, int typeCtx)
+{
+ const ParamDeclList l = op->inParameters();
+ ParamInfoList r;
+ for(ParamDeclList::const_iterator p = l.begin(); p != l.end(); ++p)
+ {
+ ParamInfo info;
+ info.name = (*p)->name();
+ info.type = (*p)->type();
+ info.typeStr = typeToString(info.type, op, (*p)->getMetaData(), (*p)->optional(), typeCtx);
+ info.optional = (*p)->optional();
+ info.tag = (*p)->tag();
+ info.param = *p;
+ r.push_back(info);
+ }
+ return r;
+}
+
+void
+SwiftGenerator::getInParams(const OperationPtr& op, ParamInfoList& required, ParamInfoList& optional)
+{
+ const ParamInfoList params = getAllInParams(op);
+ for(ParamInfoList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ if(p->optional)
+ {
+ optional.push_back(*p);
+ }
+ else
+ {
+ required.push_back(*p);
+ }
+ }
+
+ //
+ // Sort optional parameters by tag.
+ //
+ class SortFn
+ {
+ public:
+ static bool compare(const ParamInfo& lhs, const ParamInfo& rhs)
+ {
+ return lhs.tag < rhs.tag;
+ }
+ };
+ optional.sort(SortFn::compare);
+}
+
+ParamInfoList
+SwiftGenerator::getAllOutParams(const OperationPtr& op, int typeCtx)
+{
+ ParamDeclList params = op->outParameters();
+ ParamInfoList l;
+
+ for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ ParamInfo info;
+ info.name = (*p)->name();
+ info.type = (*p)->type();
+ info.typeStr = typeToString(info.type, op, (*p)->getMetaData(), (*p)->optional(), typeCtx);
+ info.optional = (*p)->optional();
+ info.tag = (*p)->tag();
+ info.param = *p;
+ l.push_back(info);
+ }
+
+ if(op->returnType())
+ {
+ ParamInfo info;
+ info.name = paramLabel("returnValue", params);
+ info.type = op->returnType();
+ info.typeStr = typeToString(info.type, op, op->getMetaData(), op->returnIsOptional(), typeCtx);
+ info.optional = op->returnIsOptional();
+ info.tag = op->returnTag();
+ l.push_back(info);
+ }
+
+ return l;
+}
+
+void
+SwiftGenerator::getOutParams(const OperationPtr& op, ParamInfoList& required, ParamInfoList& optional)
+{
+ const ParamInfoList params = getAllOutParams(op);
+ for(ParamInfoList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ if(p->optional)
+ {
+ optional.push_back(*p);
+ }
+ else
+ {
+ required.push_back(*p);
+ }
+ }
+
+ //
+ // Sort optional parameters by tag.
+ //
+ class SortFn
+ {
+ public:
+ static bool compare(const ParamInfo& lhs, const ParamInfo& rhs)
+ {
+ return lhs.tag < rhs.tag;
+ }
+ };
+ optional.sort(SortFn::compare);
+}
+
+void
+SwiftGenerator::writeMarshalInParams(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ ParamInfoList requiredInParams, optionalInParams;
+ getInParams(op, requiredInParams, optionalInParams);
+
+ out << "{ ostr in";
+ out.inc();
+ //
+ // Marshal parameters
+ // 1. required
+ // 2. optional
+ //
+
+ for(ParamInfoList::const_iterator q = requiredInParams.begin(); q != requiredInParams.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(out, q->type, op, "iceP_" + q->name, true);
+ }
+
+ for(ParamInfoList::const_iterator q = optionalInParams.begin(); q != optionalInParams.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(out, q->type, op, "iceP_" + q->name, true, q->tag);
+ }
+
+ if(op->sendsClasses(false))
+ {
+ out << nl << "ostr.writePendingValues()";
+ }
+ out.dec();
+ out << nl << "}";
+}
+
+void
+SwiftGenerator::writeMarshalOutParams(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ ParamInfoList requiredOutParams, optionalOutParams;
+ getOutParams(op, requiredOutParams, optionalOutParams);
+
+ out << "{ ostr in";
+ out.inc();
+ //
+ // Marshal parameters
+ // 1. required
+ // 2. optional (including optional return)
+ //
+
+ for(ParamInfoList::const_iterator q = requiredOutParams.begin(); q != requiredOutParams.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(out, q->type, op, "iceP_" + q->name, true);
+ }
+
+ for(ParamInfoList::const_iterator q = optionalOutParams.begin(); q != optionalOutParams.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(out, q->type, op, "iceP_" + q->name, true, q->tag);
+ }
+
+ if(op->returnsClasses(false))
+ {
+ out << nl << "ostr.writePendingValues()";
+ }
+
+ out.dec();
+ out << nl << "}";
+}
+
+void
+SwiftGenerator::writeUnmarshalOutParams(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ TypePtr returnType = op->returnType();
+
+ ParamInfoList requiredOutParams, optionalOutParams;
+ getOutParams(op, requiredOutParams, optionalOutParams);
+ const ParamInfoList allOutParams = getAllOutParams(op);
+ //
+ // Unmarshal parameters
+ // 1. required
+ // 2. return
+ // 3. optional (including optional return)
+ //
+ out << "{ istr in";
+ out.inc();
+ for(ParamInfoList::const_iterator q = requiredOutParams.begin(); q != requiredOutParams.end(); ++q)
+ {
+ string param;
+ if(isClassType(q->type))
+ {
+ out << nl << "var iceP_" << q->name << ": " << q->typeStr;
+ param = "iceP_" + q->name;
+ }
+ else
+ {
+ param = "let iceP_" + q->name + ": " + q->typeStr;
+ }
+ writeMarshalUnmarshalCode(out, q->type, op, param, false);
+ }
+
+ for(ParamInfoList::const_iterator q = optionalOutParams.begin(); q != optionalOutParams.end(); ++q)
+ {
+ string param;
+ if(isClassType(q->type))
+ {
+ out << nl << "var iceP_" << q->name << ": " << q->typeStr;
+ param = "iceP_" + q->name;
+ }
+ else
+ {
+ param = "let iceP_" + q->name + ": " + q->typeStr;
+ }
+ writeMarshalUnmarshalCode(out, q->type, op, param, false, q->tag);
+ }
+
+ if(op->returnsClasses(false))
+ {
+ out << nl << "try istr.readPendingValues()";
+ }
+
+ out << nl << "return ";
+ if(allOutParams.size() > 1)
+ {
+ out << spar;
+ }
+
+ if(returnType)
+ {
+ out << ("iceP_" + paramLabel("returnValue", op->outParameters()));
+ }
+
+ for(ParamInfoList::const_iterator q = allOutParams.begin(); q != allOutParams.end(); ++q)
+ {
+ if(q->param)
+ {
+ out << ("iceP_" + q->name);
+ }
+ }
+
+ if(allOutParams.size() > 1)
+ {
+ out << epar;
+ }
+
+ out.dec();
+ out << nl << "}";
+}
+
+void
+SwiftGenerator::writeUnmarshalInParams(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ ParamInfoList requiredInParams, optionalInParams;
+ getInParams(op, requiredInParams, optionalInParams);
+ const ParamInfoList allInParams = getAllInParams(op);
+ //
+ // Unmarshal parameters
+ // 1. required
+ // 3. optional
+ //
+ out << "{ istr in";
+ out.inc();
+ for(ParamInfoList::const_iterator q = requiredInParams.begin(); q != requiredInParams.end(); ++q)
+ {
+ if(q->param)
+ {
+ string param;
+ if(isClassType(q->type))
+ {
+ out << nl << "var iceP_" << q->name << ": " << q->typeStr;
+ param = "iceP_" + q->name;
+ }
+ else
+ {
+ param = "let iceP_" + q->name + ": " + q->typeStr;
+ }
+ writeMarshalUnmarshalCode(out, q->type, op, param, false);
+ }
+ }
+
+ for(ParamInfoList::const_iterator q = optionalInParams.begin(); q != optionalInParams.end(); ++q)
+ {
+ string param;
+ if(isClassType(q->type))
+ {
+ out << nl << "var iceP_" << q->name << ": " << q->typeStr;
+ param = "iceP_" + q->name;
+ }
+ else
+ {
+ param = "let iceP_" + q->name + ": " + q->typeStr;
+ }
+ writeMarshalUnmarshalCode(out, q->type, op, param, false, q->tag);
+ }
+
+ if(op->sendsClasses(false))
+ {
+ out << nl << "try istr.readPendingValues()";
+ }
+
+ out << nl << "return ";
+ if(allInParams.size() > 1)
+ {
+ out << spar;
+ }
+
+ for(ParamInfoList::const_iterator q = allInParams.begin(); q != allInParams.end(); ++q)
+ {
+ out << ("iceP_" + q->name);
+ }
+
+ if(allInParams.size() > 1)
+ {
+ out << epar;
+ }
+
+ out.dec();
+ out << nl << "}";
+}
+
+void
+SwiftGenerator::writeUnmarshalUserException(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ const string swiftModule = getSwiftModule(getTopLevelModule(ContainedPtr::dynamicCast(op)));
+ ExceptionList throws = op->throws();
+ throws.sort();
+ throws.unique();
+
+ out << "{ ex in";
+ out.inc();
+ out << nl << "do ";
+ out << sb;
+ out << nl << "throw ex";
+ out << eb;
+ for(ExceptionList::const_iterator q = throws.begin(); q != throws.end(); ++q)
+ {
+ out << " catch let error as " << getUnqualified(getAbsolute(*q), swiftModule) << sb;
+ out << nl << "throw error";
+ out << eb;
+ }
+ out << " catch is " << getUnqualified("Ice.UserException", swiftModule) << " {}";
+ out.dec();
+ out << nl << "}";
+}
+
+void
+SwiftGenerator::writeSwiftAttributes(::IceUtilInternal::Output& out, const StringList& metadata)
+{
+ static const string prefix = "swift:attribute:";
+ for(StringList::const_iterator q = metadata.begin(); q != metadata.end(); ++q)
+ {
+ if(q->find(prefix) == 0 && q->size() > prefix.size())
+ {
+ out << nl << q->substr(prefix.size());
+ }
+ }
+}
+
+void
+SwiftGenerator::writeProxyOperation(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ const string opName = fixIdent(op->name());
+
+ const ParamInfoList allInParams = getAllInParams(op);
+ const ParamInfoList allOutParams = getAllOutParams(op);
+ const ExceptionList allExceptions = op->throws();
+
+ const string swiftModule = getSwiftModule(getTopLevelModule(ContainedPtr::dynamicCast(op)));
+
+ out << sp;
+ writeOpDocSummary(out, op, false, false);
+ out << nl << "func " << opName;
+ out << spar;
+ for(ParamInfoList::const_iterator q = allInParams.begin(); q != allInParams.end(); ++q)
+ {
+ if(allInParams.size() == 1)
+ {
+ out << ("_ iceP_" + q->name + ": " + q->typeStr + (q->optional ? " = nil" : ""));
+ }
+ else
+ {
+ out << (q->name + " iceP_" + q->name + ": " + q->typeStr + (q->optional ? " = nil" : ""));
+ }
+ }
+ out << ("context: " + getUnqualified("Ice.Context", swiftModule) + "? = nil");
+
+ out << epar;
+ out << " throws";
+
+ if(allOutParams.size() > 0)
+ {
+ out << " -> " << operationReturnType(op);
+ }
+
+ out << sb;
+
+ //
+ // Invoke
+ //
+ out << sp;
+ out << nl;
+ if(allOutParams.size() > 0)
+ {
+ out << "return ";
+ }
+ out << "try _impl._invoke(";
+
+ out.useCurrentPosAsIndent();
+ out << "operation: \"" << op->name() << "\",";
+ out << nl << "mode: " << modeToString(op->sendMode()) << ",";
+
+ if(op->format() != DefaultFormat)
+ {
+ out << nl << "format: " << opFormatTypeToString(op);
+ out << ",";
+ }
+
+ if(allInParams.size() > 0)
+ {
+ out << nl << "write: ";
+ writeMarshalInParams(out, op);
+ out << ",";
+ }
+
+ if(allOutParams.size() > 0)
+ {
+ out << nl << "read: ";
+ writeUnmarshalOutParams(out, op);
+ out << ",";
+ }
+
+ if(allExceptions.size() > 0)
+ {
+ out << nl << "userException:";
+ writeUnmarshalUserException(out, op);
+ out << ",";
+ }
+
+ out << nl << "context: context)";
+ out.restoreIndent();
+
+ out << eb;
+}
+
+void
+SwiftGenerator::writeProxyAsyncOperation(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ const string opName = fixIdent(op->name() + "Async");
+
+ const ParamInfoList allInParams = getAllInParams(op);
+ const ParamInfoList allOutParams = getAllOutParams(op);
+ const ExceptionList allExceptions = op->throws();
+
+ const string swiftModule = getSwiftModule(getTopLevelModule(ContainedPtr::dynamicCast(op)));
+
+ out << sp;
+ writeOpDocSummary(out, op, true, false);
+ out << nl << "func " << opName;
+ out << spar;
+ for(ParamInfoList::const_iterator q = allInParams.begin(); q != allInParams.end(); ++q)
+ {
+ if(allInParams.size() == 1)
+ {
+ out << ("_ iceP_" + q->name + ": " + q->typeStr + (q->optional ? " = nil" : ""));
+ }
+ else
+ {
+ out << (q->name + " iceP_" + q->name + ": " + q->typeStr + (q->optional ? " = nil" : ""));
+ }
+ }
+ out << "context: " + getUnqualified("Ice.Context", swiftModule) + "? = nil";
+ out << "sentOn: Dispatch.DispatchQueue? = PromiseKit.conf.Q.return";
+ out << "sentFlags: Dispatch.DispatchWorkItemFlags? = nil";
+ out << "sent: ((Swift.Bool) -> Swift.Void)? = nil";
+
+ out << epar;
+ out << " -> PromiseKit.Promise<";
+ if(allOutParams.empty())
+ {
+ out << "Swift.Void";
+ }
+ else
+ {
+ out << operationReturnType(op);
+ }
+ out << ">";
+
+ out << sb;
+
+ //
+ // Invoke
+ //
+ out << sp;
+ out << nl << "return _impl._invokeAsync(";
+
+ out.useCurrentPosAsIndent();
+ out << "operation: \"" << op->name() << "\",";
+ out << nl << "mode: " << modeToString(op->sendMode()) << ",";
+
+ if(op->format() != DefaultFormat)
+ {
+ out << nl << "format: " << opFormatTypeToString(op);
+ out << ",";
+ }
+
+ if(allInParams.size() > 0)
+ {
+ out << nl << "write: ";
+ writeMarshalInParams(out, op);
+ out << ",";
+ }
+
+ if(allOutParams.size() > 0)
+ {
+ out << nl << "read: ";
+ writeUnmarshalOutParams(out, op);
+ out << ",";
+ }
+
+ if(allExceptions.size() > 0)
+ {
+ out << nl << "userException:";
+ writeUnmarshalUserException(out, op);
+ out << ",";
+ }
+
+ out << nl << "context: context,";
+ out << nl << "sentOn: sentOn,";
+ out << nl << "sentFlags: sentFlags,";
+ out << nl << "sent: sent)";
+ out.restoreIndent();
+
+ out << eb;
+}
+
+void
+SwiftGenerator::writeDispatchOperation(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ const string opName = op->name();
+
+ const ParamInfoList allInParams = getAllInParams(op);
+ const ParamInfoList allOutParams = getAllOutParams(op);
+ const ExceptionList allExceptions = op->throws();
+
+ const string swiftModule = getSwiftModule(getTopLevelModule(ContainedPtr::dynamicCast(op)));
+
+ out << sp;
+ out << nl << "func _iceD_" << opName;
+ out << spar;
+ out << ("incoming inS: " + getUnqualified("Ice.Incoming", swiftModule));
+ out << ("current: " + getUnqualified("Ice.Current", swiftModule));
+ out << epar;
+
+ out << " throws";
+
+ out << sb;
+ if(allInParams.empty())
+ {
+ out << nl << "try inS.readEmptyParams()";
+ }
+ else
+ {
+ out << nl << "let " << operationInParamsDeclaration(op) << " = try inS.read ";
+ writeUnmarshalInParams(out, op);
+ }
+
+ if(op->format() != DefaultFormat)
+ {
+ out << nl << "inS.setFormat(" << opFormatTypeToString(op) << ");";
+ }
+
+ out << sp;
+ out << nl;
+ if(!allOutParams.empty())
+ {
+ out << "let " << operationReturnDeclaration(op) << " = ";
+ }
+ out << "try self." << fixIdent(opName);
+
+ out << spar;
+ for(ParamInfoList::const_iterator q = allInParams.begin(); q != allInParams.end(); ++q)
+ {
+ out << (q->name + ": iceP_" + q->name);
+ }
+ out << "current: current";
+ out << epar;
+
+ out << sp;
+ if(allOutParams.empty())
+ {
+ out << nl << "inS.writeEmptyParams()";
+ }
+ else
+ {
+ out << nl << "inS.write ";
+ writeMarshalOutParams(out, op);
+ }
+
+ out << eb;
+}
+
+void
+SwiftGenerator::writeDispatchAsyncOperation(::IceUtilInternal::Output& out, const OperationPtr& op)
+{
+ const ParamInfoList allInParams = getAllInParams(op);
+ const ParamInfoList allOutParams = getAllOutParams(op);
+
+ const string swiftModule = getSwiftModule(getTopLevelModule(ContainedPtr::dynamicCast(op)));
+
+ out << sp;
+ out << nl << "func _iceD_" << op->name();
+ out << spar;
+ out << ("incoming inS: " + getUnqualified("Ice.Incoming", swiftModule));
+ out << ("current: " + getUnqualified("Ice.Current", swiftModule));
+ out << epar;
+
+ out << " throws";
+
+ out << sb;
+ if(allInParams.empty())
+ {
+ out << nl << "try inS.readEmptyParams()";
+ }
+ else
+ {
+ out << nl << "let " << operationInParamsDeclaration(op) << " = try inS.read ";
+ writeUnmarshalInParams(out, op);
+ }
+
+ if(op->format() != DefaultFormat)
+ {
+ out << nl << "inS.setFormat(" << opFormatTypeToString(op) << ");";
+ }
+
+ out << sp;
+ out << nl;
+ out << "firstly";
+ out << sb;
+ out << nl << fixIdent(op->name() + (operationIsAmd(op) ? "Async" : ""));
+
+ out << spar;
+ for(ParamInfoList::const_iterator q = allInParams.begin(); q != allInParams.end(); ++q)
+ {
+ out << (q->name + ": iceP_" + q->name);
+ }
+ out << "current: current";
+ out << epar;
+ out << eb;
+
+ out << ".done(on: nil)";
+ out << sb;
+ if(allOutParams.empty())
+ {
+ out << nl << "inS.writeEmptyParams()";
+ }
+ else
+ {
+ out << " " << operationReturnDeclaration(op) << " in";
+ out << nl << "inS.write ";
+ writeMarshalOutParams(out, op);
+ }
+ out << eb;
+
+ out << ".catch(on: nil)";
+ out << sb;
+ out << " err in";
+ out << nl << "inS.exception(err)";
+ out << eb;
+
+ out << eb;
+}
+
+bool
+SwiftGenerator::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ validate(p);
+ return true;
+}
+
+bool
+SwiftGenerator::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p)
+{
+ validate(p);
+ return true;
+}
+
+bool
+SwiftGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p)
+{
+ validate(p);
+ return true;
+}
+
+void
+SwiftGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p)
+{
+ validate(p);
+}
+
+void
+SwiftGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p)
+{
+ validate(p);
+}
+
+void
+SwiftGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p)
+{
+ validate(p);
+}
+
+void
+SwiftGenerator::MetaDataVisitor::visitConst(const ConstPtr& p)
+{
+ validate(p);
+}
+
+void
+SwiftGenerator::MetaDataVisitor::validate(const ContainedPtr&)
+{
+}