dgoldman updated this revision to Diff 445951. dgoldman added a comment. Minor grammar update to comment
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D130095/new/ https://reviews.llvm.org/D130095 Files: clang-tools-extra/clangd/AST.cpp clang-tools-extra/clangd/AST.h clang-tools-extra/clangd/XRefs.cpp clang-tools-extra/clangd/unittests/XRefsTests.cpp
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -957,6 +957,46 @@ Fo^o * getFoo() { return 0; } + )objc", + + R"objc(// Method decl and definition for ObjC class. + @interface Cat + - (void)$decl[[meow]]; + @end + @implementation Cat + - (void)$def[[meow]] {} + @end + void makeNoise(Cat *kitty) { + [kitty me^ow]; + } + )objc", + + R"objc(// Method decl and definition for ObjC category. + @interface Dog + @end + @interface Dog (Play) + - (void)$decl[[runAround]]; + @end + @implementation Dog (Play) + - (void)$def[[runAround]] {} + @end + void play(Dog *dog) { + [dog run^Around]; + } + )objc", + + R"objc(// Method decl and definition for ObjC class extension. + @interface Dog + @end + @interface Dog () + - (void)$decl[[howl]]; + @end + @implementation Dog + - (void)$def[[howl]] {} + @end + void play(Dog *dog) { + [dog ho^wl]; + } )objc"}; for (const char *Test : Tests) { Annotations T(Test); Index: clang-tools-extra/clangd/XRefs.cpp =================================================================== --- clang-tools-extra/clangd/XRefs.cpp +++ clang-tools-extra/clangd/XRefs.cpp @@ -83,32 +83,19 @@ if (const auto *CTD = dyn_cast<ClassTemplateDecl>(D)) if (const auto *RD = CTD->getTemplatedDecl()) return RD->getDefinition(); - // Objective-C classes can have three types of declarations: - // - // - forward declaration: @class MyClass; - // - true declaration (interface definition): @interface MyClass ... @end - // - true definition (implementation): @implementation MyClass ... @end - // - // Objective-C categories are extensions are on classes: - // - // - declaration: @interface MyClass (Ext) ... @end - // - definition: @implementation MyClass (Ext) ... @end - // - // With one special case, a class extension, which is normally used to keep - // some declarations internal to a file without exposing them in a header. - // - // - class extension declaration: @interface MyClass () ... @end - // - which really links to class definition: @implementation MyClass ... @end - if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) - return ID->getImplementation(); - if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) { - if (CD->IsClassExtension()) { - if (const auto *ID = CD->getClassInterface()) - return ID->getImplementation(); + if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { + if (MD->isThisDeclarationADefinition()) + return MD; + auto *DeclCtx = cast<Decl>(MD->getDeclContext()); + if (DeclCtx->isInvalidDecl()) return nullptr; - } - return CD->getImplementation(); + + if (const auto *CD = dyn_cast<ObjCContainerDecl>(DeclCtx)) + if (const auto *Impl = getCorrespondingObjCImpl(CD)) + return Impl->getMethod(MD->getSelector(), MD->isInstanceMethod()); } + if (const auto *CD = dyn_cast<ObjCContainerDecl>(D)) + return getCorrespondingObjCImpl(CD); // Only a single declaration is allowed. if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D)) // except cases above Index: clang-tools-extra/clangd/AST.h =================================================================== --- clang-tools-extra/clangd/AST.h +++ clang-tools-extra/clangd/AST.h @@ -93,6 +93,30 @@ SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI, const SourceManager &SM); +/// Return the corresponding implementation/definition for the given ObjC +/// container if it has one, otherwise, return nullptr. +/// +/// Objective-C classes can have three types of declarations: +/// +/// - forward declaration: @class MyClass; +/// - true declaration (interface definition): @interface MyClass ... @end +/// - true definition (implementation): @implementation MyClass ... @end +/// +/// Objective-C categories are extensions on classes: +/// +/// - declaration: @interface MyClass (Ext) ... @end +/// - definition: @implementation MyClass (Ext) ... @end +/// +/// With one special case, a class extension, which is normally used to keep +/// some declarations internal to a file without exposing them in a header. +/// +/// - class extension declaration: @interface MyClass () ... @end +/// - which really links to class definition: @implementation MyClass ... @end +/// +/// For Objective-C protocols, e.g. @protocol MyProtocol ... @end this will +/// return nullptr as protocols don't have an implementation. +const ObjCImplDecl *getCorrespondingObjCImpl(const ObjCContainerDecl *D); + /// Returns a QualType as string. The result doesn't contain unwritten scopes /// like anonymous/inline namespace. std::string printType(const QualType QT, const DeclContext &CurContext, Index: clang-tools-extra/clangd/AST.cpp =================================================================== --- clang-tools-extra/clangd/AST.cpp +++ clang-tools-extra/clangd/AST.cpp @@ -170,6 +170,9 @@ SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM) { auto L = D.getLocation(); + // For `- (void)foo` we want `foo` not the `-`. + if (const auto *MD = dyn_cast<ObjCMethodDecl>(&D)) + L = MD->getSelectorStartLoc(); if (isSpelledInSource(L, SM)) return SM.getSpellingLoc(L); return SM.getExpansionLoc(L); @@ -355,6 +358,20 @@ return SymbolID(USR); } +const ObjCImplDecl *getCorrespondingObjCImpl(const ObjCContainerDecl *D) { + if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) + return ID->getImplementation(); + if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) { + if (CD->IsClassExtension()) { + if (const auto *ID = CD->getClassInterface()) + return ID->getImplementation(); + return nullptr; + } + return CD->getImplementation(); + } + return nullptr; +} + std::string printType(const QualType QT, const DeclContext &CurContext, const llvm::StringRef Placeholder) { std::string Result;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits