xref: /llvm-project/clang/unittests/Tooling/SourceCodeTest.cpp (revision 4e600751d2f7e8e7b85a71b7128b68444bdde91b)
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