Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.

2015-10-22 Thread Benjamin Kramer via cfe-commits
bkramer updated this revision to Diff 38130.
bkramer added a comment.

Enforce :: at the beginning of the new name.


http://reviews.llvm.org/D13931

Files:
  include/clang/Tooling/Core/Lookup.h
  lib/Tooling/Core/CMakeLists.txt
  lib/Tooling/Core/Lookup.cpp
  unittests/Tooling/CMakeLists.txt
  unittests/Tooling/LookupTest.cpp

Index: unittests/Tooling/LookupTest.cpp
===
--- /dev/null
+++ unittests/Tooling/LookupTest.cpp
@@ -0,0 +1,108 @@
+//===- unittest/Tooling/LookupTest.cpp ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TestVisitor.h"
+#include "clang/Tooling/Core/Lookup.h"
+using namespace clang;
+
+namespace {
+struct GetDeclsVisitor : TestVisitor {
+  std::function OnCall;
+  SmallVector DeclStack;
+
+  bool VisitCallExpr(CallExpr *Expr) {
+OnCall(Expr);
+return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+DeclStack.push_back(D);
+bool Ret = TestVisitor::TraverseDecl(D);
+DeclStack.pop_back();
+return Ret;
+  }
+};
+
+TEST(LookupTest, replaceNestedName) {
+  GetDeclsVisitor Visitor;
+
+  auto replaceCallExpr = [&](const CallExpr *Expr,
+ StringRef ReplacementString) {
+const auto *Callee = cast(Expr->getCallee()->IgnoreImplicit());
+const ValueDecl *FD = Callee->getDecl();
+return tooling::replaceNestedName(
+Callee->getQualifier(), Visitor.DeclStack.back()->getDeclContext(), FD,
+ReplacementString);
+  };
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { namespace a { void foo(); }\n"
+  "void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
+  };
+  Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+  "void f() { b::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+  "void f() { b::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+  };
+  Visitor.runOver("void foo(); void f() { foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
+  };
+  Visitor.runOver("void foo(); void f() { ::foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver(
+  "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
+}
+
+} // end anonymous namespace
Index: unittests/Tooling/CMakeLists.txt
===
--- unittests/Tooling/CMakeLists.txt
+++ unittests/Tooling/CMakeLists.txt
@@ -6,6 +6,7 @@
 add_clang_unittest(ToolingTests
   CommentHandlerTest.cpp
   CompilationDatabaseTest.cpp
+  LookupTest.cpp
   ToolingTest.cpp
   RecursiveASTVisitorTest.cpp
   RecursiveASTVisitorTestCallVisitor.cpp
Index: lib/Tooling/Core/Lookup.cpp
===
--- /dev/null
+++ lib/Tooling/Core/Lookup.cpp
@@ -0,0 +1,113 @@
+//===--- Lookup.cpp - Framework for clang refactoring tools ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//

Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.

2015-10-22 Thread Benjamin Kramer via cfe-commits
bkramer updated this revision to Diff 38117.
bkramer added a comment.

- Removed "fully qualified" in favor of just "qualified" to clarify that the 
name should be qualified but the leading "::" is not necessary.
- Renamed isNameSpecifierGlobal
- Removed always true conditional from test


http://reviews.llvm.org/D13931

Files:
  include/clang/Tooling/Core/Lookup.h
  lib/Tooling/Core/CMakeLists.txt
  lib/Tooling/Core/Lookup.cpp
  unittests/Tooling/CMakeLists.txt
  unittests/Tooling/LookupTest.cpp

Index: unittests/Tooling/LookupTest.cpp
===
--- /dev/null
+++ unittests/Tooling/LookupTest.cpp
@@ -0,0 +1,91 @@
+//===- unittest/Tooling/LookupTest.cpp ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TestVisitor.h"
+#include "clang/Tooling/Core/Lookup.h"
+using namespace clang;
+
+namespace {
+struct GetDeclsVisitor : TestVisitor {
+  std::function OnCall;
+
+  bool VisitCallExpr(CallExpr *Expr) {
+OnCall(Expr);
+return true;
+  }
+};
+
+static std::string replaceCallExpr(const CallExpr *Expr,
+   StringRef ReplacementString) {
+  const auto *Callee = cast(Expr->getCallee()->IgnoreImplicit());
+  const ValueDecl *FD = Callee->getDecl();
+  ASTContext  = FD->getASTContext();
+  const DeclContext *DC =
+  Context.getParents(ast_type_traits::DynTypedNode::create(*Expr))[0]
+  .get();
+  return tooling::replaceNestedName(Callee->getQualifier(), DC, FD,
+ReplacementString);
+}
+
+TEST(LookupTest, replaceNestedName) {
+  GetDeclsVisitor Visitor;
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { namespace a { void foo(); }\n"
+  "void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("void foo(); void f() { foo(); }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("::bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("void foo(); void f() { ::foo(); }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo()\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver(
+  "namespace a { int foo(); }\nusing a::foo;\nauto f = foo()\n");
+}
+
+} // end anonymous namespace
Index: unittests/Tooling/CMakeLists.txt
===
--- unittests/Tooling/CMakeLists.txt
+++ unittests/Tooling/CMakeLists.txt
@@ -6,6 +6,7 @@
 add_clang_unittest(ToolingTests
   CommentHandlerTest.cpp
   CompilationDatabaseTest.cpp
+  LookupTest.cpp
   ToolingTest.cpp
   RecursiveASTVisitorTest.cpp
   RecursiveASTVisitorTestCallVisitor.cpp
Index: lib/Tooling/Core/Lookup.cpp
===
--- /dev/null
+++ lib/Tooling/Core/Lookup.cpp
@@ -0,0 +1,106 @@
+//===--- Lookup.cpp - Framework for clang refactoring tools ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+//  This file defines helper methods for clang tools performing name lookup.
+//
+//===--===//
+
+#include "clang/Tooling/Core/Lookup.h"
+#include "clang/AST/Decl.h"
+using namespace clang;
+using namespace clang::tooling;
+
+static bool 

Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.

2015-10-22 Thread Benjamin Kramer via cfe-commits
bkramer updated this revision to Diff 38122.
bkramer added a comment.

Add more comments and polish test cases.


http://reviews.llvm.org/D13931

Files:
  include/clang/Tooling/Core/Lookup.h
  lib/Tooling/Core/CMakeLists.txt
  lib/Tooling/Core/Lookup.cpp
  unittests/Tooling/CMakeLists.txt
  unittests/Tooling/LookupTest.cpp

Index: unittests/Tooling/LookupTest.cpp
===
--- /dev/null
+++ unittests/Tooling/LookupTest.cpp
@@ -0,0 +1,102 @@
+//===- unittest/Tooling/LookupTest.cpp ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TestVisitor.h"
+#include "clang/Tooling/Core/Lookup.h"
+using namespace clang;
+
+namespace {
+struct GetDeclsVisitor : TestVisitor {
+  std::function OnCall;
+  SmallVector DeclStack;
+
+  bool VisitCallExpr(CallExpr *Expr) {
+OnCall(Expr);
+return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+DeclStack.push_back(D);
+bool Ret = TestVisitor::TraverseDecl(D);
+DeclStack.pop_back();
+return Ret;
+  }
+};
+
+TEST(LookupTest, replaceNestedName) {
+  GetDeclsVisitor Visitor;
+
+  auto replaceCallExpr = [&](const CallExpr *Expr,
+ StringRef ReplacementString) {
+const auto *Callee = cast(Expr->getCallee()->IgnoreImplicit());
+const ValueDecl *FD = Callee->getDecl();
+return tooling::replaceNestedName(
+Callee->getQualifier(), Visitor.DeclStack.back()->getDeclContext(), FD,
+ReplacementString);
+  };
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { namespace a { void foo(); }\n"
+  "void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+  "void f() { b::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("void foo(); void f() { foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("::bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("void foo(); void f() { ::foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver(
+  "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
+}
+
+} // end anonymous namespace
Index: unittests/Tooling/CMakeLists.txt
===
--- unittests/Tooling/CMakeLists.txt
+++ unittests/Tooling/CMakeLists.txt
@@ -6,6 +6,7 @@
 add_clang_unittest(ToolingTests
   CommentHandlerTest.cpp
   CompilationDatabaseTest.cpp
+  LookupTest.cpp
   ToolingTest.cpp
   RecursiveASTVisitorTest.cpp
   RecursiveASTVisitorTestCallVisitor.cpp
Index: lib/Tooling/Core/Lookup.cpp
===
--- /dev/null
+++ lib/Tooling/Core/Lookup.cpp
@@ -0,0 +1,112 @@
+//===--- Lookup.cpp - Framework for clang refactoring tools ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+//  This file defines helper methods for clang tools performing name lookup.
+//
+//===--===//
+
+#include "clang/Tooling/Core/Lookup.h"
+#include "clang/AST/Decl.h"

Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.

2015-10-22 Thread Manuel Klimek via cfe-commits
klimek accepted this revision.
klimek added a comment.
This revision is now accepted and ready to land.

lg


http://reviews.llvm.org/D13931



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.

2015-10-22 Thread Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL251022: [Tooling] Add a utility function to replace one 
nested name with another. (authored by d0k).

Changed prior to commit:
  http://reviews.llvm.org/D13931?vs=38130=38131#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D13931

Files:
  cfe/trunk/include/clang/Tooling/Core/Lookup.h
  cfe/trunk/lib/Tooling/Core/CMakeLists.txt
  cfe/trunk/lib/Tooling/Core/Lookup.cpp
  cfe/trunk/unittests/Tooling/CMakeLists.txt
  cfe/trunk/unittests/Tooling/LookupTest.cpp

Index: cfe/trunk/unittests/Tooling/CMakeLists.txt
===
--- cfe/trunk/unittests/Tooling/CMakeLists.txt
+++ cfe/trunk/unittests/Tooling/CMakeLists.txt
@@ -6,6 +6,7 @@
 add_clang_unittest(ToolingTests
   CommentHandlerTest.cpp
   CompilationDatabaseTest.cpp
+  LookupTest.cpp
   ToolingTest.cpp
   RecursiveASTVisitorTest.cpp
   RecursiveASTVisitorTestCallVisitor.cpp
Index: cfe/trunk/unittests/Tooling/LookupTest.cpp
===
--- cfe/trunk/unittests/Tooling/LookupTest.cpp
+++ cfe/trunk/unittests/Tooling/LookupTest.cpp
@@ -0,0 +1,108 @@
+//===- unittest/Tooling/LookupTest.cpp ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TestVisitor.h"
+#include "clang/Tooling/Core/Lookup.h"
+using namespace clang;
+
+namespace {
+struct GetDeclsVisitor : TestVisitor {
+  std::function OnCall;
+  SmallVector DeclStack;
+
+  bool VisitCallExpr(CallExpr *Expr) {
+OnCall(Expr);
+return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+DeclStack.push_back(D);
+bool Ret = TestVisitor::TraverseDecl(D);
+DeclStack.pop_back();
+return Ret;
+  }
+};
+
+TEST(LookupTest, replaceNestedName) {
+  GetDeclsVisitor Visitor;
+
+  auto replaceCallExpr = [&](const CallExpr *Expr,
+ StringRef ReplacementString) {
+const auto *Callee = cast(Expr->getCallee()->IgnoreImplicit());
+const ValueDecl *FD = Callee->getDecl();
+return tooling::replaceNestedName(
+Callee->getQualifier(), Visitor.DeclStack.back()->getDeclContext(), FD,
+ReplacementString);
+  };
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { namespace a { void foo(); }\n"
+  "void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
+  };
+  Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+  "void f() { b::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+  "void f() { b::foo(); } }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+  };
+  Visitor.runOver("void foo(); void f() { foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
+  };
+  Visitor.runOver("void foo(); void f() { ::foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+  };
+  Visitor.runOver(
+  "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
+}
+
+} // end anonymous namespace
Index: cfe/trunk/include/clang/Tooling/Core/Lookup.h
===
--- cfe/trunk/include/clang/Tooling/Core/Lookup.h
+++ 

[PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.

2015-10-21 Thread Benjamin Kramer via cfe-commits
bkramer created this revision.
bkramer added a reviewer: klimek.
bkramer added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

One problem in clang-tidy and other clang tools face is that there is no
way to lookup an arbitrary name in the AST, that's buried deep inside Sema
and might not even be what the user wants as the new name may be freshly
inserted and not available in the AST.

A common use case for lookups is replacing one nested name with another
while minimizing namespace qualifications, so replacing 'ns::foo' with
'ns::bar' will use just 'bar' if we happen to be inside the namespace 'ns'.
This adds a little helper utility for exactly that use case.

http://reviews.llvm.org/D13931

Files:
  include/clang/Tooling/Core/Lookup.h
  lib/Tooling/Core/CMakeLists.txt
  lib/Tooling/Core/Lookup.cpp
  unittests/Tooling/CMakeLists.txt
  unittests/Tooling/LookupTest.cpp

Index: unittests/Tooling/LookupTest.cpp
===
--- /dev/null
+++ unittests/Tooling/LookupTest.cpp
@@ -0,0 +1,92 @@
+//===- unittest/Tooling/LookupTest.cpp ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TestVisitor.h"
+#include "clang/Tooling/Core/Lookup.h"
+using namespace clang;
+
+namespace {
+struct GetDeclsVisitor : TestVisitor {
+  std::function OnCall;
+
+  bool VisitCallExpr(CallExpr *Expr) {
+if (OnCall)
+  OnCall(Expr);
+return true;
+  }
+};
+
+static std::string replaceCallExpr(const CallExpr *Expr,
+   StringRef ReplacementString) {
+  const auto *Callee = cast(Expr->getCallee()->IgnoreImplicit());
+  const ValueDecl *FD = Callee->getDecl();
+  ASTContext  = FD->getASTContext();
+  const DeclContext *DC =
+  Context.getParents(ast_type_traits::DynTypedNode::create(*Expr))[0]
+  .get();
+  return tooling::replaceNestedName(Callee->getQualifier(), DC, FD,
+ReplacementString);
+}
+
+TEST(LookupTest, replaceNestedName) {
+  GetDeclsVisitor Visitor;
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace a { void f() { foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\n"
+  "namespace b { namespace a { void foo(); }\n"
+  "void f() { a::foo(); } }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("void foo(); void f() { foo(); }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("::bar", replaceCallExpr(Expr, "bar"));
+  };
+  Visitor.runOver("void foo(); void f() { ::foo(); }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("a::bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo()\n");
+
+  Visitor.OnCall = [](CallExpr *Expr) {
+EXPECT_EQ("bar", replaceCallExpr(Expr, "a::bar"));
+  };
+  Visitor.runOver(
+  "namespace a { int foo(); }\nusing a::foo;\nauto f = foo()\n");
+}
+
+} // end anonymous namespace
Index: unittests/Tooling/CMakeLists.txt
===
--- unittests/Tooling/CMakeLists.txt
+++ unittests/Tooling/CMakeLists.txt
@@ -6,6 +6,7 @@
 add_clang_unittest(ToolingTests
   CommentHandlerTest.cpp
   CompilationDatabaseTest.cpp
+  LookupTest.cpp
   ToolingTest.cpp
   RecursiveASTVisitorTest.cpp
   RecursiveASTVisitorTestCallVisitor.cpp
Index: lib/Tooling/Core/Lookup.cpp
===
--- /dev/null
+++ lib/Tooling/Core/Lookup.cpp
@@ -0,0 +1,106 @@
+//===--- Lookup.cpp - Framework for clang refactoring tools ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//

Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.

2015-10-21 Thread Manuel Klimek via cfe-commits
klimek added inline comments.


Comment at: include/clang/Tooling/Core/Lookup.h:37-38
@@ +36,4 @@
+/// \param FromDecl The declaration to which the nested name points.
+/// \param ReplacementString The replacement nested name. Should be fully
+///  qualified.
+/// \returns The new name to be inserted in place of the current nested name.

Don't most tests violate the "should be fully qualified" requirement here?


Comment at: lib/Tooling/Core/Lookup.cpp:60
@@ +59,3 @@
+
+// Otherwise strip of redundant namespace qualifications from the new name.
+std::string NS =

s/of/off/


Comment at: lib/Tooling/Core/Lookup.cpp:63-66
@@ +62,6 @@
+cast(DeclA)->getQualifiedNameAsString() + "::";
+if (NewName.startswith("::"))
+  NS = "::" + NS;
+if (NewName.startswith(NS))
+  return NewName.substr(NS.size());
+DeclA = DeclA->getParent();

If NewName is fully qualified, why would we ever want to allow that to match 
from a non-global namespace?

namespace a { namespace b { namespace c {
void foo();
}}}

-> if NewName is "::c::bar" (for whatever reason), this should probably not 
silently go to bar inside 'c', or to c::bar inside 'b'.


Comment at: lib/Tooling/Core/Lookup.cpp:72
@@ +71,3 @@
+/// Check if the name specifier begins with a written "::".
+static bool isNameSpecifierGlobal(const NestedNameSpecifier *NNS) {
+  while (NNS) {

Isn't that more like isFullyQualified then?


Comment at: unittests/Tooling/LookupTest.cpp:19-20
@@ +18,4 @@
+  bool VisitCallExpr(CallExpr *Expr) {
+if (OnCall)
+  OnCall(Expr);
+return true;

Is this ever not true?


http://reviews.llvm.org/D13931



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits