[mlir][docgen] Handle Windows line endings in doc generation.
authorScott Todd <scotttodd@google.com>
Thu, 22 Jun 2023 19:27:41 +0000 (12:27 -0700)
committerScott Todd <scotttodd@google.com>
Thu, 29 Jun 2023 16:56:49 +0000 (09:56 -0700)
The `printReindented` function searches for Unix style line endings (`\n`), but strings may have Windows style line endings (`\r\n`). Prior to this change, generated document sections could have extra indentation, which some markdown renderers interpret as code blocks rather than paragraphs.

Differential Revision: https://reviews.llvm.org/D153591

mlir/include/mlir/Support/IndentedOstream.h
mlir/unittests/Support/IndentedOstreamTest.cpp

index 5961e46..101aa8b 100644 (file)
@@ -117,7 +117,9 @@ mlir::raw_indented_ostream::printReindented(StringRef str,
   // Skip empty lines.
   while (!output.empty()) {
     auto split = output.split('\n');
-    size_t indent = split.first.find_first_not_of(" \t");
+    // Trim Windows \r characters from \r\n line endings.
+    auto firstTrimmed = split.first.rtrim('\r');
+    size_t indent = firstTrimmed.find_first_not_of(" \t");
     if (indent != StringRef::npos) {
       // Set an initial value.
       leadingWs = indent;
@@ -129,7 +131,8 @@ mlir::raw_indented_ostream::printReindented(StringRef str,
   StringRef remaining = output;
   while (!remaining.empty()) {
     auto split = remaining.split('\n');
-    size_t indent = split.first.find_first_not_of(" \t");
+    auto firstTrimmed = split.first.rtrim('\r');
+    size_t indent = firstTrimmed.find_first_not_of(" \t");
     if (indent != StringRef::npos)
       leadingWs = std::min(leadingWs, static_cast<int>(indent));
     remaining = split.second;
index 11b6e57..08a4de5 100644 (file)
@@ -108,3 +108,19 @@ TEST(FormatTest, Reindent) {
 )";
   EXPECT_THAT(os.str(), StrEq(expected));
 }
+
+TEST(FormatTest, ReindentLineEndings) {
+  std::string str;
+  llvm::raw_string_ostream os(str);
+  raw_indented_ostream ros(os);
+
+  // Similar string as the previous test, but with \r\n (Windows style) line
+  // breaks. Note that C++'s internal string representation uses \n, so just
+  // running the previous test as-is on Windows is not sufficient.
+  const auto *desc =
+      "\r\n\r\n\r\n         First line\r\n                 second line";
+  ros.printReindented(desc);
+  ros.flush();
+  const auto *expected = "First line\r\n        second line";
+  EXPECT_THAT(os.str(), StrEq(expected));
+}