[clangd] Improve document symbols support for Objective-C categories and methods

- Categories will now show up as `MyClass(Category)` instead of
  `Category` and `MyCategory()` instead of `(anonymous)` in document
  symbols

- Methods will now be shown as `-selector:` or `+selector:`
  instead of `selector:` to differentiate between instance and class
  methods in document symbols

Differential Revision: https://reviews.llvm.org/D96612
This commit is contained in:
David Goldman 2021-02-12 11:52:43 -05:00
parent 216dee9170
commit 5a2141e3a0
2 changed files with 57 additions and 1 deletions

View File

@ -172,6 +172,26 @@ getWorkspaceSymbols(llvm::StringRef Query, int Limit,
}
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<ObjCContainerDecl>(&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<ObjCMethodDecl>(&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 @@ llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const NamedDecl &ND) {
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()),

View File

@ -912,6 +912,42 @@ TEST(DocumentSymbolsTest, DependentType) {
WithDetail("<dependent type>"))))));
}
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