RefactoringTest.cpp revision 46fa4c355bd45197dff580b63240494a53b16c1d
1f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===- unittest/Tooling/RefactoringTest.cpp - Refactoring unit tests ------===// 2f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 3f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// The LLVM Compiler Infrastructure 4f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 5f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// This file is distributed under the University of Illinois Open Source 6f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// License. See LICENSE.TXT for details. 7f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 8f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===----------------------------------------------------------------------===// 9f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 10f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "RewriterTestContext.h" 11f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/AST/ASTConsumer.h" 121050e8b2252d89a0004a6fd25a58dab88b5ee625Chandler Carruth#include "clang/AST/ASTContext.h" 13f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/AST/DeclCXX.h" 14f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/AST/DeclGroup.h" 15f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/AST/RecursiveASTVisitor.h" 16f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/Diagnostic.h" 1799eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor#include "clang/Basic/DiagnosticOptions.h" 18f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/FileManager.h" 19f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/LangOptions.h" 20f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/SourceManager.h" 21f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Frontend/CompilerInstance.h" 22f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Frontend/FrontendAction.h" 23f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Frontend/TextDiagnosticPrinter.h" 24305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Core/Rewriter.h" 251050e8b2252d89a0004a6fd25a58dab88b5ee625Chandler Carruth#include "clang/Tooling/Refactoring.h" 26f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Tooling/Tooling.h" 27f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "llvm/ADT/SmallString.h" 28f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "llvm/Support/Path.h" 29f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "gtest/gtest.h" 30f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 31f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace clang { 32f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace tooling { 33f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 34f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass ReplacementTest : public ::testing::Test { 35f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek protected: 36f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement createReplacement(SourceLocation Start, unsigned Length, 37f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek llvm::StringRef ReplacementText) { 38f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return Replacement(Context.Sources, Start, Length, ReplacementText); 39f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 40f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 41f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek RewriterTestContext Context; 42f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}; 43f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 44f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, CanDeleteAllText) { 45f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = Context.createInMemoryFile("input.cpp", "text"); 46f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Location = Context.getLocation(ID, 1, 1); 47f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace(createReplacement(Location, 4, "")); 48f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace.apply(Context.Rewrite)); 49f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("", Context.getRewrittenText(ID)); 50f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 51f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 52f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, CanDeleteAllTextInTextWithNewlines) { 53f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = Context.createInMemoryFile("input.cpp", "line1\nline2\nline3"); 54f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Location = Context.getLocation(ID, 1, 1); 55f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace(createReplacement(Location, 17, "")); 56f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace.apply(Context.Rewrite)); 57f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("", Context.getRewrittenText(ID)); 58f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 59f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 60f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, CanAddText) { 61f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = Context.createInMemoryFile("input.cpp", ""); 62f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Location = Context.getLocation(ID, 1, 1); 63f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace(createReplacement(Location, 0, "result")); 64f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace.apply(Context.Rewrite)); 65f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("result", Context.getRewrittenText(ID)); 66f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 67f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 68f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, CanReplaceTextAtPosition) { 69f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = Context.createInMemoryFile("input.cpp", 70f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek "line1\nline2\nline3\nline4"); 71f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Location = Context.getLocation(ID, 2, 3); 72f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace(createReplacement(Location, 12, "x")); 73f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace.apply(Context.Rewrite)); 74f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("line1\nlixne4", Context.getRewrittenText(ID)); 75f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 76f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 77f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, CanReplaceTextAtPositionMultipleTimes) { 78f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = Context.createInMemoryFile("input.cpp", 79f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek "line1\nline2\nline3\nline4"); 80f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Location1 = Context.getLocation(ID, 2, 3); 81f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace1(createReplacement(Location1, 12, "x\ny\n")); 82f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace1.apply(Context.Rewrite)); 83f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("line1\nlix\ny\nne4", Context.getRewrittenText(ID)); 84f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 85f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // Since the original source has not been modified, the (4, 4) points to the 86f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // 'e' in the original content. 87f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Location2 = Context.getLocation(ID, 4, 4); 88f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace2(createReplacement(Location2, 1, "f")); 89f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace2.apply(Context.Rewrite)); 90f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("line1\nlix\ny\nnf4", Context.getRewrittenText(ID)); 91f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 92f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 93f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, ApplyFailsForNonExistentLocation) { 94f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace("nonexistent-file.cpp", 0, 1, ""); 95f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_FALSE(Replace.apply(Context.Rewrite)); 96f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 97f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 98f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, CanRetrivePath) { 99f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace("/path/to/file.cpp", 0, 1, ""); 100f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("/path/to/file.cpp", Replace.getFilePath()); 101f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 102f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 103f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, ReturnsInvalidPath) { 104f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace1(Context.Sources, SourceLocation(), 0, ""); 105f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace1.getFilePath().empty()); 106f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 107f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace2; 108f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(Replace2.getFilePath().empty()); 109f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 110f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 111f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, CanApplyReplacements) { 112f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = Context.createInMemoryFile("input.cpp", 113f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek "line1\nline2\nline3\nline4"); 114f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacements Replaces; 115f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 116f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 5, "replaced")); 117f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 3, 1), 118f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 5, "other")); 119f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite)); 120f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID)); 121f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 122f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 123f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, SkipsDuplicateReplacements) { 124f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = Context.createInMemoryFile("input.cpp", 125f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek "line1\nline2\nline3\nline4"); 126f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacements Replaces; 127f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 128f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 5, "replaced")); 129f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 130f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 5, "replaced")); 131f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 132f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 5, "replaced")); 133f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite)); 134f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID)); 135f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 136f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 137f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, ApplyAllFailsIfOneApplyFails) { 138f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // This test depends on the value of the file name of an invalid source 139f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // location being in the range ]a, z[. 140f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID IDa = Context.createInMemoryFile("a.cpp", "text"); 141f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID IDz = Context.createInMemoryFile("z.cpp", "text"); 142f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacements Replaces; 143f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDa, 1, 1), 144f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 4, "a")); 145f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, SourceLocation(), 146f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 5, "2")); 147f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDz, 1, 1), 148f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 4, "z")); 149f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_FALSE(applyAllReplacements(Replaces, Context.Rewrite)); 150f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("a", Context.getRewrittenText(IDa)); 151f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("z", Context.getRewrittenText(IDz)); 152f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 153f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 1546bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel JasperTEST(ShiftedCodePositionTest, FindsNewCodePosition) { 1556bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper Replacements Replaces; 1566bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper Replaces.insert(Replacement("", 0, 1, "")); 1576bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper Replaces.insert(Replacement("", 4, 3, " ")); 1586bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper // Assume ' int i;' is turned into 'int i;' and cursor is located at '|'. 1596bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(0u, shiftedCodePosition(Replaces, 0)); // |int i; 1606bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(0u, shiftedCodePosition(Replaces, 1)); // |nt i; 1616bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); // i|t i; 1626bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); // in| i; 1636bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); // int| i; 1646bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(4u, shiftedCodePosition(Replaces, 5)); // int | i; 1656bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(4u, shiftedCodePosition(Replaces, 6)); // int |i; 1666bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); // int |; 1676bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); // int i| 1686bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper} 1696bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper 1706bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel JasperTEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) { 1716bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper Replacements Replaces; 1726bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper Replaces.insert(Replacement("", 4, 0, "\"\n\"")); 1736bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper // Assume '"12345678"' is turned into '"1234"\n"5678"'. 1746bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(4u, shiftedCodePosition(Replaces, 4)); // "123|5678" 1756bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "1234|678" 1766bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper} 1776bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper 178f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass FlushRewrittenFilesTest : public ::testing::Test { 179902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindolapublic: 180902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola FlushRewrittenFilesTest() {} 181f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 182f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek ~FlushRewrittenFilesTest() { 183902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola for (llvm::StringMap<std::string>::iterator I = TemporaryFiles.begin(), 184902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola E = TemporaryFiles.end(); 185902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola I != E; ++I) { 186902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola llvm::StringRef Name = I->second; 187902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola llvm::error_code EC = llvm::sys::fs::remove(Name); 188902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola (void)EC; 189902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola assert(!EC); 190902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola } 191f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 192f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 193f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID createFile(llvm::StringRef Name, llvm::StringRef Content) { 194902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola SmallString<1024> Path; 195902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola int FD; 196902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola llvm::error_code EC = 1971ec4a86a867fc04f35d13bc9e33b04cf2171fe41Rafael Espindola llvm::sys::fs::createTemporaryFile(Name, "", FD, Path); 198902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola assert(!EC); 199902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola (void)EC; 200902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola 201902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola llvm::raw_fd_ostream OutStream(FD, true); 202f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek OutStream << Content; 203f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek OutStream.close(); 204f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek const FileEntry *File = Context.Files.getFile(Path); 205f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek assert(File != NULL); 206902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola 207902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second; 208902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola assert(Found == Path); 209902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola (void)Found; 210f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return Context.Sources.createFileID(File, SourceLocation(), SrcMgr::C_User); 211f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 212f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 213f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek std::string getFileContentFromDisk(llvm::StringRef Name) { 214902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola std::string Path = TemporaryFiles.lookup(Name); 215902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola assert(!Path.empty()); 216f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // We need to read directly from the FileManager without relaying through 217f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // a FileEntry, as otherwise we'd read through an already opened file 218f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // descriptor, which might not see the changes made. 219f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // FIXME: Figure out whether there is a way to get the SourceManger to 220f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // reopen the file. 221f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return Context.Files.getBufferForFile(Path, NULL)->getBuffer(); 222f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 223f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 224902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola llvm::StringMap<std::string> TemporaryFiles; 225f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek RewriterTestContext Context; 226f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}; 227f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 228f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) { 229f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID = createFile("input.cpp", "line1\nline2\nline3\nline4"); 230f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacements Replaces; 231f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 232f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 5, "replaced")); 233f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite)); 234f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_FALSE(Context.Rewrite.overwriteChangedFiles()); 235f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ("line1\nreplaced\nline3\nline4", 236f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek getFileContentFromDisk("input.cpp")); 237f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 238f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 239f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace { 240f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimektemplate <typename T> 241f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass TestVisitor : public clang::RecursiveASTVisitor<T> { 242f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic: 243f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek bool runOver(StringRef Code) { 244f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return runToolOnCode(new TestAction(this), Code); 245f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 246f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 247f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekprotected: 248f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek clang::SourceManager *SM; 249f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 250f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekprivate: 251f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek class FindConsumer : public clang::ASTConsumer { 252f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek public: 253f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {} 254f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 255f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek virtual void HandleTranslationUnit(clang::ASTContext &Context) { 256f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Visitor->TraverseDecl(Context.getTranslationUnitDecl()); 257f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 258f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 259f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek private: 260f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek TestVisitor *Visitor; 261f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek }; 262f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 263f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek class TestAction : public clang::ASTFrontendAction { 264f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek public: 265f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek TestAction(TestVisitor *Visitor) : Visitor(Visitor) {} 266f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 267f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek virtual clang::ASTConsumer* CreateASTConsumer( 268f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek clang::CompilerInstance& compiler, llvm::StringRef dummy) { 269f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Visitor->SM = &compiler.getSourceManager(); 270f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// TestConsumer will be deleted by the framework calling us. 271f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return new FindConsumer(Visitor); 272f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 273f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 274f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek private: 275f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek TestVisitor *Visitor; 276f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek }; 277f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}; 278f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace 279f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 280f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekvoid expectReplacementAt(const Replacement &Replace, 281f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek StringRef File, unsigned Offset, unsigned Length) { 282f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek ASSERT_TRUE(Replace.isApplicable()); 283f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ(File, Replace.getFilePath()); 284f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ(Offset, Replace.getOffset()); 285f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_EQ(Length, Replace.getLength()); 286f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 287f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 288f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass ClassDeclXVisitor : public TestVisitor<ClassDeclXVisitor> { 289f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic: 290f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek bool VisitCXXRecordDecl(CXXRecordDecl *Record) { 291f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek if (Record->getName() == "X") { 292f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replace = Replacement(*SM, Record, ""); 293f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 294f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return true; 295f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 296f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace; 297f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}; 298f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 299f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, CanBeConstructedFromNode) { 300f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek ClassDeclXVisitor ClassDeclX; 301f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(ClassDeclX.runOver(" class X;")); 302f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek expectReplacementAt(ClassDeclX.Replace, "input.cc", 5, 7); 303f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 304f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 305f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, ReplacesAtSpellingLocation) { 306f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek ClassDeclXVisitor ClassDeclX; 307f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(ClassDeclX.runOver("#define A(Y) Y\nA(class X);")); 308f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7); 309f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 310f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 311f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass CallToFVisitor : public TestVisitor<CallToFVisitor> { 312f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic: 313f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek bool VisitCallExpr(CallExpr *Call) { 314f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek if (Call->getDirectCallee()->getName() == "F") { 315f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replace = Replacement(*SM, Call, ""); 316f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 317f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return true; 318f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 319f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement Replace; 320f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}; 321f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 322f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, FunctionCall) { 323f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek CallToFVisitor CallToF; 324f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(CallToF.runOver("void F(); void G() { F(); }")); 325f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek expectReplacementAt(CallToF.Replace, "input.cc", 21, 3); 326f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 327f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 328f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, TemplatedFunctionCall) { 329f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek CallToFVisitor CallToF; 330f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek EXPECT_TRUE(CallToF.runOver( 331f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek "template <typename T> void F(); void G() { F<int>(); }")); 332f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek expectReplacementAt(CallToF.Replace, "input.cc", 43, 8); 333f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 334f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 33546fa4c355bd45197dff580b63240494a53b16c1dManuel KlimekTEST(Range, overlaps) { 33646fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_TRUE(Range(10, 10).overlapsWith(Range(0, 11))); 33746fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_TRUE(Range(0, 11).overlapsWith(Range(10, 10))); 33846fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_FALSE(Range(10, 10).overlapsWith(Range(0, 10))); 33946fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_FALSE(Range(0, 10).overlapsWith(Range(10, 10))); 34046fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_TRUE(Range(0, 10).overlapsWith(Range(2, 6))); 34146fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek} 34246fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek 34346fa4c355bd45197dff580b63240494a53b16c1dManuel KlimekTEST(Range, contains) { 34446fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_TRUE(Range(0, 10).contains(Range(0, 10))); 34546fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_TRUE(Range(0, 10).contains(Range(2, 6))); 34646fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_FALSE(Range(2, 6).contains(Range(0, 10))); 34746fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek EXPECT_FALSE(Range(0, 10).contains(Range(0, 11))); 34846fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek} 34946fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek 350f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace tooling 351f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace clang 352