brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.6 KiB · f556c24 Raw
189 lines · cpp
1//===- unittest/Tooling/FixitTest.cpp ------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Tooling/FixIt.h"10#include "clang/ASTMatchers/ASTMatchFinder.h"11#include "clang/ASTMatchers/ASTMatchers.h"12#include "clang/Testing/TestAST.h"13#include "gtest/gtest.h"14 15using namespace clang;16 17using tooling::fixit::getText;18using tooling::fixit::createRemoval;19using tooling::fixit::createReplacement;20 21namespace {22 23const CallExpr &onlyCall(ASTContext &Ctx) {24  using namespace ast_matchers;25  auto Calls = match(callExpr().bind(""), Ctx);26  EXPECT_EQ(Calls.size(), 1u);27  return *Calls.front().getNodeAs<CallExpr>("");28}29 30TEST(FixItTest, getText) {31  TestAST AST("void foo(int x, int y) { foo(x, y); }");32  const CallExpr &CE = onlyCall(AST.context());33  EXPECT_EQ("foo(x, y)", getText(CE, AST.context()));34  EXPECT_EQ("foo(x, y)", getText(CE.getSourceRange(), AST.context()));35  EXPECT_EQ("x", getText(*CE.getArg(0), AST.context()));36  EXPECT_EQ("y", getText(*CE.getArg(1), AST.context()));37 38  AST = TestAST("#define APPLY(f, x, y) f(x, y)\n"39                "void foo(int x, int y) { APPLY(foo, x, y); }");40  const CallExpr &CE2 = onlyCall(AST.context());41  EXPECT_EQ("APPLY(foo, x, y)", getText(CE2, AST.context()));42}43 44TEST(FixItTest, getTextWithMacro) {45  TestAST AST("#define F foo(\n"46              "#define OO x, y)\n"47              "void foo(int x, int y) { F OO ; }");48  const CallExpr &CE = onlyCall(AST.context());49  EXPECT_EQ("F OO", getText(CE, AST.context()));50  EXPECT_EQ("", getText(*CE.getArg(0), AST.context()));51  EXPECT_EQ("", getText(*CE.getArg(1), AST.context()));52 53  AST = TestAST("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n"54                "void foo(int x, int y) { FOO(x,y) }");55  const CallExpr &CE2 = onlyCall(AST.context());56  EXPECT_EQ("", getText(CE2, AST.context()));57  EXPECT_EQ("x", getText(*CE2.getArg(0), AST.context()));58  EXPECT_EQ("y", getText(*CE2.getArg(1), AST.context()));59}60 61TEST(FixItTest, createRemoval) {62  TestAST AST("void foo(int x, int y) { foo(x, y); }");63  const CallExpr &CE = onlyCall(AST.context());64 65  FixItHint Hint = createRemoval(CE);66  EXPECT_EQ("foo(x, y)", getText(Hint.RemoveRange.getAsRange(), AST.context()));67  EXPECT_TRUE(Hint.InsertFromRange.isInvalid());68  EXPECT_TRUE(Hint.CodeToInsert.empty());69 70  FixItHint Hint0 = createRemoval(*CE.getArg(0));71  EXPECT_EQ("x", getText(Hint0.RemoveRange.getAsRange(), AST.context()));72  EXPECT_TRUE(Hint0.InsertFromRange.isInvalid());73  EXPECT_TRUE(Hint0.CodeToInsert.empty());74 75  FixItHint Hint1 = createRemoval(*CE.getArg(1));76  EXPECT_EQ("y", getText(Hint1.RemoveRange.getAsRange(), AST.context()));77  EXPECT_TRUE(Hint1.InsertFromRange.isInvalid());78  EXPECT_TRUE(Hint1.CodeToInsert.empty());79 80  AST = TestAST("void foo(int x, int y) { foo(x + y, y + x); }");81  const CallExpr &CE2 = onlyCall(AST.context());82  Hint0 = createRemoval(*CE2.getArg(0));83  EXPECT_EQ("x + y", getText(Hint0.RemoveRange.getAsRange(), AST.context()));84 85  Hint1 = createRemoval(*CE2.getArg(1));86  EXPECT_EQ("y + x", getText(Hint1.RemoveRange.getAsRange(), AST.context()));87}88 89TEST(FixItTest, createRemovalWithMacro) {90  TestAST AST("#define FOO foo(1, 1)\n"91              "void foo(int x, int y) { FOO; }");92  const CallExpr &CE = onlyCall(AST.context());93  FixItHint Hint = createRemoval(CE);94  EXPECT_EQ("FOO", getText(Hint.RemoveRange.getAsRange(), AST.context()));95  EXPECT_TRUE(Hint.InsertFromRange.isInvalid());96  EXPECT_TRUE(Hint.CodeToInsert.empty());97 98  FixItHint Hint0 = createRemoval(*CE.getArg(0));99  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:17>",100            Hint0.RemoveRange.getBegin().printToString(AST.sourceManager()));101  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:17>",102            Hint0.RemoveRange.getEnd().printToString(AST.sourceManager()));103  EXPECT_TRUE(Hint0.InsertFromRange.isInvalid());104  EXPECT_TRUE(Hint0.CodeToInsert.empty());105 106  FixItHint Hint1 = createRemoval(*CE.getArg(1));107  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:20>",108            Hint1.RemoveRange.getBegin().printToString(AST.sourceManager()));109  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:20>",110            Hint1.RemoveRange.getEnd().printToString(AST.sourceManager()));111  EXPECT_TRUE(Hint1.InsertFromRange.isInvalid());112  EXPECT_TRUE(Hint1.CodeToInsert.empty());113 114  AST = TestAST("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n"115                "void foo(int x, int y) { FOO(x,y) }");116  const CallExpr &CE2 = onlyCall(AST.context());117  Hint = createRemoval(CE2);118  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:37>",119            Hint.RemoveRange.getBegin().printToString(AST.sourceManager()));120  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:45>",121            Hint.RemoveRange.getEnd().printToString(AST.sourceManager()));122  EXPECT_TRUE(Hint.InsertFromRange.isInvalid());123  EXPECT_TRUE(Hint.CodeToInsert.empty());124}125 126TEST(FixItTest, createReplacement) {127  for (const char *Code : {128           "void foo(int x, int y) { foo(x, y); }",129 130           "#define APPLY(f, x, y) f(x, y)\n"131           "void foo(int x, int y) { APPLY(foo, x, y); }",132 133           "#define APPLY(f, P) f(P)\n"134           "#define PAIR(x, y) x, y\n"135           "void foo(int x, int y) { APPLY(foo, PAIR(x, y)); }\n",136       }) {137    TestAST AST(Code);138    const CallExpr &CE = onlyCall(AST.context());139    const Expr *P0 = CE.getArg(0);140    const Expr *P1 = CE.getArg(1);141    FixItHint Hint0 = createReplacement(*P0, *P1, AST.context());142    FixItHint Hint1 = createReplacement(*P1, *P0, AST.context());143 144    // Validate Hint0 fields.145    EXPECT_EQ("x", getText(Hint0.RemoveRange.getAsRange(), AST.context()));146    EXPECT_TRUE(Hint0.InsertFromRange.isInvalid());147    EXPECT_EQ(Hint0.CodeToInsert, "y");148 149    // Validate Hint1 fields.150    EXPECT_EQ("y", getText(Hint1.RemoveRange.getAsRange(), AST.context()));151    EXPECT_TRUE(Hint1.InsertFromRange.isInvalid());152    EXPECT_EQ(Hint1.CodeToInsert, "x");153  }154}155 156TEST(FixItTest, createReplacementWithMacro) {157  TestAST AST("#define FOO foo(1, 1)\n"158              "void foo(int x, int y) { FOO; }");159  const CallExpr &CE = onlyCall(AST.context());160  FixItHint Hint =161      createReplacement(*CE.getArg(0), *CE.getArg(1), AST.context());162  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:17>",163            Hint.RemoveRange.getBegin().printToString(AST.sourceManager()));164  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:1:17>",165            Hint.RemoveRange.getEnd().printToString(AST.sourceManager()));166  EXPECT_TRUE(Hint.InsertFromRange.isInvalid());167  EXPECT_TRUE(Hint.CodeToInsert.empty());168 169  AST = TestAST("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n"170                "void foo(int x, int y) { FOO(x,y) }");171  const CallExpr &CE2 = onlyCall(AST.context());172  Hint = createReplacement(*CE2.getArg(0), *CE2.getArg(1), AST.context());173  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:2:30>",174            Hint.RemoveRange.getEnd().printToString(AST.sourceManager()));175  EXPECT_EQ("input.mm:2:26 <Spelling=input.mm:2:30>",176            Hint.RemoveRange.getBegin().printToString(AST.sourceManager()));177  EXPECT_TRUE(Hint.InsertFromRange.isInvalid());178  EXPECT_EQ("y", Hint.CodeToInsert);179 180  AST = TestAST("void foo(int x, int y) { foo(x + y, y + x); }");181  const CallExpr &CE3 = onlyCall(AST.context());182  Hint = createReplacement(*CE3.getArg(0), *CE3.getArg(1), AST.context());183  EXPECT_EQ("x + y", getText(Hint.RemoveRange.getAsRange(), AST.context()));184  EXPECT_TRUE(Hint.InsertFromRange.isInvalid());185  EXPECT_EQ("y + x", Hint.CodeToInsert);186}187 188} // end anonymous namespace189