diff --git a/cpp/src/slice2py/PythonUtil.cpp b/cpp/src/slice2py/PythonUtil.cpp index 5a038335018..21d3d7f3ef9 100644 --- a/cpp/src/slice2py/PythonUtil.cpp +++ b/cpp/src/slice2py/PythonUtil.cpp @@ -2257,6 +2257,25 @@ Slice::Python::CodeVisitor::writeRemarksDocComment(const StringList& remarks, bo } } +void +Slice::Python::CodeVisitor::writeSeeAlso(const StringList& seeAlso, bool needsNewline, Output& out) +{ + if (!seeAlso.empty()) + { + if (needsNewline) + { + out << nl; + } + + out << nl << "See Also"; + out << nl << "--------"; + for (const string& line : seeAlso) + { + out << nl << " " << line; + } + } +} + void Slice::Python::CodeVisitor::writeDocstring(const optional& comment, const string& prefix, Output& out) { @@ -2310,7 +2329,8 @@ Slice::Python::CodeVisitor::writeDocstring( const StringList& overview = comment->overview(); const StringList& remarks = comment->remarks(); - if (overview.empty() && remarks.empty() && docs.empty()) + const StringList& seeAlso = comment->seeAlso(); + if (overview.empty() && remarks.empty() && docs.empty() && seeAlso.empty()) { return; } @@ -2352,6 +2372,8 @@ Slice::Python::CodeVisitor::writeDocstring( writeRemarksDocComment(remarks, !overview.empty() || !docs.empty(), out); + writeSeeAlso(seeAlso, !overview.empty() || !docs.empty() || !remarks.empty(), out); + out << nl << tripleQuotes; } @@ -2380,7 +2402,8 @@ Slice::Python::CodeVisitor::writeDocstring(const optional& comment, const StringList& overview = comment->overview(); const StringList& remarks = comment->remarks(); - if (overview.empty() && remarks.empty() && docs.empty()) + const StringList& seeAlso = comment->seeAlso(); + if (overview.empty() && remarks.empty() && docs.empty() && seeAlso.empty()) { return; } @@ -2417,6 +2440,8 @@ Slice::Python::CodeVisitor::writeDocstring(const optional& comment, writeRemarksDocComment(remarks, !overview.empty() || !docs.empty(), out); + writeSeeAlso(seeAlso, !overview.empty() || !docs.empty() || !remarks.empty(), out); + out << nl << tripleQuotes; } @@ -2438,11 +2463,12 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, MethodKind me const StringList& overview = comment->overview(); const StringList& remarks = comment->remarks(); + const StringList& seeAlso = comment->seeAlso(); const StringList& returnsDoc = comment->returns(); const auto& parametersDoc = comment->parameters(); const auto& exceptionsDoc = comment->exceptions(); - if (overview.empty() && remarks.empty()) + if (overview.empty() && remarks.empty() && seeAlso.empty()) { if ((methodKind == MethodKind::SyncInvocation || methodKind == MethodKind::Dispatch) && parametersDoc.empty() && exceptionsDoc.empty() && returnsDoc.empty()) @@ -2636,6 +2662,7 @@ Slice::Python::CodeVisitor::writeDocstring(const OperationPtr& op, MethodKind me } writeRemarksDocComment(remarks, true, out); + writeSeeAlso(seeAlso, true, out); out << nl << tripleQuotes; } @@ -3004,19 +3031,25 @@ Slice::Python::pyLinkFormatter(const string& rawLink, const ContainedPtr&, const { result << "``"; - auto hashPos = rawLink.find('#'); - if (hashPos != string::npos) + // Replace "::" by "." in the raw link. This is for the situation where the user passes a Slice type + // reference but (a) the source Slice file does not include this type and (b) there is no python:identifier or + // other identifier renaming. + string targetS = rawLink; + // Replace any "::" scope separators with '.'s. + auto pos = targetS.find("::"); + while (pos != string::npos) { - if (hashPos != 0) - { - result << rawLink.substr(0, hashPos) << "."; - } - result << rawLink.substr(hashPos + 1); + targetS.replace(pos, 2, "."); + pos = targetS.find("::", pos); } - else + // Replace any '#' scope separators with '.'s. + replace(targetS.begin(), targetS.end(), '#', '.'); + // Remove any leading scope separators. + if (targetS.find('.') == 0) { - result << rawLink; + targetS.erase(0, 1); } + result << targetS; result << "``"; } diff --git a/cpp/src/slice2py/PythonUtil.h b/cpp/src/slice2py/PythonUtil.h index a96b0baf5c3..1263f41e5bf 100644 --- a/cpp/src/slice2py/PythonUtil.h +++ b/cpp/src/slice2py/PythonUtil.h @@ -453,6 +453,9 @@ namespace Slice::Python /// Writes the provided @p remarks in its own subheading in the current comment (if @p remarks is non-empty). void writeRemarksDocComment(const StringList& remarks, bool needsNewline, IceInternal::Output& out); + /// Writes the provided @p seeAlso in its own subheading in the current comment (if @p seeAlso is non-empty). + void writeSeeAlso(const StringList& seeAlso, bool needsNewline, IceInternal::Output& out); + void writeDocstring(const std::optional&, const std::string&, IceInternal::Output&); void writeDocstring(const std::optional&, const DataMemberList&, IceInternal::Output&); void writeDocstring(const std::optional&, const EnumPtr&, IceInternal::Output&); diff --git a/cpp/src/slice2swift/SwiftUtil.cpp b/cpp/src/slice2swift/SwiftUtil.cpp index d4b48b08338..380f3fcb834 100644 --- a/cpp/src/slice2swift/SwiftUtil.cpp +++ b/cpp/src/slice2swift/SwiftUtil.cpp @@ -105,8 +105,6 @@ Slice::Swift::writeDocSummary(IceInternal::Output& out, const ContainedPtr& p) hasStarted = true; } - // TODO we should add a section for '@see' tags. - const StringList& remarks = doc->remarks(); if (!remarks.empty()) { @@ -114,9 +112,20 @@ Slice::Swift::writeDocSummary(IceInternal::Output& out, const ContainedPtr& p) { out << nl << "///"; } - out << nl << "/// ## Remarks"; + out << nl << "/// - Remark:"; writeDocLines(out, remarks); } + + const StringList& seeAlso = doc->seeAlso(); + if (!seeAlso.empty()) + { + if (hasStarted) + { + out << nl << "///"; + } + out << nl << "/// - See Also:"; + writeDocLines(out, seeAlso); + } } void