v1nh1shungry updated this revision to Diff 474808.
v1nh1shungry added a comment.

Apply the review suggestions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D137817/new/

https://reviews.llvm.org/D137817

Files:
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp

Index: clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
@@ -264,6 +264,39 @@
       }
       
       int main() { 1.5_w; }
+    )cpp"},
+      {// Add using-directives for user-defined literals
+       // declared in an inline namespace
+       R"cpp(
+namespace ns1 {
+inline namespace ns2 {
+long double operator "" _w(long double);
+}
+inline namespace ns3 {
+long double operator "" _h(long double);
+}
+}
+using namespace n^s1;
+int main() {
+  1.5_h;
+  1.5_w;
+}
+    )cpp",
+       R"cpp(
+namespace ns1 {
+inline namespace ns2 {
+long double operator "" _w(long double);
+}
+inline namespace ns3 {
+long double operator "" _h(long double);
+}
+}
+using namespace ns1::ns2;
+using namespace ns1::ns3;
+int main() {
+  1.5_h;
+  1.5_w;
+}
     )cpp"}};
   for (auto C : Cases)
     EXPECT_EQ(C.second, apply(C.first)) << C.first;
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===================================================================
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -54,6 +54,10 @@
       : TargetNS(Target.getNominatedNamespace()),
         TargetCtx(Target.getDeclContext()), Results(Results) {}
 
+  FindSameUsings(const NamespaceDecl *TargetNS, const DeclContext *TargetCtx,
+                 std::vector<const UsingDirectiveDecl *> &Results)
+      : TargetNS(TargetNS), TargetCtx(TargetCtx), Results(Results) {}
+
   bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
     if (D->getNominatedNamespace() != TargetNS ||
         D->getDeclContext() != TargetCtx)
@@ -101,6 +105,43 @@
   return D;
 }
 
+// If the user-defined literal is declared in an inline namespace,
+// we add a using-directive for it
+void handleUserDefinedLiteral(const DeclContext *D, const DeclContext *Ctx,
+                              ASTContext &AST, llvm::StringSet<> &UsingToAdd) {
+  if (D->isInlineNamespace()) {
+    const auto *ND = cast<NamespaceDecl>(D);
+    // Find if there is already a wanted using-directive,
+    // if there is, we are done. Otherwise we collect it
+    std::vector<const UsingDirectiveDecl *> AllDirectives;
+    FindSameUsings(ND, Ctx, AllDirectives).TraverseAST(AST);
+    if (AllDirectives.empty()) {
+      UsingToAdd.insert(ND->getQualifiedNameAsString());
+    }
+  }
+}
+
+// Produce edit adding 'using namespace xxx::yyy;'
+// for user-defined literals declared in an inline namespace
+llvm::Optional<tooling::Replacement>
+addUsingDirectives(const llvm::StringSet<> &UsingToAdd, SourceManager &SM,
+                   SourceLocation Loc) {
+  if (UsingToAdd.empty())
+    return llvm::None;
+  // FIXME: We simply join all the using-directives with newline,
+  //        so it can't handle indent. For now this is correct
+  //        because the code action only runs on the using-directive
+  //        declared in the top level
+  std::string Directives;
+  for (const auto &Using : UsingToAdd)
+    Directives += llvm::formatv("using namespace {0};\n", Using.getKey());
+  // Remove the trailing newline
+  Directives.pop_back();
+  // For now we insert the using-directives to where the first using-directive
+  // to remove stands
+  return tooling::Replacement(SM, Loc, 0, Directives);
+}
+
 bool RemoveUsingNamespace::prepare(const Selection &Inputs) {
   // Find the 'using namespace' directive under the cursor.
   auto *CA = Inputs.ASTSelection.commonAncestor();
@@ -144,6 +185,9 @@
   // Collect all references to symbols from the namespace for which we're
   // removing the directive.
   std::vector<SourceLocation> IdentsToQualify;
+  // Collect all namespaces' name to add for user-defined literals declared
+  // in an inline namespace
+  llvm::StringSet<> UsingToAdd;
   for (auto &D : Inputs.AST->getLocalTopLevelDecls()) {
     findExplicitReferences(
         D,
@@ -164,15 +208,19 @@
             // Avoid adding qualifiers before user-defined literals, e.g.
             //   using namespace std;
             //   auto s = "foo"s; // Must not changed to auto s = "foo" std::s;
-            // FIXME: Add a using-directive for user-defined literals
+            // And add a using-directive for user-defined literals
             // declared in an inline namespace, e.g.
             //   using namespace s^td;
             //   int main() { cout << "foo"s; }
             // change to
-            //   using namespace std::literals;
+            //   using namespace std::string_literals;
             //   int main() { std::cout << "foo"s; }
-            if (Kind == DeclarationName::NameKind::CXXLiteralOperatorName)
+            if (Kind == DeclarationName::NameKind::CXXLiteralOperatorName) {
+              handleUserDefinedLiteral(T->getDeclContext(),
+                                       TargetDirective->getDeclContext(), Ctx,
+                                       UsingToAdd);
               return;
+            }
           }
           SourceLocation Loc = Ref.NameLoc;
           if (Loc.isMacroID()) {
@@ -217,6 +265,11 @@
                                               /*Length=*/0, Qualifier)))
       return std::move(Err);
   }
+  // Produce replacements to add the using directives for user-defined literals
+  if (auto AddUsing =
+          addUsingDirectives(UsingToAdd, SM, FirstUsingDirectiveLoc))
+    if (auto Err = R.add(AddUsing.value()))
+      return std::move(Err);
   return Effect::mainFileEdit(SM, std::move(R));
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to