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