dgoldman updated this revision to Diff 533640.
dgoldman added a comment.

Disable renaming categories


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,20 @@
           foo('x');
         }
       )cpp",
+
+      // ObjC class with a category.
+      R"cpp(
+        @interface [[Fo^o]]
+        @end
+        @implementation [[F^oo]]
+        @end
+        @interface [[Fo^o]] (Category)
+        @end
+        @implementation [[F^oo]] (Category)
+        @end
+
+        void func([[Fo^o]] *f) {}
+      )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -890,6 +904,14 @@
       )cpp",
        "not a supported kind", HeaderFile},
 
+      {R"cpp(// disallow - category rename.
+        @interface Foo
+        @end
+        @interface Foo (Cate^gory)
+        @end
+      )cpp",
+       "not a supported kind", HeaderFile},
+
       {
           R"cpp(
          #define MACRO 1
@@ -1468,7 +1490,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1579,12 @@
         }
       )cpp",
       },
-      {
-          // virtual templated method
-          R"cpp(
+      {// virtual templated method
+       R"cpp(
         template <typename> class Foo { virtual void [[m]](); };
         class Bar : Foo<int> { void [[^m]]() override; };
       )cpp",
-          R"cpp(
+       R"cpp(
           #include "foo.h"
 
           template<typename T> void Foo<T>::[[m]]() {}
@@ -1571,8 +1592,7 @@
           // the canonical Foo<T>::m().
           // https://github.com/clangd/clangd/issues/1325
           class Baz : Foo<float> { void m() override; };
-        )cpp"
-      },
+        )cpp"},
       {
           // rename on constructor and destructor.
           R"cpp(
@@ -1677,6 +1697,20 @@
         }
       )cpp",
       },
+      {
+          // Objective-C classes.
+          R"cpp(
+        @interface [[Fo^o]]
+        @end
+      )cpp",
+          R"cpp(
+        #include "foo.h"
+        @implementation [[F^oo]]
+        @end
+
+        void func([[Foo]] *f) {}
+      )cpp",
+      },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===================================================================
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ParentMapContext.h"
 #include "clang/AST/Stmt.h"
@@ -137,6 +138,10 @@
     if (const auto *TargetDecl = UD->getTargetDecl())
       return canonicalRenameDecl(TargetDecl);
   }
+  if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) {
+    if (const auto CI = CD->getClassInterface())
+      return canonicalRenameDecl(CI);
+  }
   return dyn_cast<NamedDecl>(D->getCanonicalDecl());
 }
 
@@ -278,6 +283,10 @@
           if (Ref.Targets.empty())
             return;
           for (const auto *Target : Ref.Targets) {
+            // Skip categories since we don't support renaming them, only
+            // the interface(s) which they reference.
+            if (isa<ObjCCategoryDecl, ObjCCategoryImplDecl>(Target))
+              continue;
             if (canonicalRenameDecl(Target) == &ND) {
               Results.push_back(Ref.NameLoc);
               return;
@@ -773,6 +782,12 @@
   if (Invalid)
     return makeError(std::move(*Invalid));
 
+  // We don't support renaming the category name, only ObjC top level container
+  // names like class and protocol names.
+  if (const auto *CD = dyn_cast<ObjCContainerDecl>(&RenameDecl))
+    if (CD->getName() != IdentifierToken->text(SM))
+      return makeError(ReasonToReject::UnsupportedSymbol);
+
   auto Reject =
       renameable(RenameDecl, RInputs.MainFilePath, RInputs.Index, Opts);
   if (Reject)
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -128,7 +128,7 @@
     return HighlightingKind::Class;
   if (isa<ObjCProtocolDecl>(D))
     return HighlightingKind::Interface;
-  if (isa<ObjCCategoryDecl>(D))
+  if (isa<ObjCCategoryDecl, ObjCCategoryImplDecl>(D))
     return HighlightingKind::Namespace;
   if (auto *MD = dyn_cast<CXXMethodDecl>(D))
     return MD->isStatic() ? HighlightingKind::StaticMethod
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -704,8 +704,24 @@
                                   {OCID->getClassInterface()}});
       Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
                                   OCID->getCategoryNameLoc(),
-                                  /*IsDecl=*/true,
+                                  /*IsDecl=*/false,
                                   {OCID->getCategoryDecl()}});
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  OCID->getCategoryNameLoc(),
+                                  /*IsDecl=*/true,
+                                  {OCID}});
+    }
+
+    void VisitObjCImplementationDecl(const ObjCImplementationDecl *OIMD) {
+      if (const auto *CI = OIMD->getClassInterface())
+        Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                    OIMD->getLocation(),
+                                    /*IsDecl=*/false,
+                                    {CI}});
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  OIMD->getLocation(),
+                                  /*IsDecl=*/true,
+                                  {OIMD}});
     }
   };
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to