diff options
author | Jose <jose@zeroc.com> | 2019-05-28 20:13:19 +0200 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2019-05-28 20:13:19 +0200 |
commit | 62c538287e6ea5ad1a1a3e0958f9c7deb3c5712e (patch) | |
tree | c6b39dc8d73c21d4b5bbb5796ad3301166c137ba /cpp/src | |
parent | Use nil as default value for optional parameters (diff) | |
download | ice-62c538287e6ea5ad1a1a3e0958f9c7deb3c5712e.tar.bz2 ice-62c538287e6ea5ad1a1a3e0958f9c7deb3c5712e.tar.xz ice-62c538287e6ea5ad1a1a3e0958f9c7deb3c5712e.zip |
Add Swift documentation comments
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/slice2swift/Gen.cpp | 205 | ||||
-rw-r--r-- | cpp/src/slice2swift/SwiftUtil.cpp | 694 | ||||
-rw-r--r-- | cpp/src/slice2swift/SwiftUtil.h | 27 |
3 files changed, 924 insertions, 2 deletions
diff --git a/cpp/src/slice2swift/Gen.cpp b/cpp/src/slice2swift/Gen.cpp index ca30448b6fa..1de3ad6be19 100644 --- a/cpp/src/slice2swift/Gen.cpp +++ b/cpp/src/slice2swift/Gen.cpp @@ -363,6 +363,7 @@ Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) } out << sp; + writeDocSummary(out, p); writeSwiftAttributes(out, p->getMetaData()); out << nl << "open class " << fixIdent(name) << ": "; if(base) @@ -408,6 +409,9 @@ Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) writeMemberwiseInitializer(out, members, baseMembers, allMembers, p, p->isLocal(), rootClass, extraParams); out << sp; + out << nl << "/// Returns the Slice type ID of this exception."; + out << nl << "///"; + out << nl << "/// - returns: `Swift.String` - the Slice type ID of this exception."; out << nl << "open override class func ice_staticId() -> Swift.String"; out << sb; out << nl << "return \"" << p->scoped() << "\""; @@ -416,6 +420,9 @@ Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) if(p->isLocal()) { out << sp; + out << nl << "/// Returns a string representation of this exception"; + out << nl << "///"; + out << nl << "/// - returns: `Swift.String` - The string representaton of this exception."; out << nl << "open override func ice_print() -> Swift.String"; out << sb; out << nl << "return _" << name << "Description"; @@ -467,6 +474,10 @@ Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) if(preserved && !basePreserved) { out << sp; + out << nl << "/// Returns the sliced data if the exception has a preserved-slice base class and has been"; + out << nl << "/// sliced during un-marshaling, nil is returned otherwise."; + out << nl << "///"; + out << nl << "/// - returns: `Ice.SlicedData` - The sliced data."; out << nl << "open override func ice_getSlicedData() -> " << getUnqualified("Ice.SlicedData", swiftModule) << "?" << sb; out << nl << "return _slicedData"; @@ -506,6 +517,7 @@ Gen::TypesVisitor::visitStructStart(const StructPtr& p) bool isClass = containsClassMembers(p); out << sp; + writeDocSummary(out, p); writeSwiftAttributes(out, p->getMetaData()); out << nl << "public " << (isClass ? "class " : "struct ") << name; if(legalKeyType) @@ -518,14 +530,19 @@ Gen::TypesVisitor::visitStructStart(const StructPtr& p) writeDefaultInitializer(out, false, true); writeMemberwiseInitializer(out, members, p); - out << eb << nl; + out << eb; if(!p->isLocal()) { + out << sp; + out << nl << "/// An `Ice.InputStream` extension to read `" << name << "` structured values from the stream."; out << nl << "public extension " << getUnqualified("Ice.InputStream", swiftModule); out << sb; out << sp; + out << nl << "/// Read a `" << name << "` structured value from the stream."; + out << nl << "///"; + out << nl << "/// - returns: `" << name << "` - The structured value read from the stream."; out << nl << "func read() throws -> " << name; out << sb; out << nl << (isClass ? "let" : "var") << " v = " << name << "()"; @@ -537,6 +554,11 @@ Gen::TypesVisitor::visitStructStart(const StructPtr& p) out << eb; out << sp; + out << nl << "/// Read an optional `" << name << "?` structured value from the stream."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Swift.Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - returns: `" << name << "?` - The structured value read from the stream."; out << nl << "func read(tag: Swift.Int32) throws -> " << name << "?"; out << sb; out << nl << "guard try readOptional(tag: tag, expectedFormat: " << optionalFormat << ") else"; @@ -557,9 +579,13 @@ Gen::TypesVisitor::visitStructStart(const StructPtr& p) out << eb; out << sp; + out << nl << "/// An `Ice.OutputStream` extension to write `" << name << "` structured values from the stream."; out << nl << "public extension " << getUnqualified("Ice.OutputStream", swiftModule); out << sb; + out << nl << "/// Write a `" << name << "` structured value to the stream."; + out << nl << "///"; + out << nl << "/// - parameter _: `" << name << "` - The value to write to the stream."; out << nl << "func write(_ v: " << name << ")" << sb; for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { @@ -568,6 +594,11 @@ Gen::TypesVisitor::visitStructStart(const StructPtr& p) out << eb; out << sp; + out << nl << "/// Write an optional `" << name << "?` structured value to the stream."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Swift.Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - parameter value: `" << name << "?` - The value to write to the stream."; out << nl << "func write(tag: Swift.Int32, value: " << name << "?)" << sb; out << nl << "if let v = value" << sb; out << nl << "if writeOptional(tag: tag, format: " << optionalFormat << ")" << sb; @@ -604,6 +635,7 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p) BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); out << sp; + writeDocSummary(out, p); out << nl << "public typealias " << fixIdent(name) << " = "; if(builtin && builtin->kind() == Builtin::KindByte) @@ -631,9 +663,16 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p) const string optionalFormat = getUnqualified(getOptionalFormat(p), swiftModule); out << sp; + out << nl << "/// Helper class to read and write `" << fixIdent(name) << "` sequence values from"; + out << nl << "/// `Ice.InputStream` and `Ice.OutputStream`."; out << nl << "public struct " << name << "Helper"; out << sb; + out << nl << "/// Read a `" << fixIdent(name) << "` sequence from the stream."; + out << nl << "///"; + out << nl << "/// - parameter istr: `Ice.InputStream` - The stream to read from."; + out << nl << "///"; + out << nl << "/// - returns: `" << fixIdent(name) << "` - The sequence read from the stream."; out << nl << "public static func read(from istr: " << istr << ") throws -> " << fixIdent(name); out << sb; @@ -662,6 +701,13 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p) out << nl << "return v"; out << eb; + out << nl << "/// Read an optional `" << fixIdent(name) << "?` sequence from the stream."; + out << nl << "///"; + out << nl << "/// - parameter istr: `Ice.InputStream` - The stream to read from."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Swift.Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - returns: `" << fixIdent(name) << "` - The sequence read from the stream."; out << nl << "public static func read(from istr: " << istr << ", tag: Swift.Int32) throws -> " << fixIdent(name) << "?"; out << sb; @@ -681,6 +727,11 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p) out << eb; out << sp; + out << nl << "/// Wite a `" << fixIdent(name) << "` sequence to the stream."; + out << nl << "///"; + out << nl << "/// - parameter ostr: `Ice.OuputStream` - The stream to write to."; + out << nl << "///"; + out << nl << "/// - parameter value: `" << fixIdent(name) << "` - The sequence value to write to the stream."; out << nl << "public static func write(to ostr: " << ostr << ", value v: " << fixIdent(name) << ")"; out << sb; out << nl << "ostr.write(size: v.count)"; @@ -691,6 +742,13 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p) out << eb; out << sp; + out << nl << "/// Wite an optional `" << fixIdent(name) << "?` sequence to the stream."; + out << nl << "///"; + out << nl << "/// - parameter ostr: `Ice.OuputStream` - The stream to write to."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - parameter value: `" << fixIdent(name) << "` The sequence value to write to the stream."; out << nl << "public static func write(to ostr: " << ostr << ", tag: Swift.Int32, value v: " << fixIdent(name) << "?)"; out << sb; @@ -737,6 +795,7 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) const string keyType = typeToString(p->keyType(), p, p->keyMetaData(), false, typeCtx); const string valueType = typeToString(p->valueType(), p, p->valueMetaData(), false, typeCtx); out << sp; + writeDocSummary(out, p); out << nl << "public typealias " << fixIdent(name) << " = [" << keyType << ": " << valueType << "]"; if(p->isLocal()) @@ -752,9 +811,16 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) const int minWireSize = p->keyType()->minWireSize() + p->valueType()->minWireSize(); out << sp; + out << nl << "/// Helper class to read and write `" << fixIdent(name) << "` dictionary values from"; + out << nl << "/// `Ice.InputStream` and `Ice.OutputStream`."; out << nl << "public struct " << name << "Helper"; out << sb; + out << nl << "/// Read a `" << fixIdent(name) << "` dictionary from the stream."; + out << nl << "///"; + out << nl << "/// - parameter istr: `Ice.InputStream` - The stream to read from."; + out << nl << "///"; + out << nl << "/// - returns: `" << fixIdent(name) << "` - The dictionary read from the stream."; out << nl << "public static func read(from istr: " << istr << ") throws -> " << fixIdent(name); out << sb; out << nl << "let sz = try Swift.Int(istr.readSize())"; @@ -794,6 +860,13 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) out << nl << "return v"; out << eb; + out << nl << "/// Read an optional `" << fixIdent(name) << "?` dictionary from the stream."; + out << nl << "///"; + out << nl << "/// - parameter istr: `Ice.InputStream` - The stream to read from."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - returns: `" << fixIdent(name) << "` - The dictionary read from the stream."; out << nl << "public static func read(from istr: " << istr << ", tag: Swift.Int32) throws -> " << fixIdent(name) << "?"; out << sb; @@ -813,6 +886,11 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) out << eb; out << sp; + out << nl << "/// Wite a `" << fixIdent(name) << "` dictionary to the stream."; + out << nl << "///"; + out << nl << "/// - parameter ostr: `Ice.OuputStream` - The stream to write to."; + out << nl << "///"; + out << nl << "/// - parameter value: `" << fixIdent(name) << "` - The dictionary value to write to the stream."; out << nl << "public static func write(to ostr: " << ostr << ", value v: " << fixIdent(name) << ")"; out << sb; out << nl << "ostr.write(size: v.count)"; @@ -824,6 +902,13 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) out << eb; out << sp; + out << nl << "/// Wite an optional `" << fixIdent(name) << "?` dictionary to the stream."; + out << nl << "///"; + out << nl << "/// - parameter ostr: `Ice.OuputStream` - The stream to write to."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - parameter value: `" << fixIdent(name) << "` - The dictionary value to write to the stream."; out << nl << "public static func write(to ostr: " << ostr << ", tag: Swift.Int32, value v: " << fixIdent(name) << "?)"; out << sb; @@ -862,12 +947,20 @@ Gen::TypesVisitor::visitEnum(const EnumPtr& p) const string optionalFormat = getOptionalFormat(p); out << sp; + writeDocSummary(out, p); writeSwiftAttributes(out, p->getMetaData()); out << nl << "public enum " << name << ": " << enumType; out << sb; for(EnumeratorList::const_iterator en = enumerators.begin(); en != enumerators.end(); ++en) { + StringList sl = splitComment((*en)->comment()); + out << nl << "/// " << fixIdent((*en)->name()); + if(!sl.empty()) + { + out << " "; + writeDocLines(out, sl, false); + } out << nl << "case " << fixIdent((*en)->name()) << " = " << (*en)->value(); } @@ -883,6 +976,9 @@ Gen::TypesVisitor::visitEnum(const EnumPtr& p) out << sb; out << sp; + out << nl << "/// Read an enumerated value."; + out << nl << "///"; + out << nl << "/// - returns: `" << name << "` - The enumarated value."; out << nl << "func read() throws -> " << name; out << sb; out << nl << "let rawValue: " << enumType << " = try read(enumMaxValue: " << p->maxValue() << ")"; @@ -894,6 +990,11 @@ Gen::TypesVisitor::visitEnum(const EnumPtr& p) out << eb; out << sp; + out << nl << "/// Read an optional enumerated value from the stream."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - returns: `" << name << "` - The enumerated value."; out << nl << "func read(tag: Swift.Int32) throws -> " << name << "?"; out << sb; out << nl << "guard try readOptional(tag: tag, expectedFormat: " << optionalFormat << ") else"; @@ -910,12 +1011,20 @@ Gen::TypesVisitor::visitEnum(const EnumPtr& p) out << sb; out << sp; + out << nl << "/// Writes an enumerated value to the stream."; + out << nl << "///"; + out << nl << "/// parameter _: `" << name << "` - The enumerator to write."; out << nl << "func write(_ v: " << name << ")"; out << sb; out << nl << "write(enum: v.rawValue, maxValue: " << p->maxValue() << ")"; out << eb; out << sp; + out << nl << "/// Writes an optional enumerated value to the stream."; + out << nl << "///"; + out << nl << "/// parameter tag: `Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// parameter _: `" << name << "` - The enumerator to write."; out << nl << "func write(tag: Swift.Int32, value: " << name << "?)"; out << sb; out << nl << "guard let v = value else"; @@ -935,6 +1044,7 @@ Gen::TypesVisitor::visitConst(const ConstPtr& p) const TypePtr type = p->type(); const string swiftModule = getSwiftModule(getTopLevelModule(ContainedPtr::dynamicCast(p))); + writeDocSummary(out, p); out << nl << "public let " << name << ": " << typeToString(type, p) << " = "; writeConstantValue(out, type, p->valueType(), p->value(), p->getMetaData(), swiftModule); out << nl; @@ -985,6 +1095,7 @@ Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) const string prxI = name + "PrxI"; out << sp; + writeProxyDocSummary(out, p, swiftModule); out << nl << "public protocol " << prx << ":"; if(!hasBase) { @@ -1005,6 +1116,10 @@ Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) out << eb; out << sp; + out << nl << "/// Returns the Slice type id of the interface or class associated with this proxy class."; + out << nl << "///"; + out << nl << "/// - returns: `String` the Slice type id of the interface or class associated with"; + out << nl << "/// this proxy type"; out << nl; if(swiftModule == "Ice") { @@ -1028,6 +1143,24 @@ Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) // checkedCast // out << sp; + out << nl << "/// Casts a proxy to the requested type. This call contacts the server and verifies that the object"; + out << nl << "/// implements this type."; + out << nl << "///"; + out << nl << "/// It will throw a local exception if a communication error occurs. You can optionally supply a"; + out << nl << "/// facet name and a context map."; + out << nl << "///"; + out << nl << "/// - parameter prx: `Ice.ObjectPrx` - The proxy to be cast."; + out << nl << "///"; + out << nl << "/// - parameter type: `" << prx << ".Protocol` - The proxy type to cast to."; + out << nl << "///"; + out << nl << "/// - parameter facet: `String` - The optional name of the desired facet."; + out << nl << "///"; + out << nl << "/// - parameter context: `Ice.Context` The optional context dictionary for the remote invocation."; + out << nl << "///"; + out << nl << "/// - returns: `" << prx << "` - A proxy with the requested type or nil if the objet does not"; + out << nl << "/// support this type."; + out << nl << "///"; + out << nl << "/// - throws: `Ice.LocalException` if a communication error occurs."; out << nl << "public func checkedCast" << spar << ("prx: " + getUnqualified("Ice.ObjectPrx", swiftModule)) << ("type: " + prx + ".Protocol") @@ -1042,6 +1175,16 @@ Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) // uncheckedCast // out << sp; + out << nl << "/// Downcasts the given proxy to this type without contacting the remote server."; + out << nl << "///"; + out << nl << "///"; + out << nl << "/// - parameter prx: `Ice.ObjectPrx` The proxy to be cast."; + out << nl << "///"; + out << nl << "/// - parameter type: `" << prx << ".Protocol` - The proxy type to cast to."; + out << nl << "///"; + out << nl << "/// - parameter facet: `String` - The optional name of the desired facet"; + out << nl << "///"; + out << nl << "/// - returns: `" << prx << "` - A proxy with the requested type"; out << nl << "public func uncheckedCast" << spar << ("prx: " + getUnqualified("Ice.ObjectPrx", swiftModule)) << ("type: " + prx + ".Protocol") @@ -1054,6 +1197,11 @@ Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) // ice_staticId // out << sp; + out << nl << "/// Returns the Slice type id of the interface or class associated with this proxy type."; + out << nl << "///"; + out << nl << "/// parameter type: `" << prx << ".Protocol` - The proxy type to retrieve the type id."; + out << nl << "///"; + out << nl << "/// returns: `String` - The type id of the interface or class associated with this proxy type."; out << nl << "public func ice_staticId" << spar << ("_ type: " + prx + ".Protocol") << epar << " -> Swift.String"; out << sb; out << nl << "return " << prxI << ".ice_staticId()"; @@ -1063,15 +1211,28 @@ Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) // InputStream extension // out << sp; + out << nl << "/// Extension to `Ice.InputStream` class to support reading proxy of type"; + out << nl << "/// `" << prx << "`."; out << nl << "public extension " << getUnqualified("Ice.InputStream", swiftModule); out << sb; + out << nl << "/// Extracts a proxy from the stream. The stream must have been initialized with a communicator."; + out << nl << "///"; + out << nl << "/// - parameter type: `" << prx << ".Protocol` - The type of the proxy to be extracted."; + out << nl << "///"; + out << nl << "/// - returns: `" << prx << "?` - The extracted proxy"; out << nl << "func read(_ type: " << prx << ".Protocol) throws -> " << prx << "?"; out << sb; out << nl << "return try read() as " << prxI << "?"; out << eb; - out << sp; + out << nl << "/// Extracts a proxy from the stream. The stream must have been initialized with a communicator."; + out << nl << "///"; + out << nl << "/// - parameter tag: `Int32` - The numeric tag associated with the value."; + out << nl << "///"; + out << nl << "/// - parameter type: `" << prx << ".Protocol` - The type of the proxy to be extracted."; + out << nl << "///"; + out << nl << "/// - returns: `" << prx << "` - The extracted proxy."; out << nl << "func read(tag: Swift.Int32, type: " << prx << ".Protocol) throws -> " << prx << "?"; out << sb; out << nl << "return try read(tag: tag) as " << prxI << "?"; @@ -1080,6 +1241,7 @@ Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) out << eb; out << sp; + writeProxyDocSummary(out, p, swiftModule); out << nl << "public extension " << prx; out << sb; @@ -1173,6 +1335,7 @@ Gen::ValueVisitor::visitClassDefStart(const ClassDefPtr& p) out << eb; out << sp; + writeDocSummary(out, p); writeSwiftAttributes(out, p->getMetaData()); out << nl << "open class " << fixIdent(name) << ": "; if(base) @@ -1206,11 +1369,17 @@ Gen::ValueVisitor::visitClassDefStart(const ClassDefPtr& p) writeMemberwiseInitializer(out, members, baseMembers, allMembers, p, p->isLocal(), !base); out << sp; + out << nl << "/// Returns the Slice type ID of the most-derived interface supported by this object."; + out << nl << "///"; + out << nl << "/// - returns: `String` - The Slice type ID of the most-derived interface supported by this object"; out << nl << "open override func ice_id() -> Swift.String" << sb; out << nl << "return \"" << p->scoped() << "\""; out << eb; out << sp; + out << nl << "/// Returns the Slice type ID of the interface supported by this object."; + out << nl << "///"; + out << nl << "/// - returns: `String` - The Slice type ID of the interface supported by this object."; out << nl << "open override class func ice_staticId() -> Swift.String" << sb; out << nl << "return \"" << p->scoped() << "\""; out << eb; @@ -1268,6 +1437,10 @@ Gen::ValueVisitor::visitClassDefStart(const ClassDefPtr& p) if(preserved && !basePreserved) { out << sp; + out << nl << "/// Returns the sliced data if the value has a preserved-slice base class and has been sliced"; + out << nl << "/// during un-marshaling of the value, nil is returned otherwise."; + out << nl << "///"; + out << nl << "/// returns: `Ice.SlicedData?` - The sliced data or nil"; out << nl << "open override func ice_getSlicedData() -> " << getUnqualified("Ice.SlicedData?", swiftModule) << sb; out << nl << "return _slicedData"; @@ -1347,6 +1520,7 @@ Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) const string name = fixIdent(getUnqualified(getAbsolute(p), swiftModule) + (p->isInterface() ? "" : "Disp")); out << sp; + writeDocSummary(out, p); out << nl << "public protocol " << name << ":"; if(!hasBase) @@ -1387,6 +1561,7 @@ Gen::ObjectVisitor::visitOperation(const OperationPtr& op) const ExceptionList allExceptions = op->throws(); out << sp; + writeOpDocSummary(out, op, isAmd, true); out << nl << "func " << opName; out << spar; for(ParamInfoList::const_iterator q = allInParams.begin(); q != allInParams.end(); ++q) @@ -1461,23 +1636,43 @@ Gen::ObjectExtVisitor::visitClassDefStart(const ClassDefPtr& p) ids << "]"; out << sp; + writeServantDocSummary(out, p, swiftModule); out << nl << "public extension " << fixIdent(name); out << sb; out << sp; + out << nl << "/// Returns the Slice type ID of the most-derived interface supported by this object."; + out << nl << "///"; + out << nl << "/// parameter current: `Ice.Current` - The Current object for the invocation."; + out << nl << "///"; + out << nl << "/// - returns: `String` - The Slice type ID of the most-derived interface supported by this object"; out << nl << "func ice_id(current _: Current) throws -> Swift.String"; out << sb; out << nl << "return \"" << p->scoped() << "\""; out << eb; out << sp; + out << nl << "/// Returns the Slice type IDs of the interfaces supported by this object"; + out << nl << "///"; + out << nl << "/// - parameter current: `Ice.Current` The Current object for the invocation."; + out << nl << "///"; + out << nl << "/// - returns: `[Swift.String]` The Slice type IDs of the interfaces supported by this object,"; + out << nl << "/// in base-to-derived order."; out << nl << "func ice_ids(current _: Current) throws -> [Swift.String]"; out << sb; out << nl << "return " << ids.str(); out << eb; out << sp; + out << nl << "/// Tests whether this object supports a specific Slice interface."; + out << nl << "///"; + out << nl << "/// - parameter s: `Swift.String` - The name of the interface to be check."; + out << nl << "///"; + out << nl << "/// - parameter current: `Ice.Current` - The Current object for the invocation."; + out << nl << "///"; + out << nl << "/// - returns: `Bool` - True if this object supports the interface specified by s or derives"; + out << nl << "/// from the interface specified by s."; out << nl << "func ice_isA(s: Swift.String, current _: Current) throws -> Swift.Bool"; out << sb; out << nl << "return " << ids.str() << ".contains(s)"; @@ -1582,6 +1777,9 @@ Gen::LocalObjectVisitor::visitClassDefStart(const ClassDefPtr& p) const ParamDeclList params = op->parameters(); out << sp; + writeDocSummary(out, p); + out << nl << "///"; + writeOpDocSummary(out, op, false, false, true); out << nl << "public typealias " << name << " = "; out << spar; for(ParamDeclList::const_iterator i = params.begin(); i != params.end(); ++i) @@ -1654,6 +1852,7 @@ Gen::LocalObjectVisitor::visitClassDefStart(const ClassDefPtr& p) // Local interfaces and local classes map to Swift protocol // out << sp; + writeDocSummary(out, p); out << nl << "public protocol " << fixIdent(name) << ":"; if(bases.empty()) { @@ -1691,6 +1890,7 @@ Gen::LocalObjectVisitor::visitOperation(const OperationPtr& p) int typeCtx = TypeContextInParam | TypeContextLocal; out << sp; + writeOpDocSummary(out, p, false, false, true); writeSwiftAttributes(out, p->getMetaData()); out << nl << "func " << name; out << spar; @@ -1757,6 +1957,7 @@ Gen::LocalObjectVisitor::visitOperation(const OperationPtr& p) if(p->hasMetaData("async-oneway")) { out << sp; + writeOpDocSummary(out, p, true, false, true); out << nl << "func " << name << "Async"; out << spar; for(ParamDeclList::const_iterator i = inParams.begin(); i != inParams.end(); ++i) diff --git a/cpp/src/slice2swift/SwiftUtil.cpp b/cpp/src/slice2swift/SwiftUtil.cpp index dbf4b9452a2..936ae19afb8 100644 --- a/cpp/src/slice2swift/SwiftUtil.cpp +++ b/cpp/src/slice2swift/SwiftUtil.cpp @@ -213,6 +213,697 @@ Slice::getTopLevelModule(const TypePtr& 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); + } + } + + const ParamInfoList allInParams = getAllInParams(p); + 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 invocation."; + } + else + { + out << nl << "/// - parameter context: `Ice.Context` Optional request context."; + } + } + + 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` - Promise object that "; + if(dispatch) + { + out << "must be resolved with the return values of the dispatch."; + } + else + { + out << "will be resolved with the return values of the invocation."; + } + } + else + { + const ParamInfoList allOutParams = getAllOutParams(p); + 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: a tuple with the following fields:"; + for(ParamInfoList::const_iterator q = allOutParams.begin(); q != allOutParams.end(); ++q) + { + 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; @@ -873,6 +1564,7 @@ SwiftGenerator::writeMembers(IceUtilInternal::Output& out, 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) @@ -1754,6 +2446,7 @@ SwiftGenerator::writeProxyOperation(::IceUtilInternal::Output& out, const Operat 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) @@ -1839,6 +2532,7 @@ SwiftGenerator::writeProxyAsyncOperation(::IceUtilInternal::Output& out, const O 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) diff --git a/cpp/src/slice2swift/SwiftUtil.h b/cpp/src/slice2swift/SwiftUtil.h index 951e33a9e38..645c36b9a3f 100644 --- a/cpp/src/slice2swift/SwiftUtil.h +++ b/cpp/src/slice2swift/SwiftUtil.h @@ -37,6 +37,18 @@ struct ParamInfo typedef std::list<ParamInfo> ParamInfoList; +struct DocElements +{ + StringList overview; + bool deprecated; + StringList deprecateReason; + StringList misc; + StringList seeAlso; + StringList returns; + std::map<std::string, StringList> params; + std::map<std::string, StringList> exceptions; +}; + class SwiftGenerator : private IceUtil::noncopyable { public: @@ -47,6 +59,21 @@ public: protected: + void trimLines(StringList&); + StringList splitComment(const std::string&); + bool parseCommentLine(const std::string&, const std::string&, bool, std::string&, std::string&); + DocElements parseComment(const ContainedPtr&); + void writeDocLines(IceUtilInternal::Output&, const StringList&, bool commentFirst = true, + const std::string& space = " "); + void writeDocSentence(IceUtilInternal::Output&, const StringList&); + void writeSeeAlso(IceUtilInternal::Output&, const StringList&, const ContainerPtr&); + void writeDocSummary(IceUtilInternal::Output&, const ContainedPtr&); + void writeOpDocSummary(IceUtilInternal::Output&, const OperationPtr&, bool, bool, bool = false); + + void writeProxyDocSummary(IceUtilInternal::Output&, const ClassDefPtr&, const std::string&); + void writeServantDocSummary(IceUtilInternal::Output&, const ClassDefPtr&, const std::string&); + void writeMemberDoc(IceUtilInternal::Output&, const DataMemberPtr&); + std::string paramLabel(const std::string&, const ParamDeclList&); std::string operationReturnType(const OperationPtr&); bool operationReturnIsTuple(const OperationPtr&); |