LookupTest.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. //===- unittest/Tooling/LookupTest.cpp ------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "TestVisitor.h"
  9. #include "clang/Tooling/Core/Lookup.h"
  10. using namespace clang;
  11. namespace {
  12. struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
  13. std::function<void(CallExpr *)> OnCall;
  14. std::function<void(RecordTypeLoc)> OnRecordTypeLoc;
  15. SmallVector<Decl *, 4> DeclStack;
  16. bool VisitCallExpr(CallExpr *Expr) {
  17. if (OnCall)
  18. OnCall(Expr);
  19. return true;
  20. }
  21. bool VisitRecordTypeLoc(RecordTypeLoc Loc) {
  22. if (OnRecordTypeLoc)
  23. OnRecordTypeLoc(Loc);
  24. return true;
  25. }
  26. bool TraverseDecl(Decl *D) {
  27. DeclStack.push_back(D);
  28. bool Ret = TestVisitor::TraverseDecl(D);
  29. DeclStack.pop_back();
  30. return Ret;
  31. }
  32. };
  33. TEST(LookupTest, replaceNestedFunctionName) {
  34. GetDeclsVisitor Visitor;
  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(), Callee->getLocation(),
  41. Visitor.DeclStack.back()->getDeclContext(), FD, ReplacementString);
  42. };
  43. Visitor.OnCall = [&](CallExpr *Expr) {
  44. EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
  45. };
  46. Visitor.runOver("namespace a { void foo(); }\n"
  47. "namespace a { void f() { foo(); } }\n");
  48. Visitor.OnCall = [&](CallExpr *Expr) {
  49. EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
  50. };
  51. Visitor.runOver("namespace a { void foo(); }\n"
  52. "namespace a { void f() { foo(); } }\n");
  53. Visitor.OnCall = [&](CallExpr *Expr) {
  54. EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
  55. };
  56. Visitor.runOver("namespace a { void foo(); }\n"
  57. "namespace b { void f() { a::foo(); } }\n");
  58. Visitor.OnCall = [&](CallExpr *Expr) {
  59. EXPECT_EQ("::a::bar", replaceCallExpr(Expr, "::a::bar"));
  60. };
  61. Visitor.runOver("namespace a { void foo(); }\n"
  62. "namespace b { namespace a { void foo(); }\n"
  63. "void f() { a::foo(); } }\n");
  64. Visitor.OnCall = [&](CallExpr *Expr) {
  65. EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
  66. };
  67. Visitor.runOver("namespace a { namespace b { void foo(); }\n"
  68. "void f() { b::foo(); } }\n");
  69. Visitor.OnCall = [&](CallExpr *Expr) {
  70. EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
  71. };
  72. Visitor.runOver("namespace a { namespace b { void foo(); }\n"
  73. "void f() { b::foo(); } }\n");
  74. Visitor.OnCall = [&](CallExpr *Expr) {
  75. EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
  76. };
  77. Visitor.runOver("void foo(); void f() { foo(); }\n");
  78. Visitor.OnCall = [&](CallExpr *Expr) {
  79. EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
  80. };
  81. Visitor.runOver("void foo(); void f() { ::foo(); }\n");
  82. Visitor.OnCall = [&](CallExpr *Expr) {
  83. EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
  84. };
  85. Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
  86. Visitor.OnCall = [&](CallExpr *Expr) {
  87. EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
  88. };
  89. Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
  90. Visitor.OnCall = [&](CallExpr *Expr) {
  91. EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
  92. };
  93. Visitor.runOver(
  94. "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
  95. Visitor.OnCall = [&](CallExpr *Expr) {
  96. EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
  97. };
  98. Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
  99. "namespace a { namespace b { namespace {"
  100. "void f() { foo(); }"
  101. "} } }\n");
  102. Visitor.OnCall = [&](CallExpr *Expr) {
  103. EXPECT_EQ("x::bar", replaceCallExpr(Expr, "::a::x::bar"));
  104. };
  105. Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
  106. "namespace a { namespace b { namespace c {"
  107. "void f() { foo(); }"
  108. "} } }\n");
  109. // If the shortest name is ambiguous, we need to add more qualifiers.
  110. Visitor.OnCall = [&](CallExpr *Expr) {
  111. EXPECT_EQ("a::y::bar", replaceCallExpr(Expr, "::a::y::bar"));
  112. };
  113. Visitor.runOver(R"(
  114. namespace a {
  115. namespace b {
  116. namespace x { void foo() {} }
  117. namespace y { void foo() {} }
  118. }
  119. }
  120. namespace a {
  121. namespace b {
  122. void f() { x::foo(); }
  123. }
  124. })");
  125. Visitor.OnCall = [&](CallExpr *Expr) {
  126. // y::bar would be ambiguous due to "a::b::y".
  127. EXPECT_EQ("::y::bar", replaceCallExpr(Expr, "::y::bar"));
  128. };
  129. Visitor.runOver(R"(
  130. namespace a {
  131. namespace b {
  132. void foo() {}
  133. namespace y { }
  134. }
  135. }
  136. namespace a {
  137. namespace b {
  138. void f() { foo(); }
  139. }
  140. })");
  141. Visitor.OnCall = [&](CallExpr *Expr) {
  142. EXPECT_EQ("y::bar", replaceCallExpr(Expr, "::y::bar"));
  143. };
  144. Visitor.runOver(R"(
  145. namespace a {
  146. namespace b {
  147. namespace x { void foo() {} }
  148. namespace y { void foo() {} }
  149. }
  150. }
  151. void f() { a::b::x::foo(); }
  152. )");
  153. }
  154. TEST(LookupTest, replaceNestedClassName) {
  155. GetDeclsVisitor Visitor;
  156. auto replaceRecordTypeLoc = [&](RecordTypeLoc TLoc,
  157. StringRef ReplacementString) {
  158. const auto *FD = cast<CXXRecordDecl>(TLoc.getDecl());
  159. return tooling::replaceNestedName(
  160. nullptr, TLoc.getBeginLoc(), Visitor.DeclStack.back()->getDeclContext(),
  161. FD, ReplacementString);
  162. };
  163. Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
  164. // Filter Types by name since there are other `RecordTypeLoc` in the test
  165. // file.
  166. if (Type.getDecl()->getQualifiedNameAsString() == "a::b::Foo") {
  167. EXPECT_EQ("x::Bar", replaceRecordTypeLoc(Type, "::a::x::Bar"));
  168. }
  169. };
  170. Visitor.runOver("namespace a { namespace b {\n"
  171. "class Foo;\n"
  172. "namespace c { Foo f();; }\n"
  173. "} }\n");
  174. Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
  175. // Filter Types by name since there are other `RecordTypeLoc` in the test
  176. // file.
  177. // `a::b::Foo` in using shadow decl is not `TypeLoc`.
  178. if (Type.getDecl()->getQualifiedNameAsString() == "a::b::Foo") {
  179. EXPECT_EQ("Bar", replaceRecordTypeLoc(Type, "::a::x::Bar"));
  180. }
  181. };
  182. Visitor.runOver("namespace a { namespace b { class Foo {}; } }\n"
  183. "namespace c { using a::b::Foo; Foo f();; }\n");
  184. // Rename TypeLoc `x::y::Old` to new name `x::Foo` at [0] and check that the
  185. // type is replaced with "Foo" instead of "x::Foo". Although there is a symbol
  186. // `x::y::Foo` in c.cc [1], it should not make "Foo" at [0] ambiguous because
  187. // it's not visible at [0].
  188. Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
  189. if (Type.getDecl()->getQualifiedNameAsString() == "x::y::Old") {
  190. EXPECT_EQ("Foo", replaceRecordTypeLoc(Type, "::x::Foo"));
  191. }
  192. };
  193. Visitor.runOver(R"(
  194. // a.h
  195. namespace x {
  196. namespace y {
  197. class Old {};
  198. class Other {};
  199. }
  200. }
  201. // b.h
  202. namespace x {
  203. namespace y {
  204. // This is to be renamed to x::Foo
  205. // The expected replacement is "Foo".
  206. Old f; // [0].
  207. }
  208. }
  209. // c.cc
  210. namespace x {
  211. namespace y {
  212. using Foo = ::x::y::Other; // [1]
  213. }
  214. }
  215. )");
  216. }
  217. } // end anonymous namespace