1 //===- unittest/Tooling/SourceCodeTest.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Tooling/Transformer/SourceCode.h" 10 #include "TestVisitor.h" 11 #include "clang/Basic/Diagnostic.h" 12 #include "llvm/Testing/Support/Annotations.h" 13 #include "llvm/Testing/Support/Error.h" 14 #include "llvm/Testing/Support/SupportHelpers.h" 15 #include <gmock/gmock.h> 16 #include <gtest/gtest.h> 17 18 using namespace clang; 19 20 using llvm::Failed; 21 using llvm::Succeeded; 22 using llvm::ValueIs; 23 using tooling::getExtendedText; 24 using tooling::getRangeForEdit; 25 using tooling::getText; 26 using tooling::validateEditRange; 27 28 namespace { 29 30 struct IntLitVisitor : TestVisitor<IntLitVisitor> { 31 bool VisitIntegerLiteral(IntegerLiteral *Expr) { 32 OnIntLit(Expr, Context); 33 return true; 34 } 35 36 std::function<void(IntegerLiteral *, ASTContext *Context)> OnIntLit; 37 }; 38 39 struct CallsVisitor : TestVisitor<CallsVisitor> { 40 bool VisitCallExpr(CallExpr *Expr) { 41 OnCall(Expr, Context); 42 return true; 43 } 44 45 std::function<void(CallExpr *, ASTContext *Context)> OnCall; 46 }; 47 48 // Equality matcher for `clang::CharSourceRange`, which lacks `operator==`. 49 MATCHER_P(EqualsRange, R, "") { 50 return arg.isTokenRange() == R.isTokenRange() && 51 arg.getBegin() == R.getBegin() && arg.getEnd() == R.getEnd(); 52 } 53 54 static ::testing::Matcher<CharSourceRange> AsRange(const SourceManager &SM, 55 llvm::Annotations::Range R) { 56 return EqualsRange(CharSourceRange::getCharRange( 57 SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.Begin), 58 SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.End))); 59 } 60 61 TEST(SourceCodeTest, getText) { 62 CallsVisitor Visitor; 63 64 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 65 EXPECT_EQ("foo(x, y)", getText(*CE, *Context)); 66 }; 67 Visitor.runOver("void foo(int x, int y) { foo(x, y); }"); 68 69 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 70 EXPECT_EQ("APPLY(foo, x, y)", getText(*CE, *Context)); 71 }; 72 Visitor.runOver("#define APPLY(f, x, y) f(x, y)\n" 73 "void foo(int x, int y) { APPLY(foo, x, y); }"); 74 } 75 76 TEST(SourceCodeTest, getTextWithMacro) { 77 CallsVisitor Visitor; 78 79 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 80 EXPECT_EQ("F OO", getText(*CE, *Context)); 81 Expr *P0 = CE->getArg(0); 82 Expr *P1 = CE->getArg(1); 83 EXPECT_EQ("", getText(*P0, *Context)); 84 EXPECT_EQ("", getText(*P1, *Context)); 85 }; 86 Visitor.runOver("#define F foo(\n" 87 "#define OO x, y)\n" 88 "void foo(int x, int y) { F OO ; }"); 89 90 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 91 EXPECT_EQ("", getText(*CE, *Context)); 92 Expr *P0 = CE->getArg(0); 93 Expr *P1 = CE->getArg(1); 94 EXPECT_EQ("x", getText(*P0, *Context)); 95 EXPECT_EQ("y", getText(*P1, *Context)); 96 }; 97 Visitor.runOver("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n" 98 "void foo(int x, int y) { FOO(x,y) }"); 99 } 100 101 TEST(SourceCodeTest, getExtendedText) { 102 CallsVisitor Visitor; 103 104 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 105 EXPECT_EQ("foo(x, y);", 106 getExtendedText(*CE, tok::TokenKind::semi, *Context)); 107 108 Expr *P0 = CE->getArg(0); 109 Expr *P1 = CE->getArg(1); 110 EXPECT_EQ("x", getExtendedText(*P0, tok::TokenKind::semi, *Context)); 111 EXPECT_EQ("x,", getExtendedText(*P0, tok::TokenKind::comma, *Context)); 112 EXPECT_EQ("y", getExtendedText(*P1, tok::TokenKind::semi, *Context)); 113 }; 114 Visitor.runOver("void foo(int x, int y) { foo(x, y); }"); 115 Visitor.runOver("void foo(int x, int y) { if (true) foo(x, y); }"); 116 Visitor.runOver("int foo(int x, int y) { if (true) return 3 + foo(x, y); }"); 117 Visitor.runOver("void foo(int x, int y) { for (foo(x, y);;) ++x; }"); 118 Visitor.runOver( 119 "bool foo(int x, int y) { for (;foo(x, y);) x = 1; return true; }"); 120 121 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 122 EXPECT_EQ("foo()", getExtendedText(*CE, tok::TokenKind::semi, *Context)); 123 }; 124 Visitor.runOver("bool foo() { if (foo()) return true; return false; }"); 125 Visitor.runOver("void foo() { int x; for (;; foo()) ++x; }"); 126 Visitor.runOver("int foo() { return foo() + 3; }"); 127 } 128 129 TEST(SourceCodeTest, EditRangeWithMacroExpansionsShouldSucceed) { 130 // The call expression, whose range we are extracting, includes two macro 131 // expansions. 132 llvm::Annotations Code(R"cpp( 133 #define M(a) a * 13 134 int foo(int x, int y); 135 int a = $r[[foo(M(1), M(2))]]; 136 )cpp"); 137 138 CallsVisitor Visitor; 139 140 Visitor.OnCall = [&Code](CallExpr *CE, ASTContext *Context) { 141 auto Range = CharSourceRange::getTokenRange(CE->getSourceRange()); 142 EXPECT_THAT(getRangeForEdit(Range, *Context), 143 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 144 }; 145 Visitor.runOver(Code.code()); 146 } 147 148 TEST(SourceCodeTest, EditWholeMacroExpansionShouldSucceed) { 149 llvm::Annotations Code(R"cpp( 150 #define FOO 10 151 int a = $r[[FOO]]; 152 )cpp"); 153 154 IntLitVisitor Visitor; 155 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 156 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 157 EXPECT_THAT(getRangeForEdit(Range, *Context), 158 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 159 }; 160 Visitor.runOver(Code.code()); 161 } 162 163 TEST(SourceCodeTest, EditPartialMacroExpansionShouldFail) { 164 std::string Code = R"cpp( 165 #define BAR 10+ 166 int c = BAR 3.0; 167 )cpp"; 168 169 IntLitVisitor Visitor; 170 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 171 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 172 EXPECT_FALSE(getRangeForEdit(Range, *Context).hasValue()); 173 }; 174 Visitor.runOver(Code); 175 } 176 177 TEST(SourceCodeTest, EditWholeMacroArgShouldSucceed) { 178 llvm::Annotations Code(R"cpp( 179 #define FOO(a) a + 7.0; 180 int a = FOO($r[[10]]); 181 )cpp"); 182 183 IntLitVisitor Visitor; 184 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 185 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 186 EXPECT_THAT(getRangeForEdit(Range, *Context), 187 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 188 }; 189 Visitor.runOver(Code.code()); 190 } 191 192 TEST(SourceCodeTest, EditPartialMacroArgShouldSucceed) { 193 llvm::Annotations Code(R"cpp( 194 #define FOO(a) a + 7.0; 195 int a = FOO($r[[10]] + 10.0); 196 )cpp"); 197 198 IntLitVisitor Visitor; 199 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 200 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 201 EXPECT_THAT(getRangeForEdit(Range, *Context), 202 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 203 }; 204 Visitor.runOver(Code.code()); 205 } 206 207 TEST(SourceCodeTest, EditRangeWithMacroExpansionsIsValid) { 208 // The call expression, whose range we are extracting, includes two macro 209 // expansions. 210 llvm::StringRef Code = R"cpp( 211 #define M(a) a * 13 212 int foo(int x, int y); 213 int a = foo(M(1), M(2)); 214 )cpp"; 215 216 CallsVisitor Visitor; 217 218 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 219 auto Range = CharSourceRange::getTokenRange(CE->getSourceRange()); 220 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 221 Succeeded()); 222 }; 223 Visitor.runOver(Code); 224 } 225 226 TEST(SourceCodeTest, SpellingRangeOfMacroArgIsValid) { 227 llvm::StringRef Code = R"cpp( 228 #define FOO(a) a + 7.0; 229 int a = FOO(10); 230 )cpp"; 231 232 IntLitVisitor Visitor; 233 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 234 SourceLocation ArgLoc = 235 Context->getSourceManager().getSpellingLoc(Expr->getBeginLoc()); 236 // The integer literal is a single token. 237 auto ArgRange = CharSourceRange::getTokenRange(ArgLoc); 238 EXPECT_THAT_ERROR(validateEditRange(ArgRange, Context->getSourceManager()), 239 Succeeded()); 240 }; 241 Visitor.runOver(Code); 242 } 243 244 TEST(SourceCodeTest, InvalidEditRangeIsInvalid) { 245 llvm::StringRef Code = "int c = 10;"; 246 247 // We use the visitor just to get a valid context. 248 IntLitVisitor Visitor; 249 Visitor.OnIntLit = [](IntegerLiteral *, ASTContext *Context) { 250 CharSourceRange Invalid; 251 EXPECT_THAT_ERROR(validateEditRange(Invalid, Context->getSourceManager()), 252 Failed()); 253 }; 254 Visitor.runOver(Code); 255 } 256 257 TEST(SourceCodeTest, InvertedEditRangeIsInvalid) { 258 llvm::StringRef Code = R"cpp( 259 int foo(int x); 260 int a = foo(2); 261 )cpp"; 262 263 CallsVisitor Visitor; 264 Visitor.OnCall = [](CallExpr *Expr, ASTContext *Context) { 265 auto InvertedRange = CharSourceRange::getTokenRange( 266 SourceRange(Expr->getEndLoc(), Expr->getBeginLoc())); 267 EXPECT_THAT_ERROR( 268 validateEditRange(InvertedRange, Context->getSourceManager()), 269 Failed()); 270 }; 271 Visitor.runOver(Code); 272 } 273 274 TEST(SourceCodeTest, MacroArgIsInvalid) { 275 llvm::StringRef Code = R"cpp( 276 #define FOO(a) a + 7.0; 277 int a = FOO(10); 278 )cpp"; 279 280 IntLitVisitor Visitor; 281 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 282 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 283 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 284 Failed()); 285 }; 286 Visitor.runOver(Code); 287 } 288 289 TEST(SourceCodeTest, EditWholeMacroExpansionIsInvalid) { 290 llvm::StringRef Code = R"cpp( 291 #define FOO 10 292 int a = FOO; 293 )cpp"; 294 295 IntLitVisitor Visitor; 296 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 297 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 298 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 299 Failed()); 300 301 }; 302 Visitor.runOver(Code); 303 } 304 305 TEST(SourceCodeTest, EditPartialMacroExpansionIsInvalid) { 306 llvm::StringRef Code = R"cpp( 307 #define BAR 10+ 308 int c = BAR 3.0; 309 )cpp"; 310 311 IntLitVisitor Visitor; 312 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 313 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 314 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 315 Failed()); 316 }; 317 Visitor.runOver(Code); 318 } 319 } // end anonymous namespace 320