From abbef0ef07296b928924146210607a11be17d0a1 Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Wed, 29 Mar 2017 00:24:36 +0000 Subject: [PATCH] Revert "Added `applyAtomicChanges` function." This broke GreenDragon: http://lab.llvm.org:8080/green/job/clang-stage2-cmake-modulesRDA_build/4776/ Reverting this commit and all follow-up commits. llvm-svn: 298967 --- .../clang/Tooling/Refactoring/AtomicChange.h | 34 -- clang/lib/Tooling/Refactoring/AtomicChange.cpp | 179 --------- clang/unittests/Tooling/RefactoringTest.cpp | 430 --------------------- 3 files changed, 643 deletions(-) diff --git a/clang/include/clang/Tooling/Refactoring/AtomicChange.h b/clang/include/clang/Tooling/Refactoring/AtomicChange.h index f8d11c2..f437c4b 100644 --- a/clang/include/clang/Tooling/Refactoring/AtomicChange.h +++ b/clang/include/clang/Tooling/Refactoring/AtomicChange.h @@ -16,7 +16,6 @@ #define LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H #include "clang/Basic/SourceManager.h" -#include "clang/Format/Format.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -124,39 +123,6 @@ private: tooling::Replacements Replaces; }; -// Defines specs for applying changes. -struct ApplyChangesSpec { - // If true, cleans up redundant/erroneous code around changed code with - // clang-format's cleanup functionality, e.g. redundant commas around deleted - // parameter or empty namespaces introduced by deletions. - bool Cleanup = true; - - format::FormatStyle Style = format::getNoStyle(); - - // Options for selectively formatting changes with clang-format: - // kAll: Format all changed lines. - // kNone: Don't format anything. - // kViolations: Format lines exceeding the `ColumnLimit` in `Style`. - enum FormatOption { kAll, kNone, kViolations }; - - FormatOption Format = kNone; -}; - -/// \brief Applies all AtomicChanges in \p Changes to the \p Code. -/// -/// This completely ignores the file path in each change and replaces them with -/// \p FilePath, i.e. callers are responsible for ensuring all changes are for -/// the same file. -/// -/// \returns The changed code if all changes are applied successfully; -/// otherwise, an llvm::Error carrying llvm::StringError is returned (the Error -/// message can be converted to string with `llvm::toString()` and the -/// error_code should be ignored). -llvm::Expected -applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code, - llvm::ArrayRef Changes, - const ApplyChangesSpec &Spec); - } // end namespace tooling } // end namespace clang diff --git a/clang/lib/Tooling/Refactoring/AtomicChange.cpp b/clang/lib/Tooling/Refactoring/AtomicChange.cpp index 20c30ad..02c5510 100644 --- a/clang/lib/Tooling/Refactoring/AtomicChange.cpp +++ b/clang/lib/Tooling/Refactoring/AtomicChange.cpp @@ -84,116 +84,6 @@ template <> struct MappingTraits { namespace clang { namespace tooling { -namespace { - -// Returns true if there is any line that violates \p ColumnLimit in range -// [Start, End]. -bool violatesColumnLimit(llvm::StringRef Code, unsigned ColumnLimit, - unsigned Start, unsigned End) { - auto StartPos = Code.rfind('\n', Start); - StartPos = (StartPos == llvm::StringRef::npos) ? 0 : StartPos + 1; - - auto EndPos = Code.find("\n", End); - if (EndPos == llvm::StringRef::npos) - EndPos = Code.size(); - - llvm::SmallVector Lines; - Code.substr(StartPos, EndPos - StartPos).split(Lines, '\n'); - for (llvm::StringRef Line : Lines) - if (Line.size() > ColumnLimit) - return true; - return false; -} - -std::vector -getRangesForFormating(llvm::StringRef Code, unsigned ColumnLimit, - ApplyChangesSpec::FormatOption Format, - const clang::tooling::Replacements &Replaces) { - // kNone suppresses formatting entirely. - if (Format == ApplyChangesSpec::kNone) - return {}; - std::vector Ranges; - // This works assuming that replacements are ordered by offset. - // FIXME: use `getAffectedRanges()` to calculate when it does not include '\n' - // at the end of an insertion in affected ranges. - int Offset = 0; - for (const clang::tooling::Replacement &R : Replaces) { - int Start = R.getOffset() + Offset; - int End = Start + R.getReplacementText().size(); - if (!R.getReplacementText().empty() && - R.getReplacementText().back() == '\n' && R.getLength() == 0 && - R.getOffset() > 0 && R.getOffset() <= Code.size() && - Code[R.getOffset() - 1] == '\n') - // If we are inserting at the start of a line and the replacement ends in - // a newline, we don't need to format the subsequent line. - --End; - Offset += R.getReplacementText().size() - R.getLength(); - - if (Format == ApplyChangesSpec::kAll || - violatesColumnLimit(Code, ColumnLimit, Start, End)) - Ranges.emplace_back(Start, End - Start); - } - return Ranges; -} - -inline llvm::Error make_string_error(const llvm::Twine &Message) { - return llvm::make_error(Message, - llvm::inconvertibleErrorCode()); -} - -// Creates replacements for inserting/deleting #include headers. -llvm::Expected -createReplacementsForHeaders(llvm::StringRef FilePath, llvm::StringRef Code, - llvm::ArrayRef Changes, - const format::FormatStyle &Style) { - // Create header insertion/deletion replacements to be cleaned up - // (i.e. converted to real insertion/deletion replacements). - Replacements HeaderReplacements; - for (const auto &Change : Changes) { - for (llvm::StringRef Header : Change.getInsertedHeaders()) { - std::string EscapedHeader = - Header.startswith("<") || Header.startswith("\"") - ? Header.str() - : ("\"" + Header + "\"").str(); - std::string ReplacementText = "#include " + EscapedHeader; - // Offset UINT_MAX and length 0 indicate that the replacement is a header - // insertion. - llvm::Error Err = HeaderReplacements.add( - tooling::Replacement(FilePath, UINT_MAX, 0, ReplacementText)); - if (Err) - return std::move(Err); - } - for (const std::string &Header : Change.getRemovedHeaders()) { - // Offset UINT_MAX and length 1 indicate that the replacement is a header - // deletion. - llvm::Error Err = - HeaderReplacements.add(Replacement(FilePath, UINT_MAX, 1, Header)); - if (Err) - return std::move(Err); - } - } - - // cleanupAroundReplacements() converts header insertions/deletions into - // actual replacements that add/remove headers at the right location. - return clang::format::cleanupAroundReplacements(Code, HeaderReplacements, - Style); -} - -// Combine replacements in all Changes as a `Replacements`. This ignores the -// file path in all replacements and replaces them with \p FilePath. -llvm::Expected -combineReplacementsInChanges(llvm::StringRef FilePath, - llvm::ArrayRef Changes) { - Replacements Replaces; - for (const auto &Change : Changes) - for (const auto &R : Change.getReplacements()) - if (auto Err = Replaces.add(Replacement( - FilePath, R.getOffset(), R.getLength(), R.getReplacementText()))) - return std::move(Err); - return Replaces; -} - -} // end namespace AtomicChange::AtomicChange(const SourceManager &SM, SourceLocation KeyPosition) { @@ -278,74 +168,5 @@ void AtomicChange::removeHeader(llvm::StringRef Header) { RemovedHeaders.push_back(Header); } -llvm::Expected -applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code, - llvm::ArrayRef Changes, - const ApplyChangesSpec &Spec) { - llvm::Expected HeaderReplacements = - createReplacementsForHeaders(FilePath, Code, Changes, Spec.Style); - if (!HeaderReplacements) - return make_string_error( - "Failed to create replacements for header changes: " + - llvm::toString(HeaderReplacements.takeError())); - - llvm::Expected Replaces = - combineReplacementsInChanges(FilePath, Changes); - if (!Replaces) - return make_string_error("Failed to combine replacements in all changes: " + - llvm::toString(Replaces.takeError())); - - Replacements AllReplaces = std::move(*Replaces); - for (const auto &R : *HeaderReplacements) { - llvm::Error Err = AllReplaces.add(R); - if (Err) - return make_string_error( - "Failed to combine existing replacements with header replacements: " + - llvm::toString(std::move(Err))); - } - - if (Spec.Cleanup) { - llvm::Expected CleanReplaces = - format::cleanupAroundReplacements(Code, AllReplaces, Spec.Style); - if (!CleanReplaces) - return make_string_error("Failed to cleanup around replacements: " + - llvm::toString(CleanReplaces.takeError())); - AllReplaces = std::move(*CleanReplaces); - } - - // Apply all replacements. - llvm::Expected ChangedCode = - applyAllReplacements(Code, AllReplaces); - if (!ChangedCode) - return make_string_error("Failed to apply all replacements: " + - llvm::toString(ChangedCode.takeError())); - - // Sort inserted headers. This is done even if other formatting is turned off - // as incorrectly sorted headers are always just wrong, it's not a matter of - // taste. - Replacements HeaderSortingReplacements = format::sortIncludes( - Spec.Style, *ChangedCode, AllReplaces.getAffectedRanges(), FilePath); - ChangedCode = applyAllReplacements(*ChangedCode, HeaderSortingReplacements); - if (!ChangedCode) - return make_string_error( - "Failed to apply replacements for sorting includes: " + - llvm::toString(ChangedCode.takeError())); - - AllReplaces = AllReplaces.merge(HeaderSortingReplacements); - - std::vector FormatRanges = getRangesForFormating( - *ChangedCode, Spec.Style.ColumnLimit, Spec.Format, AllReplaces); - if (!FormatRanges.empty()) { - Replacements FormatReplacements = - format::reformat(Spec.Style, *ChangedCode, FormatRanges, FilePath); - ChangedCode = applyAllReplacements(*ChangedCode, FormatReplacements); - if (!ChangedCode) - return make_string_error( - "Failed to apply replacements for formatting changed code: " + - llvm::toString(ChangedCode.takeError())); - } - return ChangedCode; -} - } // end namespace tooling } // end namespace clang diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp index 7ac5a1d..c5633d3 100644 --- a/clang/unittests/Tooling/RefactoringTest.cpp +++ b/clang/unittests/Tooling/RefactoringTest.cpp @@ -1290,435 +1290,5 @@ TEST_F(AtomicChangeTest, InsertAfterWithInvalidLocation) { Replacement(Context.Sources, SourceLocation(), 0, "b"))); } -class ApplyAtomicChangesTest : public ::testing::Test { -protected: - ApplyAtomicChangesTest() : FilePath("file.cc") { - Spec.Cleanup = true; - Spec.Format = ApplyChangesSpec::kAll; - Spec.Style = format::getLLVMStyle(); - } - - ~ApplyAtomicChangesTest() override {} - - void setInput(llvm::StringRef Input) { - Code = Input; - FID = Context.createInMemoryFile(FilePath, Code); - } - - SourceLocation getLoc(unsigned Offset) const { - return Context.Sources.getLocForStartOfFile(FID).getLocWithOffset(Offset); - } - - AtomicChange replacementToAtomicChange(llvm::StringRef Key, unsigned Offset, - unsigned Length, - llvm::StringRef Text) { - AtomicChange Change(FilePath, Key); - llvm::Error Err = - Change.replace(Context.Sources, getLoc(Offset), Length, Text); - EXPECT_FALSE(Err); - return Change; - } - - std::string rewrite(bool FailureExpected = false) { - llvm::Expected ChangedCode = - applyAtomicChanges(FilePath, Code, Changes, Spec); - EXPECT_EQ(FailureExpected, !ChangedCode); - if (!ChangedCode) { - llvm::errs() << "Failed to apply changes: " - << llvm::toString(ChangedCode.takeError()) << "\n"; - return ""; - } - return *ChangedCode; - } - - RewriterTestContext Context; - FileID FID; - ApplyChangesSpec Spec; - std::string Code; - std::string FilePath; - llvm::SmallVector Changes; -}; - -TEST_F(ApplyAtomicChangesTest, BasicRefactoring) { - setInput("int a;"); - AtomicChange Change(FilePath, "key1"); - Changes.push_back(replacementToAtomicChange("key1", 4, 1, "b")); - EXPECT_EQ("int b;", rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, SeveralRefactorings) { - setInput("int a;\n" - "int b;"); - Changes.push_back(replacementToAtomicChange("key1", 0, 3, "float")); - Changes.push_back(replacementToAtomicChange("key2", 4, 1, "f")); - Changes.push_back(replacementToAtomicChange("key3", 11, 1, "g")); - Changes.push_back(replacementToAtomicChange("key4", 7, 3, "float")); - EXPECT_EQ("float f;\n" - "float g;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, IgnorePathsInRefactorings) { - setInput("int a;\n" - "int b;"); - Changes.push_back(replacementToAtomicChange("key1", 4, 1, "aa")); - - FileID ID = Context.createInMemoryFile("AnotherFile", "12345678912345"); - Changes.emplace_back("AnotherFile", "key2"); - auto Err = Changes.back().replace( - Context.Sources, - Context.Sources.getLocForStartOfFile(ID).getLocWithOffset(11), 1, "bb"); - ASSERT_TRUE(!Err); - EXPECT_EQ("int aa;\n" - "int bb;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, AppliesDuplicateInsertions) { - setInput("int a;"); - Changes.push_back(replacementToAtomicChange("key1", 5, 0, "b")); - Changes.push_back(replacementToAtomicChange("key2", 5, 0, "b")); - EXPECT_EQ("int abb;", rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, BailsOnOverlappingRefactorings) { - setInput("int a;"); - Changes.push_back(replacementToAtomicChange("key1", 0, 5, "float f")); - Changes.push_back(replacementToAtomicChange("key2", 4, 1, "b")); - EXPECT_EQ("", rewrite(/*FailureExpected=*/true)); -} - -TEST_F(ApplyAtomicChangesTest, BasicReformatting) { - setInput("int a;"); - Changes.push_back(replacementToAtomicChange("key1", 5, 1, "b")); - EXPECT_EQ("int b;", rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, OnlyFormatWhenViolateColumnLimits) { - Spec.Format = ApplyChangesSpec::kViolations; - Spec.Style.ColumnLimit = 8; - setInput("int a;\n" - "int a;\n" - "int aaaaaaaa;\n"); - Changes.push_back(replacementToAtomicChange("key1", 5, 1, "x")); - Changes.push_back(replacementToAtomicChange("key2", 15, 1, "x")); - Changes.push_back(replacementToAtomicChange("key3", 23, 8, "xx")); - EXPECT_EQ("int x;\n" - "int x;\n" - "int xx;\n", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, LastLineViolateColumnLimits) { - Spec.Format = ApplyChangesSpec::kViolations; - Spec.Style.ColumnLimit = 8; - setInput("int a;\n" - "int a;"); - Changes.push_back(replacementToAtomicChange("key1", 0, 1, "i")); - Changes.push_back(replacementToAtomicChange("key2", 15, 2, "y;")); - EXPECT_EQ("int a;\n" - "int y;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, LastLineWithNewlineViolateColumnLimits) { - Spec.Format = ApplyChangesSpec::kViolations; - Spec.Style.ColumnLimit = 8; - setInput("int a;\n" - "int a;\n"); - Changes.push_back(replacementToAtomicChange("key1", 0, 1, "i")); - Changes.push_back(replacementToAtomicChange("key2", 14, 3, "y;\n")); - EXPECT_EQ("int a;\n" - "int y;\n", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, Longer) { - setInput("int a;"); - Changes.push_back(replacementToAtomicChange("key1", 5, 1, "bbb")); - EXPECT_EQ("int bbb;", rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, Shorter) { - setInput("int aaa;"); - Changes.push_back(replacementToAtomicChange("key1", 5, 3, "b")); - EXPECT_EQ("int b;", rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, OnlyFormatChangedLines) { - setInput("int aaa;\n" - "int a = b;\n" - "int bbb;"); - Changes.push_back(replacementToAtomicChange("key1", 14, 1, "b")); - EXPECT_EQ("int aaa;\n" - "int b = b;\n" - "int bbb;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, DisableFormatting) { - Spec.Format = ApplyChangesSpec::kNone; - setInput("int aaa;\n" - "int a = b;\n" - "int bbb;"); - Changes.push_back(replacementToAtomicChange("key1", 14, 1, "b")); - EXPECT_EQ("int aaa;\n" - "int b = b;\n" - "int bbb;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, AdaptsToLocalPointerStyle) { - setInput("int *aaa;\n" - "int *bbb;"); - Changes.push_back(replacementToAtomicChange("key1", 0, 0, "int* ccc;\n")); - EXPECT_EQ("int *ccc;\n" - "int *aaa;\n" - "int *bbb;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, AcceptsSurroundingFormatting) { - setInput(" int aaa;\n" - " int a = b;\n" - " int bbb;"); - Changes.push_back(replacementToAtomicChange("key1", 20, 1, "b")); - EXPECT_EQ(" int aaa;\n" - " int b = b;\n" - " int bbb;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, BailsOutOnConflictingChanges) { - setInput("int c;\n" - "int f;"); - // Insertions at the same offset are only allowed in the same AtomicChange. - Changes.push_back(replacementToAtomicChange("key1", 0, 0, "int a;\n")); - Changes.push_back(replacementToAtomicChange("key2", 0, 0, "int b;\n")); - EXPECT_EQ("", rewrite(/*FailureExpected=*/true)); -} - -TEST_F(ApplyAtomicChangesTest, InsertsNewIncludesInRightOrder) { - setInput("int a;"); - Changes.emplace_back(FilePath, "key1"); - Changes.back().addHeader("b"); - Changes.back().addHeader("c"); - Changes.emplace_back(FilePath, "key2"); - Changes.back().addHeader("a"); - EXPECT_EQ("#include \"a\"\n" - "#include \"b\"\n" - "#include \"c\"\n" - "int a;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, RemoveAndSortIncludes) { - setInput(R"( -#include "a" -#include "b" -#include "c" - -int a; - )"); - Changes.emplace_back(FilePath, "key1"); - Changes.back().removeHeader("b"); - EXPECT_EQ(R"( -#include "a" -#include "c" - -int a; - )", - rewrite()); -} -TEST_F(ApplyAtomicChangesTest, InsertsSystemIncludes) { - setInput("#include \n" - "#include \n" - "\n" - "#include \"a\"\n" - "#include \"c\"\n"); - Changes.emplace_back(FilePath, "key1"); - Changes.back().addHeader(""); // Already exists. - Changes.back().addHeader(""); - Changes.back().addHeader(""); - Changes.back().addHeader("\"b-already-escaped\""); - EXPECT_EQ("#include \n" - "#include \n" - "#include \n" - "#include \n" - "\n" - "#include \"a\"\n" - "#include \"b-already-escaped\"\n" - "#include \"c\"\n", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, RemoveSystemIncludes) { - setInput(R"( -#include -#include - -#include "c" - -int a; - )"); - Changes.emplace_back(FilePath, "key1"); - Changes.back().removeHeader(""); - EXPECT_EQ(R"( -#include - -#include "c" - -int a; - )", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, - DoNotFormatFollowingLinesIfSeparatedWithNewline) { - setInput("#ifndef __H__\n" - "#define __H__\n" - "#include \"b\"\n" - "\n" - "int a;\n" - "int a;\n" - "int a;\n" - "#endif // __H__\n"); - Changes.push_back(replacementToAtomicChange("key1", - llvm::StringRef("#ifndef __H__\n" - "#define __H__\n" - "\n" - "#include \"b\"\n" - "int a;\n" - "int ") - .size(), - 1, "b")); - Changes.back().addHeader("a"); - EXPECT_EQ("#ifndef __H__\n" - "#define __H__\n" - "#include \"a\"\n" - "#include \"b\"\n" - "\n" - "int a;\n" - "int b;\n" - "int a;\n" - "#endif // __H__\n", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, FormatsCorrectLineWhenHeaderIsRemoved) { - setInput("#include \"a\"\n" - "\n" - "int a;\n" - "int a;\n" - "int a;"); - Changes.push_back(replacementToAtomicChange("key1", 27, 1, "b")); - Changes.back().removeHeader("a"); - EXPECT_EQ("\n" - "int a;\n" - "int b;\n" - "int a;", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, CleansUpCtorInitializers) { - setInput("A::A() : a(), b() {}\n" - "A::A() : a(), b() {}\n" - "A::A() : a(), b() {}\n" - "A::A() : a()/**/, b() {}\n" - "A::A() : a() ,// \n" - " /**/ b() {}"); - Changes.emplace_back(FilePath, "key1"); - auto Err = Changes.back().replace(Context.Sources, getLoc(9), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(35), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(51), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(56), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(72), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(97), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(118), 3, ""); - ASSERT_TRUE(!Err); - EXPECT_EQ("A::A() : b() {}\n" - "A::A() : a() {}\n" - "A::A() {}\n" - "A::A() : b() {}\n" - "A::A() {}", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, CleansUpParameterLists) { - setInput("void f(int i, float f, string s);\n" - "f(1, 2.0f, \"a\");\n" - "g(1, 1);"); - Changes.emplace_back(FilePath, "key1"); - auto Err = Changes.back().replace(Context.Sources, getLoc(7), 5, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(23), 8, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(36), 1, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(45), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(53), 1, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(56), 1, ""); - ASSERT_TRUE(!Err); - EXPECT_EQ("void f(float f);\n" - "f(2.0f);\n" - "g();", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, DisableCleanup) { - Spec.Cleanup = false; - setInput("void f(int i, float f, string s);\n" - "f(1, 2.0f, \"a\");\n" - "g(1, 1);"); - Changes.emplace_back(FilePath, "key1"); - auto Err = Changes.back().replace(Context.Sources, getLoc(7), 5, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(23), 8, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(36), 1, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(45), 3, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(53), 1, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(56), 1, ""); - ASSERT_TRUE(!Err); - EXPECT_EQ("void f(, float f, );\n" - "f(, 2.0f, );\n" - "g(, );", - rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, EverythingDeleted) { - setInput("int a;"); - Changes.push_back(replacementToAtomicChange("key1", 0, 6, "")); - EXPECT_EQ("", rewrite()); -} - -TEST_F(ApplyAtomicChangesTest, DoesNotDeleteInserts) { - setInput("int a;\n" - "int b;"); - Changes.emplace_back(FilePath, "key1"); - auto Err = Changes.back().replace(Context.Sources, getLoc(4), 1, ""); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(4), 0, "b"); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(11), 0, "a"); - ASSERT_TRUE(!Err); - Err = Changes.back().replace(Context.Sources, getLoc(11), 1, ""); - ASSERT_TRUE(!Err); - EXPECT_EQ("int b;\n" - "int a;", - rewrite()); -} - } // end namespace tooling } // end namespace clang -- 2.7.4