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
123b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane// FIXME: Remove this test case when Replacements is implemented as std::vector
124b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane// instead of std::set. The other ReplacementTest tests will need to be updated
125b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane// at that point as well.
126b58cfd93c49727c1d471ce71901502df824556c7Edwin VaneTEST_F(ReplacementTest, VectorCanApplyReplacements) {
127b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane  FileID ID = Context.createInMemoryFile("input.cpp",
128b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane                                         "line1\nline2\nline3\nline4");
129b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane  std::vector<Replacement> Replaces;
130b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane  Replaces.push_back(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
131b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane                                 5, "replaced"));
132b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane  Replaces.push_back(
133b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane      Replacement(Context.Sources, Context.getLocation(ID, 3, 1), 5, "other"));
134b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
135b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane  EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
136b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane}
137b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane
138f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, SkipsDuplicateReplacements) {
139f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  FileID ID = Context.createInMemoryFile("input.cpp",
140f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                                         "line1\nline2\nline3\nline4");
141f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replacements Replaces;
142f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
143f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                              5, "replaced"));
144f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
145f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                              5, "replaced"));
146f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
147f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                              5, "replaced"));
148f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
149f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID));
150f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
151f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
152f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(ReplacementTest, ApplyAllFailsIfOneApplyFails) {
153f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  // This test depends on the value of the file name of an invalid source
154f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  // location being in the range ]a, z[.
155f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  FileID IDa = Context.createInMemoryFile("a.cpp", "text");
156f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  FileID IDz = Context.createInMemoryFile("z.cpp", "text");
157f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replacements Replaces;
158f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDa, 1, 1),
159f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                              4, "a"));
160f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replaces.insert(Replacement(Context.Sources, SourceLocation(),
161f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                              5, "2"));
162f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDz, 1, 1),
163f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                              4, "z"));
164f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_FALSE(applyAllReplacements(Replaces, Context.Rewrite));
165f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_EQ("a", Context.getRewrittenText(IDa));
166f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_EQ("z", Context.getRewrittenText(IDz));
167f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
168f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
1696bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel JasperTEST(ShiftedCodePositionTest, FindsNewCodePosition) {
1706bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  Replacements Replaces;
1716bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  Replaces.insert(Replacement("", 0, 1, ""));
1726bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  Replaces.insert(Replacement("", 4, 3, " "));
1736bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  // Assume ' int   i;' is turned into 'int i;' and cursor is located at '|'.
1746bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(0u, shiftedCodePosition(Replaces, 0)); // |int   i;
1756bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(0u, shiftedCodePosition(Replaces, 1)); //  |nt   i;
1766bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); //  i|t   i;
1776bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); //  in|   i;
1786bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); //  int|  i;
1796bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(4u, shiftedCodePosition(Replaces, 5)); //  int | i;
180a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(4u, shiftedCodePosition(Replaces, 6)); //  int  |i;
181a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); //  int   |;
182a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); //  int   i|
183a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane}
184a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane
185a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane// FIXME: Remove this test case when Replacements is implemented as std::vector
186a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane// instead of std::set. The other ReplacementTest tests will need to be updated
187a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane// at that point as well.
188a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin VaneTEST(ShiftedCodePositionTest, VectorFindsNewCodePositionWithInserts) {
189a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  std::vector<Replacement> Replaces;
190a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  Replaces.push_back(Replacement("", 0, 1, ""));
191a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  Replaces.push_back(Replacement("", 4, 3, " "));
192a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  // Assume ' int   i;' is turned into 'int i;' and cursor is located at '|'.
193a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(0u, shiftedCodePosition(Replaces, 0)); // |int   i;
194a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(0u, shiftedCodePosition(Replaces, 1)); //  |nt   i;
195a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); //  i|t   i;
196a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); //  in|   i;
197a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); //  int|  i;
198a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane  EXPECT_EQ(4u, shiftedCodePosition(Replaces, 5)); //  int | i;
1996bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(4u, shiftedCodePosition(Replaces, 6)); //  int  |i;
2006bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); //  int   |;
2016bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); //  int   i|
2026bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper}
2036bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper
2046bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel JasperTEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) {
2056bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  Replacements Replaces;
2066bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  Replaces.insert(Replacement("", 4, 0, "\"\n\""));
2076bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  // Assume '"12345678"' is turned into '"1234"\n"5678"'.
2086bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(4u, shiftedCodePosition(Replaces, 4)); // "123|5678"
2096bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper  EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "1234|678"
2106bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper}
2116bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper
212f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass FlushRewrittenFilesTest : public ::testing::Test {
213902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindolapublic:
214902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola   FlushRewrittenFilesTest() {}
215f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
216f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  ~FlushRewrittenFilesTest() {
217902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    for (llvm::StringMap<std::string>::iterator I = TemporaryFiles.begin(),
218902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola                                                E = TemporaryFiles.end();
219902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola         I != E; ++I) {
220902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola      llvm::StringRef Name = I->second;
221ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      std::error_code EC = llvm::sys::fs::remove(Name);
222902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola      (void)EC;
223902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola      assert(!EC);
224902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    }
225f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  }
226f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
227f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  FileID createFile(llvm::StringRef Name, llvm::StringRef Content) {
228902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    SmallString<1024> Path;
229902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    int FD;
230ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
231902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    assert(!EC);
232902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    (void)EC;
233902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola
234902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    llvm::raw_fd_ostream OutStream(FD, true);
235f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    OutStream << Content;
236f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    OutStream.close();
237f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    const FileEntry *File = Context.Files.getFile(Path);
238ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    assert(File != nullptr);
239902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola
240902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second;
241902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    assert(Found == Path);
242902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    (void)Found;
243f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    return Context.Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
244f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  }
245f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
246f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  std::string getFileContentFromDisk(llvm::StringRef Name) {
247902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    std::string Path = TemporaryFiles.lookup(Name);
248902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola    assert(!Path.empty());
249f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    // We need to read directly from the FileManager without relaying through
250f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    // a FileEntry, as otherwise we'd read through an already opened file
251f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    // descriptor, which might not see the changes made.
252f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    // FIXME: Figure out whether there is a way to get the SourceManger to
253f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    // reopen the file.
2546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    std::unique_ptr<const llvm::MemoryBuffer> FileBuffer(
255ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        Context.Files.getBufferForFile(Path, nullptr));
2566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return FileBuffer->getBuffer();
257f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  }
258f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
259902a86385361d5d0a3ae731c89a5b62e470dd875Rafael Espindola  llvm::StringMap<std::string> TemporaryFiles;
260f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  RewriterTestContext Context;
261f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek};
262f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
263f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
264f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  FileID ID = createFile("input.cpp", "line1\nline2\nline3\nline4");
265f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replacements Replaces;
266f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
267f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                              5, "replaced"));
268f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
269f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_FALSE(Context.Rewrite.overwriteChangedFiles());
270f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_EQ("line1\nreplaced\nline3\nline4",
271f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek            getFileContentFromDisk("input.cpp"));
272f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
273f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
274f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace {
275f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimektemplate <typename T>
276f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass TestVisitor : public clang::RecursiveASTVisitor<T> {
277f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic:
278f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  bool runOver(StringRef Code) {
279f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    return runToolOnCode(new TestAction(this), Code);
280f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  }
281f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
282f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekprotected:
283f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  clang::SourceManager *SM;
284f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
285f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekprivate:
286f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  class FindConsumer : public clang::ASTConsumer {
287f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  public:
288f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {}
289f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
290f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    virtual void HandleTranslationUnit(clang::ASTContext &Context) {
291f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek      Visitor->TraverseDecl(Context.getTranslationUnitDecl());
292f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    }
293f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
294f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  private:
295f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    TestVisitor *Visitor;
296f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  };
297f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
298f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  class TestAction : public clang::ASTFrontendAction {
299f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  public:
300f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    TestAction(TestVisitor *Visitor) : Visitor(Visitor) {}
301f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
302f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    virtual clang::ASTConsumer* CreateASTConsumer(
303f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek        clang::CompilerInstance& compiler, llvm::StringRef dummy) {
304f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek      Visitor->SM = &compiler.getSourceManager();
305f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek      /// TestConsumer will be deleted by the framework calling us.
306f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek      return new FindConsumer(Visitor);
307f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    }
308f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
309f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  private:
310f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    TestVisitor *Visitor;
311f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  };
312f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek};
313f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace
314f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
315f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekvoid expectReplacementAt(const Replacement &Replace,
316f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek                         StringRef File, unsigned Offset, unsigned Length) {
317f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  ASSERT_TRUE(Replace.isApplicable());
318f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_EQ(File, Replace.getFilePath());
319f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_EQ(Offset, Replace.getOffset());
320f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_EQ(Length, Replace.getLength());
321f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
322f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
323f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass ClassDeclXVisitor : public TestVisitor<ClassDeclXVisitor> {
324f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic:
325f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  bool VisitCXXRecordDecl(CXXRecordDecl *Record) {
326f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    if (Record->getName() == "X") {
327f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek      Replace = Replacement(*SM, Record, "");
328f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    }
329f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    return true;
330f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  }
331f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replacement Replace;
332f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek};
333f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
334f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, CanBeConstructedFromNode) {
335f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  ClassDeclXVisitor ClassDeclX;
336f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_TRUE(ClassDeclX.runOver("     class X;"));
337f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  expectReplacementAt(ClassDeclX.Replace, "input.cc", 5, 7);
338f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
339f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
340f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, ReplacesAtSpellingLocation) {
341f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  ClassDeclXVisitor ClassDeclX;
342f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_TRUE(ClassDeclX.runOver("#define A(Y) Y\nA(class X);"));
343f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7);
344f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
345f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
346f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass CallToFVisitor : public TestVisitor<CallToFVisitor> {
347f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic:
348f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  bool VisitCallExpr(CallExpr *Call) {
349f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    if (Call->getDirectCallee()->getName() == "F") {
350f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek      Replace = Replacement(*SM, Call, "");
351f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    }
352f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    return true;
353f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  }
354f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Replacement Replace;
355f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek};
356f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
357f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, FunctionCall) {
358f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  CallToFVisitor CallToF;
359f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_TRUE(CallToF.runOver("void F(); void G() { F(); }"));
360f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  expectReplacementAt(CallToF.Replace, "input.cc", 21, 3);
361f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
362f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
363f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekTEST(Replacement, TemplatedFunctionCall) {
364f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  CallToFVisitor CallToF;
365f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  EXPECT_TRUE(CallToF.runOver(
366f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek        "template <typename T> void F(); void G() { F<int>(); }"));
367f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  expectReplacementAt(CallToF.Replace, "input.cc", 43, 8);
368f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
369f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
37046fa4c355bd45197dff580b63240494a53b16c1dManuel KlimekTEST(Range, overlaps) {
37146fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_TRUE(Range(10, 10).overlapsWith(Range(0, 11)));
37246fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_TRUE(Range(0, 11).overlapsWith(Range(10, 10)));
37346fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_FALSE(Range(10, 10).overlapsWith(Range(0, 10)));
37446fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_FALSE(Range(0, 10).overlapsWith(Range(10, 10)));
37546fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_TRUE(Range(0, 10).overlapsWith(Range(2, 6)));
376f758bc7125d59bca12bb6c5f1d3c9025f395710eEdwin Vane  EXPECT_TRUE(Range(2, 6).overlapsWith(Range(0, 10)));
37746fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek}
37846fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek
37946fa4c355bd45197dff580b63240494a53b16c1dManuel KlimekTEST(Range, contains) {
38046fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_TRUE(Range(0, 10).contains(Range(0, 10)));
38146fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_TRUE(Range(0, 10).contains(Range(2, 6)));
38246fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_FALSE(Range(2, 6).contains(Range(0, 10)));
38346fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek  EXPECT_FALSE(Range(0, 10).contains(Range(0, 11)));
38446fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek}
38546fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek
386d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin VaneTEST(DeduplicateTest, removesDuplicates) {
387d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  std::vector<Replacement> Input;
388d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileA", 50, 0, " foo "));
389d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileA", 10, 3, " bar "));
390d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileA", 10, 2, " bar ")); // Length differs
391d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileA", 9,  3, " bar ")); // Offset differs
392d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileA", 50, 0, " foo ")); // Duplicate
393d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileA", 51, 3, " bar "));
394d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileB", 51, 3, " bar ")); // Filename differs!
395d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Input.push_back(Replacement("fileA", 51, 3, " moo ")); // Replacement text
396d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane                                                         // differs!
397d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
398d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  std::vector<Replacement> Expected;
399d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Expected.push_back(Replacement("fileA", 9,  3, " bar "));
400d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Expected.push_back(Replacement("fileA", 10, 2, " bar "));
401d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Expected.push_back(Replacement("fileA", 10, 3, " bar "));
402d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Expected.push_back(Replacement("fileA", 50, 0, " foo "));
403d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Expected.push_back(Replacement("fileA", 51, 3, " bar "));
404d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Expected.push_back(Replacement("fileA", 51, 3, " moo "));
405d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  Expected.push_back(Replacement("fileB", 51, 3, " bar "));
406d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
407d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  std::vector<Range> Conflicts; // Ignored for this test
408d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  deduplicate(Input, Conflicts);
409d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
410d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  ASSERT_TRUE(Expected == Input);
411d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane}
412d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
413d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin VaneTEST(DeduplicateTest, detectsConflicts) {
414d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  {
415d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    std::vector<Replacement> Input;
416d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    Input.push_back(Replacement("fileA", 0, 5, " foo "));
417d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    Input.push_back(Replacement("fileA", 0, 5, " foo ")); // Duplicate not a
418d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane                                                          // conflict.
419d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    Input.push_back(Replacement("fileA", 2, 6, " bar "));
420d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    Input.push_back(Replacement("fileA", 7, 3, " moo "));
421d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
422d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    std::vector<Range> Conflicts;
423d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    deduplicate(Input, Conflicts);
424d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
425d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    // One duplicate is removed and the remaining three items form one
426d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    // conflicted range.
427d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    ASSERT_EQ(3u, Input.size());
428d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    ASSERT_EQ(1u, Conflicts.size());
429d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    ASSERT_EQ(0u, Conflicts.front().getOffset());
430d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    ASSERT_EQ(3u, Conflicts.front().getLength());
431d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  }
432d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  {
433d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    std::vector<Replacement> Input;
434d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
435d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    // Expected sorted order is shown. It is the sorted order to which the
436d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    // returned conflict info refers to.
437d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    Input.push_back(Replacement("fileA", 0,  5, " foo "));  // 0
438d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    Input.push_back(Replacement("fileA", 5,  5, " bar "));  // 1
43995f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    Input.push_back(Replacement("fileA", 6,  0, " bar "));  // 3
440d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    Input.push_back(Replacement("fileA", 5,  5, " moo "));  // 2
44195f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    Input.push_back(Replacement("fileA", 7,  2, " bar "));  // 4
44295f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    Input.push_back(Replacement("fileA", 15, 5, " golf ")); // 5
44395f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    Input.push_back(Replacement("fileA", 16, 5, " bag "));  // 6
44495f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    Input.push_back(Replacement("fileA", 10, 3, " club ")); // 7
44595f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane
44695f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    // #3 is special in that it is completely contained by another conflicting
44795f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    // Replacement. #4 ensures #3 hasn't messed up the conflicting range size.
448d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
449d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    std::vector<Range> Conflicts;
450d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    deduplicate(Input, Conflicts);
451d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
452d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    // No duplicates
45395f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    ASSERT_EQ(8u, Input.size());
454d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    ASSERT_EQ(2u, Conflicts.size());
455d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    ASSERT_EQ(1u, Conflicts[0].getOffset());
45695f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    ASSERT_EQ(4u, Conflicts[0].getLength());
45795f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane    ASSERT_EQ(6u, Conflicts[1].getOffset());
458d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane    ASSERT_EQ(2u, Conflicts[1].getLength());
459d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane  }
460d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane}
461d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane
462f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace tooling
463f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace clang
464