Skip to content

Commit

Permalink
[clangd] Index unscoped enums in class scope for code completion
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-anders committed Nov 2, 2022
1 parent 2e36dad commit a68bcd8
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 7 deletions.
8 changes: 7 additions & 1 deletion clang-tools-extra/clangd/CodeComplete.cpp
Expand Up @@ -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))
Expand All @@ -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;
}
Expand Down
41 changes: 36 additions & 5 deletions clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
Expand Up @@ -1316,6 +1316,11 @@ TEST_F(SymbolCollectorTest, IncludeEnums) {
Black
};
}
class Color3 {
enum {
Blue
};
};
)";
runSymbolCollector(Header, /*Main=*/"");
EXPECT_THAT(Symbols,
Expand All @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/clangd/unittests/TestIndex.cpp
Expand Up @@ -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");
}
Expand Down
2 changes: 2 additions & 0 deletions clang-tools-extra/clangd/unittests/TestIndex.h
Expand Up @@ -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.
Expand Down

0 comments on commit a68bcd8

Please sign in to comment.