From fb37f3844eb7768b0076eb65e9d1ed3af6f92893 Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 15 Jan 2025 17:23:41 +0100 Subject: [PATCH 1/3] Cleanup C# doc comment generation --- cpp/src/slice2cs/CsUtil.h | 3 +- cpp/src/slice2cs/Gen.cpp | 738 ++++++-------------------------------- cpp/src/slice2cs/Gen.h | 31 +- cpp/src/slice2js/Gen.cpp | 1 + 4 files changed, 127 insertions(+), 646 deletions(-) diff --git a/cpp/src/slice2cs/CsUtil.h b/cpp/src/slice2cs/CsUtil.h index 2fb1807d5f1..762c0bb540d 100644 --- a/cpp/src/slice2cs/CsUtil.h +++ b/cpp/src/slice2cs/CsUtil.h @@ -38,6 +38,8 @@ namespace Slice const std::string& prefix = "", const std::string& suffix = ""); + static std::string fixId(const std::string&, unsigned int = 0, bool = false); + protected: // // Returns the namespace prefix of a Contained entity. @@ -47,7 +49,6 @@ namespace Slice static std::string resultStructName(const std::string&, const std::string&, bool = false); static std::string resultType(const OperationPtr&, const std::string&, bool = false); static std::string taskResultType(const OperationPtr&, const std::string&, bool = false); - static std::string fixId(const std::string&, unsigned int = 0, bool = false); static std::string getOptionalFormat(const TypePtr&); static std::string getStaticId(const TypePtr&); static std::string typeToString(const TypePtr&, const std::string&, bool = false); diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 77e20e844f5..5a10f931105 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -29,6 +29,66 @@ using namespace IceInternal; namespace { + void writeDocLines(Output& out, const StringList& lines) + { + for (const auto& line : lines) + { + out << nl << "///"; + if (!line.empty()) + { + out << " " << line; + } + } + } + + /// Returns a C# formatted link to the provided Slice identifier. + string csLinkFormatter(string identifier, string memberComponent) + { + string result = ""; + } + + string toCsIdent(const string& s) + { + string::size_type pos = s.find('#'); + if (pos == string::npos) + { + return s; + } + + string result = s; + if (pos == 0) + { + return result.erase(0, 1); + } + + result[pos] = '.'; + return result; + } + + void writeSeeAlso(Output& out, const StringList& lines) + { + for (const auto& line : lines) + { + if (!line.empty()) + { + out << nl << "/// "; + } + } + } + string sliceModeToIceMode(Operation::Mode opMode) { string mode; @@ -653,657 +713,98 @@ Slice::CsVisitor::writeDataMemberInitializers(const DataMemberList& dataMembers, } } -string -Slice::CsVisitor::toCsIdent(const string& s) -{ - string::size_type pos = s.find('#'); - if (pos == string::npos) - { - return s; - } - - string result = s; - if (pos == 0) - { - return result.erase(0, 1); - } - - result[pos] = '.'; - return result; -} - -string -Slice::CsVisitor::editMarkup(const string& s) -{ - // - // Strip HTML markup and javadoc links--VS doesn't display them. - // - string result = s; - string::size_type pos = 0; - do - { - pos = result.find('<', pos); - if (pos != string::npos) - { - string::size_type endpos = result.find('>', pos); - string::size_type wspos = result.find(' ', pos); - if (endpos == string::npos && wspos == string::npos) - { - break; - } - - if (wspos < endpos) - { - // If we found a whitespace before the end tag marker '>', The '<' char doesn't correspond to the start - // of a HTML tag, and we replace it with < escape code. - result.replace(pos, 1, "<", 4); - } - else - { - result.erase(pos, endpos - pos + 1); - } - } - } while (pos != string::npos); - - // replace remaining '>' chars with '>' escape code, tags have been already strip above. - pos = 0; - do - { - pos = result.find('>', pos); - if (pos != string::npos) - { - result.replace(pos, 1, ">", 4); - } - } while (pos != string::npos); - - const string link = "{@link"; - pos = 0; - do - { - pos = result.find(link, pos); - if (pos != string::npos) - { - result.erase(pos, link.size() + 1); // erase following white space too - string::size_type endpos = result.find('}', pos); - if (endpos != string::npos) - { - string ident = result.substr(pos, endpos - pos); - result.erase(pos, endpos - pos + 1); - result.insert(pos, toCsIdent(ident)); - } - } - } while (pos != string::npos); - - // - // Strip @see sections because VS does not display them. - // - static const string seeTag = "@see"; - pos = 0; - do - { - // - // Look for the next @ and delete up to that, or - // to the end of the string, if not found. - // - pos = result.find(seeTag, pos); - if (pos != string::npos) - { - string::size_type next = result.find('@', pos + seeTag.size()); - if (next != string::npos) - { - result.erase(pos, next - pos); - } - else - { - result.erase(pos, string::npos); - } - } - } while (pos != string::npos); - - // - // Replace @param, @return, and @throws with corresponding , , and tags. - // - static const string paramTag = "@param"; - pos = 0; - do - { - pos = result.find(paramTag, pos); - if (pos != string::npos) - { - result.erase(pos, paramTag.size() + 1); - - string::size_type startIdent = result.find_first_not_of(" \t", pos); - if (startIdent != string::npos) - { - string::size_type endIdent = result.find_first_of(" \t", startIdent); - if (endIdent != string::npos) - { - string ident = result.substr(startIdent, endIdent - startIdent); - string::size_type endComment = result.find_first_of("@<", endIdent); - string comment = result.substr( - endIdent + 1, - endComment == string::npos ? endComment : endComment - endIdent - 1); - result.erase(startIdent, endComment == string::npos ? string::npos : endComment - startIdent); - string newComment = "" + comment + "\n"; - result.insert(startIdent, newComment); - pos = startIdent + newComment.size(); - } - } - else - { - pos += paramTag.size(); - } - } - } while (pos != string::npos); - - static const string returnTag = "@return"; - pos = result.find(returnTag); - if (pos != string::npos) - { - result.erase(pos, returnTag.size() + 1); - string::size_type endComment = result.find_first_of("@<", pos); - string comment = result.substr(pos, endComment == string::npos ? endComment : endComment - pos); - result.erase(pos, endComment == string::npos ? string::npos : endComment - pos); - string newComment = "" + comment + "\n"; - result.insert(pos, newComment); - pos = pos + newComment.size(); - } - - static const string throwsTag = "@throws"; - pos = 0; - do - { - pos = result.find(throwsTag, pos); - if (pos != string::npos) - { - result.erase(pos, throwsTag.size() + 1); - - string::size_type startIdent = result.find_first_not_of(" \t", pos); - if (startIdent != string::npos) - { - string::size_type endIdent = result.find_first_of(" \t", startIdent); - if (endIdent != string::npos) - { - string ident = result.substr(startIdent, endIdent - startIdent); - string::size_type endComment = result.find_first_of("@<", endIdent); - string comment = result.substr( - endIdent + 1, - endComment == string::npos ? endComment : endComment - endIdent - 1); - result.erase(startIdent, endComment == string::npos ? string::npos : endComment - startIdent); - string newComment = "" + comment + "\n"; - result.insert(startIdent, newComment); - pos = startIdent + newComment.size(); - } - } - else - { - pos += throwsTag.size(); - } - } - } while (pos != string::npos); - - return result; -} - -StringList -Slice::CsVisitor::splitIntoLines(const string& comment) -{ - string s = editMarkup(comment); - StringList result; - string::size_type pos = 0; - string::size_type nextPos; - while ((nextPos = s.find_first_of('\n', pos)) != string::npos) - { - result.emplace_back(s, pos, nextPos - pos); - pos = nextPos + 1; - } - string lastLine = string(s, pos); - if (lastLine.find_first_not_of(" \t\n\r") != string::npos) - { - result.push_back(lastLine); - } - return result; -} - void -Slice::CsVisitor::splitDocComment(const ContainedPtr& p, StringList& summaryLines, StringList& remarksLines) +Slice::CsVisitor::writeDocComment(const ContainedPtr& p) { - string s = p->docComment(); - - const string paramTag = "@param"; - const string throwsTag = "@throws"; - const string exceptionTag = "@exception"; - const string returnTag = "@return"; - - unsigned int i; - - for (i = 0; i < s.size(); ++i) - { - if (s[i] == '.' && (i + 1 >= s.size() || isspace(static_cast(s[i + 1])))) - { - ++i; - break; - } - else if ( - s[i] == '@' && - (s.substr(i, paramTag.size()) == paramTag || s.substr(i, throwsTag.size()) == throwsTag || - s.substr(i, exceptionTag.size()) == exceptionTag || s.substr(i, returnTag.size()) == returnTag)) - { - break; - } - } - - summaryLines = splitIntoLines(trim(s.substr(0, i))); - if (!summaryLines.empty()) - { - remarksLines = splitIntoLines(trim(s.substr(i))); - } -} - -void -Slice::CsVisitor::writeDocComment(const ContainedPtr& p, const string& extraParam) -{ - StringList summaryLines; - StringList remarksLines; - splitDocComment(p, summaryLines, remarksLines); - - if (summaryLines.empty()) + DocCommentPtr comment = p->parseDocComment(csLinkFormatter, true); + if (!comment) { return; } - _out << nl << "/// "; - - for (const auto& summaryLine : summaryLines) - { - _out << nl << "///"; - if (!summaryLine.empty()) - { - _out << " " << summaryLine; - } - } - - bool summaryClosed = false; - - if (!remarksLines.empty()) - { - for (const auto& remarksLine : remarksLines) - { - // - // The first param, returns, or exception tag ends the description. - // - static const string paramTag = ""; - _out << nl << "/// " << remarksLine; - summaryClosed = true; - } - else - { - _out << nl << "///"; - if (!remarksLine.empty()) - { - _out << " " << remarksLine; - } - } - } - } - - if (!summaryClosed) + StringList overview = comment->overview(); + if (!overview.empty()) { + _out << nl << "/// "; + writeDocLines(_out, overview); _out << nl << "/// "; } - if (!extraParam.empty()) - { - _out << nl << "/// " << extraParam; - } - - _out << sp; + writeSeeAlso(_out, comment->seeAlso()); } void -Slice::CsVisitor::writeDocCommentAMI( - const OperationPtr& p, - ParamDir paramType, - const string& extraParam1, - const string& extraParam2, - const string& extraParam3) +Slice::CsVisitor::writeOpDocComment(const OperationPtr& op, const vector& extraParams, bool isAsync) { - StringList summaryLines; - StringList remarksLines; - splitDocComment(p, summaryLines, remarksLines); - - if (summaryLines.empty()) + DocCommentPtr comment = op->parseDocComment(csLinkFormatter, true); + if (!comment) { return; } - // - // Output the leading comment block up until the first tag. - // - _out << nl << "/// "; - for (const auto& summaryLine : summaryLines) - { - _out << nl << "///"; - if (!summaryLine.empty()) - { - _out << " " << summaryLine; - } - } - - bool done = false; - for (auto i = remarksLines.begin(); i != remarksLines.end() && !done; ++i) - { - string::size_type pos = i->find('<'); - done = true; - if (pos != string::npos) - { - if (pos != 0) - { - _out << nl << "/// " << i->substr(0, pos); - } - } - else - { - _out << nl << "///"; - if (!(*i).empty()) - { - _out << " " << *i; - } - } - } - _out << nl << "/// "; - - // - // Write the comments for the parameters. - // - writeDocCommentParam(p, paramType, false); - - if (!extraParam1.empty()) - { - _out << nl << "/// " << extraParam1; - } - - if (!extraParam2.empty()) - { - _out << nl << "/// " << extraParam2; - } - - if (!extraParam3.empty()) - { - _out << nl << "/// " << extraParam3; - } - - if (paramType == InParam) + StringList overview = comment->overview(); + if (!overview.empty()) { - _out << nl << "/// An asynchronous result object."; - } - else if (p->returnType()) - { - // - // Find the comment for the return value (if any). - // - static const string returnsTag = ""; - static const string returnsCloseTag = ""; - bool doneReturn = false; - bool foundReturn = false; - for (auto i = remarksLines.begin(); i != remarksLines.end() && !doneReturn; ++i) - { - if (!foundReturn) - { - string::size_type pos = i->find(returnsTag); - if (pos != string::npos) - { - foundReturn = true; - string::size_type endpos = i->find(returnsCloseTag, pos + 1); - if (endpos != string::npos) - { - _out << nl << "/// " << i->substr(pos, endpos - pos + returnsCloseTag.size()); - doneReturn = true; - } - else - { - _out << nl << "/// " << i->substr(pos); - } - } - } - else - { - string::size_type pos = i->find(returnsCloseTag); - if (pos != string::npos) - { - _out << nl << "/// " << i->substr(0, pos + returnsCloseTag.size()); - doneReturn = true; - } - else - { - _out << nl << "///"; - if (!(*i).empty()) - { - _out << " " << *i; - } - } - } - } - if (foundReturn && !doneReturn) - { - _out << returnsCloseTag; - } + _out << nl << "/// "; + writeDocLines(_out, overview); + _out << nl << "/// "; } -} -void -Slice::CsVisitor::writeDocCommentTaskAsyncAMI( - const OperationPtr& p, - const string& extraParam1, - const string& extraParam2, - const string& extraParam3) -{ - StringList summaryLines; - StringList remarksLines; - splitDocComment(p, summaryLines, remarksLines); + writeParameterDocComments(comment, isAsync ? op->inParameters() : op->parameters()); - if (summaryLines.empty()) + for (const auto& extraParam : extraParams) { - return; + _out << nl << "/// " << extraParam; } - // - // Output the leading comment block up until the first tag. - // - _out << nl << "/// "; - for (const auto& summaryLine : summaryLines) + if (isAsync) { - _out << nl << "///"; - if (!summaryLine.empty()) - { - _out << " " << summaryLine; - } + _out << nl << "/// A task that represents the asynchronous operation."; } - - bool done = false; - for (auto i = remarksLines.begin(); i != remarksLines.end() && !done; ++i) + else if (op->returnType()) { - string::size_type pos = i->find('<'); - done = true; - if (pos != string::npos) - { - if (pos != 0) - { - _out << nl << "/// " << i->substr(0, pos); - } - } - else + StringList returns = comment->returns(); + if (!returns.empty()) { - _out << nl << "///"; - if (!(*i).empty()) - { - _out << " " << *i; - } + _out << nl << "/// "; + writeDocLines(_out, returns); + _out << nl << "/// "; } } - _out << nl << "/// "; - - // - // Write the comments for the parameters. - // - writeDocCommentParam(p, InParam, false); - - if (!extraParam1.empty()) - { - _out << nl << "/// " << extraParam1; - } - - if (!extraParam2.empty()) - { - _out << nl << "/// " << extraParam2; - } - if (!extraParam3.empty()) + for (const auto& [exceptionName, exceptionLines] : comment->exceptions()) { - _out << nl << "/// " << extraParam3; - } - - _out << nl << "/// The task object representing the asynchronous operation."; -} - -void -Slice::CsVisitor::writeDocCommentAMD(const OperationPtr& p, const string& extraParam) -{ - StringList summaryLines; - StringList remarksLines; - splitDocComment(p, summaryLines, remarksLines); - - if (summaryLines.empty()) - { - return; - } - - // - // Output the leading comment block up until the first tag. - // - _out << nl << "/// "; - for (const auto& summaryLine : summaryLines) - { - _out << nl << "///"; - if (!summaryLine.empty()) + string name = exceptionName; + ExceptionPtr ex = op->container()->lookupException(exceptionName, false); + if (ex) { - _out << " " << summaryLine; + name = ex->scoped(); } - } + name = fixId(name); - bool done = false; - for (auto i = remarksLines.begin(); i != remarksLines.end() && !done; ++i) - { - string::size_type pos = i->find('<'); - done = true; - if (pos != string::npos) - { - if (pos != 0) - { - _out << nl << "/// " << i->substr(0, pos); - } - } - else + if (!exceptionLines.empty()) { - _out << nl << "///"; - if (!(*i).empty()) - { - _out << " " << *i; - } + _out << nl << "/// "; + writeDocLines(_out, exceptionLines); + _out << nl << "/// "; } } - _out << nl << "/// "; - // - // Write the comments for the parameters. - // - writeDocCommentParam(p, InParam, true); - - if (!extraParam.empty()) - { - _out << nl << "/// " << extraParam; - } - - _out << nl << "/// The task object representing the asynchronous operation."; + writeSeeAlso(_out, comment->seeAlso()); } void -Slice::CsVisitor::writeDocCommentParam(const OperationPtr& p, ParamDir paramType, bool /*amd*/) +Slice::CsVisitor::writeParameterDocComments(const DocCommentPtr& comment, const ParameterList& parameters) { - // - // Collect the names of the in- or -out parameters to be documented. - // - ParameterList tmp = p->parameters(); - vector params; - for (const auto& q : tmp) + auto commentParameters = comment->parameters(); + for (const auto& param : parameters) { - if (q->isOutParam() && paramType == OutParam) + auto q = commentParameters.find(param->name()); + if (q != commentParameters.end()) { - params.push_back(q->name()); - } - else if (!q->isOutParam() && paramType == InParam) - { - params.push_back(q->name()); - } - } - - // - // Print the comments for all the parameters that appear in the parameter list. - // - StringList summaryLines; - StringList remarksLines; - splitDocComment(p, summaryLines, remarksLines); - - const string paramTag = "find(""); - if (endpos == string::npos) - { - i = j; - string s = *j++; - _out << nl << "///"; - if (!s.empty()) - { - _out << " " << s; - } - } - else - { - _out << nl << "/// " << *j++; - break; - } - } - } - } + _out << nl << "/// name()) << "\">"; + writeDocLines(_out, q->second); + _out << nl << "/// "; } } } @@ -1685,14 +1186,9 @@ Slice::Gen::TypesVisitor::visitOperation(const OperationPtr& op) vector params, args; string opName = getDispatchParams(op, retS, params, args, ns); _out << sp; - if (amd) - { - writeDocCommentAMD(op, "The Current object for the dispatch."); - } - else - { - writeDocComment(op, "The Current object for the dispatch."); - } + + writeOpDocComment(op, {"The Current object for the dispatch."}, amd); + emitAttributes(op); emitObsoleteAttribute(op, _out); _out << nl << retS << " " << opName << spar << params << epar << ";"; @@ -2038,7 +1534,7 @@ Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p) { _out << ','; } - writeDocComment(*en, ""); + writeDocComment(*en); _out << nl << fixId((*en)->name()); if (hasExplicitValues) { @@ -2367,7 +1863,10 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) // string context = getEscapedParamName(p, "context"); _out << sp; - writeDocComment(p, "The Context map to send with the invocation."); + writeOpDocComment( + p, + {"The Context map to send with the invocation."}, + false); emitObsoleteAttribute(p, _out); _out << nl << retS << " " << name << spar << getParams(p, ns) << ("global::System.Collections.Generic.Dictionary? " + context + " = null") << epar @@ -2383,11 +1882,12 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) string progress = getEscapedParamName(p, "progress"); _out << sp; - writeDocCommentTaskAsyncAMI( + writeOpDocComment( p, - "Context map to send with the invocation.", - "Sent progress provider.", - "A cancellation token that receives the cancellation requests."); + {"Context map to send with the invocation.", + "Sent progress provider.", + "A cancellation token that receives the cancellation requests."}, + true); emitObsoleteAttribute(p, _out); _out << nl << taskResultType(p, ns); _out << " " << p->name() << "Async" << spar << inParams diff --git a/cpp/src/slice2cs/Gen.h b/cpp/src/slice2cs/Gen.h index abd24effb17..a2b1720203e 100644 --- a/cpp/src/slice2cs/Gen.h +++ b/cpp/src/slice2cs/Gen.h @@ -53,32 +53,11 @@ namespace Slice // Generates "= null!" for non-nullable fields (Slice class and exception only). void writeDataMemberInitializers(const DataMemberList&, unsigned int); - std::string toCsIdent(const std::string&); - std::string editMarkup(const std::string&); - StringList splitIntoLines(const std::string&); - void splitDocComment(const ContainedPtr&, StringList&, StringList&); - StringList getSummary(const ContainedPtr&); - void writeDocComment(const ContainedPtr&, const std::string& = ""); - void writeDocCommentOp(const OperationPtr&); - - enum ParamDir - { - InParam, - OutParam - }; - void writeDocCommentAMI( - const OperationPtr&, - ParamDir, - const std::string& = "", - const std::string& = "", - const std::string& = ""); - void writeDocCommentTaskAsyncAMI( - const OperationPtr&, - const std::string& = "", - const std::string& = "", - const std::string& = ""); - void writeDocCommentAMD(const OperationPtr&, const std::string&); - void writeDocCommentParam(const OperationPtr&, ParamDir, bool); + void writeDocComment(const ContainedPtr&); + + void + writeOpDocComment(const OperationPtr& operation, const std::vector& extraParams, bool isAsync); + void writeParameterDocComments(const DocCommentPtr&, const ParameterList&); void moduleStart(const ModulePtr&); void moduleEnd(const ModulePtr&); diff --git a/cpp/src/slice2js/Gen.cpp b/cpp/src/slice2js/Gen.cpp index 508ff2170a8..38cb268b638 100644 --- a/cpp/src/slice2js/Gen.cpp +++ b/cpp/src/slice2js/Gen.cpp @@ -141,6 +141,7 @@ namespace out << l.front(); l.pop_front(); } + for (const auto& i : l) { out << nl << " *"; From 8a0d8623f14a6304d95f4257cd9d0876e195ec1a Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 15 Jan 2025 21:14:20 +0100 Subject: [PATCH 2/3] Escape XML entities --- cpp/src/Slice/Parser.cpp | 37 ++++++++++++++++++++++++++++++++++--- cpp/src/Slice/Parser.h | 11 ++++++++++- cpp/src/slice2cs/Gen.cpp | 4 ++-- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 1105e8a4ee7..4be42e33e71 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -614,7 +614,7 @@ namespace } } - StringList splitComment(string comment, function linkFormatter, bool stripMarkup) + StringList splitComment(string comment, function linkFormatter, bool stripMarkup, bool xmlEscape) { string::size_type pos = 0; @@ -634,6 +634,37 @@ namespace comment.erase(pos, endpos - pos + 1); } } while (pos != string::npos); + + // Escape XML entities. + if (xmlEscape) + { + const string amp = "&"; + const string lt = "<"; + const string gt = ">"; + + pos = 0; + while ((pos = comment.find_first_of("&<>", pos)) != string::npos) + { + switch (comment[pos]) + { + case '&': + comment.replace(pos, 1, amp); + pos += amp.size(); + break; + case '<': + comment.replace(pos, 1, lt); + pos += lt.size(); + break; + case '>': + comment.replace(pos, 1, gt); + pos += gt.size(); + break; + default: + assert(false); + break; + } + } + } } // Fix any link tags using the provided link formatter. @@ -729,14 +760,14 @@ namespace } DocCommentPtr -Slice::Contained::parseDocComment(function linkFormatter, bool stripMarkup) const +Slice::Contained::parseDocComment(function linkFormatter, bool stripMarkup, bool xmlEscape) const { // Some tags are only valid if they're applied to an operation. // If they aren't, we want to ignore the tag and issue a warning. bool isOperation = dynamic_cast(this); // Split the comment's raw text up into lines. - StringList lines = splitComment(_docComment, std::move(linkFormatter), stripMarkup); + StringList lines = splitComment(_docComment, std::move(linkFormatter), stripMarkup, xmlEscape); if (lines.empty()) { return nullptr; diff --git a/cpp/src/Slice/Parser.h b/cpp/src/Slice/Parser.h index 27e5b48c24d..cba281a760d 100644 --- a/cpp/src/Slice/Parser.h +++ b/cpp/src/Slice/Parser.h @@ -371,9 +371,18 @@ namespace Slice [[nodiscard]] int line() const; [[nodiscard]] std::string docComment() const; + + /// Parses the documentation comment into a structured format. + /// + /// @param linkFormatter A function used to format links according to the expected documentation format. + /// @param stripMarkup If true, removes all HTML markup from the parsed comment. Defaults to false. + /// @param xmlEscape If true, escapes all XML special characters in the parsed comment. Defaults to false. + /// @return The parsed documentation comment or nullptr if the element does not contain a documentation + /// comment. [[nodiscard]] DocCommentPtr parseDocComment( std::function linkFormatter, - bool stripMarkup = false) const; + bool stripMarkup = false, + bool xmlEscape = false) const; [[nodiscard]] int includeLevel() const; diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 5a10f931105..4b1bc4c0730 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -716,7 +716,7 @@ Slice::CsVisitor::writeDataMemberInitializers(const DataMemberList& dataMembers, void Slice::CsVisitor::writeDocComment(const ContainedPtr& p) { - DocCommentPtr comment = p->parseDocComment(csLinkFormatter, true); + DocCommentPtr comment = p->parseDocComment(csLinkFormatter, true, true); if (!comment) { return; @@ -736,7 +736,7 @@ Slice::CsVisitor::writeDocComment(const ContainedPtr& p) void Slice::CsVisitor::writeOpDocComment(const OperationPtr& op, const vector& extraParams, bool isAsync) { - DocCommentPtr comment = op->parseDocComment(csLinkFormatter, true); + DocCommentPtr comment = op->parseDocComment(csLinkFormatter, true, true); if (!comment) { return; From f6cfa8a7243f4541c7ff4b5ab86a49f28776f55a Mon Sep 17 00:00:00 2001 From: Jose Date: Thu, 16 Jan 2025 10:03:47 +0100 Subject: [PATCH 3/3] clang format fixes --- cpp/src/Slice/Parser.cpp | 36 +++++++++++++++++++----------------- cpp/src/Slice/Parser.h | 2 +- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 4be42e33e71..98c0b346419 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -614,7 +614,8 @@ namespace } } - StringList splitComment(string comment, function linkFormatter, bool stripMarkup, bool xmlEscape) + StringList + splitComment(string comment, function linkFormatter, bool stripMarkup, bool xmlEscape) { string::size_type pos = 0; @@ -647,21 +648,21 @@ namespace { switch (comment[pos]) { - case '&': - comment.replace(pos, 1, amp); - pos += amp.size(); - break; - case '<': - comment.replace(pos, 1, lt); - pos += lt.size(); - break; - case '>': - comment.replace(pos, 1, gt); - pos += gt.size(); - break; - default: - assert(false); - break; + case '&': + comment.replace(pos, 1, amp); + pos += amp.size(); + break; + case '<': + comment.replace(pos, 1, lt); + pos += lt.size(); + break; + case '>': + comment.replace(pos, 1, gt); + pos += gt.size(); + break; + default: + assert(false); + break; } } } @@ -760,7 +761,8 @@ namespace } DocCommentPtr -Slice::Contained::parseDocComment(function linkFormatter, bool stripMarkup, bool xmlEscape) const +Slice::Contained::parseDocComment(function linkFormatter, bool stripMarkup, bool xmlEscape) + const { // Some tags are only valid if they're applied to an operation. // If they aren't, we want to ignore the tag and issue a warning. diff --git a/cpp/src/Slice/Parser.h b/cpp/src/Slice/Parser.h index cba281a760d..630e66a4299 100644 --- a/cpp/src/Slice/Parser.h +++ b/cpp/src/Slice/Parser.h @@ -374,7 +374,7 @@ namespace Slice /// Parses the documentation comment into a structured format. /// - /// @param linkFormatter A function used to format links according to the expected documentation format. + /// @param linkFormatter A function used to format links according to the expected documentation format. /// @param stripMarkup If true, removes all HTML markup from the parsed comment. Defaults to false. /// @param xmlEscape If true, escapes all XML special characters in the parsed comment. Defaults to false. /// @return The parsed documentation comment or nullptr if the element does not contain a documentation