llvm-project/clang/unittests/Tooling/ReplacementsYamlTest.cpp
Dmitry Polukhin 9e7fddbd36 [yaml][clang-tidy] Fix multiline YAML serialization
Summary:
New line duplication logic introduced in https://reviews.llvm.org/D63482
has two issues: (1) there is no logic that removes duplicate newlines
when clang-apply-replacment reads YAML and (2) in general such logic
should be applied to all strings and should happen on string
serialization level instead in YAML parser.

This diff changes multiline strings quotation from single quote `'` to
double `"`. It solves problems with internal newlines because now they are
escaped. Also double quotation solves the problem with leading whitespace after
newline. In case of single quotation YAML parsers should remove leading
whitespace according to specification. In case of double quotation these
leading are internal space and they are preserved. There is no way to
instruct YAML parsers to preserve leading whitespaces after newline so
double quotation is the only viable option that solves all problems at
once.

Test Plan: check-all

Reviewers: gribozavr, mgehre, yvvan

Subscribers: xazax.hun, hiraditya, cfe-commits, llvm-commits

Tags: #clang-tools-extra, #clang, #llvm

Differential Revision: https://reviews.llvm.org/D80301
2020-07-09 02:41:58 -07:00

123 lines
5.0 KiB
C++

//===- unittests/Tooling/ReplacementsYamlTest.cpp - Serialization tests ---===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Tests for serialization of Replacements.
//
//===----------------------------------------------------------------------===//
#include "clang/Tooling/ReplacementsYaml.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang::tooling;
TEST(ReplacementsYamlTest, serializesReplacements) {
TranslationUnitReplacements Doc;
Doc.MainSourceFile = "/path/to/source.cpp";
Doc.Replacements.emplace_back("/path/to/file1.h", 232, 56, "replacement #1");
Doc.Replacements.emplace_back("/path/to/file2.h", 301, 2, "replacement #2");
std::string YamlContent;
llvm::raw_string_ostream YamlContentStream(YamlContent);
yaml::Output YAML(YamlContentStream);
YAML << Doc;
// 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: 232\n"
" Length: 56\n"
" ReplacementText: 'replacement #1'\n"
" - FilePath: '/path/to/file2.h'\n"
" Offset: 301\n"
" Length: 2\n"
" ReplacementText: 'replacement #2'\n"
"...\n",
YamlContentStream.str().c_str());
}
TEST(ReplacementsYamlTest, serializesNewLines) {
TranslationUnitReplacements Doc;
Doc.MainSourceFile = "/path/to/source.cpp";
Doc.Replacements.emplace_back("/path/to/file1.h", 0, 0, "#include <utility>\n");
std::string YamlContent;
llvm::raw_string_ostream YamlContentStream(YamlContent);
yaml::Output YAML(YamlContentStream);
YAML << Doc;
// 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",
YamlContentStream.str().c_str());
}
TEST(ReplacementsYamlTest, deserializesReplacements) {
std::string YamlContent = "---\n"
"MainSourceFile: /path/to/source.cpp\n"
"Replacements:\n"
" - FilePath: /path/to/file1.h\n"
" Offset: 232\n"
" Length: 56\n"
" ReplacementText: 'replacement #1'\n"
" - FilePath: /path/to/file2.h\n"
" Offset: 301\n"
" Length: 2\n"
" ReplacementText: 'replacement #2'\n"
"...\n";
TranslationUnitReplacements DocActual;
yaml::Input YAML(YamlContent);
YAML >> DocActual;
ASSERT_FALSE(YAML.error());
ASSERT_EQ(2u, DocActual.Replacements.size());
ASSERT_EQ("/path/to/source.cpp", DocActual.MainSourceFile);
ASSERT_EQ("/path/to/file1.h", DocActual.Replacements[0].getFilePath());
ASSERT_EQ(232u, DocActual.Replacements[0].getOffset());
ASSERT_EQ(56u, DocActual.Replacements[0].getLength());
ASSERT_EQ("replacement #1", DocActual.Replacements[0].getReplacementText());
ASSERT_EQ("/path/to/file2.h", DocActual.Replacements[1].getFilePath());
ASSERT_EQ(301u, DocActual.Replacements[1].getOffset());
ASSERT_EQ(2u, DocActual.Replacements[1].getLength());
ASSERT_EQ("replacement #2", DocActual.Replacements[1].getReplacementText());
}
TEST(ReplacementsYamlTest, deserializesWithoutContext) {
// Make sure a doc can be read without the context field.
std::string YamlContent = "---\n"
"MainSourceFile: /path/to/source.cpp\n"
"Replacements:\n"
" - FilePath: target_file.h\n"
" Offset: 1\n"
" Length: 10\n"
" ReplacementText: replacement\n"
"...\n";
TranslationUnitReplacements DocActual;
yaml::Input YAML(YamlContent);
YAML >> DocActual;
ASSERT_FALSE(YAML.error());
ASSERT_EQ("/path/to/source.cpp", DocActual.MainSourceFile);
ASSERT_EQ(1u, DocActual.Replacements.size());
ASSERT_EQ("target_file.h", DocActual.Replacements[0].getFilePath());
ASSERT_EQ(1u, DocActual.Replacements[0].getOffset());
ASSERT_EQ(10u, DocActual.Replacements[0].getLength());
ASSERT_EQ("replacement", DocActual.Replacements[0].getReplacementText());
}