diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -78,6 +78,18 @@ return VD->getDefinition(); if (const auto *FD = dyn_cast(D)) return FD->getDefinition(); + if (const auto *PD = dyn_cast(D)) + return PD->getDefinition(); + // Objective-C classes can have three types of declarations: + // + // - forward declaration: @class MyClass; + // - definition declaration: @interface MyClass ... @end + // - implementation: @implementation MyClass ... @end + if (const auto *ID = dyn_cast(D)) { + if (const auto *IMD = ID->getImplementation()) + return IMD; + return ID->getDefinition(); + } // Only a single declaration is allowed. if (isa(D) || isa(D) || isa(D)) // except cases above diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -674,7 +674,37 @@ enum class E { [[A]], B }; E e = E::A^; }; - )cpp"}; + )cpp", + + R"objc(//objc + @protocol $decl[[Dog]]; + @protocol $def[[Dog]] + - (void)bark; + @end + id getDoggo() { + return 0; + } + )objc", + + R"objc(//objc + @class $decl[[Foo]]; + @interface $def[[Foo]] + @end + Fo^o * getFoo() { + return 0; + } + )objc", + + R"objc(//objc + @class $decl[[Foo]]; + @interface Foo + @end + @implementation $def[[Foo]] + @end + Fo^o * getFoo() { + return 0; + } + )objc"}; for (const char *Test : Tests) { Annotations T(Test); llvm::Optional WantDecl; @@ -689,6 +719,11 @@ TestTU TU; TU.Code = std::string(T.code()); + std::string ObjcPrefix = "//objc"; + if (strncmp(Test, ObjcPrefix.c_str(), ObjcPrefix.size()) == 0) { + TU.Filename = "TestTU.m"; + } + // FIXME: Auto-completion in a template requires disabling delayed template // parsing. TU.ExtraArgs.push_back("-fno-delayed-template-parsing");