diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/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}}); } }; diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -128,7 +128,7 @@ return HighlightingKind::Class; if (isa(D)) return HighlightingKind::Interface; - if (isa(D)) + if (isa(D)) return HighlightingKind::Namespace; if (auto *MD = dyn_cast(D)) return MD->isStatic() ? HighlightingKind::StaticMethod diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/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(D)) { + if (const auto CI = CD->getClassInterface()) + return canonicalRenameDecl(CI); + } return dyn_cast(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(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(&RenameDecl)) + if (CD->getName() != IdentifierToken->text(SM)) + return makeError(ReasonToReject::UnsupportedSymbol); + auto Reject = renameable(RenameDecl, RInputs.MainFilePath, RInputs.Index, Opts); if (Reject) diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/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 class Foo { virtual void [[m]](); }; class Bar : Foo { void [[^m]]() override; }; )cpp", - R"cpp( + R"cpp( #include "foo.h" template void Foo::[[m]]() {} @@ -1571,8 +1592,7 @@ // the canonical Foo::m(). // https://github.com/clangd/clangd/issues/1325 class Baz : Foo { 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;