njames93 updated this revision to Diff 249856.
njames93 added a comment.
Herald added a subscriber: mgorny.
- Moved escape/unescape impl to source file
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D76037/new/
https://reviews.llvm.org/D76037
Files:
clang/include/clang/Tooling/ReplacementsYaml.h
clang/lib/Tooling/CMakeLists.txt
clang/lib/Tooling/ReplacementsYaml.cpp
clang/unittests/Tooling/ReplacementsYamlTest.cpp
Index: clang/unittests/Tooling/ReplacementsYamlTest.cpp
===================================================================
--- clang/unittests/Tooling/ReplacementsYamlTest.cpp
+++ clang/unittests/Tooling/ReplacementsYamlTest.cpp
@@ -46,28 +46,35 @@
YamlContentStream.str().c_str());
}
-TEST(ReplacementsYamlTest, serializesNewLines) {
- TranslationUnitReplacements Doc;
+TEST(ReplacementsYamlTest, handlesEscaped) {
+ TranslationUnitReplacements Doc, NewDoc;
Doc.MainSourceFile = "/path/to/source.cpp";
- Doc.Replacements.emplace_back("/path/to/file1.h", 0, 0, "#include <utility>\n");
+ const StringRef FilePath = "/path/to/file1.h";
+ Doc.Replacements.emplace_back(FilePath, 0, 0, "#include <utility>\n");
+ Doc.Replacements.emplace_back(FilePath, 0, 0, "'\\\t\r\n");
- std::string YamlContent;
- llvm::raw_string_ostream YamlContentStream(YamlContent);
+ SmallString<512> YamlContent;
+ llvm::raw_svector_ostream YamlContentStream(YamlContent);
yaml::Output YAML(YamlContentStream);
YAML << Doc;
+ yaml::Input IYAML(YamlContent);
+ IYAML >> NewDoc;
- // NOTE: If this test starts to fail for no obvious reason, check whitespace.
- ASSERT_STREQ("---\n"
- "MainSourceFile: '/path/to/source.cpp'\n"
- "Replacements:\n"
- " - FilePath: '/path/to/file1.h'\n"
- " Offset: 0\n"
- " Length: 0\n"
- " ReplacementText: '#include <utility>\n\n'\n"
- "...\n",
- YamlContentStream.str().c_str());
+ ASSERT_EQ(Doc.MainSourceFile, NewDoc.MainSourceFile);
+ ASSERT_EQ(Doc.Replacements.size(), NewDoc.Replacements.size());
+ if (Doc.Replacements.size() != NewDoc.Replacements.size()) {
+ for (auto DocR = Doc.Replacements.begin(),
+ NewDocR = NewDoc.Replacements.begin(),
+ DocE = Doc.Replacements.end();
+ DocR != DocE; DocR++, NewDocR++) {
+ ASSERT_EQ(DocR->getFilePath(), NewDocR->getFilePath());
+ ASSERT_EQ(DocR->getLength(), NewDocR->getLength());
+ ASSERT_EQ(DocR->getOffset(), NewDocR->getOffset());
+ ASSERT_EQ(DocR->getReplacementText(), NewDocR->getReplacementText());
+ }
+ }
}
TEST(ReplacementsYamlTest, deserializesReplacements) {
Index: clang/lib/Tooling/ReplacementsYaml.cpp
===================================================================
--- /dev/null
+++ clang/lib/Tooling/ReplacementsYaml.cpp
@@ -0,0 +1,73 @@
+//===-- ReplacementsYaml.cpp -- Serialiazation for Replacements -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/ReplacementsYaml.h"
+
+namespace llvm {
+namespace yaml {
+
+namespace {
+struct Escapes {
+ char EscapeChar;
+ char WrittenChar;
+};
+} // namespace
+
+static constexpr Escapes EscapeChars[] = {
+ {'\n', 'n'}, {'\r', 'r'}, {'\t', 't'}, {'\\', '\\'}};
+
+std::string
+MappingTraits<clang::tooling::Replacement>::NormalizedReplacement::escape(
+ StringRef Str) {
+
+ std::string Res;
+ llvm::raw_string_ostream Builder(Res);
+ for (char C : Str) {
+ if (llvm::none_of(EscapeChars, [&](Escapes Escape) {
+ if (C == Escape.EscapeChar) {
+ Builder << '\\' << Escape.WrittenChar;
+ return true;
+ }
+ return false;
+ })) {
+ Builder << C;
+ }
+ }
+ return Res;
+}
+std::string
+MappingTraits<clang::tooling::Replacement>::NormalizedReplacement::unescape(
+ StringRef Str) {
+ std::string Res;
+ llvm::raw_string_ostream Builder(Res);
+ while (!Str.empty()) {
+ if (Str.consume_front("\\")) {
+ if (Str.empty()) {
+ Builder << '\\';
+ break;
+ }
+ char C = Str.front();
+ Str = Str.drop_front();
+ if (llvm::none_of(EscapeChars, [&](Escapes Escape) {
+ if (C == Escape.WrittenChar) {
+ Builder << Escape.EscapeChar;
+ return true;
+ }
+ return false;
+ })) {
+ Builder << '\\' << C;
+ }
+ continue;
+ }
+ Builder << Str.front();
+ Str = Str.drop_front();
+ }
+ return Res;
+}
+} // namespace yaml
+} // namespace llvm
\ No newline at end of file
Index: clang/lib/Tooling/CMakeLists.txt
===================================================================
--- clang/lib/Tooling/CMakeLists.txt
+++ clang/lib/Tooling/CMakeLists.txt
@@ -25,6 +25,7 @@
JSONCompilationDatabase.cpp
Refactoring.cpp
RefactoringCallbacks.cpp
+ ReplacementsYaml.cpp
StandaloneExecution.cpp
Tooling.cpp
Index: clang/include/clang/Tooling/ReplacementsYaml.h
===================================================================
--- clang/include/clang/Tooling/ReplacementsYaml.h
+++ clang/include/clang/Tooling/ReplacementsYaml.h
@@ -35,17 +35,16 @@
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(escape(R.getReplacementText())) {}
+
+ std::string escape(StringRef Str);
+
+ std::string unescape(StringRef Str);
clang::tooling::Replacement denormalize(const IO &) {
return clang::tooling::Replacement(FilePath, Offset, Length,
- ReplacementText);
+ unescape(ReplacementText));
}
std::string FilePath;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits