1//===- unittest/Tooling/LookupTest.cpp ------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "TestVisitor.h"
11#include "clang/Tooling/Core/Lookup.h"
12using namespace clang;
13
14namespace {
15struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
16  std::function<void(CallExpr *)> OnCall;
17  SmallVector<Decl *, 4> DeclStack;
18
19  bool VisitCallExpr(CallExpr *Expr) {
20    OnCall(Expr);
21    return true;
22  }
23
24  bool TraverseDecl(Decl *D) {
25    DeclStack.push_back(D);
26    bool Ret = TestVisitor::TraverseDecl(D);
27    DeclStack.pop_back();
28    return Ret;
29  }
30};
31
32TEST(LookupTest, replaceNestedName) {
33  GetDeclsVisitor Visitor;
34
35  auto replaceCallExpr = [&](const CallExpr *Expr,
36                             StringRef ReplacementString) {
37    const auto *Callee = cast<DeclRefExpr>(Expr->getCallee()->IgnoreImplicit());
38    const ValueDecl *FD = Callee->getDecl();
39    return tooling::replaceNestedName(
40        Callee->getQualifier(), Visitor.DeclStack.back()->getDeclContext(), FD,
41        ReplacementString);
42  };
43
44  Visitor.OnCall = [&](CallExpr *Expr) {
45    EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
46  };
47  Visitor.runOver("namespace a { void foo(); }\n"
48                  "namespace a { void f() { foo(); } }\n");
49
50  Visitor.OnCall = [&](CallExpr *Expr) {
51    EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
52  };
53  Visitor.runOver("namespace a { void foo(); }\n"
54                  "namespace a { void f() { foo(); } }\n");
55
56  Visitor.OnCall = [&](CallExpr *Expr) {
57    EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
58  };
59  Visitor.runOver("namespace a { void foo(); }\n"
60                  "namespace b { void f() { a::foo(); } }\n");
61
62  Visitor.OnCall = [&](CallExpr *Expr) {
63    EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
64  };
65  Visitor.runOver("namespace a { void foo(); }\n"
66                  "namespace b { namespace a { void foo(); }\n"
67                  "void f() { a::foo(); } }\n");
68
69  Visitor.OnCall = [&](CallExpr *Expr) {
70    EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
71  };
72  Visitor.runOver("namespace a { namespace b { void foo(); }\n"
73                  "void f() { b::foo(); } }\n");
74
75  Visitor.OnCall = [&](CallExpr *Expr) {
76    EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
77  };
78  Visitor.runOver("namespace a { namespace b { void foo(); }\n"
79                  "void f() { b::foo(); } }\n");
80
81  Visitor.OnCall = [&](CallExpr *Expr) {
82    EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
83  };
84  Visitor.runOver("void foo(); void f() { foo(); }\n");
85
86  Visitor.OnCall = [&](CallExpr *Expr) {
87    EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
88  };
89  Visitor.runOver("void foo(); void f() { ::foo(); }\n");
90
91  Visitor.OnCall = [&](CallExpr *Expr) {
92    EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
93  };
94  Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
95
96  Visitor.OnCall = [&](CallExpr *Expr) {
97    EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
98  };
99  Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
100
101  Visitor.OnCall = [&](CallExpr *Expr) {
102    EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
103  };
104  Visitor.runOver(
105      "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
106}
107
108} // end anonymous namespace
109