diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc index 423033e101..2bd45fc74d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc +++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc @@ -21,71 +21,85 @@ namespace compiler { namespace csharp { // Functions to create C# XML documentation comments. -// Currently this only includes documentation comments containing text specified as comments -// in the .proto file; documentation comments generated just from field/message/enum/proto names -// is inlined in the relevant code. If more control is required, that code can be moved here. +// Currently this only includes documentation comments containing text specified +// as comments in the .proto file; documentation comments generated just from +// field/message/enum/proto names is inlined in the relevant code. If more +// control is required, that code can be moved here. void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) { - std::string comments = location.leading_comments.empty() ? - location.trailing_comments : location.leading_comments; - if (comments.empty()) { - return; - } - // XML escaping... no need for apostrophes etc as the whole text is going to be a child - // node of a summary element, not part of an attribute. - comments = absl::StrReplaceAll(comments, {{"&", "&"}, {"<", "<"}}); - std::vector lines; - lines = absl::StrSplit(comments, "\n", absl::AllowEmpty()); - // TODO: We really should work out which part to put in the summary and which to put in the remarks... - // but that needs to be part of a bigger effort to understand the markdown better anyway. - printer->Print("/// \n"); - bool last_was_empty = false; - // We squash multiple blank lines down to one, and remove any trailing blank lines. We need - // to preserve the blank lines themselves, as this is relevant in the markdown. - // Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too. - // (We don't skip "just whitespace" lines, either.) - for (std::vector::iterator it = lines.begin(); - it != lines.end(); ++it) { - std::string line = *it; - if (line.empty()) { - last_was_empty = true; - } else { - if (last_was_empty) { - printer->Print("///\n"); - } - last_was_empty = false; - printer->Print("///$line$\n", "line", *it); + std::string comments = location.leading_comments.empty() + ? location.trailing_comments + : location.leading_comments; + if (comments.empty()) { + return; + } + // XML escaping... no need for apostrophes etc as the whole text is going to + // be a child node of a summary element, not part of an attribute. + comments = absl::StrReplaceAll(comments, {{"&", "&"}, {"<", "<"}}); + std::vector lines; + lines = absl::StrSplit(comments, "\n", absl::AllowEmpty()); + // TODO: We really should work out which part to put in the summary and which + // to put in the remarks... but that needs to be part of a bigger effort to + // understand the markdown better anyway. + printer->Print("/// \n"); + bool last_was_empty = false; + // We squash multiple blank lines down to one, and remove any trailing blank + // lines. We need to preserve the blank lines themselves, as this is relevant + // in the markdown. Note that we can't remove leading or trailing whitespace + // as *that's* relevant in markdown too. (We don't skip "just whitespace" + // lines, either.) + for (std::vector::iterator it = lines.begin(); it != lines.end(); + ++it) { + std::string line = *it; + if (line.empty()) { + last_was_empty = true; + } else { + if (last_was_empty) { + printer->Print("///\n"); + } + last_was_empty = false; + // If the comment has an extra slash at the start then this can cause the + // C# compiler to complain when generating the XML documentation Issue + // https://github.com/grpc/grpc/issues/35905 + if (line[0] == '/') { + line.replace(0, 1, "/"); } + printer->Print("///$line$\n", "line", line); } - printer->Print("/// \n"); + } + printer->Print("/// \n"); } template -static void WriteDocCommentBody( - io::Printer* printer, const DescriptorType* descriptor) { - SourceLocation location; - if (descriptor->GetSourceLocation(&location)) { - WriteDocCommentBodyImpl(printer, location); - } +static void WriteDocCommentBody(io::Printer* printer, + const DescriptorType* descriptor) { + SourceLocation location; + if (descriptor->GetSourceLocation(&location)) { + WriteDocCommentBodyImpl(printer, location); + } } void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { - WriteDocCommentBody(printer, message); + WriteDocCommentBody(printer, message); } -void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field) { - WriteDocCommentBody(printer, field); +void WritePropertyDocComment(io::Printer* printer, + const FieldDescriptor* field) { + WriteDocCommentBody(printer, field); } -void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor) { - WriteDocCommentBody(printer, enumDescriptor); +void WriteEnumDocComment(io::Printer* printer, + const EnumDescriptor* enumDescriptor) { + WriteDocCommentBody(printer, enumDescriptor); } -void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) { - WriteDocCommentBody(printer, value); +void WriteEnumValueDocComment(io::Printer* printer, + const EnumValueDescriptor* value) { + WriteDocCommentBody(printer, value); } -void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) { - WriteDocCommentBody(printer, method); +void WriteMethodDocComment(io::Printer* printer, + const MethodDescriptor* method) { + WriteDocCommentBody(printer, method); } } // namespace csharp