diff options
16 files changed, 442 insertions, 60 deletions
diff --git a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp index 58372b60ce7..0f1b0d45f3e 100644 --- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp @@ -23,16 +23,25 @@ #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" +#include <algorithm> using namespace clang; using namespace clang::tooling; +void HeaderOverride::recordReplacements( + llvm::StringRef TransformID, const clang::tooling::Replacements &Replaces) { + HeaderChangeDoc.TransformID = TransformID; + HeaderChangeDoc.Replacements.resize(Replaces.size()); + std::copy(Replaces.begin(), Replaces.end(), + HeaderChangeDoc.Replacements.begin()); +} + SourceOverrides::SourceOverrides(llvm::StringRef MainFileName, bool TrackChanges) : MainFileName(MainFileName), TrackChanges(TrackChanges) {} -void -SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces) { +void SourceOverrides::applyReplacements(tooling::Replacements &Replaces, + llvm::StringRef TransformName) { llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts( new DiagnosticOptions()); DiagnosticsEngine Diagnostics( @@ -40,11 +49,12 @@ SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces) { DiagOpts.getPtr()); FileManager Files((FileSystemOptions())); SourceManager SM(Diagnostics, Files); - applyReplacements(Replaces, SM); + applyReplacements(Replaces, SM, TransformName); } -void SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces, - clang::SourceManager &SM) { +void SourceOverrides::applyReplacements(tooling::Replacements &Replaces, + SourceManager &SM, + llvm::StringRef TransformName) { applyOverrides(SM); Rewriter Rewrites(SM, LangOptions()); @@ -56,12 +66,6 @@ void SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces, if (!Success) llvm::errs() << "error: failed to apply some replacements."; - applyRewrites(Rewrites); - if (TrackChanges) - adjustChangedRanges(Replaces); -} - -void SourceOverrides::applyRewrites(Rewriter &Rewrites) { std::string ResultBuf; for (Rewriter::buffer_iterator I = Rewrites.buffer_begin(), @@ -89,36 +93,50 @@ void SourceOverrides::applyRewrites(Rewriter &Rewrites) { // will be stored as well for later output to disk. Applying replacements // in memory will always be necessary as the source goes down the transform // pipeline. - HeaderOverride &HeaderOv = Headers[FileName]; - HeaderOv.FileOverride.swap(ResultBuf); // "Create" HeaderOverride if not already existing - if (HeaderOv.FileName.empty()) - HeaderOv.FileName = FileName; + if (HeaderOv.getFileName().empty()) + HeaderOv = HeaderOverride(FileName, MainFileName); + + HeaderOv.swapContentOverride(ResultBuf); } -} -void SourceOverrides::adjustChangedRanges(const Replacements &Replaces) { - // Start by grouping replacements by file name + // Separate replacements to header files Replacements MainFileReplaces; - llvm::StringMap<Replacements> HeadersReplaces; - - for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; - ++I) { + ReplacementsMap HeadersReplaces; + for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end(); + I != E; ++I) { llvm::StringRef ReplacementFileName = I->getFilePath(); - if (ReplacementFileName == MainFileName) + if (ReplacementFileName == MainFileName) { MainFileReplaces.insert(*I); - else - HeadersReplaces[ReplacementFileName].insert(*I); + continue; + } + + HeadersReplaces[ReplacementFileName].insert(*I); } - // Then adjust the changed ranges for each individual file - MainFileChanges.adjustChangedRanges(Replaces); - for (llvm::StringMap<Replacements>::iterator I = HeadersReplaces.begin(), - E = HeadersReplaces.end(); + // Record all replacements to headers. + for (ReplacementsMap::const_iterator I = HeadersReplaces.begin(), + E = HeadersReplaces.end(); + I != E; ++I) { + HeaderOverride &HeaderOv = Headers[I->getKey()]; + HeaderOv.recordReplacements(TransformName, I->getValue()); + } + + if (TrackChanges) + adjustChangedRanges(MainFileReplaces, HeadersReplaces); +} + +void +SourceOverrides::adjustChangedRanges(const Replacements &MainFileReplaces, + const ReplacementsMap &HeadersReplaces) { + // Adjust the changed ranges for each individual file + MainFileChanges.adjustChangedRanges(MainFileReplaces); + for (ReplacementsMap::const_iterator I = HeadersReplaces.begin(), + E = HeadersReplaces.end(); I != E; ++I) { - Headers[I->getKey()].Changes.adjustChangedRanges(I->getValue()); + Headers[I->getKey()].adjustChangedRanges(I->getValue()); } } @@ -131,11 +149,11 @@ void SourceOverrides::applyOverrides(SourceManager &SM) const { for (HeaderOverrides::const_iterator I = Headers.begin(), E = Headers.end(); I != E; ++I) { - assert(!I->second.FileOverride.empty() && + assert(!I->second.getContentOverride().empty() && "Header override should not be empty!"); SM.overrideFileContents( - FM.getFile(I->second.FileName), - llvm::MemoryBuffer::getMemBuffer(I->second.FileOverride)); + FM.getFile(I->second.getFileName()), + llvm::MemoryBuffer::getMemBuffer(I->second.getContentOverride())); } } diff --git a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h index 2bb3daea7b0..9ca4006077e 100644 --- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h +++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h @@ -16,6 +16,7 @@ #ifndef CPP11_MIGRATE_FILE_OVERRIDES_H #define CPP11_MIGRATE_FILE_OVERRIDES_H +#include "Core/ReplacementsYaml.h" #include "clang/Tooling/Refactoring.h" #include "llvm/ADT/StringMap.h" @@ -58,13 +59,54 @@ private: }; /// \brief Container for storing override information for a single headers. -struct HeaderOverride { +class HeaderOverride { +public: + /// \brief Constructors. + /// @{ HeaderOverride() {} - HeaderOverride(llvm::StringRef FileName) : FileName(FileName) {} + HeaderOverride(llvm::StringRef HeaderFileName, + llvm::StringRef SourceFileName) { + HeaderChangeDoc.HeaderFileName = HeaderFileName; + HeaderChangeDoc.SourceFileName = SourceFileName; + } + /// @} + + /// \brief Getter for FileName. + llvm::StringRef getFileName() const { + return HeaderChangeDoc.HeaderFileName; + } + + /// \brief Accessor for ContentOverride. + /// @{ + llvm::StringRef getContentOverride() const { return ContentOverride; } + void setContentOverride(const llvm::StringRef S) { ContentOverride = S; } + /// @} + + /// \brief Getter for Changes. + const ChangedRanges &getChanges() const { return Changes; } - std::string FileName; - std::string FileOverride; + /// \brief Swaps the content of ContentOverride with \param S + void swapContentOverride(std::string &S) { ContentOverride.swap(S); } + + /// \brief Getter for HeaderChangeDoc. + const HeaderChangeDocument &getHeaderChangeDoc() const { + return HeaderChangeDoc; + } + + /// \brief Stores the replacements made by a transform to the header this + /// object represents. + void recordReplacements(llvm::StringRef TransformID, + const clang::tooling::Replacements &Replaces); + + /// \brief Helper function to adjust the changed ranges. + void adjustChangedRanges(const clang::tooling::Replacements &Replaces) { + Changes.adjustChangedRanges(Replaces); + } + +private: + std::string ContentOverride; ChangedRanges Changes; + HeaderChangeDocument HeaderChangeDoc; }; /// \brief Container mapping header file names to override information. @@ -100,8 +142,10 @@ public: /// \param Replaces The replacements to apply. /// \param SM A user provided SourceManager to be used when applying rewrites. void applyReplacements(clang::tooling::Replacements &Replaces, - clang::SourceManager &SM); - void applyReplacements(clang::tooling::Replacements &Replaces); + clang::SourceManager &SM, + llvm::StringRef TransformName); + void applyReplacements(clang::tooling::Replacements &Replaces, + llvm::StringRef TransformName); /// \brief Convenience function for applying this source's overrides to /// the given SourceManager. @@ -118,13 +162,16 @@ public: /// @} private: + typedef llvm::StringMap<clang::tooling::Replacements> ReplacementsMap; + /// \brief Flatten the Rewriter buffers of \p Rewrite and store results as /// file content overrides. void applyRewrites(clang::Rewriter &Rewrite); /// \brief Adjust the changed ranges to reflect the parts of the files that /// have been replaced. - void adjustChangedRanges(const clang::tooling::Replacements &Replaces); + void adjustChangedRanges(const clang::tooling::Replacements &Replaces, + const ReplacementsMap &HeadersReplaces); const std::string MainFileName; std::string MainFileOverride; diff --git a/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp b/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp index 3fd77612bbf..e50206fc0f7 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp @@ -47,10 +47,10 @@ void Reformatter::reformatChanges(SourceOverrides &Overrides, I != E; ++I) { const HeaderOverride &Header = I->getValue(); const tooling::Replacements &HeaderReplaces = - reformatSingleFile(Header.FileName, Header.Changes, SM); + reformatSingleFile(Header.getFileName(), Header.getChanges(), SM); Replaces.insert(HeaderReplaces.begin(), HeaderReplaces.end()); } - Overrides.applyReplacements(Replaces, SM); + Overrides.applyReplacements(Replaces, SM, "reformatter"); } tooling::Replacements Reformatter::reformatSingleFile( diff --git a/clang-tools-extra/cpp11-migrate/Core/ReplacementsYaml.h b/clang-tools-extra/cpp11-migrate/Core/ReplacementsYaml.h new file mode 100644 index 00000000000..e19f4b43888 --- /dev/null +++ b/clang-tools-extra/cpp11-migrate/Core/ReplacementsYaml.h @@ -0,0 +1,102 @@ +//===-- Core/ReplacementsYaml.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file provides structs to store the migrator specific header +/// replacements and the YAML traits for Replacements. +/// +//===----------------------------------------------------------------------===// + +#ifndef CPP11_MIGRATE_REPLACEMENTS_YAML_H +#define CPP11_MIGRATE_REPLACEMENTS_YAML_H + +#include "clang/Tooling/Refactoring.h" +#include "llvm/Support/YAMLTraits.h" +#include <vector> +#include <string> + +/// \brief The top-level YAML document that contains the details for the +/// replacement. +struct HeaderChangeDocument { + std::string TransformID; + std::vector<clang::tooling::Replacement> Replacements; + std::string HeaderFileName; + std::string SourceFileName; +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement) + +namespace llvm { +namespace yaml { + +/// \brief ScalarTraits to read/write std::string objects. +template <> +struct ScalarTraits<std::string> { + static void output(const std::string &Val, void *, llvm::raw_ostream &Out) { + // We need to put quotes around the string to make sure special characters + // in the string is not treated as YAML tokens. + std::string NormalizedVal = std::string("\"") + Val + std::string("\""); + Out << NormalizedVal; + } + + static StringRef input(StringRef Scalar, void *, std::string &Val) { + Val = Scalar; + return StringRef(); + } +}; + +/// \brief Specialized MappingTraits for Repleacements to be converted to/from +/// a YAML File. +template <> +struct MappingTraits<clang::tooling::Replacement> { + /// \brief Normalize clang::tooling::Replacement to provide direct access to + /// its members. + struct NormalizedReplacement { + NormalizedReplacement(const IO &) + : FilePath(""), Offset(0), Length(0), ReplacementText("") {} + + NormalizedReplacement(const IO &, const clang::tooling::Replacement &R) + : FilePath(R.getFilePath()), Offset(R.getOffset()), + Length(R.getLength()), ReplacementText(R.getReplacementText()) {} + + clang::tooling::Replacement denormalize(const IO &) { + return clang::tooling::Replacement(FilePath, Offset, Length, + ReplacementText); + } + + std::string FilePath; + unsigned int Offset; + unsigned int Length; + std::string ReplacementText; + }; + + static void mapping(IO &Io, clang::tooling::Replacement &R) { + MappingNormalization<NormalizedReplacement, clang::tooling::Replacement> + Keys(Io, R); + Io.mapRequired("Offset", Keys->Offset); + Io.mapRequired("Length", Keys->Length); + Io.mapRequired("ReplacementText", Keys->ReplacementText); + } +}; + +/// \brief Specialized MappingTraits for HeaderChangeDocument to be converted +/// to/from a YAML File. +template <> +struct MappingTraits<HeaderChangeDocument> { + static void mapping(IO &Io, HeaderChangeDocument &TD) { + Io.mapRequired("TransformID", TD.TransformID); + Io.mapRequired("Replacements", TD.Replacements); + Io.mapRequired("HeaderFileName", TD.HeaderFileName); + Io.mapRequired("SourceFileName", TD.SourceFileName); + } +}; +} // end namespace yaml +} // end namespace llvm + +#endif // CPP11_MIGRATE_REPLACEMENTS_YAML_H diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp index 92520638502..bd08716d974 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp @@ -118,7 +118,7 @@ bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) { void Transform::handleEndSource() { if (!getReplacements().empty()) { SourceOverrides &SO = Overrides->getOrCreate(CurrentSource); - SO.applyReplacements(getReplacements()); + SO.applyReplacements(getReplacements(), getName()); } if (Options().EnableTiming) diff --git a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp index 10370f959e2..4c0744fde70 100644 --- a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp +++ b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp @@ -325,13 +325,40 @@ int main(int argc, const char **argv) { for (HeaderOverrides::const_iterator HeaderI = Overrides.headers_begin(), HeaderE = Overrides.headers_end(); HeaderI != HeaderE; ++HeaderI) { - assert(!HeaderI->second.FileOverride.empty() && + assert(!HeaderI->second.getContentOverride().empty() && "A header override should not be empty"); std::string ErrorInfo; std::string HeaderFileName = HeaderI->getKey(); llvm::raw_fd_ostream HeaderStream(HeaderFileName.c_str(), ErrorInfo, llvm::sys::fs::F_Binary); - HeaderStream << HeaderI->second.FileOverride; + if (!ErrorInfo.empty()) { + llvm::errs() << "Error opening file: " << ErrorInfo << "\n"; + continue; + } + HeaderStream << HeaderI->second.getContentOverride(); + + // Replacements for header files need to be written in a YAML file for + // every transform and will be merged together with an external tool. + llvm::SmallString<128> ReplacementsHeaderName; + llvm::SmallString<64> Error; + bool Result = generateReplacementsFileName(I->getKey(), HeaderFileName, + ReplacementsHeaderName, Error); + if (!Result) { + llvm::errs() << "Failed to generate replacements filename:" << Error + << "\n"; + continue; + } + + llvm::raw_fd_ostream ReplacementsFile(ReplacementsHeaderName.c_str(), + ErrorInfo, + llvm::sys::fs::F_Binary); + if (!ErrorInfo.empty()) { + llvm::errs() << "Error opening file: " << ErrorInfo << "\n"; + continue; + } + llvm::yaml::Output YAML(ReplacementsFile); + YAML << const_cast<HeaderChangeDocument &>( + HeaderI->getValue().getHeaderChangeDoc()); } } diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.cpp b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.cpp new file mode 100644 index 00000000000..9c4f0e543ce --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.cpp @@ -0,0 +1,16 @@ +// This is just a dummy run command to keep lit happy. Tests for this file are +// in main.cpp +// RUN: true + +#include "common.h" + +void func1(int &I) { +} + +void func2() { + container C1; + container C2; + for (container::iterator I = C1.begin(), E = C1.end(); I != E; ++I) { + C2.push_back(*I); + } +} diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h new file mode 100644 index 00000000000..3bb98cc705c --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h @@ -0,0 +1,27 @@ +#ifndef CPP11_MIGRATE_TEST_HEADER_REPLACEMENTS_COMMON_H +#define CPP11_MIGRATE_TEST_HEADER_REPLACEMENTS_COMMON_H + +struct container { + struct iterator { + int &operator*(); + const int &operator*() const; + iterator &operator++(); + bool operator!=(const iterator &other); + }; + + iterator begin(); + iterator end(); + void push_back(const int &); +}; + +void func1(int &I); +void func2(); + +void dostuff() { + container C; + for (container::iterator I = C.begin(), E = C.end(); I != E; ++I) { + func1(*I); + } +} + +#endif // CPP11_MIGRATE_TEST_HEADER_REPLACEMENTS_COMMON_H diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h.yaml b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h.yaml new file mode 100644 index 00000000000..9123bd8db16 --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h.yaml @@ -0,0 +1,12 @@ +--- +TransformID: "LoopConvert" +Replacements: + - Offset: 432 + Length: 61 + ReplacementText: "(auto & elem : C)" + - Offset: 506 + Length: 2 + ReplacementText: "elem" +HeaderFileName: "common.h" +SourceFileName: "main.cpp" +... diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main.cpp b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main.cpp new file mode 100644 index 00000000000..72c32f1cdea --- /dev/null +++ b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main.cpp @@ -0,0 +1,39 @@ +// The following block tests the following: +// - Only 1 file is generated per translation unit and header file +// - Replacements are written in YAML that matches the expected YAML file +// RUN: rm -rf %t/Test +// RUN: mkdir -p %t/Test +// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %t/Test +// RUN: cpp11-migrate -loop-convert -headers -include=%t/Test %t/Test/main.cpp %t/Test/common.cpp -- +// Check that only 1 file is generated per translation unit and header file. +// RUN: ls -1 %t/Test | grep -c "main.cpp_common.h_.*.yaml" | grep "^1$" +// RUN: ls -1 %t/Test | grep -c "common.cpp_common.h_.*.yaml" | grep "^1$" +// We need to remove the path from FileNames in the generated YAML file because it will have a path in the temp directory +// RUN: sed -i -e 's/^\(HeaderFileName:\|SourceFileName:\).*[\/\\]\(.*\)"$/\1 "\2"/g' %t/Test/main.cpp_common.h_*.yaml +// RUN: cp %S/common.h.yaml %t/Test/main.cpp_common.h.yaml +// RUN: diff -b %t/Test/main.cpp_common.h.yaml %t/Test/main.cpp_common.h_*.yaml +// RUN: sed -i -e 's/^\(HeaderFileName:\|SourceFileName:\).*[\/\\]\(.*\)"$/\1 "\2"/g' %t/Test/common.cpp_common.h_*.yaml +// RUN: cp %S/common.h.yaml %t/Test/common.cpp_common.h.yaml +// RUN: sed -i -e 's/^SourceFileName: "main.cpp"$/SourceFileName: "common.cpp"/g' %t/Test/common.cpp_common.h.yaml +// RUN: diff -b %t/Test/common.cpp_common.h.yaml %t/Test/common.cpp_common.h_*.yaml +// +// The following block tests the following: +// - YAML files are written only when -headers is used +// RUN: rm -rf %t/Test +// RUN: mkdir -p %t/Test +// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %t/Test +// RUN: cpp11-migrate -loop-convert -headers -include=%t/Test %t/Test/main.cpp -- +// RUN: cpp11-migrate -loop-convert %t/Test/common.cpp -- +// Check that only one YAML file is generated from main.cpp and common.h and not from common.cpp and common.h since -header is not specified +// RUN: ls -1 %t/Test | grep -c "main.cpp_common.h_.*.yaml" | grep "^1$" +// RUN: ls -1 %t/Test | not grep "common.cpp_common.h_.*.yaml" +// We need to remove the path from FileName in the generated YAML file because it will have a path in the temp directory +// RUN: sed -i -e 's/^\(HeaderFileName:\|SourceFileName:\).*[\/\\]\(.*\)"$/\1 "\2"/g' %t/Test/main.cpp_common.h_*.yaml +// RUN: diff -b %S/common.h.yaml %t/Test/main.cpp_common.h_*.yaml + +#include "common.h" + +void test_header_replacement() { + dostuff(); + func2(); +} diff --git a/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt b/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt index 1f647d5dc19..8da010f0dbd 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt +++ b/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt @@ -11,6 +11,7 @@ add_extra_unittest(Cpp11MigrateTests ReformattingTest.cpp
IncludeExcludeTest.cpp
PerfSupportTest.cpp
+ ReplacementsYamlTest.cpp
TransformTest.cpp
UniqueHeaderNameTest.cpp
)
diff --git a/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp index 39ed662cbec..382c5a8c737 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp @@ -30,8 +30,10 @@ TEST(SourceOverridesTest, Interface) { Replacements Replaces; unsigned ReplacementLength = strlen("std::vector<such_a_long_name_for_a_type>::const_iterator"); - Replaces.insert(Replacement(FileName, 0, ReplacementLength, "auto")); - Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager()); + Replaces.insert( + Replacement(FileName, 0, ReplacementLength, "auto")); + Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager(), + "use-auto"); EXPECT_TRUE(Overrides.isSourceOverriden()); std::string ExpectedContent = "auto long_type =\n" diff --git a/clang-tools-extra/unittests/cpp11-migrate/IncludeExcludeTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/IncludeExcludeTest.cpp index 8b772c49451..52a9d32d1f6 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/IncludeExcludeTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/IncludeExcludeTest.cpp @@ -7,24 +7,13 @@ // //===----------------------------------------------------------------------===// +#include "Utility.h" #include "Core/IncludeExcludeInfo.h" #include "gtest/gtest.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include <fstream> -// FIXME: copied from unittests/Support/Path.cpp -#define ASSERT_NO_ERROR(x) \ - if (llvm::error_code ASSERT_NO_ERROR_ec = x) { \ - llvm::SmallString<128> MessageStorage; \ - llvm::raw_svector_ostream Message(MessageStorage); \ - Message << #x ": did not return errc::success.\n" \ - << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ - << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ - GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ - } else { \ - } - TEST(IncludeExcludeTest, ParseString) { IncludeExcludeInfo IEManager; llvm::error_code Err = IEManager.readListFromString( diff --git a/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp index fcde6b81db4..a5caa0a3d77 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp @@ -39,7 +39,8 @@ TEST(Reformatter, SingleReformat) { FileName, Changes, VFHelper.getNewSourceManager()); SourceOverrides Overrides(FileName, /*TrackChanges=*/false); - Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager()); + Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager(), + "reformatter"); std::string Expected, Result; diff --git a/clang-tools-extra/unittests/cpp11-migrate/ReplacementsYamlTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/ReplacementsYamlTest.cpp new file mode 100644 index 00000000000..7b95e4dcadd --- /dev/null +++ b/clang-tools-extra/unittests/cpp11-migrate/ReplacementsYamlTest.cpp @@ -0,0 +1,76 @@ +//===- unittests/cpp11-migrate/ReplacementsYamlTest.cpp -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Test for the Yaml files generated by transforms on header files. +// +//===----------------------------------------------------------------------===// + +#include "Utility.h" +#include "Core/FileOverrides.h" +#include "gtest/gtest.h" + +using namespace llvm; + +TEST(ReplacementsYamlTest, writeReadTest) { + using clang::tooling::Replacement; + + const std::string HeaderFileName = "/path/to/common.h"; + const std::string SourceFileName = "/path/to/source.cpp"; + const std::string TransformID = "loop-convert"; + const unsigned int ReplacementOffset1 = 232; + const unsigned int ReplacementLength1 = 56; + const std::string ReplacementText1 = "(auto & elem : V)"; + const unsigned int ReplacementOffset2 = 301; + const unsigned int ReplacementLength2 = 2; + const std::string ReplacementText2 = "elem"; + + HeaderChangeDocument HCD; + HCD.TransformID = TransformID; + HCD.Replacements.push_back(Replacement(HeaderFileName, ReplacementOffset1, + ReplacementLength1, ReplacementText1)); + HCD.Replacements.push_back(Replacement(HeaderFileName, ReplacementOffset2, + ReplacementLength2, ReplacementText2)); + + HCD.HeaderFileName = HeaderFileName.c_str(); + HCD.SourceFileName = SourceFileName.c_str(); + + std::string YamlContent; + llvm::raw_string_ostream YamlContentStream(YamlContent); + + // Write to the YAML file. + { + yaml::Output YAML(YamlContentStream); + YAML << HCD; + YamlContentStream.str(); + ASSERT_NE(YamlContent.length(), 0u); + } + + // Read from the YAML file and verify that what was written is exactly what + // we read back. + { + HeaderChangeDocument HCDActual; + yaml::Input YAML(YamlContent); + YAML >> HCDActual; + ASSERT_NO_ERROR(YAML.error()); + EXPECT_EQ(HeaderFileName, HCDActual.HeaderFileName); + EXPECT_EQ(SourceFileName, HCDActual.SourceFileName); + EXPECT_EQ(TransformID, HCDActual.TransformID); + ASSERT_EQ(2u, HCDActual.Replacements.size()); + + EXPECT_EQ(ReplacementOffset1, HCDActual.Replacements[0].getOffset()); + EXPECT_EQ(ReplacementLength1, HCDActual.Replacements[0].getLength()); + EXPECT_EQ(ReplacementText1, + HCDActual.Replacements[0].getReplacementText().str()); + + EXPECT_EQ(ReplacementOffset2, HCDActual.Replacements[1].getOffset()); + EXPECT_EQ(ReplacementLength2, HCDActual.Replacements[1].getLength()); + EXPECT_EQ(ReplacementText2, + HCDActual.Replacements[1].getReplacementText().str()); + } +} diff --git a/clang-tools-extra/unittests/cpp11-migrate/Utility.h b/clang-tools-extra/unittests/cpp11-migrate/Utility.h new file mode 100644 index 00000000000..54291d941a3 --- /dev/null +++ b/clang-tools-extra/unittests/cpp11-migrate/Utility.h @@ -0,0 +1,25 @@ +//=-- cpp11-migrate/Utility.h - Utility functions and macros-----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CPP11_MIGRATE_UNITTESTS_UTILITY_H +#define CPP11_MIGRATE_UNITTESTS_UTILITY_H + +// FIXME: copied from unittests/Support/Path.cpp +#define ASSERT_NO_ERROR(x) \ + if (llvm::error_code ASSERT_NO_ERROR_ec = x) { \ + llvm::SmallString<128> MessageStorage; \ + llvm::raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } + +#endif // CPP11_MIGRATE_UNITTESTS_UTILITY_H |