1 //===- unittests/Rewrite/RewriterTest.cpp - Rewriter tests ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Rewrite/Core/Rewriter.h"
10 #include "clang/Tooling/Tooling.h"
11 #include "gtest/gtest.h"
12 
13 using namespace clang;
14 
15 namespace {
16 
17 struct RangeTypeTest {
18   std::unique_ptr<ASTUnit> AST;
19   Rewriter Rewrite;
20   SourceLocation FileStart;
21   CharSourceRange CRange; // covers exact char range
22   CharSourceRange TRange; // extends CRange to whole tokens
23   SourceRange SRange;     // different type but behaves like TRange
makeLoc__anon424d0f6b0111::RangeTypeTest24   SourceLocation makeLoc(int Off) { return FileStart.getLocWithOffset(Off); }
makeCharRange__anon424d0f6b0111::RangeTypeTest25   CharSourceRange makeCharRange(int StartOff, int EndOff) {
26     return CharSourceRange::getCharRange(makeLoc(StartOff), makeLoc(EndOff));
27   }
RangeTypeTest__anon424d0f6b0111::RangeTypeTest28   RangeTypeTest(StringRef Code, int StartOff, int EndOff) {
29     AST = tooling::buildASTFromCode(Code);
30     ASTContext &C = AST->getASTContext();
31     Rewrite = Rewriter(C.getSourceManager(), C.getLangOpts());
32     FileStart = AST->getStartOfMainFileID();
33     CRange = makeCharRange(StartOff, EndOff);
34     SRange = CRange.getAsRange();
35     TRange = CharSourceRange::getTokenRange(SRange);
36   }
37 };
38 
TEST(Rewriter,GetRewrittenTextRangeTypes)39 TEST(Rewriter, GetRewrittenTextRangeTypes) {
40   // Check that correct text is retrieved for each range type.  Check again
41   // after a modification.  Ranges remain in terms of the original text but
42   // include the new text.
43   StringRef Code = "int main() { return 0; }";
44   //              get char range ^~~    = "ret"
45   //             get token range ^~~+++ = "return"
46   //            get source range ^~~+++ = "return"
47   //                  insert "x" ^
48   //              get char range ^~~    = "xret"
49   //             get token range ^~~+++ = "xreturn"
50   //            get source range ^~~+++ = "xreturn"
51   RangeTypeTest T(Code, 13, 16);
52   EXPECT_EQ(T.Rewrite.getRewrittenText(T.CRange), "ret");
53   EXPECT_EQ(T.Rewrite.getRewrittenText(T.TRange), "return");
54   EXPECT_EQ(T.Rewrite.getRewrittenText(T.SRange), "return");
55   T.Rewrite.InsertText(T.makeLoc(13), "x");
56   EXPECT_EQ(T.Rewrite.getRewrittenText(T.CRange), "xret");
57   EXPECT_EQ(T.Rewrite.getRewrittenText(T.TRange), "xreturn");
58   EXPECT_EQ(T.Rewrite.getRewrittenText(T.SRange), "xreturn");
59 }
60 
TEST(Rewriter,ReplaceTextRangeTypes)61 TEST(Rewriter, ReplaceTextRangeTypes) {
62   // Check that correct text is replaced for each range type.  Ranges remain in
63   // terms of the original text but include the new text.
64   StringRef Code = "int main(int argc, char *argv[]) { return argc; }";
65   //                            replace char range with "foo" ^~
66   //                                                      get ^~~~~ = "foogc;"
67   //                           replace token range with "bar" ^~++
68   //                                                      get ^~~~~ = "bar;"
69   //                            replace source range with "0" ^~++
70   //                                                      get ^~~~~ = "0;"
71   RangeTypeTest T(Code, 42, 44);
72   T.Rewrite.ReplaceText(T.CRange, "foo");
73   EXPECT_EQ(T.Rewrite.getRewrittenText(T.makeCharRange(42, 47)), "foogc;");
74   T.Rewrite.ReplaceText(T.TRange, "bar");
75   EXPECT_EQ(T.Rewrite.getRewrittenText(T.makeCharRange(42, 47)), "bar;");
76   T.Rewrite.ReplaceText(T.SRange, "0");
77   EXPECT_EQ(T.Rewrite.getRewrittenText(T.makeCharRange(42, 47)), "0;");
78 }
79 
80 } // anonymous namespace
81