diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp --- a/clang-tools-extra/clangd/FindSymbols.cpp +++ b/clang-tools-extra/clangd/FindSymbols.cpp @@ -172,6 +172,26 @@ } namespace { +std::string getSymbolName(ASTContext &Ctx, const NamedDecl &ND) { + // Print `MyClass(Category)` instead of `Category` and `MyClass()` instead + // of `anonymous`. + if (const auto *Container = dyn_cast(&ND)) + return printObjCContainer(*Container); + // Differentiate between class and instance methods: print `-foo` instead of + // `foo` and `+sharedInstance` instead of `sharedInstance`. + if (const auto *Method = dyn_cast(&ND)) { + std::string Name; + llvm::raw_string_ostream OS(Name); + + OS << (Method->isInstanceMethod() ? '-' : '+'); + Method->getSelector().print(OS); + + OS.flush(); + return Name; + } + return printName(Ctx, ND); +} + std::string getSymbolDetail(ASTContext &Ctx, const NamedDecl &ND) { PrintingPolicy P(Ctx.getPrintingPolicy()); P.SuppressScope = true; @@ -220,7 +240,7 @@ SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind); DocumentSymbol SI; - SI.name = printName(Ctx, ND); + SI.name = getSymbolName(Ctx, ND); SI.kind = SK; SI.deprecated = ND.isDeprecated(); SI.range = Range{sourceLocToPosition(SM, SymbolRange->getBegin()), 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 @@ -912,6 +912,42 @@ WithDetail("")))))); } +TEST(DocumentSymbolsTest, ObjCCategoriesAndClassExtensions) { + TestTU TU; + TU.ExtraArgs = {"-xobjective-c++", "-Wno-objc-root-class"}; + Annotations Main(R"cpp( + $Cat[[@interface Cat + + (id)sharedCat; + @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")), + Children(AllOf(WithName("+sharedCat"), + WithKind(SymbolKind::Method)))), + 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