From 46575f60380b18bf20c5f4cafc5fd06f561c4e7b Mon Sep 17 00:00:00 2001 From: v1nh1shungry Date: Wed, 28 Dec 2022 13:34:41 +0100 Subject: [PATCH] [clangd] Fix action `RemoveUsingNamespace` for inline namespace Existing version ignores symbols declared in an inline namespace `ns` when removing `using namespace ns` Reviewed By: tom-anders Differential Revision: https://reviews.llvm.org/D138028 --- .../clangd/refactor/tweaks/RemoveUsingNamespace.cpp | 20 +++++++++----------- .../unittests/tweaks/RemoveUsingNamespaceTests.cpp | 11 +++++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp b/clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp index f4228ae..ec02beb 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp @@ -89,16 +89,15 @@ bool isTopLevelDecl(const SelectionTree::Node *Node) { return Node->Parent && Node->Parent->ASTNode.get(); } -// Returns the first visible context that contains this DeclContext. -// For example: Returns ns1 for S1 and a. -// namespace ns1 { -// inline namespace ns2 { struct S1 {}; } -// enum E { a, b, c, d }; -// } -const DeclContext *visibleContext(const DeclContext *D) { - while (D->isInlineNamespace() || D->isTransparentContext()) +// Return true if `LHS` is declared in `RHS` +bool isDeclaredIn(const NamedDecl *LHS, const DeclContext *RHS) { + const auto *D = LHS->getDeclContext(); + while (D->isInlineNamespace() || D->isTransparentContext()) { + if (D->Equals(RHS)) + return true; D = D->getParent(); - return D; + } + return D->Equals(RHS); } bool RemoveUsingNamespace::prepare(const Selection &Inputs) { @@ -152,8 +151,7 @@ Expected RemoveUsingNamespace::apply(const Selection &Inputs) { return; // This reference is already qualified. for (auto *T : Ref.Targets) { - if (!visibleContext(T->getDeclContext()) - ->Equals(TargetDirective->getNominatedNamespace())) + if (!isDeclaredIn(T, TargetDirective->getNominatedNamespace())) return; auto Kind = T->getDeclName().getNameKind(); // Avoid adding qualifiers before operators, e.g. diff --git a/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp index 03a46d9..b031153 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp @@ -264,6 +264,17 @@ TEST_F(RemoveUsingNamespaceTest, All) { } int main() { 1.5_w; } + )cpp"}, + { + R"cpp( + namespace a { inline namespace b { void foobar(); } } + using namespace a::[[b]]; + int main() { foobar(); } + )cpp", + R"cpp( + namespace a { inline namespace b { void foobar(); } } + + int main() { a::b::foobar(); } )cpp"}}; for (auto C : Cases) EXPECT_EQ(C.second, apply(C.first)) << C.first; -- 2.7.4