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