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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits