Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.
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::functionOnCall; + 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.
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::functionOnCall; + + 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.
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::functionOnCall; + 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.
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.
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::functionOnCall; + 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 +++
Re: [PATCH] D13931: [Tooling] Add a utility function to replace one nested name with another.
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