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"
1184f2271aSYitzhak Mandelbaum #include "clang/Basic/Diagnostic.h"
12ecfa0b24SGabriel Matute #include "clang/Basic/SourceLocation.h"
13ecfa0b24SGabriel Matute #include "clang/Lex/Lexer.h"
142e97a1e1SYitzhak Mandelbaum #include "llvm/Testing/Support/Annotations.h"
15b9d2bf38SYitzhak Mandelbaum #include "llvm/Testing/Support/Error.h"
162e97a1e1SYitzhak Mandelbaum #include "llvm/Testing/Support/SupportHelpers.h"
172e97a1e1SYitzhak Mandelbaum #include <gmock/gmock.h>
182e97a1e1SYitzhak Mandelbaum #include <gtest/gtest.h>
1984f2271aSYitzhak Mandelbaum 
2084f2271aSYitzhak Mandelbaum using namespace clang;
2184f2271aSYitzhak Mandelbaum 
22b9d2bf38SYitzhak Mandelbaum using llvm::Failed;
23b9d2bf38SYitzhak Mandelbaum using llvm::Succeeded;
242e97a1e1SYitzhak Mandelbaum using llvm::ValueIs;
2538b4516dSYitzhak Mandelbaum using tooling::getAssociatedRange;
26ecfa0b24SGabriel Matute using tooling::getExtendedRange;
2784f2271aSYitzhak Mandelbaum using tooling::getExtendedText;
282e97a1e1SYitzhak Mandelbaum using tooling::getRangeForEdit;
292e97a1e1SYitzhak Mandelbaum using tooling::getText;
30ecfa0b24SGabriel Matute using tooling::maybeExtendRange;
31b9d2bf38SYitzhak Mandelbaum using tooling::validateEditRange;
3284f2271aSYitzhak Mandelbaum 
3384f2271aSYitzhak Mandelbaum namespace {
3484f2271aSYitzhak Mandelbaum 
352e97a1e1SYitzhak Mandelbaum struct IntLitVisitor : TestVisitor<IntLitVisitor> {
VisitIntegerLiteral__anon42750e5d0111::IntLitVisitor362e97a1e1SYitzhak Mandelbaum   bool VisitIntegerLiteral(IntegerLiteral *Expr) {
372e97a1e1SYitzhak Mandelbaum     OnIntLit(Expr, Context);
382e97a1e1SYitzhak Mandelbaum     return true;
392e97a1e1SYitzhak Mandelbaum   }
402e97a1e1SYitzhak Mandelbaum 
412e97a1e1SYitzhak Mandelbaum   std::function<void(IntegerLiteral *, ASTContext *Context)> OnIntLit;
422e97a1e1SYitzhak Mandelbaum };
432e97a1e1SYitzhak Mandelbaum 
4484f2271aSYitzhak Mandelbaum struct CallsVisitor : TestVisitor<CallsVisitor> {
VisitCallExpr__anon42750e5d0111::CallsVisitor4584f2271aSYitzhak Mandelbaum   bool VisitCallExpr(CallExpr *Expr) {
4684f2271aSYitzhak Mandelbaum     OnCall(Expr, Context);
4784f2271aSYitzhak Mandelbaum     return true;
4884f2271aSYitzhak Mandelbaum   }
4984f2271aSYitzhak Mandelbaum 
5084f2271aSYitzhak Mandelbaum   std::function<void(CallExpr *, ASTContext *Context)> OnCall;
5184f2271aSYitzhak Mandelbaum };
5284f2271aSYitzhak Mandelbaum 
532e97a1e1SYitzhak Mandelbaum // Equality matcher for `clang::CharSourceRange`, which lacks `operator==`.
542e97a1e1SYitzhak Mandelbaum MATCHER_P(EqualsRange, R, "") {
552e97a1e1SYitzhak Mandelbaum   return arg.isTokenRange() == R.isTokenRange() &&
562e97a1e1SYitzhak Mandelbaum          arg.getBegin() == R.getBegin() && arg.getEnd() == R.getEnd();
572e97a1e1SYitzhak Mandelbaum }
582e97a1e1SYitzhak Mandelbaum 
59ecfa0b24SGabriel Matute MATCHER_P2(EqualsAnnotatedRange, Context, R, "") {
6038b4516dSYitzhak Mandelbaum   if (arg.getBegin().isMacroID()) {
6138b4516dSYitzhak Mandelbaum     *result_listener << "which starts in a macro";
6238b4516dSYitzhak Mandelbaum     return false;
6338b4516dSYitzhak Mandelbaum   }
6438b4516dSYitzhak Mandelbaum   if (arg.getEnd().isMacroID()) {
6538b4516dSYitzhak Mandelbaum     *result_listener << "which ends in a macro";
6638b4516dSYitzhak Mandelbaum     return false;
6738b4516dSYitzhak Mandelbaum   }
6838b4516dSYitzhak Mandelbaum 
69ecfa0b24SGabriel Matute   CharSourceRange Range = Lexer::getAsCharRange(
70ecfa0b24SGabriel Matute       arg, Context->getSourceManager(), Context->getLangOpts());
71ecfa0b24SGabriel Matute   unsigned Begin = Context->getSourceManager().getFileOffset(Range.getBegin());
72ecfa0b24SGabriel Matute   unsigned End = Context->getSourceManager().getFileOffset(Range.getEnd());
7338b4516dSYitzhak Mandelbaum 
74ecfa0b24SGabriel Matute   *result_listener << "which is a " << (arg.isTokenRange() ? "Token" : "Char")
75ecfa0b24SGabriel Matute                    << " range [" << Begin << "," << End << ")";
7638b4516dSYitzhak Mandelbaum   return Begin == R.Begin && End == R.End;
7738b4516dSYitzhak Mandelbaum }
7838b4516dSYitzhak Mandelbaum 
AsRange(const SourceManager & SM,llvm::Annotations::Range R)792e97a1e1SYitzhak Mandelbaum static ::testing::Matcher<CharSourceRange> AsRange(const SourceManager &SM,
802e97a1e1SYitzhak Mandelbaum                                                    llvm::Annotations::Range R) {
812e97a1e1SYitzhak Mandelbaum   return EqualsRange(CharSourceRange::getCharRange(
822e97a1e1SYitzhak Mandelbaum       SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.Begin),
832e97a1e1SYitzhak Mandelbaum       SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.End)));
842e97a1e1SYitzhak Mandelbaum }
852e97a1e1SYitzhak Mandelbaum 
8638b4516dSYitzhak Mandelbaum // Base class for visitors that expect a single match corresponding to a
8738b4516dSYitzhak Mandelbaum // specific annotated range.
8838b4516dSYitzhak Mandelbaum template <typename T> class AnnotatedCodeVisitor : public TestVisitor<T> {
89ecfa0b24SGabriel Matute protected:
9038b4516dSYitzhak Mandelbaum   int MatchCount = 0;
91ecfa0b24SGabriel Matute   llvm::Annotations Code;
9238b4516dSYitzhak Mandelbaum 
9338b4516dSYitzhak Mandelbaum public:
AnnotatedCodeVisitor()9438b4516dSYitzhak Mandelbaum   AnnotatedCodeVisitor() : Code("$r[[]]") {}
95ecfa0b24SGabriel Matute   // Helper for tests of `getAssociatedRange`.
VisitDeclHelper(Decl * Decl)9638b4516dSYitzhak Mandelbaum   bool VisitDeclHelper(Decl *Decl) {
9738b4516dSYitzhak Mandelbaum     // Only consider explicit declarations.
9838b4516dSYitzhak Mandelbaum     if (Decl->isImplicit())
9938b4516dSYitzhak Mandelbaum       return true;
10038b4516dSYitzhak Mandelbaum 
10138b4516dSYitzhak Mandelbaum     ++MatchCount;
10238b4516dSYitzhak Mandelbaum     EXPECT_THAT(getAssociatedRange(*Decl, *this->Context),
103ecfa0b24SGabriel Matute                 EqualsAnnotatedRange(this->Context, Code.range("r")))
10438b4516dSYitzhak Mandelbaum         << Code.code();
10538b4516dSYitzhak Mandelbaum     return true;
10638b4516dSYitzhak Mandelbaum   }
10738b4516dSYitzhak Mandelbaum 
runOverAnnotated(llvm::StringRef AnnotatedCode,std::vector<std::string> Args={})10838b4516dSYitzhak Mandelbaum   bool runOverAnnotated(llvm::StringRef AnnotatedCode,
10938b4516dSYitzhak Mandelbaum                         std::vector<std::string> Args = {}) {
11038b4516dSYitzhak Mandelbaum     Code = llvm::Annotations(AnnotatedCode);
11138b4516dSYitzhak Mandelbaum     MatchCount = 0;
11238b4516dSYitzhak Mandelbaum     Args.push_back("-std=c++11");
11338b4516dSYitzhak Mandelbaum     Args.push_back("-fno-delayed-template-parsing");
11438b4516dSYitzhak Mandelbaum     bool result = tooling::runToolOnCodeWithArgs(this->CreateTestAction(),
11538b4516dSYitzhak Mandelbaum                                                  Code.code(), Args);
11638b4516dSYitzhak Mandelbaum     EXPECT_EQ(MatchCount, 1) << AnnotatedCode;
11738b4516dSYitzhak Mandelbaum     return result;
11838b4516dSYitzhak Mandelbaum   }
11938b4516dSYitzhak Mandelbaum };
12038b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,getText)12184f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getText) {
12284f2271aSYitzhak Mandelbaum   CallsVisitor Visitor;
12384f2271aSYitzhak Mandelbaum 
12484f2271aSYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
12584f2271aSYitzhak Mandelbaum     EXPECT_EQ("foo(x, y)", getText(*CE, *Context));
12684f2271aSYitzhak Mandelbaum   };
12784f2271aSYitzhak Mandelbaum   Visitor.runOver("void foo(int x, int y) { foo(x, y); }");
12884f2271aSYitzhak Mandelbaum 
12984f2271aSYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
13084f2271aSYitzhak Mandelbaum     EXPECT_EQ("APPLY(foo, x, y)", getText(*CE, *Context));
13184f2271aSYitzhak Mandelbaum   };
13284f2271aSYitzhak Mandelbaum   Visitor.runOver("#define APPLY(f, x, y) f(x, y)\n"
13384f2271aSYitzhak Mandelbaum                   "void foo(int x, int y) { APPLY(foo, x, y); }");
13484f2271aSYitzhak Mandelbaum }
13584f2271aSYitzhak Mandelbaum 
TEST(SourceCodeTest,getTextWithMacro)13684f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getTextWithMacro) {
13784f2271aSYitzhak Mandelbaum   CallsVisitor Visitor;
13884f2271aSYitzhak Mandelbaum 
13984f2271aSYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
14084f2271aSYitzhak Mandelbaum     EXPECT_EQ("F OO", getText(*CE, *Context));
14184f2271aSYitzhak Mandelbaum     Expr *P0 = CE->getArg(0);
14284f2271aSYitzhak Mandelbaum     Expr *P1 = CE->getArg(1);
14384f2271aSYitzhak Mandelbaum     EXPECT_EQ("", getText(*P0, *Context));
14484f2271aSYitzhak Mandelbaum     EXPECT_EQ("", getText(*P1, *Context));
14584f2271aSYitzhak Mandelbaum   };
14684f2271aSYitzhak Mandelbaum   Visitor.runOver("#define F foo(\n"
14784f2271aSYitzhak Mandelbaum                   "#define OO x, y)\n"
14884f2271aSYitzhak Mandelbaum                   "void foo(int x, int y) { F OO ; }");
14984f2271aSYitzhak Mandelbaum 
15084f2271aSYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
15184f2271aSYitzhak Mandelbaum     EXPECT_EQ("", getText(*CE, *Context));
15284f2271aSYitzhak Mandelbaum     Expr *P0 = CE->getArg(0);
15384f2271aSYitzhak Mandelbaum     Expr *P1 = CE->getArg(1);
15484f2271aSYitzhak Mandelbaum     EXPECT_EQ("x", getText(*P0, *Context));
15584f2271aSYitzhak Mandelbaum     EXPECT_EQ("y", getText(*P1, *Context));
15684f2271aSYitzhak Mandelbaum   };
15784f2271aSYitzhak Mandelbaum   Visitor.runOver("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n"
15884f2271aSYitzhak Mandelbaum                   "void foo(int x, int y) { FOO(x,y) }");
15984f2271aSYitzhak Mandelbaum }
16084f2271aSYitzhak Mandelbaum 
TEST(SourceCodeTest,getExtendedText)16184f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getExtendedText) {
16284f2271aSYitzhak Mandelbaum   CallsVisitor Visitor;
16384f2271aSYitzhak Mandelbaum 
16484f2271aSYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
16584f2271aSYitzhak Mandelbaum     EXPECT_EQ("foo(x, y);",
16684f2271aSYitzhak Mandelbaum               getExtendedText(*CE, tok::TokenKind::semi, *Context));
16784f2271aSYitzhak Mandelbaum 
16884f2271aSYitzhak Mandelbaum     Expr *P0 = CE->getArg(0);
16984f2271aSYitzhak Mandelbaum     Expr *P1 = CE->getArg(1);
17084f2271aSYitzhak Mandelbaum     EXPECT_EQ("x", getExtendedText(*P0, tok::TokenKind::semi, *Context));
17184f2271aSYitzhak Mandelbaum     EXPECT_EQ("x,", getExtendedText(*P0, tok::TokenKind::comma, *Context));
17284f2271aSYitzhak Mandelbaum     EXPECT_EQ("y", getExtendedText(*P1, tok::TokenKind::semi, *Context));
17384f2271aSYitzhak Mandelbaum   };
17484f2271aSYitzhak Mandelbaum   Visitor.runOver("void foo(int x, int y) { foo(x, y); }");
17584f2271aSYitzhak Mandelbaum   Visitor.runOver("void foo(int x, int y) { if (true) foo(x, y); }");
17684f2271aSYitzhak Mandelbaum   Visitor.runOver("int foo(int x, int y) { if (true) return 3 + foo(x, y); }");
17784f2271aSYitzhak Mandelbaum   Visitor.runOver("void foo(int x, int y) { for (foo(x, y);;) ++x; }");
17884f2271aSYitzhak Mandelbaum   Visitor.runOver(
17984f2271aSYitzhak Mandelbaum       "bool foo(int x, int y) { for (;foo(x, y);) x = 1; return true; }");
18084f2271aSYitzhak Mandelbaum 
18184f2271aSYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
18284f2271aSYitzhak Mandelbaum     EXPECT_EQ("foo()", getExtendedText(*CE, tok::TokenKind::semi, *Context));
18384f2271aSYitzhak Mandelbaum   };
18484f2271aSYitzhak Mandelbaum   Visitor.runOver("bool foo() { if (foo()) return true; return false; }");
18584f2271aSYitzhak Mandelbaum   Visitor.runOver("void foo() { int x; for (;; foo()) ++x; }");
18684f2271aSYitzhak Mandelbaum   Visitor.runOver("int foo() { return foo() + 3; }");
18784f2271aSYitzhak Mandelbaum }
18884f2271aSYitzhak Mandelbaum 
TEST(SourceCodeTest,maybeExtendRange_TokenRange)189ecfa0b24SGabriel Matute TEST(SourceCodeTest, maybeExtendRange_TokenRange) {
190ecfa0b24SGabriel Matute   struct ExtendTokenRangeVisitor
191ecfa0b24SGabriel Matute       : AnnotatedCodeVisitor<ExtendTokenRangeVisitor> {
192ecfa0b24SGabriel Matute     bool VisitCallExpr(CallExpr *CE) {
193ecfa0b24SGabriel Matute       ++MatchCount;
194ecfa0b24SGabriel Matute       EXPECT_THAT(getExtendedRange(*CE, tok::TokenKind::semi, *Context),
195ecfa0b24SGabriel Matute                   EqualsAnnotatedRange(Context, Code.range("r")));
196ecfa0b24SGabriel Matute       return true;
197ecfa0b24SGabriel Matute     }
198ecfa0b24SGabriel Matute   };
199ecfa0b24SGabriel Matute 
200ecfa0b24SGabriel Matute   ExtendTokenRangeVisitor Visitor;
201ecfa0b24SGabriel Matute   // Extends to include semicolon.
202ecfa0b24SGabriel Matute   Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }");
203ecfa0b24SGabriel Matute   // Does not extend to include semicolon.
204ecfa0b24SGabriel Matute   Visitor.runOverAnnotated(
205ecfa0b24SGabriel Matute       "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }");
206ecfa0b24SGabriel Matute }
207ecfa0b24SGabriel Matute 
TEST(SourceCodeTest,maybeExtendRange_CharRange)208ecfa0b24SGabriel Matute TEST(SourceCodeTest, maybeExtendRange_CharRange) {
209ecfa0b24SGabriel Matute   struct ExtendCharRangeVisitor : AnnotatedCodeVisitor<ExtendCharRangeVisitor> {
210ecfa0b24SGabriel Matute     bool VisitCallExpr(CallExpr *CE) {
211ecfa0b24SGabriel Matute       ++MatchCount;
212ecfa0b24SGabriel Matute       CharSourceRange Call = Lexer::getAsCharRange(CE->getSourceRange(),
213ecfa0b24SGabriel Matute                                                    Context->getSourceManager(),
214ecfa0b24SGabriel Matute                                                    Context->getLangOpts());
215ecfa0b24SGabriel Matute       EXPECT_THAT(maybeExtendRange(Call, tok::TokenKind::semi, *Context),
216ecfa0b24SGabriel Matute                   EqualsAnnotatedRange(Context, Code.range("r")));
217ecfa0b24SGabriel Matute       return true;
218ecfa0b24SGabriel Matute     }
219ecfa0b24SGabriel Matute   };
220ecfa0b24SGabriel Matute   ExtendCharRangeVisitor Visitor;
221ecfa0b24SGabriel Matute   // Extends to include semicolon.
222ecfa0b24SGabriel Matute   Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }");
223ecfa0b24SGabriel Matute   // Does not extend to include semicolon.
224ecfa0b24SGabriel Matute   Visitor.runOverAnnotated(
225ecfa0b24SGabriel Matute       "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }");
226ecfa0b24SGabriel Matute }
227ecfa0b24SGabriel Matute 
TEST(SourceCodeTest,getAssociatedRange)22838b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRange) {
22938b4516dSYitzhak Mandelbaum   struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> {
23038b4516dSYitzhak Mandelbaum     bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); }
23138b4516dSYitzhak Mandelbaum   };
23238b4516dSYitzhak Mandelbaum   VarDeclsVisitor Visitor;
23338b4516dSYitzhak Mandelbaum 
23438b4516dSYitzhak Mandelbaum   // Includes semicolon.
23538b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[int x = 4;]]");
23638b4516dSYitzhak Mandelbaum 
23738b4516dSYitzhak Mandelbaum   // Includes newline and semicolon.
23838b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[int x = 4;\n]]");
23938b4516dSYitzhak Mandelbaum 
24038b4516dSYitzhak Mandelbaum   // Includes trailing comments.
24138b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[int x = 4; // Comment\n]]");
24238b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[int x = 4; /* Comment */\n]]");
24338b4516dSYitzhak Mandelbaum 
24438b4516dSYitzhak Mandelbaum   // Does *not* include trailing comments when another entity appears between
24538b4516dSYitzhak Mandelbaum   // the decl and the comment.
24638b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[int x = 4;]] class C {}; // Comment\n");
24738b4516dSYitzhak Mandelbaum 
24838b4516dSYitzhak Mandelbaum   // Includes attributes.
24938b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated(R"cpp(
25038b4516dSYitzhak Mandelbaum       #define ATTR __attribute__((deprecated("message")))
25138b4516dSYitzhak Mandelbaum       $r[[ATTR
25238b4516dSYitzhak Mandelbaum       int x;]])cpp");
25338b4516dSYitzhak Mandelbaum 
25438b4516dSYitzhak Mandelbaum   // Includes attributes and comments together.
25538b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated(R"cpp(
25638b4516dSYitzhak Mandelbaum       #define ATTR __attribute__((deprecated("message")))
25738b4516dSYitzhak Mandelbaum       $r[[ATTR
25838b4516dSYitzhak Mandelbaum       // Commment.
25938b4516dSYitzhak Mandelbaum       int x;]])cpp");
26038b4516dSYitzhak Mandelbaum }
26138b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,getAssociatedRangeClasses)26238b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeClasses) {
26338b4516dSYitzhak Mandelbaum   struct RecordDeclsVisitor : AnnotatedCodeVisitor<RecordDeclsVisitor> {
26438b4516dSYitzhak Mandelbaum     bool VisitRecordDecl(RecordDecl *Decl) { return VisitDeclHelper(Decl); }
26538b4516dSYitzhak Mandelbaum   };
26638b4516dSYitzhak Mandelbaum   RecordDeclsVisitor Visitor;
26738b4516dSYitzhak Mandelbaum 
26838b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[class A;]]");
26938b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[class A {};]]");
27038b4516dSYitzhak Mandelbaum 
27138b4516dSYitzhak Mandelbaum   // Includes leading template annotation.
27238b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[template <typename T> class A;]]");
27338b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[template <typename T> class A {};]]");
27438b4516dSYitzhak Mandelbaum }
27538b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,getAssociatedRangeClassTemplateSpecializations)27638b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) {
27738b4516dSYitzhak Mandelbaum   struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor<CXXRecordDeclsVisitor> {
27838b4516dSYitzhak Mandelbaum     bool VisitCXXRecordDecl(CXXRecordDecl *Decl) {
27938b4516dSYitzhak Mandelbaum       return Decl->getTemplateSpecializationKind() !=
28038b4516dSYitzhak Mandelbaum                  TSK_ExplicitSpecialization ||
28138b4516dSYitzhak Mandelbaum              VisitDeclHelper(Decl);
28238b4516dSYitzhak Mandelbaum     }
28338b4516dSYitzhak Mandelbaum   };
28438b4516dSYitzhak Mandelbaum   CXXRecordDeclsVisitor Visitor;
28538b4516dSYitzhak Mandelbaum 
28638b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated(R"cpp(
28738b4516dSYitzhak Mandelbaum       template <typename T> class A{};
28838b4516dSYitzhak Mandelbaum       $r[[template <> class A<int>;]])cpp");
28938b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated(R"cpp(
29038b4516dSYitzhak Mandelbaum       template <typename T> class A{};
29138b4516dSYitzhak Mandelbaum       $r[[template <> class A<int> {};]])cpp");
29238b4516dSYitzhak Mandelbaum }
29338b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,getAssociatedRangeFunctions)29438b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeFunctions) {
29538b4516dSYitzhak Mandelbaum   struct FunctionDeclsVisitor : AnnotatedCodeVisitor<FunctionDeclsVisitor> {
29638b4516dSYitzhak Mandelbaum     bool VisitFunctionDecl(FunctionDecl *Decl) { return VisitDeclHelper(Decl); }
29738b4516dSYitzhak Mandelbaum   };
29838b4516dSYitzhak Mandelbaum   FunctionDeclsVisitor Visitor;
29938b4516dSYitzhak Mandelbaum 
30038b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[int f();]]");
30138b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[int f() { return 0; }]]");
30238b4516dSYitzhak Mandelbaum   // Includes leading template annotation.
30338b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[template <typename T> int f();]]");
30438b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated("$r[[template <typename T> int f() { return 0; }]]");
30538b4516dSYitzhak Mandelbaum }
30638b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,getAssociatedRangeMemberTemplates)30738b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) {
30838b4516dSYitzhak Mandelbaum   struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor<CXXMethodDeclsVisitor> {
30938b4516dSYitzhak Mandelbaum     bool VisitCXXMethodDecl(CXXMethodDecl *Decl) {
31038b4516dSYitzhak Mandelbaum       // Only consider the definition of the template.
31138b4516dSYitzhak Mandelbaum       return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl);
31238b4516dSYitzhak Mandelbaum     }
31338b4516dSYitzhak Mandelbaum   };
31438b4516dSYitzhak Mandelbaum   CXXMethodDeclsVisitor Visitor;
31538b4516dSYitzhak Mandelbaum 
31638b4516dSYitzhak Mandelbaum   Visitor.runOverAnnotated(R"cpp(
31738b4516dSYitzhak Mandelbaum       template <typename C>
31838b4516dSYitzhak Mandelbaum       struct A { template <typename T> int member(T v); };
31938b4516dSYitzhak Mandelbaum 
32038b4516dSYitzhak Mandelbaum       $r[[template <typename C>
32138b4516dSYitzhak Mandelbaum       template  <typename T>
32238b4516dSYitzhak Mandelbaum       int A<C>::member(T v) { return 0; }]])cpp");
32338b4516dSYitzhak Mandelbaum }
32438b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,getAssociatedRangeWithComments)32538b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeWithComments) {
32638b4516dSYitzhak Mandelbaum   struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> {
32738b4516dSYitzhak Mandelbaum     bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); }
32838b4516dSYitzhak Mandelbaum   };
32938b4516dSYitzhak Mandelbaum 
33038b4516dSYitzhak Mandelbaum   VarDeclsVisitor Visitor;
33138b4516dSYitzhak Mandelbaum   auto Visit = [&](llvm::StringRef AnnotatedCode) {
33238b4516dSYitzhak Mandelbaum     Visitor.runOverAnnotated(AnnotatedCode, {"-fparse-all-comments"});
33338b4516dSYitzhak Mandelbaum   };
33438b4516dSYitzhak Mandelbaum 
33538b4516dSYitzhak Mandelbaum   // Includes leading comments.
33638b4516dSYitzhak Mandelbaum   Visit("$r[[// Comment.\nint x = 4;]]");
33738b4516dSYitzhak Mandelbaum   Visit("$r[[// Comment.\nint x = 4;\n]]");
33838b4516dSYitzhak Mandelbaum   Visit("$r[[/* Comment.*/\nint x = 4;\n]]");
33938b4516dSYitzhak Mandelbaum   // ... even if separated by (extra) horizontal whitespace.
34038b4516dSYitzhak Mandelbaum   Visit("$r[[/* Comment.*/  \nint x = 4;\n]]");
34138b4516dSYitzhak Mandelbaum 
34238b4516dSYitzhak Mandelbaum   // Includes comments even in the presence of trailing whitespace.
34338b4516dSYitzhak Mandelbaum   Visit("$r[[// Comment.\nint x = 4;]]  ");
34438b4516dSYitzhak Mandelbaum 
34538b4516dSYitzhak Mandelbaum   // Includes comments when the declaration is followed by the beginning or end
34638b4516dSYitzhak Mandelbaum   // of a compound statement.
34738b4516dSYitzhak Mandelbaum   Visit(R"cpp(
34838b4516dSYitzhak Mandelbaum   void foo() {
34938b4516dSYitzhak Mandelbaum     $r[[/* C */
35038b4516dSYitzhak Mandelbaum     int x = 4;
35138b4516dSYitzhak Mandelbaum   ]]};)cpp");
35238b4516dSYitzhak Mandelbaum   Visit(R"cpp(
35338b4516dSYitzhak Mandelbaum   void foo() {
35438b4516dSYitzhak Mandelbaum     $r[[/* C */
35538b4516dSYitzhak Mandelbaum     int x = 4;
35638b4516dSYitzhak Mandelbaum    ]]{ class Foo {}; }
35738b4516dSYitzhak Mandelbaum    })cpp");
35838b4516dSYitzhak Mandelbaum 
35938b4516dSYitzhak Mandelbaum   // Includes comments inside macros (when decl is in the same macro).
36038b4516dSYitzhak Mandelbaum   Visit(R"cpp(
36138b4516dSYitzhak Mandelbaum       #define DECL /* Comment */ int x
36238b4516dSYitzhak Mandelbaum       $r[[DECL;]])cpp");
36338b4516dSYitzhak Mandelbaum 
36438b4516dSYitzhak Mandelbaum   // Does not include comments when only the decl or the comment come from a
36538b4516dSYitzhak Mandelbaum   // macro.
36638b4516dSYitzhak Mandelbaum   // FIXME: Change code to allow this.
36738b4516dSYitzhak Mandelbaum   Visit(R"cpp(
36838b4516dSYitzhak Mandelbaum       #define DECL int x
36938b4516dSYitzhak Mandelbaum       // Comment
37038b4516dSYitzhak Mandelbaum       $r[[DECL;]])cpp");
37138b4516dSYitzhak Mandelbaum   Visit(R"cpp(
37238b4516dSYitzhak Mandelbaum       #define COMMENT /* Comment */
37338b4516dSYitzhak Mandelbaum       COMMENT
37438b4516dSYitzhak Mandelbaum       $r[[int x;]])cpp");
37538b4516dSYitzhak Mandelbaum 
37638b4516dSYitzhak Mandelbaum   // Includes multi-line comments.
37738b4516dSYitzhak Mandelbaum   Visit(R"cpp(
37838b4516dSYitzhak Mandelbaum       $r[[/* multi
37938b4516dSYitzhak Mandelbaum        * line
38038b4516dSYitzhak Mandelbaum        * comment
38138b4516dSYitzhak Mandelbaum        */
38238b4516dSYitzhak Mandelbaum       int x;]])cpp");
38338b4516dSYitzhak Mandelbaum   Visit(R"cpp(
38438b4516dSYitzhak Mandelbaum       $r[[// multi
38538b4516dSYitzhak Mandelbaum       // line
38638b4516dSYitzhak Mandelbaum       // comment
38738b4516dSYitzhak Mandelbaum       int x;]])cpp");
38838b4516dSYitzhak Mandelbaum 
38938b4516dSYitzhak Mandelbaum   // Does not include comments separated by multiple empty lines.
39038b4516dSYitzhak Mandelbaum   Visit("// Comment.\n\n\n$r[[int x = 4;\n]]");
39138b4516dSYitzhak Mandelbaum   Visit("/* Comment.*/\n\n\n$r[[int x = 4;\n]]");
39238b4516dSYitzhak Mandelbaum 
39338b4516dSYitzhak Mandelbaum   // Does not include comments before a *series* of declarations.
39438b4516dSYitzhak Mandelbaum   Visit(R"cpp(
39538b4516dSYitzhak Mandelbaum       // Comment.
39638b4516dSYitzhak Mandelbaum       $r[[int x = 4;
39738b4516dSYitzhak Mandelbaum       ]]class foo {};)cpp");
39838b4516dSYitzhak Mandelbaum 
39938b4516dSYitzhak Mandelbaum   // Does not include IfThisThenThat comments
40038b4516dSYitzhak Mandelbaum   Visit("// LINT.IfChange.\n$r[[int x = 4;]]");
40138b4516dSYitzhak Mandelbaum   Visit("// LINT.ThenChange.\n$r[[int x = 4;]]");
40238b4516dSYitzhak Mandelbaum 
40338b4516dSYitzhak Mandelbaum   // Includes attributes.
40438b4516dSYitzhak Mandelbaum   Visit(R"cpp(
40538b4516dSYitzhak Mandelbaum       #define ATTR __attribute__((deprecated("message")))
40638b4516dSYitzhak Mandelbaum       $r[[ATTR
40738b4516dSYitzhak Mandelbaum       int x;]])cpp");
40838b4516dSYitzhak Mandelbaum 
40938b4516dSYitzhak Mandelbaum   // Includes attributes and comments together.
41038b4516dSYitzhak Mandelbaum   Visit(R"cpp(
41138b4516dSYitzhak Mandelbaum       #define ATTR __attribute__((deprecated("message")))
41238b4516dSYitzhak Mandelbaum       $r[[ATTR
41338b4516dSYitzhak Mandelbaum       // Commment.
41438b4516dSYitzhak Mandelbaum       int x;]])cpp");
41538b4516dSYitzhak Mandelbaum }
41638b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,getAssociatedRangeInvalidForPartialExpansions)41738b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) {
41838b4516dSYitzhak Mandelbaum   struct FailingVarDeclsVisitor : TestVisitor<FailingVarDeclsVisitor> {
41938b4516dSYitzhak Mandelbaum     FailingVarDeclsVisitor() {}
42038b4516dSYitzhak Mandelbaum     bool VisitVarDecl(VarDecl *Decl) {
42138b4516dSYitzhak Mandelbaum       EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid());
42238b4516dSYitzhak Mandelbaum       return true;
42338b4516dSYitzhak Mandelbaum     }
42438b4516dSYitzhak Mandelbaum   };
42538b4516dSYitzhak Mandelbaum 
42638b4516dSYitzhak Mandelbaum   FailingVarDeclsVisitor Visitor;
42738b4516dSYitzhak Mandelbaum   // Should fail because it only includes a part of the expansion.
42838b4516dSYitzhak Mandelbaum   std::string Code = R"cpp(
42938b4516dSYitzhak Mandelbaum       #define DECL class foo { }; int x
43038b4516dSYitzhak Mandelbaum       DECL;)cpp";
43138b4516dSYitzhak Mandelbaum   Visitor.runOver(Code);
43238b4516dSYitzhak Mandelbaum }
43338b4516dSYitzhak Mandelbaum 
TEST(SourceCodeTest,EditRangeWithMacroExpansionsShouldSucceed)4342e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditRangeWithMacroExpansionsShouldSucceed) {
4352e97a1e1SYitzhak Mandelbaum   // The call expression, whose range we are extracting, includes two macro
4362e97a1e1SYitzhak Mandelbaum   // expansions.
4372e97a1e1SYitzhak Mandelbaum   llvm::Annotations Code(R"cpp(
4382e97a1e1SYitzhak Mandelbaum #define M(a) a * 13
4392e97a1e1SYitzhak Mandelbaum int foo(int x, int y);
4402e97a1e1SYitzhak Mandelbaum int a = $r[[foo(M(1), M(2))]];
4412e97a1e1SYitzhak Mandelbaum )cpp");
4422e97a1e1SYitzhak Mandelbaum 
4432e97a1e1SYitzhak Mandelbaum   CallsVisitor Visitor;
4442e97a1e1SYitzhak Mandelbaum 
4452e97a1e1SYitzhak Mandelbaum   Visitor.OnCall = [&Code](CallExpr *CE, ASTContext *Context) {
4462e97a1e1SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(CE->getSourceRange());
4472e97a1e1SYitzhak Mandelbaum     EXPECT_THAT(getRangeForEdit(Range, *Context),
4482e97a1e1SYitzhak Mandelbaum                 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
4492e97a1e1SYitzhak Mandelbaum   };
4502e97a1e1SYitzhak Mandelbaum   Visitor.runOver(Code.code());
4512e97a1e1SYitzhak Mandelbaum }
4522e97a1e1SYitzhak Mandelbaum 
TEST(SourceCodeTest,EditWholeMacroExpansionShouldSucceed)4532e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroExpansionShouldSucceed) {
4542e97a1e1SYitzhak Mandelbaum   llvm::Annotations Code(R"cpp(
4552e97a1e1SYitzhak Mandelbaum #define FOO 10
4562e97a1e1SYitzhak Mandelbaum int a = $r[[FOO]];
4572e97a1e1SYitzhak Mandelbaum )cpp");
4582e97a1e1SYitzhak Mandelbaum 
4592e97a1e1SYitzhak Mandelbaum   IntLitVisitor Visitor;
4602e97a1e1SYitzhak Mandelbaum   Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {
4612e97a1e1SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
4622e97a1e1SYitzhak Mandelbaum     EXPECT_THAT(getRangeForEdit(Range, *Context),
4632e97a1e1SYitzhak Mandelbaum                 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
4642e97a1e1SYitzhak Mandelbaum   };
4652e97a1e1SYitzhak Mandelbaum   Visitor.runOver(Code.code());
4662e97a1e1SYitzhak Mandelbaum }
4672e97a1e1SYitzhak Mandelbaum 
TEST(SourceCodeTest,EditPartialMacroExpansionShouldFail)4682e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditPartialMacroExpansionShouldFail) {
4692e97a1e1SYitzhak Mandelbaum   std::string Code = R"cpp(
4702e97a1e1SYitzhak Mandelbaum #define BAR 10+
4712e97a1e1SYitzhak Mandelbaum int c = BAR 3.0;
4722e97a1e1SYitzhak Mandelbaum )cpp";
4732e97a1e1SYitzhak Mandelbaum 
4742e97a1e1SYitzhak Mandelbaum   IntLitVisitor Visitor;
4752e97a1e1SYitzhak Mandelbaum   Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
4762e97a1e1SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
477*b8df4093SKazu Hirata     EXPECT_FALSE(getRangeForEdit(Range, *Context));
4782e97a1e1SYitzhak Mandelbaum   };
4792e97a1e1SYitzhak Mandelbaum   Visitor.runOver(Code);
4802e97a1e1SYitzhak Mandelbaum }
4812e97a1e1SYitzhak Mandelbaum 
TEST(SourceCodeTest,EditWholeMacroArgShouldSucceed)4822e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroArgShouldSucceed) {
4832e97a1e1SYitzhak Mandelbaum   llvm::Annotations Code(R"cpp(
4842e97a1e1SYitzhak Mandelbaum #define FOO(a) a + 7.0;
4852e97a1e1SYitzhak Mandelbaum int a = FOO($r[[10]]);
4862e97a1e1SYitzhak Mandelbaum )cpp");
4872e97a1e1SYitzhak Mandelbaum 
4882e97a1e1SYitzhak Mandelbaum   IntLitVisitor Visitor;
4892e97a1e1SYitzhak Mandelbaum   Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {
4902e97a1e1SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
4912e97a1e1SYitzhak Mandelbaum     EXPECT_THAT(getRangeForEdit(Range, *Context),
4922e97a1e1SYitzhak Mandelbaum                 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
4932e97a1e1SYitzhak Mandelbaum   };
4942e97a1e1SYitzhak Mandelbaum   Visitor.runOver(Code.code());
4952e97a1e1SYitzhak Mandelbaum }
4962e97a1e1SYitzhak Mandelbaum 
TEST(SourceCodeTest,EditPartialMacroArgShouldSucceed)4972e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditPartialMacroArgShouldSucceed) {
4982e97a1e1SYitzhak Mandelbaum   llvm::Annotations Code(R"cpp(
4992e97a1e1SYitzhak Mandelbaum #define FOO(a) a + 7.0;
5002e97a1e1SYitzhak Mandelbaum int a = FOO($r[[10]] + 10.0);
5012e97a1e1SYitzhak Mandelbaum )cpp");
5022e97a1e1SYitzhak Mandelbaum 
5032e97a1e1SYitzhak Mandelbaum   IntLitVisitor Visitor;
5042e97a1e1SYitzhak Mandelbaum   Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {
5052e97a1e1SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
5062e97a1e1SYitzhak Mandelbaum     EXPECT_THAT(getRangeForEdit(Range, *Context),
5072e97a1e1SYitzhak Mandelbaum                 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
5082e97a1e1SYitzhak Mandelbaum   };
5092e97a1e1SYitzhak Mandelbaum   Visitor.runOver(Code.code());
5102e97a1e1SYitzhak Mandelbaum }
5112e97a1e1SYitzhak Mandelbaum 
TEST(SourceCodeTest,EditRangeWithMacroExpansionsIsValid)512b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditRangeWithMacroExpansionsIsValid) {
513b9d2bf38SYitzhak Mandelbaum   // The call expression, whose range we are extracting, includes two macro
514b9d2bf38SYitzhak Mandelbaum   // expansions.
515b9d2bf38SYitzhak Mandelbaum   llvm::StringRef Code = R"cpp(
516b9d2bf38SYitzhak Mandelbaum #define M(a) a * 13
517b9d2bf38SYitzhak Mandelbaum int foo(int x, int y);
518b9d2bf38SYitzhak Mandelbaum int a = foo(M(1), M(2));
519b9d2bf38SYitzhak Mandelbaum )cpp";
520b9d2bf38SYitzhak Mandelbaum 
521b9d2bf38SYitzhak Mandelbaum   CallsVisitor Visitor;
522b9d2bf38SYitzhak Mandelbaum 
523b9d2bf38SYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
524b9d2bf38SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(CE->getSourceRange());
525b9d2bf38SYitzhak Mandelbaum     EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
526b9d2bf38SYitzhak Mandelbaum                       Succeeded());
527b9d2bf38SYitzhak Mandelbaum   };
528b9d2bf38SYitzhak Mandelbaum   Visitor.runOver(Code);
529b9d2bf38SYitzhak Mandelbaum }
530b9d2bf38SYitzhak Mandelbaum 
TEST(SourceCodeTest,SpellingRangeOfMacroArgIsValid)531b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, SpellingRangeOfMacroArgIsValid) {
532b9d2bf38SYitzhak Mandelbaum   llvm::StringRef Code = R"cpp(
533b9d2bf38SYitzhak Mandelbaum #define FOO(a) a + 7.0;
534b9d2bf38SYitzhak Mandelbaum int a = FOO(10);
535b9d2bf38SYitzhak Mandelbaum )cpp";
536b9d2bf38SYitzhak Mandelbaum 
537b9d2bf38SYitzhak Mandelbaum   IntLitVisitor Visitor;
538b9d2bf38SYitzhak Mandelbaum   Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
539b9d2bf38SYitzhak Mandelbaum     SourceLocation ArgLoc =
540b9d2bf38SYitzhak Mandelbaum         Context->getSourceManager().getSpellingLoc(Expr->getBeginLoc());
541b9d2bf38SYitzhak Mandelbaum     // The integer literal is a single token.
542b9d2bf38SYitzhak Mandelbaum     auto ArgRange = CharSourceRange::getTokenRange(ArgLoc);
543b9d2bf38SYitzhak Mandelbaum     EXPECT_THAT_ERROR(validateEditRange(ArgRange, Context->getSourceManager()),
544b9d2bf38SYitzhak Mandelbaum                       Succeeded());
545b9d2bf38SYitzhak Mandelbaum   };
546b9d2bf38SYitzhak Mandelbaum   Visitor.runOver(Code);
547b9d2bf38SYitzhak Mandelbaum }
548b9d2bf38SYitzhak Mandelbaum 
TEST(SourceCodeTest,InvalidEditRangeIsInvalid)549b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, InvalidEditRangeIsInvalid) {
550b9d2bf38SYitzhak Mandelbaum   llvm::StringRef Code = "int c = 10;";
551b9d2bf38SYitzhak Mandelbaum 
552b9d2bf38SYitzhak Mandelbaum   // We use the visitor just to get a valid context.
553b9d2bf38SYitzhak Mandelbaum   IntLitVisitor Visitor;
554b9d2bf38SYitzhak Mandelbaum   Visitor.OnIntLit = [](IntegerLiteral *, ASTContext *Context) {
555b9d2bf38SYitzhak Mandelbaum     CharSourceRange Invalid;
556b9d2bf38SYitzhak Mandelbaum     EXPECT_THAT_ERROR(validateEditRange(Invalid, Context->getSourceManager()),
557b9d2bf38SYitzhak Mandelbaum                       Failed());
558b9d2bf38SYitzhak Mandelbaum   };
559b9d2bf38SYitzhak Mandelbaum   Visitor.runOver(Code);
560b9d2bf38SYitzhak Mandelbaum }
561b9d2bf38SYitzhak Mandelbaum 
TEST(SourceCodeTest,InvertedEditRangeIsInvalid)562b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, InvertedEditRangeIsInvalid) {
563b9d2bf38SYitzhak Mandelbaum   llvm::StringRef Code = R"cpp(
564b9d2bf38SYitzhak Mandelbaum int foo(int x);
565b9d2bf38SYitzhak Mandelbaum int a = foo(2);
566b9d2bf38SYitzhak Mandelbaum )cpp";
567b9d2bf38SYitzhak Mandelbaum 
568b9d2bf38SYitzhak Mandelbaum   CallsVisitor Visitor;
569b9d2bf38SYitzhak Mandelbaum   Visitor.OnCall = [](CallExpr *Expr, ASTContext *Context) {
570b9d2bf38SYitzhak Mandelbaum     auto InvertedRange = CharSourceRange::getTokenRange(
571b9d2bf38SYitzhak Mandelbaum         SourceRange(Expr->getEndLoc(), Expr->getBeginLoc()));
572b9d2bf38SYitzhak Mandelbaum     EXPECT_THAT_ERROR(
573b9d2bf38SYitzhak Mandelbaum         validateEditRange(InvertedRange, Context->getSourceManager()),
574b9d2bf38SYitzhak Mandelbaum         Failed());
575b9d2bf38SYitzhak Mandelbaum   };
576b9d2bf38SYitzhak Mandelbaum   Visitor.runOver(Code);
577b9d2bf38SYitzhak Mandelbaum }
578b9d2bf38SYitzhak Mandelbaum 
TEST(SourceCodeTest,MacroArgIsInvalid)579b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, MacroArgIsInvalid) {
580b9d2bf38SYitzhak Mandelbaum   llvm::StringRef Code = R"cpp(
581b9d2bf38SYitzhak Mandelbaum #define FOO(a) a + 7.0;
582b9d2bf38SYitzhak Mandelbaum int a = FOO(10);
583b9d2bf38SYitzhak Mandelbaum )cpp";
584b9d2bf38SYitzhak Mandelbaum 
585b9d2bf38SYitzhak Mandelbaum   IntLitVisitor Visitor;
586b9d2bf38SYitzhak Mandelbaum   Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
587b9d2bf38SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
588b9d2bf38SYitzhak Mandelbaum     EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
589b9d2bf38SYitzhak Mandelbaum                       Failed());
590b9d2bf38SYitzhak Mandelbaum   };
591b9d2bf38SYitzhak Mandelbaum   Visitor.runOver(Code);
592b9d2bf38SYitzhak Mandelbaum }
593b9d2bf38SYitzhak Mandelbaum 
TEST(SourceCodeTest,EditWholeMacroExpansionIsInvalid)594b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroExpansionIsInvalid) {
595b9d2bf38SYitzhak Mandelbaum   llvm::StringRef Code = R"cpp(
596b9d2bf38SYitzhak Mandelbaum #define FOO 10
597b9d2bf38SYitzhak Mandelbaum int a = FOO;
598b9d2bf38SYitzhak Mandelbaum )cpp";
599b9d2bf38SYitzhak Mandelbaum 
600b9d2bf38SYitzhak Mandelbaum   IntLitVisitor Visitor;
601b9d2bf38SYitzhak Mandelbaum   Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
602b9d2bf38SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
603b9d2bf38SYitzhak Mandelbaum     EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
604b9d2bf38SYitzhak Mandelbaum                       Failed());
605b9d2bf38SYitzhak Mandelbaum 
606b9d2bf38SYitzhak Mandelbaum   };
607b9d2bf38SYitzhak Mandelbaum   Visitor.runOver(Code);
608b9d2bf38SYitzhak Mandelbaum }
609b9d2bf38SYitzhak Mandelbaum 
TEST(SourceCodeTest,EditPartialMacroExpansionIsInvalid)610b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditPartialMacroExpansionIsInvalid) {
611b9d2bf38SYitzhak Mandelbaum   llvm::StringRef Code = R"cpp(
612b9d2bf38SYitzhak Mandelbaum #define BAR 10+
613b9d2bf38SYitzhak Mandelbaum int c = BAR 3.0;
614b9d2bf38SYitzhak Mandelbaum )cpp";
615b9d2bf38SYitzhak Mandelbaum 
616b9d2bf38SYitzhak Mandelbaum   IntLitVisitor Visitor;
617b9d2bf38SYitzhak Mandelbaum   Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
618b9d2bf38SYitzhak Mandelbaum     auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
619b9d2bf38SYitzhak Mandelbaum     EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
620b9d2bf38SYitzhak Mandelbaum                       Failed());
621b9d2bf38SYitzhak Mandelbaum   };
622b9d2bf38SYitzhak Mandelbaum   Visitor.runOver(Code);
623b9d2bf38SYitzhak Mandelbaum }
6246e519910SBalázs Kéri 
TEST(SourceCodeTest,GetCallReturnType_Dependent)6256e519910SBalázs Kéri TEST(SourceCodeTest, GetCallReturnType_Dependent) {
6266e519910SBalázs Kéri   llvm::Annotations Code{R"cpp(
6276e519910SBalázs Kéri template<class T, class F>
6286e519910SBalázs Kéri void templ(const T& t, F f) {}
6296e519910SBalázs Kéri 
6306e519910SBalázs Kéri template<class T, class F>
6316e519910SBalázs Kéri void templ1(const T& t, F f) {
6326e519910SBalázs Kéri   $test1[[f(t)]];
6336e519910SBalázs Kéri }
6346e519910SBalázs Kéri 
6356e519910SBalázs Kéri int f_overload(int) { return 1; }
6366e519910SBalázs Kéri int f_overload(double) { return 2; }
6376e519910SBalázs Kéri 
6386e519910SBalázs Kéri void f1() {
6396e519910SBalázs Kéri   int i = 0;
6406e519910SBalázs Kéri   templ(i, [](const auto &p) {
6416e519910SBalázs Kéri     $test2[[f_overload(p)]];
6426e519910SBalázs Kéri   });
6436e519910SBalázs Kéri }
6446e519910SBalázs Kéri 
6456e519910SBalázs Kéri struct A {
6466e519910SBalázs Kéri   void f_overload(int);
6476e519910SBalázs Kéri   void f_overload(double);
6486e519910SBalázs Kéri };
6496e519910SBalázs Kéri 
6506e519910SBalázs Kéri void f2() {
6516e519910SBalázs Kéri  int i = 0;
6526e519910SBalázs Kéri  templ(i, [](const auto &p) {
6536e519910SBalázs Kéri    A a;
6546e519910SBalázs Kéri    $test3[[a.f_overload(p)]];
6556e519910SBalázs Kéri  });
6566e519910SBalázs Kéri }
6576e519910SBalázs Kéri )cpp"};
6586e519910SBalázs Kéri 
6596e519910SBalázs Kéri   llvm::Annotations::Range R1 = Code.range("test1");
6606e519910SBalázs Kéri   llvm::Annotations::Range R2 = Code.range("test2");
6616e519910SBalázs Kéri   llvm::Annotations::Range R3 = Code.range("test3");
6626e519910SBalázs Kéri 
6636e519910SBalázs Kéri   CallsVisitor Visitor;
6646e519910SBalázs Kéri   Visitor.OnCall = [&R1, &R2, &R3](CallExpr *Expr, ASTContext *Context) {
6656e519910SBalázs Kéri     unsigned Begin = Context->getSourceManager().getFileOffset(
6666e519910SBalázs Kéri         Expr->getSourceRange().getBegin());
6676e519910SBalázs Kéri     unsigned End = Context->getSourceManager().getFileOffset(
6686e519910SBalázs Kéri         Expr->getSourceRange().getEnd());
6696e519910SBalázs Kéri     llvm::Annotations::Range R{Begin, End + 1};
6706e519910SBalázs Kéri 
6716e519910SBalázs Kéri     QualType CalleeType = Expr->getCallee()->getType();
6726e519910SBalázs Kéri     if (R == R1) {
6736e519910SBalázs Kéri       ASSERT_TRUE(CalleeType->isDependentType());
6746e519910SBalázs Kéri       EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);
6756e519910SBalázs Kéri     } else if (R == R2) {
6766e519910SBalázs Kéri       ASSERT_FALSE(CalleeType->isDependentType());
6776e519910SBalázs Kéri       ASSERT_TRUE(CalleeType->isSpecificPlaceholderType(BuiltinType::Overload));
6786e519910SBalázs Kéri       ASSERT_TRUE(isa<UnresolvedLookupExpr>(Expr->getCallee()));
6796e519910SBalázs Kéri       EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);
6806e519910SBalázs Kéri     } else if (R == R3) {
6816e519910SBalázs Kéri       ASSERT_FALSE(CalleeType->isDependentType());
6826e519910SBalázs Kéri       ASSERT_TRUE(
6836e519910SBalázs Kéri           CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember));
6846e519910SBalázs Kéri       ASSERT_TRUE(isa<UnresolvedMemberExpr>(Expr->getCallee()));
6856e519910SBalázs Kéri       EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);
6866e519910SBalázs Kéri     }
6876e519910SBalázs Kéri   };
6886e519910SBalázs Kéri   Visitor.runOver(Code.code(), CallsVisitor::Lang_CXX14);
6896e519910SBalázs Kéri }
6906e519910SBalázs Kéri 
69184f2271aSYitzhak Mandelbaum } // end anonymous namespace
692