[clang-tools-extra] a68bcd8 - [clangd] Index unscoped enums in class scope for code completion
Tom Praschan via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 2 03:51:24 PDT 2022
Author: Tom Praschan
Date: 2022-11-02T12:50:50+01:00
New Revision: a68bcd81dcc90fc7d6fbe4013569774a19097c4a
URL: https://github.com/llvm/llvm-project/commit/a68bcd81dcc90fc7d6fbe4013569774a19097c4a
DIFF: https://github.com/llvm/llvm-project/commit/a68bcd81dcc90fc7d6fbe4013569774a19097c4a.diff
LOG: [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
Added:
Modified:
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
clang-tools-extra/clangd/unittests/TestIndex.cpp
clang-tools-extra/clangd/unittests/TestIndex.h
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 5612fc599fb50..a3e518b4ba054 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -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;
}
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index db700556e1d24..77451bf445e0f 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -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;
diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index 8dc7877c17849..bb651b851afeb 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -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) {
diff --git a/clang-tools-extra/clangd/unittests/TestIndex.cpp b/clang-tools-extra/clangd/unittests/TestIndex.cpp
index c247a9c2e90c9..11282bc34231a 100644
--- a/clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ b/clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -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");
}
diff --git a/clang-tools-extra/clangd/unittests/TestIndex.h b/clang-tools-extra/clangd/unittests/TestIndex.h
index 0cd8a713c31dd..9280b0b12a67f 100644
--- a/clang-tools-extra/clangd/unittests/TestIndex.h
+++ b/clang-tools-extra/clangd/unittests/TestIndex.h
@@ -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.
More information about the cfe-commits
mailing list