184f2271aSYitzhak Mandelbaum //===- unittest/Tooling/SourceCodeTest.cpp --------------------------------===// 284f2271aSYitzhak Mandelbaum // 384f2271aSYitzhak Mandelbaum // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 484f2271aSYitzhak Mandelbaum // See https://llvm.org/LICENSE.txt for license information. 584f2271aSYitzhak Mandelbaum // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 684f2271aSYitzhak Mandelbaum // 784f2271aSYitzhak Mandelbaum //===----------------------------------------------------------------------===// 884f2271aSYitzhak Mandelbaum 9fbdf8352SYitzhak Mandelbaum #include "clang/Tooling/Transformer/SourceCode.h" 1084f2271aSYitzhak Mandelbaum #include "TestVisitor.h" 11345c4822SEric Li #include "clang/ASTMatchers/ASTMatchFinder.h" 1284f2271aSYitzhak Mandelbaum #include "clang/Basic/Diagnostic.h" 13ecfa0b24SGabriel Matute #include "clang/Basic/SourceLocation.h" 14ecfa0b24SGabriel Matute #include "clang/Lex/Lexer.h" 153432f4bfSJordan Rupprecht #include "llvm/Testing/Annotations/Annotations.h" 16b9d2bf38SYitzhak Mandelbaum #include "llvm/Testing/Support/Error.h" 172e97a1e1SYitzhak Mandelbaum #include "llvm/Testing/Support/SupportHelpers.h" 182e97a1e1SYitzhak Mandelbaum #include <gmock/gmock.h> 192e97a1e1SYitzhak Mandelbaum #include <gtest/gtest.h> 2084f2271aSYitzhak Mandelbaum 2184f2271aSYitzhak Mandelbaum using namespace clang; 22345c4822SEric Li using namespace clang::ast_matchers; 2384f2271aSYitzhak Mandelbaum 24b9d2bf38SYitzhak Mandelbaum using llvm::Failed; 25b9d2bf38SYitzhak Mandelbaum using llvm::Succeeded; 262e97a1e1SYitzhak Mandelbaum using llvm::ValueIs; 27345c4822SEric Li using testing::Optional; 2838b4516dSYitzhak Mandelbaum using tooling::getAssociatedRange; 29ecfa0b24SGabriel Matute using tooling::getExtendedRange; 3084f2271aSYitzhak Mandelbaum using tooling::getExtendedText; 312307029bSEric Li using tooling::getFileRangeForEdit; 322e97a1e1SYitzhak Mandelbaum using tooling::getText; 33ecfa0b24SGabriel Matute using tooling::maybeExtendRange; 34b9d2bf38SYitzhak Mandelbaum using tooling::validateEditRange; 3584f2271aSYitzhak Mandelbaum 3684f2271aSYitzhak Mandelbaum namespace { 3784f2271aSYitzhak Mandelbaum 38*4e600751SSirraide struct IntLitVisitor : TestVisitor { 39*4e600751SSirraide bool VisitIntegerLiteral(IntegerLiteral *Expr) override { 402e97a1e1SYitzhak Mandelbaum OnIntLit(Expr, Context); 412e97a1e1SYitzhak Mandelbaum return true; 422e97a1e1SYitzhak Mandelbaum } 432e97a1e1SYitzhak Mandelbaum 442e97a1e1SYitzhak Mandelbaum std::function<void(IntegerLiteral *, ASTContext *Context)> OnIntLit; 452e97a1e1SYitzhak Mandelbaum }; 462e97a1e1SYitzhak Mandelbaum 47*4e600751SSirraide struct CallsVisitor : TestVisitor { 48*4e600751SSirraide bool VisitCallExpr(CallExpr *Expr) override { 4984f2271aSYitzhak Mandelbaum OnCall(Expr, Context); 5084f2271aSYitzhak Mandelbaum return true; 5184f2271aSYitzhak Mandelbaum } 5284f2271aSYitzhak Mandelbaum 5384f2271aSYitzhak Mandelbaum std::function<void(CallExpr *, ASTContext *Context)> OnCall; 5484f2271aSYitzhak Mandelbaum }; 5584f2271aSYitzhak Mandelbaum 56*4e600751SSirraide struct TypeLocVisitor : TestVisitor { 57*4e600751SSirraide bool VisitTypeLoc(TypeLoc TL) override { 58345c4822SEric Li OnTypeLoc(TL, Context); 59345c4822SEric Li return true; 60345c4822SEric Li } 61345c4822SEric Li 62345c4822SEric Li std::function<void(TypeLoc, ASTContext *Context)> OnTypeLoc; 63345c4822SEric Li }; 64345c4822SEric Li 652e97a1e1SYitzhak Mandelbaum // Equality matcher for `clang::CharSourceRange`, which lacks `operator==`. 662e97a1e1SYitzhak Mandelbaum MATCHER_P(EqualsRange, R, "") { 672e97a1e1SYitzhak Mandelbaum return arg.isTokenRange() == R.isTokenRange() && 682e97a1e1SYitzhak Mandelbaum arg.getBegin() == R.getBegin() && arg.getEnd() == R.getEnd(); 692e97a1e1SYitzhak Mandelbaum } 702e97a1e1SYitzhak Mandelbaum 71ecfa0b24SGabriel Matute MATCHER_P2(EqualsAnnotatedRange, Context, R, "") { 7238b4516dSYitzhak Mandelbaum if (arg.getBegin().isMacroID()) { 7338b4516dSYitzhak Mandelbaum *result_listener << "which starts in a macro"; 7438b4516dSYitzhak Mandelbaum return false; 7538b4516dSYitzhak Mandelbaum } 7638b4516dSYitzhak Mandelbaum if (arg.getEnd().isMacroID()) { 7738b4516dSYitzhak Mandelbaum *result_listener << "which ends in a macro"; 7838b4516dSYitzhak Mandelbaum return false; 7938b4516dSYitzhak Mandelbaum } 8038b4516dSYitzhak Mandelbaum 81ecfa0b24SGabriel Matute CharSourceRange Range = Lexer::getAsCharRange( 82ecfa0b24SGabriel Matute arg, Context->getSourceManager(), Context->getLangOpts()); 83ecfa0b24SGabriel Matute unsigned Begin = Context->getSourceManager().getFileOffset(Range.getBegin()); 84ecfa0b24SGabriel Matute unsigned End = Context->getSourceManager().getFileOffset(Range.getEnd()); 8538b4516dSYitzhak Mandelbaum 86ecfa0b24SGabriel Matute *result_listener << "which is a " << (arg.isTokenRange() ? "Token" : "Char") 87ecfa0b24SGabriel Matute << " range [" << Begin << "," << End << ")"; 8838b4516dSYitzhak Mandelbaum return Begin == R.Begin && End == R.End; 8938b4516dSYitzhak Mandelbaum } 9038b4516dSYitzhak Mandelbaum 912e97a1e1SYitzhak Mandelbaum static ::testing::Matcher<CharSourceRange> AsRange(const SourceManager &SM, 922e97a1e1SYitzhak Mandelbaum llvm::Annotations::Range R) { 932e97a1e1SYitzhak Mandelbaum return EqualsRange(CharSourceRange::getCharRange( 942e97a1e1SYitzhak Mandelbaum SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.Begin), 952e97a1e1SYitzhak Mandelbaum SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.End))); 962e97a1e1SYitzhak Mandelbaum } 972e97a1e1SYitzhak Mandelbaum 9838b4516dSYitzhak Mandelbaum // Base class for visitors that expect a single match corresponding to a 9938b4516dSYitzhak Mandelbaum // specific annotated range. 100*4e600751SSirraide class AnnotatedCodeVisitor : public TestVisitor { 101ecfa0b24SGabriel Matute protected: 10238b4516dSYitzhak Mandelbaum int MatchCount = 0; 103ecfa0b24SGabriel Matute llvm::Annotations Code; 10438b4516dSYitzhak Mandelbaum 10538b4516dSYitzhak Mandelbaum public: 10638b4516dSYitzhak Mandelbaum AnnotatedCodeVisitor() : Code("$r[[]]") {} 107ecfa0b24SGabriel Matute // Helper for tests of `getAssociatedRange`. 10838b4516dSYitzhak Mandelbaum bool VisitDeclHelper(Decl *Decl) { 10938b4516dSYitzhak Mandelbaum // Only consider explicit declarations. 11038b4516dSYitzhak Mandelbaum if (Decl->isImplicit()) 11138b4516dSYitzhak Mandelbaum return true; 11238b4516dSYitzhak Mandelbaum 11338b4516dSYitzhak Mandelbaum ++MatchCount; 11438b4516dSYitzhak Mandelbaum EXPECT_THAT(getAssociatedRange(*Decl, *this->Context), 115ecfa0b24SGabriel Matute EqualsAnnotatedRange(this->Context, Code.range("r"))) 11638b4516dSYitzhak Mandelbaum << Code.code(); 11738b4516dSYitzhak Mandelbaum return true; 11838b4516dSYitzhak Mandelbaum } 11938b4516dSYitzhak Mandelbaum 12038b4516dSYitzhak Mandelbaum bool runOverAnnotated(llvm::StringRef AnnotatedCode, 12138b4516dSYitzhak Mandelbaum std::vector<std::string> Args = {}) { 12238b4516dSYitzhak Mandelbaum Code = llvm::Annotations(AnnotatedCode); 12338b4516dSYitzhak Mandelbaum MatchCount = 0; 12438b4516dSYitzhak Mandelbaum Args.push_back("-std=c++11"); 12538b4516dSYitzhak Mandelbaum Args.push_back("-fno-delayed-template-parsing"); 12638b4516dSYitzhak Mandelbaum bool result = tooling::runToolOnCodeWithArgs(this->CreateTestAction(), 12738b4516dSYitzhak Mandelbaum Code.code(), Args); 12838b4516dSYitzhak Mandelbaum EXPECT_EQ(MatchCount, 1) << AnnotatedCode; 12938b4516dSYitzhak Mandelbaum return result; 13038b4516dSYitzhak Mandelbaum } 13138b4516dSYitzhak Mandelbaum }; 13238b4516dSYitzhak Mandelbaum 13384f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getText) { 13484f2271aSYitzhak Mandelbaum CallsVisitor Visitor; 13584f2271aSYitzhak Mandelbaum 13684f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 13784f2271aSYitzhak Mandelbaum EXPECT_EQ("foo(x, y)", getText(*CE, *Context)); 13884f2271aSYitzhak Mandelbaum }; 13984f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { foo(x, y); }"); 14084f2271aSYitzhak Mandelbaum 14184f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 14284f2271aSYitzhak Mandelbaum EXPECT_EQ("APPLY(foo, x, y)", getText(*CE, *Context)); 14384f2271aSYitzhak Mandelbaum }; 14484f2271aSYitzhak Mandelbaum Visitor.runOver("#define APPLY(f, x, y) f(x, y)\n" 14584f2271aSYitzhak Mandelbaum "void foo(int x, int y) { APPLY(foo, x, y); }"); 14684f2271aSYitzhak Mandelbaum } 14784f2271aSYitzhak Mandelbaum 14884f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getTextWithMacro) { 14984f2271aSYitzhak Mandelbaum CallsVisitor Visitor; 15084f2271aSYitzhak Mandelbaum 15184f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 15284f2271aSYitzhak Mandelbaum EXPECT_EQ("F OO", getText(*CE, *Context)); 15384f2271aSYitzhak Mandelbaum Expr *P0 = CE->getArg(0); 15484f2271aSYitzhak Mandelbaum Expr *P1 = CE->getArg(1); 15584f2271aSYitzhak Mandelbaum EXPECT_EQ("", getText(*P0, *Context)); 15684f2271aSYitzhak Mandelbaum EXPECT_EQ("", getText(*P1, *Context)); 15784f2271aSYitzhak Mandelbaum }; 15884f2271aSYitzhak Mandelbaum Visitor.runOver("#define F foo(\n" 15984f2271aSYitzhak Mandelbaum "#define OO x, y)\n" 16084f2271aSYitzhak Mandelbaum "void foo(int x, int y) { F OO ; }"); 16184f2271aSYitzhak Mandelbaum 16284f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 16384f2271aSYitzhak Mandelbaum EXPECT_EQ("", getText(*CE, *Context)); 16484f2271aSYitzhak Mandelbaum Expr *P0 = CE->getArg(0); 16584f2271aSYitzhak Mandelbaum Expr *P1 = CE->getArg(1); 16684f2271aSYitzhak Mandelbaum EXPECT_EQ("x", getText(*P0, *Context)); 16784f2271aSYitzhak Mandelbaum EXPECT_EQ("y", getText(*P1, *Context)); 16884f2271aSYitzhak Mandelbaum }; 16984f2271aSYitzhak Mandelbaum Visitor.runOver("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n" 17084f2271aSYitzhak Mandelbaum "void foo(int x, int y) { FOO(x,y) }"); 17184f2271aSYitzhak Mandelbaum } 17284f2271aSYitzhak Mandelbaum 17384f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getExtendedText) { 17484f2271aSYitzhak Mandelbaum CallsVisitor Visitor; 17584f2271aSYitzhak Mandelbaum 17684f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 17784f2271aSYitzhak Mandelbaum EXPECT_EQ("foo(x, y);", 17884f2271aSYitzhak Mandelbaum getExtendedText(*CE, tok::TokenKind::semi, *Context)); 17984f2271aSYitzhak Mandelbaum 18084f2271aSYitzhak Mandelbaum Expr *P0 = CE->getArg(0); 18184f2271aSYitzhak Mandelbaum Expr *P1 = CE->getArg(1); 18284f2271aSYitzhak Mandelbaum EXPECT_EQ("x", getExtendedText(*P0, tok::TokenKind::semi, *Context)); 18384f2271aSYitzhak Mandelbaum EXPECT_EQ("x,", getExtendedText(*P0, tok::TokenKind::comma, *Context)); 18484f2271aSYitzhak Mandelbaum EXPECT_EQ("y", getExtendedText(*P1, tok::TokenKind::semi, *Context)); 18584f2271aSYitzhak Mandelbaum }; 18684f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { foo(x, y); }"); 18784f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { if (true) foo(x, y); }"); 18884f2271aSYitzhak Mandelbaum Visitor.runOver("int foo(int x, int y) { if (true) return 3 + foo(x, y); }"); 18984f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { for (foo(x, y);;) ++x; }"); 19084f2271aSYitzhak Mandelbaum Visitor.runOver( 19184f2271aSYitzhak Mandelbaum "bool foo(int x, int y) { for (;foo(x, y);) x = 1; return true; }"); 19284f2271aSYitzhak Mandelbaum 19384f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 19484f2271aSYitzhak Mandelbaum EXPECT_EQ("foo()", getExtendedText(*CE, tok::TokenKind::semi, *Context)); 19584f2271aSYitzhak Mandelbaum }; 19684f2271aSYitzhak Mandelbaum Visitor.runOver("bool foo() { if (foo()) return true; return false; }"); 19784f2271aSYitzhak Mandelbaum Visitor.runOver("void foo() { int x; for (;; foo()) ++x; }"); 19884f2271aSYitzhak Mandelbaum Visitor.runOver("int foo() { return foo() + 3; }"); 19984f2271aSYitzhak Mandelbaum } 20084f2271aSYitzhak Mandelbaum 201ecfa0b24SGabriel Matute TEST(SourceCodeTest, maybeExtendRange_TokenRange) { 202*4e600751SSirraide struct ExtendTokenRangeVisitor : AnnotatedCodeVisitor { 203*4e600751SSirraide bool VisitCallExpr(CallExpr *CE) override { 204ecfa0b24SGabriel Matute ++MatchCount; 205ecfa0b24SGabriel Matute EXPECT_THAT(getExtendedRange(*CE, tok::TokenKind::semi, *Context), 206ecfa0b24SGabriel Matute EqualsAnnotatedRange(Context, Code.range("r"))); 207ecfa0b24SGabriel Matute return true; 208ecfa0b24SGabriel Matute } 209ecfa0b24SGabriel Matute }; 210ecfa0b24SGabriel Matute 211ecfa0b24SGabriel Matute ExtendTokenRangeVisitor Visitor; 212ecfa0b24SGabriel Matute // Extends to include semicolon. 213ecfa0b24SGabriel Matute Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }"); 214ecfa0b24SGabriel Matute // Does not extend to include semicolon. 215ecfa0b24SGabriel Matute Visitor.runOverAnnotated( 216ecfa0b24SGabriel Matute "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }"); 217ecfa0b24SGabriel Matute } 218ecfa0b24SGabriel Matute 219ecfa0b24SGabriel Matute TEST(SourceCodeTest, maybeExtendRange_CharRange) { 220*4e600751SSirraide struct ExtendCharRangeVisitor : AnnotatedCodeVisitor { 221*4e600751SSirraide bool VisitCallExpr(CallExpr *CE) override { 222ecfa0b24SGabriel Matute ++MatchCount; 223ecfa0b24SGabriel Matute CharSourceRange Call = Lexer::getAsCharRange(CE->getSourceRange(), 224ecfa0b24SGabriel Matute Context->getSourceManager(), 225ecfa0b24SGabriel Matute Context->getLangOpts()); 226ecfa0b24SGabriel Matute EXPECT_THAT(maybeExtendRange(Call, tok::TokenKind::semi, *Context), 227ecfa0b24SGabriel Matute EqualsAnnotatedRange(Context, Code.range("r"))); 228ecfa0b24SGabriel Matute return true; 229ecfa0b24SGabriel Matute } 230ecfa0b24SGabriel Matute }; 231ecfa0b24SGabriel Matute ExtendCharRangeVisitor Visitor; 232ecfa0b24SGabriel Matute // Extends to include semicolon. 233ecfa0b24SGabriel Matute Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }"); 234ecfa0b24SGabriel Matute // Does not extend to include semicolon. 235ecfa0b24SGabriel Matute Visitor.runOverAnnotated( 236ecfa0b24SGabriel Matute "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }"); 237ecfa0b24SGabriel Matute } 238ecfa0b24SGabriel Matute 23938b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRange) { 240*4e600751SSirraide struct VarDeclsVisitor : AnnotatedCodeVisitor { 241*4e600751SSirraide bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); } 24238b4516dSYitzhak Mandelbaum }; 24338b4516dSYitzhak Mandelbaum VarDeclsVisitor Visitor; 24438b4516dSYitzhak Mandelbaum 24538b4516dSYitzhak Mandelbaum // Includes semicolon. 24638b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4;]]"); 24738b4516dSYitzhak Mandelbaum 24838b4516dSYitzhak Mandelbaum // Includes newline and semicolon. 24938b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4;\n]]"); 25038b4516dSYitzhak Mandelbaum 25138b4516dSYitzhak Mandelbaum // Includes trailing comments. 25238b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4; // Comment\n]]"); 25338b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4; /* Comment */\n]]"); 25438b4516dSYitzhak Mandelbaum 25538b4516dSYitzhak Mandelbaum // Does *not* include trailing comments when another entity appears between 25638b4516dSYitzhak Mandelbaum // the decl and the comment. 25738b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4;]] class C {}; // Comment\n"); 25838b4516dSYitzhak Mandelbaum 25938b4516dSYitzhak Mandelbaum // Includes attributes. 26038b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp( 261b78d5380SSaleem Abdulrasool $r[[__attribute__((deprecated("message"))) 26238b4516dSYitzhak Mandelbaum int x;]])cpp"); 26338b4516dSYitzhak Mandelbaum 26438b4516dSYitzhak Mandelbaum // Includes attributes and comments together. 26538b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp( 266b78d5380SSaleem Abdulrasool $r[[__attribute__((deprecated("message"))) 267b78d5380SSaleem Abdulrasool // Comment. 268b78d5380SSaleem Abdulrasool int x;]])cpp"); 269b78d5380SSaleem Abdulrasool 270b78d5380SSaleem Abdulrasool // Includes attributes through macro expansion. 271b78d5380SSaleem Abdulrasool Visitor.runOverAnnotated(R"cpp( 272b78d5380SSaleem Abdulrasool #define MACRO_EXPANSION __attribute__((deprecated("message"))) 273b78d5380SSaleem Abdulrasool $r[[MACRO_EXPANSION 274b78d5380SSaleem Abdulrasool int x;]])cpp"); 275b78d5380SSaleem Abdulrasool 276b78d5380SSaleem Abdulrasool // Includes attributes through macro expansion with comments. 277b78d5380SSaleem Abdulrasool Visitor.runOverAnnotated(R"cpp( 278b78d5380SSaleem Abdulrasool #define MACRO_EXPANSION __attribute__((deprecated("message"))) 279b78d5380SSaleem Abdulrasool $r[[MACRO_EXPANSION 2805674a3c8SGabriel Ravier // Comment. 28138b4516dSYitzhak Mandelbaum int x;]])cpp"); 28238b4516dSYitzhak Mandelbaum } 28338b4516dSYitzhak Mandelbaum 28438b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeClasses) { 285*4e600751SSirraide struct RecordDeclsVisitor : AnnotatedCodeVisitor { 286*4e600751SSirraide bool VisitRecordDecl(RecordDecl *Decl) override { 287*4e600751SSirraide return VisitDeclHelper(Decl); 288*4e600751SSirraide } 28938b4516dSYitzhak Mandelbaum }; 29038b4516dSYitzhak Mandelbaum RecordDeclsVisitor Visitor; 29138b4516dSYitzhak Mandelbaum 29238b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[class A;]]"); 29338b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[class A {};]]"); 29438b4516dSYitzhak Mandelbaum 29538b4516dSYitzhak Mandelbaum // Includes leading template annotation. 29638b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> class A;]]"); 29738b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> class A {};]]"); 29838b4516dSYitzhak Mandelbaum } 29938b4516dSYitzhak Mandelbaum 30038b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) { 301*4e600751SSirraide struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor { 302*4e600751SSirraide bool VisitCXXRecordDecl(CXXRecordDecl *Decl) override { 30338b4516dSYitzhak Mandelbaum return Decl->getTemplateSpecializationKind() != 30438b4516dSYitzhak Mandelbaum TSK_ExplicitSpecialization || 30538b4516dSYitzhak Mandelbaum VisitDeclHelper(Decl); 30638b4516dSYitzhak Mandelbaum } 30738b4516dSYitzhak Mandelbaum }; 30838b4516dSYitzhak Mandelbaum CXXRecordDeclsVisitor Visitor; 30938b4516dSYitzhak Mandelbaum 31038b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp( 31138b4516dSYitzhak Mandelbaum template <typename T> class A{}; 31238b4516dSYitzhak Mandelbaum $r[[template <> class A<int>;]])cpp"); 31338b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp( 31438b4516dSYitzhak Mandelbaum template <typename T> class A{}; 31538b4516dSYitzhak Mandelbaum $r[[template <> class A<int> {};]])cpp"); 31638b4516dSYitzhak Mandelbaum } 31738b4516dSYitzhak Mandelbaum 31838b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeFunctions) { 319*4e600751SSirraide struct FunctionDeclsVisitor : AnnotatedCodeVisitor { 320*4e600751SSirraide bool VisitFunctionDecl(FunctionDecl *Decl) override { 321*4e600751SSirraide return VisitDeclHelper(Decl); 322*4e600751SSirraide } 32338b4516dSYitzhak Mandelbaum }; 32438b4516dSYitzhak Mandelbaum FunctionDeclsVisitor Visitor; 32538b4516dSYitzhak Mandelbaum 32638b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int f();]]"); 32738b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int f() { return 0; }]]"); 32838b4516dSYitzhak Mandelbaum // Includes leading template annotation. 32938b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> int f();]]"); 33038b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> int f() { return 0; }]]"); 33138b4516dSYitzhak Mandelbaum } 33238b4516dSYitzhak Mandelbaum 33338b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) { 334*4e600751SSirraide struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor { 335*4e600751SSirraide bool VisitCXXMethodDecl(CXXMethodDecl *Decl) override { 33638b4516dSYitzhak Mandelbaum // Only consider the definition of the template. 33738b4516dSYitzhak Mandelbaum return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl); 33838b4516dSYitzhak Mandelbaum } 33938b4516dSYitzhak Mandelbaum }; 34038b4516dSYitzhak Mandelbaum CXXMethodDeclsVisitor Visitor; 34138b4516dSYitzhak Mandelbaum 34238b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp( 34338b4516dSYitzhak Mandelbaum template <typename C> 34438b4516dSYitzhak Mandelbaum struct A { template <typename T> int member(T v); }; 34538b4516dSYitzhak Mandelbaum 34638b4516dSYitzhak Mandelbaum $r[[template <typename C> 34738b4516dSYitzhak Mandelbaum template <typename T> 34838b4516dSYitzhak Mandelbaum int A<C>::member(T v) { return 0; }]])cpp"); 34938b4516dSYitzhak Mandelbaum } 35038b4516dSYitzhak Mandelbaum 35138b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeWithComments) { 352*4e600751SSirraide struct VarDeclsVisitor : AnnotatedCodeVisitor { 353*4e600751SSirraide bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); } 35438b4516dSYitzhak Mandelbaum }; 35538b4516dSYitzhak Mandelbaum 35638b4516dSYitzhak Mandelbaum VarDeclsVisitor Visitor; 35738b4516dSYitzhak Mandelbaum auto Visit = [&](llvm::StringRef AnnotatedCode) { 35838b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(AnnotatedCode, {"-fparse-all-comments"}); 35938b4516dSYitzhak Mandelbaum }; 36038b4516dSYitzhak Mandelbaum 36138b4516dSYitzhak Mandelbaum // Includes leading comments. 36238b4516dSYitzhak Mandelbaum Visit("$r[[// Comment.\nint x = 4;]]"); 36338b4516dSYitzhak Mandelbaum Visit("$r[[// Comment.\nint x = 4;\n]]"); 36438b4516dSYitzhak Mandelbaum Visit("$r[[/* Comment.*/\nint x = 4;\n]]"); 36538b4516dSYitzhak Mandelbaum // ... even if separated by (extra) horizontal whitespace. 36638b4516dSYitzhak Mandelbaum Visit("$r[[/* Comment.*/ \nint x = 4;\n]]"); 36738b4516dSYitzhak Mandelbaum 36838b4516dSYitzhak Mandelbaum // Includes comments even in the presence of trailing whitespace. 36938b4516dSYitzhak Mandelbaum Visit("$r[[// Comment.\nint x = 4;]] "); 37038b4516dSYitzhak Mandelbaum 37138b4516dSYitzhak Mandelbaum // Includes comments when the declaration is followed by the beginning or end 37238b4516dSYitzhak Mandelbaum // of a compound statement. 37338b4516dSYitzhak Mandelbaum Visit(R"cpp( 37438b4516dSYitzhak Mandelbaum void foo() { 37538b4516dSYitzhak Mandelbaum $r[[/* C */ 37638b4516dSYitzhak Mandelbaum int x = 4; 37738b4516dSYitzhak Mandelbaum ]]};)cpp"); 37838b4516dSYitzhak Mandelbaum Visit(R"cpp( 37938b4516dSYitzhak Mandelbaum void foo() { 38038b4516dSYitzhak Mandelbaum $r[[/* C */ 38138b4516dSYitzhak Mandelbaum int x = 4; 38238b4516dSYitzhak Mandelbaum ]]{ class Foo {}; } 38338b4516dSYitzhak Mandelbaum })cpp"); 38438b4516dSYitzhak Mandelbaum 38538b4516dSYitzhak Mandelbaum // Includes comments inside macros (when decl is in the same macro). 38638b4516dSYitzhak Mandelbaum Visit(R"cpp( 38738b4516dSYitzhak Mandelbaum #define DECL /* Comment */ int x 38838b4516dSYitzhak Mandelbaum $r[[DECL;]])cpp"); 38938b4516dSYitzhak Mandelbaum 39038b4516dSYitzhak Mandelbaum Visit(R"cpp( 39138b4516dSYitzhak Mandelbaum #define DECL int x 392b67d3702SDaniel Grumberg $r[[// Comment 393b67d3702SDaniel Grumberg DECL;]])cpp"); 394b67d3702SDaniel Grumberg // Does not include comments when only the comment come from a macro. 39538b4516dSYitzhak Mandelbaum Visit(R"cpp( 39638b4516dSYitzhak Mandelbaum #define COMMENT /* Comment */ 39738b4516dSYitzhak Mandelbaum COMMENT 39838b4516dSYitzhak Mandelbaum $r[[int x;]])cpp"); 39938b4516dSYitzhak Mandelbaum 40038b4516dSYitzhak Mandelbaum // Includes multi-line comments. 40138b4516dSYitzhak Mandelbaum Visit(R"cpp( 40238b4516dSYitzhak Mandelbaum $r[[/* multi 40338b4516dSYitzhak Mandelbaum * line 40438b4516dSYitzhak Mandelbaum * comment 40538b4516dSYitzhak Mandelbaum */ 40638b4516dSYitzhak Mandelbaum int x;]])cpp"); 40738b4516dSYitzhak Mandelbaum Visit(R"cpp( 40838b4516dSYitzhak Mandelbaum $r[[// multi 40938b4516dSYitzhak Mandelbaum // line 41038b4516dSYitzhak Mandelbaum // comment 41138b4516dSYitzhak Mandelbaum int x;]])cpp"); 41238b4516dSYitzhak Mandelbaum 41338b4516dSYitzhak Mandelbaum // Does not include comments separated by multiple empty lines. 41438b4516dSYitzhak Mandelbaum Visit("// Comment.\n\n\n$r[[int x = 4;\n]]"); 41538b4516dSYitzhak Mandelbaum Visit("/* Comment.*/\n\n\n$r[[int x = 4;\n]]"); 41638b4516dSYitzhak Mandelbaum 41738b4516dSYitzhak Mandelbaum // Does not include comments before a *series* of declarations. 41838b4516dSYitzhak Mandelbaum Visit(R"cpp( 41938b4516dSYitzhak Mandelbaum // Comment. 42038b4516dSYitzhak Mandelbaum $r[[int x = 4; 42138b4516dSYitzhak Mandelbaum ]]class foo {};)cpp"); 42238b4516dSYitzhak Mandelbaum 42338b4516dSYitzhak Mandelbaum // Does not include IfThisThenThat comments 42438b4516dSYitzhak Mandelbaum Visit("// LINT.IfChange.\n$r[[int x = 4;]]"); 42538b4516dSYitzhak Mandelbaum Visit("// LINT.ThenChange.\n$r[[int x = 4;]]"); 42638b4516dSYitzhak Mandelbaum 42738b4516dSYitzhak Mandelbaum // Includes attributes. 42838b4516dSYitzhak Mandelbaum Visit(R"cpp( 429b78d5380SSaleem Abdulrasool $r[[__attribute__((deprecated("message"))) 43038b4516dSYitzhak Mandelbaum int x;]])cpp"); 43138b4516dSYitzhak Mandelbaum 43238b4516dSYitzhak Mandelbaum // Includes attributes and comments together. 43338b4516dSYitzhak Mandelbaum Visit(R"cpp( 434b78d5380SSaleem Abdulrasool $r[[__attribute__((deprecated("message"))) 435b78d5380SSaleem Abdulrasool // Comment. 436b78d5380SSaleem Abdulrasool int x;]])cpp"); 437b78d5380SSaleem Abdulrasool 438b78d5380SSaleem Abdulrasool // Includes attributes through macro expansion. 439b78d5380SSaleem Abdulrasool Visitor.runOverAnnotated(R"cpp( 440b78d5380SSaleem Abdulrasool #define MACRO_EXPANSION __attribute__((deprecated("message"))) 441b78d5380SSaleem Abdulrasool $r[[MACRO_EXPANSION 442b78d5380SSaleem Abdulrasool int x;]])cpp"); 443b78d5380SSaleem Abdulrasool 444b78d5380SSaleem Abdulrasool // Includes attributes through macro expansion with comments. 445b78d5380SSaleem Abdulrasool Visitor.runOverAnnotated(R"cpp( 446b78d5380SSaleem Abdulrasool #define MACRO_EXPANSION __attribute__((deprecated("message"))) 447b78d5380SSaleem Abdulrasool $r[[MACRO_EXPANSION 4485674a3c8SGabriel Ravier // Comment. 44938b4516dSYitzhak Mandelbaum int x;]])cpp"); 45038b4516dSYitzhak Mandelbaum } 45138b4516dSYitzhak Mandelbaum 45238b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) { 453*4e600751SSirraide struct FailingVarDeclsVisitor : TestVisitor { 45438b4516dSYitzhak Mandelbaum FailingVarDeclsVisitor() {} 455*4e600751SSirraide bool VisitVarDecl(VarDecl *Decl) override { 45638b4516dSYitzhak Mandelbaum EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid()); 45738b4516dSYitzhak Mandelbaum return true; 45838b4516dSYitzhak Mandelbaum } 45938b4516dSYitzhak Mandelbaum }; 46038b4516dSYitzhak Mandelbaum 46138b4516dSYitzhak Mandelbaum FailingVarDeclsVisitor Visitor; 46238b4516dSYitzhak Mandelbaum // Should fail because it only includes a part of the expansion. 46338b4516dSYitzhak Mandelbaum std::string Code = R"cpp( 46438b4516dSYitzhak Mandelbaum #define DECL class foo { }; int x 46538b4516dSYitzhak Mandelbaum DECL;)cpp"; 46638b4516dSYitzhak Mandelbaum Visitor.runOver(Code); 46738b4516dSYitzhak Mandelbaum } 46838b4516dSYitzhak Mandelbaum 4692307029bSEric Li class GetFileRangeForEditTest : public testing::TestWithParam<bool> {}; 4702307029bSEric Li INSTANTIATE_TEST_SUITE_P(WithAndWithoutExpansions, GetFileRangeForEditTest, 471a78d4b5bSEric Li testing::Bool()); 472a78d4b5bSEric Li 4732307029bSEric Li TEST_P(GetFileRangeForEditTest, EditRangeWithMacroExpansionsShouldSucceed) { 4742e97a1e1SYitzhak Mandelbaum // The call expression, whose range we are extracting, includes two macro 4752e97a1e1SYitzhak Mandelbaum // expansions. 4762e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp( 4772e97a1e1SYitzhak Mandelbaum #define M(a) a * 13 4782e97a1e1SYitzhak Mandelbaum int foo(int x, int y); 4792e97a1e1SYitzhak Mandelbaum int a = $r[[foo(M(1), M(2))]]; 4802e97a1e1SYitzhak Mandelbaum )cpp"); 4812e97a1e1SYitzhak Mandelbaum 4822e97a1e1SYitzhak Mandelbaum CallsVisitor Visitor; 4832e97a1e1SYitzhak Mandelbaum Visitor.OnCall = [&Code](CallExpr *CE, ASTContext *Context) { 4842e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(CE->getSourceRange()); 4852307029bSEric Li EXPECT_THAT(getFileRangeForEdit(Range, *Context, GetParam()), 4862e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 4872e97a1e1SYitzhak Mandelbaum }; 4882e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code()); 4892e97a1e1SYitzhak Mandelbaum } 4902e97a1e1SYitzhak Mandelbaum 4912e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroExpansionShouldSucceed) { 4922e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp( 4932e97a1e1SYitzhak Mandelbaum #define FOO 10 4942e97a1e1SYitzhak Mandelbaum int a = $r[[FOO]]; 4952e97a1e1SYitzhak Mandelbaum )cpp"); 4962e97a1e1SYitzhak Mandelbaum 4972e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor; 4982e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 4992e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 5002307029bSEric Li EXPECT_THAT(getFileRangeForEdit(Range, *Context), 5012e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 5022e97a1e1SYitzhak Mandelbaum }; 5032e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code()); 5042e97a1e1SYitzhak Mandelbaum } 5052e97a1e1SYitzhak Mandelbaum 506a78d4b5bSEric Li TEST(SourceCodeTest, EditInvolvingExpansionIgnoringExpansionShouldFail) { 507a78d4b5bSEric Li // If we specify to ignore macro expansions, none of these call expressions 508a78d4b5bSEric Li // should have an editable range. 509a78d4b5bSEric Li llvm::Annotations Code(R"cpp( 510a78d4b5bSEric Li #define M1(x) x(1) 511a78d4b5bSEric Li #define M2(x, y) x ## y 512a78d4b5bSEric Li #define M3(x) foobar(x) 513a78d4b5bSEric Li int foobar(int); 514a78d4b5bSEric Li int a = M1(foobar); 515a78d4b5bSEric Li int b = M2(foo, bar(2)); 516a78d4b5bSEric Li int c = M3(3); 517a78d4b5bSEric Li )cpp"); 518a78d4b5bSEric Li 519a78d4b5bSEric Li CallsVisitor Visitor; 520a78d4b5bSEric Li Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 521a78d4b5bSEric Li auto Range = CharSourceRange::getTokenRange(CE->getSourceRange()); 522a78d4b5bSEric Li EXPECT_FALSE( 5232307029bSEric Li getFileRangeForEdit(Range, *Context, /*IncludeMacroExpansion=*/false)); 524a78d4b5bSEric Li }; 525a78d4b5bSEric Li Visitor.runOver(Code.code()); 526a78d4b5bSEric Li } 527a78d4b5bSEric Li 528345c4822SEric Li TEST(SourceCodeTest, InnerNestedTemplate) { 529345c4822SEric Li llvm::Annotations Code(R"cpp( 530345c4822SEric Li template <typename T> 531345c4822SEric Li struct A {}; 532345c4822SEric Li template <typename T> 533345c4822SEric Li struct B {}; 534345c4822SEric Li template <typename T> 535345c4822SEric Li struct C {}; 536345c4822SEric Li 537345c4822SEric Li void f(A<B<C<int>$r[[>>]]); 538345c4822SEric Li )cpp"); 539345c4822SEric Li 540345c4822SEric Li TypeLocVisitor Visitor; 541345c4822SEric Li Visitor.OnTypeLoc = [&](TypeLoc TL, ASTContext *Context) { 542345c4822SEric Li if (TL.getSourceRange().isInvalid()) 543345c4822SEric Li return; 544345c4822SEric Li 545345c4822SEric Li // There are no macros, so every TypeLoc's range should be valid. 546345c4822SEric Li auto Range = CharSourceRange::getTokenRange(TL.getSourceRange()); 547345c4822SEric Li auto LastTokenRange = CharSourceRange::getTokenRange(TL.getEndLoc()); 548345c4822SEric Li EXPECT_TRUE(getFileRangeForEdit(Range, *Context, 549345c4822SEric Li /*IncludeMacroExpansion=*/false)) 550345c4822SEric Li << TL.getSourceRange().printToString(Context->getSourceManager()); 551345c4822SEric Li EXPECT_TRUE(getFileRangeForEdit(LastTokenRange, *Context, 552345c4822SEric Li /*IncludeMacroExpansion=*/false)) 553345c4822SEric Li << TL.getEndLoc().printToString(Context->getSourceManager()); 554345c4822SEric Li 555345c4822SEric Li if (auto matches = match( 556345c4822SEric Li templateSpecializationTypeLoc( 557345c4822SEric Li loc(templateSpecializationType( 558345c4822SEric Li hasDeclaration(cxxRecordDecl(hasName("A"))))), 559345c4822SEric Li hasTemplateArgumentLoc( 560345c4822SEric Li 0, templateArgumentLoc(hasTypeLoc(typeLoc().bind("b"))))), 561345c4822SEric Li TL, *Context); 562345c4822SEric Li !matches.empty()) { 563345c4822SEric Li // A range where the start token is split, but the end token is not. 564345c4822SEric Li auto OuterTL = TL; 565345c4822SEric Li auto MiddleTL = *matches[0].getNodeAs<TypeLoc>("b"); 566345c4822SEric Li EXPECT_THAT( 567345c4822SEric Li getFileRangeForEdit(CharSourceRange::getTokenRange( 568345c4822SEric Li MiddleTL.getEndLoc(), OuterTL.getEndLoc()), 569345c4822SEric Li *Context, /*IncludeMacroExpansion=*/false), 570345c4822SEric Li Optional(EqualsAnnotatedRange(Context, Code.range("r")))); 571345c4822SEric Li } 572345c4822SEric Li }; 573345c4822SEric Li Visitor.runOver(Code.code(), TypeLocVisitor::Lang_CXX11); 574345c4822SEric Li } 575345c4822SEric Li 5762307029bSEric Li TEST_P(GetFileRangeForEditTest, EditPartialMacroExpansionShouldFail) { 5772e97a1e1SYitzhak Mandelbaum std::string Code = R"cpp( 5782e97a1e1SYitzhak Mandelbaum #define BAR 10+ 5792e97a1e1SYitzhak Mandelbaum int c = BAR 3.0; 5802e97a1e1SYitzhak Mandelbaum )cpp"; 5812e97a1e1SYitzhak Mandelbaum 5822e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor; 5832e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 5842e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 5852307029bSEric Li EXPECT_FALSE(getFileRangeForEdit(Range, *Context, GetParam())); 5862e97a1e1SYitzhak Mandelbaum }; 5872e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code); 5882e97a1e1SYitzhak Mandelbaum } 5892e97a1e1SYitzhak Mandelbaum 5902307029bSEric Li TEST_P(GetFileRangeForEditTest, EditWholeMacroArgShouldSucceed) { 5912e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp( 5922e97a1e1SYitzhak Mandelbaum #define FOO(a) a + 7.0; 5932e97a1e1SYitzhak Mandelbaum int a = FOO($r[[10]]); 5942e97a1e1SYitzhak Mandelbaum )cpp"); 5952e97a1e1SYitzhak Mandelbaum 5962e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor; 5972e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 5982e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 5992307029bSEric Li EXPECT_THAT(getFileRangeForEdit(Range, *Context, GetParam()), 6002e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 6012e97a1e1SYitzhak Mandelbaum }; 6022e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code()); 6032e97a1e1SYitzhak Mandelbaum } 6042e97a1e1SYitzhak Mandelbaum 6052307029bSEric Li TEST_P(GetFileRangeForEditTest, EditPartialMacroArgShouldSucceed) { 6062e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp( 6072e97a1e1SYitzhak Mandelbaum #define FOO(a) a + 7.0; 6082e97a1e1SYitzhak Mandelbaum int a = FOO($r[[10]] + 10.0); 6092e97a1e1SYitzhak Mandelbaum )cpp"); 6102e97a1e1SYitzhak Mandelbaum 6112e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor; 6122e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 6132e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 6142307029bSEric Li EXPECT_THAT(getFileRangeForEdit(Range, *Context, GetParam()), 6152e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 6162e97a1e1SYitzhak Mandelbaum }; 6172e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code()); 6182e97a1e1SYitzhak Mandelbaum } 6192e97a1e1SYitzhak Mandelbaum 620b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditRangeWithMacroExpansionsIsValid) { 621b9d2bf38SYitzhak Mandelbaum // The call expression, whose range we are extracting, includes two macro 622b9d2bf38SYitzhak Mandelbaum // expansions. 623b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp( 624b9d2bf38SYitzhak Mandelbaum #define M(a) a * 13 625b9d2bf38SYitzhak Mandelbaum int foo(int x, int y); 626b9d2bf38SYitzhak Mandelbaum int a = foo(M(1), M(2)); 627b9d2bf38SYitzhak Mandelbaum )cpp"; 628b9d2bf38SYitzhak Mandelbaum 629b9d2bf38SYitzhak Mandelbaum CallsVisitor Visitor; 630b9d2bf38SYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 631b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(CE->getSourceRange()); 632b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 633b9d2bf38SYitzhak Mandelbaum Succeeded()); 634b9d2bf38SYitzhak Mandelbaum }; 635b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code); 636b9d2bf38SYitzhak Mandelbaum } 637b9d2bf38SYitzhak Mandelbaum 638b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, SpellingRangeOfMacroArgIsValid) { 639b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp( 640b9d2bf38SYitzhak Mandelbaum #define FOO(a) a + 7.0; 641b9d2bf38SYitzhak Mandelbaum int a = FOO(10); 642b9d2bf38SYitzhak Mandelbaum )cpp"; 643b9d2bf38SYitzhak Mandelbaum 644b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor; 645b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 646b9d2bf38SYitzhak Mandelbaum SourceLocation ArgLoc = 647b9d2bf38SYitzhak Mandelbaum Context->getSourceManager().getSpellingLoc(Expr->getBeginLoc()); 648b9d2bf38SYitzhak Mandelbaum // The integer literal is a single token. 649b9d2bf38SYitzhak Mandelbaum auto ArgRange = CharSourceRange::getTokenRange(ArgLoc); 650b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(ArgRange, Context->getSourceManager()), 651b9d2bf38SYitzhak Mandelbaum Succeeded()); 652b9d2bf38SYitzhak Mandelbaum }; 653b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code); 654b9d2bf38SYitzhak Mandelbaum } 655b9d2bf38SYitzhak Mandelbaum 656b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, InvalidEditRangeIsInvalid) { 657b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = "int c = 10;"; 658b9d2bf38SYitzhak Mandelbaum 659b9d2bf38SYitzhak Mandelbaum // We use the visitor just to get a valid context. 660b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor; 661b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *, ASTContext *Context) { 662b9d2bf38SYitzhak Mandelbaum CharSourceRange Invalid; 663b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Invalid, Context->getSourceManager()), 664b9d2bf38SYitzhak Mandelbaum Failed()); 665b9d2bf38SYitzhak Mandelbaum }; 666b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code); 667b9d2bf38SYitzhak Mandelbaum } 668b9d2bf38SYitzhak Mandelbaum 669b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, InvertedEditRangeIsInvalid) { 670b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp( 671b9d2bf38SYitzhak Mandelbaum int foo(int x); 672b9d2bf38SYitzhak Mandelbaum int a = foo(2); 673b9d2bf38SYitzhak Mandelbaum )cpp"; 674b9d2bf38SYitzhak Mandelbaum 675b9d2bf38SYitzhak Mandelbaum CallsVisitor Visitor; 676b9d2bf38SYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *Expr, ASTContext *Context) { 677b9d2bf38SYitzhak Mandelbaum auto InvertedRange = CharSourceRange::getTokenRange( 678b9d2bf38SYitzhak Mandelbaum SourceRange(Expr->getEndLoc(), Expr->getBeginLoc())); 679b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR( 680b9d2bf38SYitzhak Mandelbaum validateEditRange(InvertedRange, Context->getSourceManager()), 681b9d2bf38SYitzhak Mandelbaum Failed()); 682b9d2bf38SYitzhak Mandelbaum }; 683b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code); 684b9d2bf38SYitzhak Mandelbaum } 685b9d2bf38SYitzhak Mandelbaum 686b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, MacroArgIsInvalid) { 687b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp( 688b9d2bf38SYitzhak Mandelbaum #define FOO(a) a + 7.0; 689b9d2bf38SYitzhak Mandelbaum int a = FOO(10); 690b9d2bf38SYitzhak Mandelbaum )cpp"; 691b9d2bf38SYitzhak Mandelbaum 692b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor; 693b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 694b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 695b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 696b9d2bf38SYitzhak Mandelbaum Failed()); 697b9d2bf38SYitzhak Mandelbaum }; 698b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code); 699b9d2bf38SYitzhak Mandelbaum } 700b9d2bf38SYitzhak Mandelbaum 701b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroExpansionIsInvalid) { 702b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp( 703b9d2bf38SYitzhak Mandelbaum #define FOO 10 704b9d2bf38SYitzhak Mandelbaum int a = FOO; 705b9d2bf38SYitzhak Mandelbaum )cpp"; 706b9d2bf38SYitzhak Mandelbaum 707b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor; 708b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 709b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 710b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 711b9d2bf38SYitzhak Mandelbaum Failed()); 712b9d2bf38SYitzhak Mandelbaum 713b9d2bf38SYitzhak Mandelbaum }; 714b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code); 715b9d2bf38SYitzhak Mandelbaum } 716b9d2bf38SYitzhak Mandelbaum 717b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditPartialMacroExpansionIsInvalid) { 718b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp( 719b9d2bf38SYitzhak Mandelbaum #define BAR 10+ 720b9d2bf38SYitzhak Mandelbaum int c = BAR 3.0; 721b9d2bf38SYitzhak Mandelbaum )cpp"; 722b9d2bf38SYitzhak Mandelbaum 723b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor; 724b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 725b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 726b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 727b9d2bf38SYitzhak Mandelbaum Failed()); 728b9d2bf38SYitzhak Mandelbaum }; 729b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code); 730b9d2bf38SYitzhak Mandelbaum } 7316e519910SBalázs Kéri 7326e519910SBalázs Kéri TEST(SourceCodeTest, GetCallReturnType_Dependent) { 7336e519910SBalázs Kéri llvm::Annotations Code{R"cpp( 7346e519910SBalázs Kéri template<class T, class F> 7356e519910SBalázs Kéri void templ(const T& t, F f) {} 7366e519910SBalázs Kéri 7376e519910SBalázs Kéri template<class T, class F> 7386e519910SBalázs Kéri void templ1(const T& t, F f) { 7396e519910SBalázs Kéri $test1[[f(t)]]; 7406e519910SBalázs Kéri } 7416e519910SBalázs Kéri 7426e519910SBalázs Kéri int f_overload(int) { return 1; } 7436e519910SBalázs Kéri int f_overload(double) { return 2; } 7446e519910SBalázs Kéri 7456e519910SBalázs Kéri void f1() { 7466e519910SBalázs Kéri int i = 0; 7476e519910SBalázs Kéri templ(i, [](const auto &p) { 7486e519910SBalázs Kéri $test2[[f_overload(p)]]; 7496e519910SBalázs Kéri }); 7506e519910SBalázs Kéri } 7516e519910SBalázs Kéri 7526e519910SBalázs Kéri struct A { 7536e519910SBalázs Kéri void f_overload(int); 7546e519910SBalázs Kéri void f_overload(double); 7556e519910SBalázs Kéri }; 7566e519910SBalázs Kéri 7576e519910SBalázs Kéri void f2() { 7586e519910SBalázs Kéri int i = 0; 7596e519910SBalázs Kéri templ(i, [](const auto &p) { 7606e519910SBalázs Kéri A a; 7616e519910SBalázs Kéri $test3[[a.f_overload(p)]]; 7626e519910SBalázs Kéri }); 7636e519910SBalázs Kéri } 7646e519910SBalázs Kéri )cpp"}; 7656e519910SBalázs Kéri 7666e519910SBalázs Kéri llvm::Annotations::Range R1 = Code.range("test1"); 7676e519910SBalázs Kéri llvm::Annotations::Range R2 = Code.range("test2"); 7686e519910SBalázs Kéri llvm::Annotations::Range R3 = Code.range("test3"); 7696e519910SBalázs Kéri 7706e519910SBalázs Kéri CallsVisitor Visitor; 7716e519910SBalázs Kéri Visitor.OnCall = [&R1, &R2, &R3](CallExpr *Expr, ASTContext *Context) { 7726e519910SBalázs Kéri unsigned Begin = Context->getSourceManager().getFileOffset( 7736e519910SBalázs Kéri Expr->getSourceRange().getBegin()); 7746e519910SBalázs Kéri unsigned End = Context->getSourceManager().getFileOffset( 7756e519910SBalázs Kéri Expr->getSourceRange().getEnd()); 7766e519910SBalázs Kéri llvm::Annotations::Range R{Begin, End + 1}; 7776e519910SBalázs Kéri 7786e519910SBalázs Kéri QualType CalleeType = Expr->getCallee()->getType(); 7796e519910SBalázs Kéri if (R == R1) { 7806e519910SBalázs Kéri ASSERT_TRUE(CalleeType->isDependentType()); 7816e519910SBalázs Kéri EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy); 7826e519910SBalázs Kéri } else if (R == R2) { 7836e519910SBalázs Kéri ASSERT_FALSE(CalleeType->isDependentType()); 7846e519910SBalázs Kéri ASSERT_TRUE(CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)); 7856e519910SBalázs Kéri ASSERT_TRUE(isa<UnresolvedLookupExpr>(Expr->getCallee())); 7866e519910SBalázs Kéri EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy); 7876e519910SBalázs Kéri } else if (R == R3) { 7886e519910SBalázs Kéri ASSERT_FALSE(CalleeType->isDependentType()); 7896e519910SBalázs Kéri ASSERT_TRUE( 7906e519910SBalázs Kéri CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)); 7916e519910SBalázs Kéri ASSERT_TRUE(isa<UnresolvedMemberExpr>(Expr->getCallee())); 7926e519910SBalázs Kéri EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy); 7936e519910SBalázs Kéri } 7946e519910SBalázs Kéri }; 7956e519910SBalázs Kéri Visitor.runOver(Code.code(), CallsVisitor::Lang_CXX14); 7966e519910SBalázs Kéri } 7976e519910SBalázs Kéri 79884f2271aSYitzhak Mandelbaum } // end anonymous namespace 799