diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -221,6 +221,14 @@ return Out.str(); } + if (const ObjCContainerDecl *C = dyn_cast(&ND)) + return printObjCContainer(*C); + if (const ObjCMethodDecl *Method = dyn_cast(&ND)) { + Out << (Method->isInstanceMethod() ? '-' : '+'); + Method->getSelector().print(Out); + return Out.str(); + } + if (isAnonymous(ND.getDeclName())) { // Come up with a presentation for an anonymous entity. if (isa(ND)) diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp --- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp @@ -848,6 +848,39 @@ SymRange(Main.range("forwardfunc"))))); } +TEST(DocumentSymbolsTest, ObjCCategoriesAndClassExtensions) { + TestTU TU; + TU.ExtraArgs = {"-xobjective-c++", "-Wno-objc-root-class"}; + Annotations Main(R"cpp( + $Cat[[@interface Cat + @end]] + $SneakyCat[[@interface Cat (Sneaky) + - (id)sneak:(id)behavior; + @end]] + + $MeowCat[[@interface Cat () + - (void)meow; + @end]] + $PurCat[[@interface Cat () + - (void)pur; + @end]] + )cpp"); + TU.Code = Main.code().str(); + EXPECT_THAT( + getSymbols(TU.build()), + ElementsAre( + AllOf(WithName("Cat"), SymRange(Main.range("Cat"))), + AllOf(WithName("Cat(Sneaky)"), SymRange(Main.range("SneakyCat")), + Children( + AllOf(WithName("-sneak:"), WithKind(SymbolKind::Method)))), + AllOf( + WithName("Cat()"), SymRange(Main.range("MeowCat")), + Children(AllOf(WithName("-meow"), WithKind(SymbolKind::Method)))), + AllOf(WithName("Cat()"), SymRange(Main.range("PurCat")), + Children( + AllOf(WithName("-pur"), WithKind(SymbolKind::Method)))))); +} + } // namespace } // namespace clangd } // namespace clang