[clangd] Improve ObjC protocol suggestions from the index

When querying the index during an ObjC protocol name lookup for code
completion, we should only suggest ObjC protocols.

Differential Revision: https://reviews.llvm.org/D127125
This commit is contained in:
David Goldman 2022-06-06 12:19:32 -04:00
parent f3250da1b9
commit bc1f24332a
4 changed files with 56 additions and 2 deletions

View File

@ -1673,6 +1673,14 @@ private:
return Output;
}
bool includeSymbolFromIndex(const Symbol &Sym) {
if (CCContextKind == CodeCompletionContext::CCC_ObjCProtocolName) {
return Sym.SymInfo.Lang == index::SymbolLanguage::ObjC &&
Sym.SymInfo.Kind == index::SymbolKind::Protocol;
}
return true;
}
SymbolSlab queryIndex() {
trace::Span Tracer("Query index");
SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));
@ -1706,8 +1714,10 @@ private:
// Run the query against the index.
SymbolSlab::Builder ResultsBuilder;
if (Opts.Index->fuzzyFind(
Req, [&](const Symbol &Sym) { ResultsBuilder.insert(Sym); }))
if (Opts.Index->fuzzyFind(Req, [&](const Symbol &Sym) {
if (includeSymbolFromIndex(Sym))
ResultsBuilder.insert(Sym);
}))
Incomplete = true;
return std::move(ResultsBuilder).build();
}

View File

@ -3167,6 +3167,20 @@ TEST(CompletionTest, ObjectiveCMethodDeclarationFromMiddle) {
EXPECT_THAT(C, ElementsAre(signature("(id)object")));
}
TEST(CompletionTest, ObjectiveCProtocolFromIndex) {
Symbol FoodClass = objcClass("FoodClass");
Symbol SymFood = objcProtocol("Food");
Symbol SymFooey = objcProtocol("Fooey");
auto Results = completions(R"objc(
id<Foo^>
)objc",
{SymFood, FoodClass, SymFooey},
/*Opts=*/{}, "Foo.m");
auto C = Results.Completions;
EXPECT_THAT(C, UnorderedElementsAre(named("Food"), named("Fooey")));
}
TEST(CompletionTest, CursorInSnippets) {
clangd::CodeCompleteOptions Options;
Options.EnableSnippets = true;

View File

@ -81,6 +81,28 @@ Symbol conceptSym(llvm::StringRef Name) {
return sym(Name, index::SymbolKind::Concept, "@CT@\\0");
}
Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
llvm::StringRef USRPrefix) {
Symbol Sym;
std::string USR = USRPrefix.str() + Name.str();
Sym.Name = Name;
Sym.Scope = "";
Sym.ID = SymbolID(USR);
Sym.SymInfo.Kind = Kind;
Sym.SymInfo.Lang = index::SymbolLanguage::ObjC;
Sym.Flags |= Symbol::IndexedForCodeCompletion;
Sym.Origin = SymbolOrigin::Static;
return Sym;
}
Symbol objcClass(llvm::StringRef Name) {
return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
}
Symbol objcProtocol(llvm::StringRef Name) {
return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
}
SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames) {
SymbolSlab::Builder Slab;
for (llvm::StringRef QName : QualifiedNames)

View File

@ -34,6 +34,14 @@ Symbol ns(llvm::StringRef Name);
// Create a C++20 concept symbol.
Symbol conceptSym(llvm::StringRef Name);
// Create an Objective-C symbol.
Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
llvm::StringRef USRPrefix);
// Create an @interface or @implementation.
Symbol objcClass(llvm::StringRef Name);
// Create an @protocol.
Symbol objcProtocol(llvm::StringRef Name);
// Create a slab of symbols with the given qualified names as IDs and names.
SymbolSlab generateSymbols(std::vector<std::string> QualifiedNames);