DmitryPolukhin updated this revision to Diff 270206.
DmitryPolukhin added a comment.

Fix single new line handling, it should be replace with space


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80301/new/

https://reviews.llvm.org/D80301

Files:
  clang/include/clang/Tooling/ReplacementsYaml.h
  llvm/lib/Support/YAMLTraits.cpp
  llvm/unittests/Support/YAMLIOTest.cpp

Index: llvm/unittests/Support/YAMLIOTest.cpp
===================================================================
--- llvm/unittests/Support/YAMLIOTest.cpp
+++ llvm/unittests/Support/YAMLIOTest.cpp
@@ -274,8 +274,8 @@
 
 TEST(YAMLIO, MultilineStrings) {
   WithStringField Original;
-  Original.str1 = "a multiline string\nfoobarbaz";
-  Original.str2 = "another one\rfoobarbaz";
+  Original.str1 = "a\n\nmultiline\nstring\nfoobarbaz ";
+  Original.str2 = "another one\rfoobarbaz\n";
   Original.str3 = "a one-line string";
 
   std::string Serialized;
@@ -285,10 +285,10 @@
     YOut << Original;
   }
   auto Expected = "---\n"
-                  "str1:            'a multiline string\n"
-                  "foobarbaz'\n"
+                  "str1:            'a\n\n\n\nmultiline\n\nstring\n\n"
+                  "foobarbaz '\n"
                   "str2:            'another one\r"
-                  "foobarbaz'\n"
+                  "foobarbaz\n\n'\n"
                   "str3:            a one-line string\n"
                   "...\n";
   ASSERT_EQ(Serialized, Expected);
@@ -305,6 +305,25 @@
   EXPECT_EQ(Original.str1, Deserialized.str1);
   EXPECT_EQ(Original.str2, Deserialized.str2);
   EXPECT_EQ(Original.str3, Deserialized.str3);
+
+  // Check deserialization of single '\n' that should be converted to space.
+  Serialized = "---\n"
+               "str1:            'a\n\n\n\nmultiline\n\nstring\n\n"
+               "foobarbaz\n'\n"
+               "str2:            'another\none\r"
+               "foobarbaz\n\n'\n"
+               "str3:            a one-line string\n"
+               "...\n";
+  {
+    Input YIn(Serialized);
+    YIn >> Deserialized;
+    ASSERT_FALSE(YIn.error())
+        << "Parsing error occurred during deserialization. Serialized string:\n"
+        << Serialized;
+  }
+  EXPECT_EQ(Original.str1, Deserialized.str1);
+  EXPECT_EQ(Original.str2, Deserialized.str2);
+  EXPECT_EQ(Original.str3, Deserialized.str3);
 }
 
 TEST(YAMLIO, NoQuotesForTab) {
Index: llvm/lib/Support/YAMLTraits.cpp
===================================================================
--- llvm/lib/Support/YAMLTraits.cpp
+++ llvm/lib/Support/YAMLTraits.cpp
@@ -876,13 +876,38 @@
 }
 
 void ScalarTraits<std::string>::output(const std::string &Val, void *,
-                                     raw_ostream &Out) {
-  Out << Val;
+                                       raw_ostream &Out) {
+  SmallVector<StringRef, 8> Lines;
+  StringRef(Val).split(Lines, '\n');
+  bool First = true;
+  for (StringRef Line : Lines) {
+    if (First)
+      First = false;
+    else
+      Out << "\n\n";
+    Out << Line;
+  }
 }
 
 StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
-                                         std::string &Val) {
-  Val = Scalar.str();
+                                           std::string &Val) {
+  Val.clear();
+  SmallVector<StringRef, 8> Lines;
+  Scalar.split(Lines, '\n');
+  size_t C = Lines.size();
+  for (size_t I = 0; I < C; ++I) {
+    Val += Lines[I];
+    // Next empty line means that it was '\n\n' that should convert to '\n'.
+    // +2 here because we need separator only if more elements will be added.
+    if (I + 2 < C && Lines[I + 1].empty()) {
+      Val += '\n';
+      ++I;
+    } else if ((I + 1 < C && !Lines[I + 1].empty()) ||
+               (I + 2 == C && Lines[I + 1].empty())) {
+      // Single '\n' should be converted to space ' '.
+      Val += ' ';
+    }
+  }
   return StringRef();
 }
 
Index: clang/include/clang/Tooling/ReplacementsYaml.h
===================================================================
--- clang/include/clang/Tooling/ReplacementsYaml.h
+++ clang/include/clang/Tooling/ReplacementsYaml.h
@@ -35,13 +35,7 @@
 
     NormalizedReplacement(const IO &, const clang::tooling::Replacement &R)
         : FilePath(R.getFilePath()), Offset(R.getOffset()),
-          Length(R.getLength()), ReplacementText(R.getReplacementText()) {
-      size_t lineBreakPos = ReplacementText.find('\n');
-      while (lineBreakPos != std::string::npos) {
-        ReplacementText.replace(lineBreakPos, 1, "\n\n");
-        lineBreakPos = ReplacementText.find('\n', lineBreakPos + 2);
-      }
-    }
+          Length(R.getLength()), ReplacementText(R.getReplacementText()) {}
 
     clang::tooling::Replacement denormalize(const IO &) {
       return clang::tooling::Replacement(FilePath, Offset, Length,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to