mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 06:10:12 +00:00
[clangd] Index unscoped enums in class scope for code completion
Fixes https://github.com/clangd/clangd/issues/1082 Differential Revision: https://reviews.llvm.org/D136925
This commit is contained in:
parent
2e36dadbd6
commit
a68bcd81dc
@ -2123,6 +2123,9 @@ bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {
|
||||
};
|
||||
return false;
|
||||
};
|
||||
auto InClassScope = [](const NamedDecl &ND) {
|
||||
return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
|
||||
};
|
||||
// We only complete symbol's name, which is the same as the name of the
|
||||
// *primary* template in case of template specializations.
|
||||
if (isExplicitTemplateSpecialization(&ND))
|
||||
@ -2138,8 +2141,11 @@ bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {
|
||||
if (InTopLevelScope(ND))
|
||||
return true;
|
||||
|
||||
// Always index enum constants, even if they're not in the top level scope:
|
||||
// when
|
||||
// --all-scopes-completion is set, we'll want to complete those as well.
|
||||
if (const auto *EnumDecl = dyn_cast<clang::EnumDecl>(ND.getDeclContext()))
|
||||
return InTopLevelScope(*EnumDecl) && !EnumDecl->isScoped();
|
||||
return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl)) && !EnumDecl->isScoped();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2967,14 +2967,20 @@ TEST(CompletionTest, AllScopesCompletion) {
|
||||
}
|
||||
)cpp",
|
||||
{cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
|
||||
cls("na::nb::Clangd4")},
|
||||
cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
|
||||
Opts);
|
||||
EXPECT_THAT(
|
||||
Results.Completions,
|
||||
UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1")),
|
||||
AllOf(qualifier("ny::"), named("Clangd2")),
|
||||
AllOf(qualifier(""), scope(""), named("Clangd3")),
|
||||
AllOf(qualifier("nb::"), named("Clangd4"))));
|
||||
UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),
|
||||
kind(CompletionItemKind::Class)),
|
||||
AllOf(qualifier("ny::"), named("Clangd2"),
|
||||
kind(CompletionItemKind::Class)),
|
||||
AllOf(qualifier(""), scope(""), named("Clangd3"),
|
||||
kind(CompletionItemKind::Class)),
|
||||
AllOf(qualifier("nb::"), named("Clangd4"),
|
||||
kind(CompletionItemKind::Class)),
|
||||
AllOf(qualifier("C::"), named("Clangd5"),
|
||||
kind(CompletionItemKind::EnumMember))));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, NoQualifierIfShadowed) {
|
||||
@ -3358,6 +3364,31 @@ TEST(CompletionTest, UsingDecl) {
|
||||
kind(CompletionItemKind::Reference))));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, Enums) {
|
||||
const char *Header(R"cpp(
|
||||
namespace ns {
|
||||
enum Unscoped { Clangd1 };
|
||||
class C {
|
||||
enum Unscoped { Clangd2 };
|
||||
};
|
||||
enum class Scoped { Clangd3 };
|
||||
})cpp");
|
||||
const char *Source(R"cpp(
|
||||
void bar() {
|
||||
Clangd^
|
||||
})cpp");
|
||||
auto Index = TestTU::withHeaderCode(Header).index();
|
||||
clangd::CodeCompleteOptions Opts;
|
||||
Opts.Index = Index.get();
|
||||
Opts.AllScopes = true;
|
||||
auto R = completions(Source, {}, Opts);
|
||||
EXPECT_THAT(R.Completions,
|
||||
ElementsAre(AllOf(scope("ns::"), named("Clangd1"),
|
||||
kind(CompletionItemKind::EnumMember)),
|
||||
AllOf(scope("ns::C::"), named("Clangd2"),
|
||||
kind(CompletionItemKind::EnumMember))));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, ScopeIsUnresolved) {
|
||||
clangd::CodeCompleteOptions Opts = {};
|
||||
Opts.AllScopes = true;
|
||||
|
@ -1316,6 +1316,11 @@ TEST_F(SymbolCollectorTest, IncludeEnums) {
|
||||
Black
|
||||
};
|
||||
}
|
||||
class Color3 {
|
||||
enum {
|
||||
Blue
|
||||
};
|
||||
};
|
||||
)";
|
||||
runSymbolCollector(Header, /*Main=*/"");
|
||||
EXPECT_THAT(Symbols,
|
||||
@ -1326,7 +1331,9 @@ TEST_F(SymbolCollectorTest, IncludeEnums) {
|
||||
AllOf(qName("Color2"), forCodeCompletion(true)),
|
||||
AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
|
||||
AllOf(qName("ns"), forCodeCompletion(true)),
|
||||
AllOf(qName("ns::Black"), forCodeCompletion(true))));
|
||||
AllOf(qName("ns::Black"), forCodeCompletion(true)),
|
||||
AllOf(qName("Color3"), forCodeCompletion(true)),
|
||||
AllOf(qName("Color3::Blue"), forCodeCompletion(true))));
|
||||
}
|
||||
|
||||
TEST_F(SymbolCollectorTest, NamelessSymbols) {
|
||||
|
@ -69,6 +69,10 @@ Symbol enm(llvm::StringRef Name) {
|
||||
return sym(Name, index::SymbolKind::Enum, "@E@\\0");
|
||||
}
|
||||
|
||||
Symbol enmConstant(llvm::StringRef Name) {
|
||||
return sym(Name, index::SymbolKind::EnumConstant, "@\\0");
|
||||
}
|
||||
|
||||
Symbol var(llvm::StringRef Name) {
|
||||
return sym(Name, index::SymbolKind::Variable, "@\\0");
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ Symbol func(llvm::StringRef Name);
|
||||
Symbol cls(llvm::StringRef Name);
|
||||
// Creates an enum symbol.
|
||||
Symbol enm(llvm::StringRef Name);
|
||||
// Creates an enum constant symbol.
|
||||
Symbol enmConstant(llvm::StringRef Name);
|
||||
// Creates a variable symbol.
|
||||
Symbol var(llvm::StringRef Name);
|
||||
// Creates a namespace symbol.
|
||||
|
Loading…
Reference in New Issue
Block a user