diff options
| -rw-r--r-- | clang-tools-extra/clangd/CodeComplete.cpp | 6 | ||||
| -rw-r--r-- | clang-tools-extra/clangd/index/FileIndex.cpp | 2 | ||||
| -rw-r--r-- | clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp | 46 |
3 files changed, 47 insertions, 7 deletions
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index e2fc5019708..fa6c5d18a71 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -642,8 +642,10 @@ clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const { Result.IncludeGlobals = IncludeGlobals; Result.IncludeBriefComments = IncludeBriefComments; - // Enable index-based code completion when Index is provided. - Result.IncludeNamespaceLevelDecls = !Index; + // When an is used, Sema is responsible for completing the main file, + // the index can provide results from the preamble. + // Tell Sema not to deserialize the preamble to look for results. + Result.LoadExternal = !Index; return Result; } diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp index 1f3cc38d25b..43e8d322f4b 100644 --- a/clang-tools-extra/clangd/index/FileIndex.cpp +++ b/clang-tools-extra/clangd/index/FileIndex.cpp @@ -20,6 +20,8 @@ std::unique_ptr<SymbolSlab> indexAST(ASTContext &Ctx, std::shared_ptr<Preprocessor> PP, llvm::ArrayRef<const Decl *> Decls) { SymbolCollector::Options CollectorOpts; + // Code completion gets main-file results from Sema. + // But we leave this option on because features like go-to-definition want it. CollectorOpts.IndexMainFiles = true; auto Collector = std::make_shared<SymbolCollector>(std::move(CollectorOpts)); Collector->setPreprocessor(std::move(PP)); diff --git a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp index 39f9117ae04..3329794b985 100644 --- a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp +++ b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp @@ -57,6 +57,7 @@ using ::testing::Contains; using ::testing::Each; using ::testing::ElementsAre; using ::testing::Not; +using ::testing::UnorderedElementsAre; class IgnoreDiagnostics : public DiagnosticsConsumer { void @@ -104,7 +105,7 @@ CompletionList completions(StringRef Text, /*StorePreamblesInMemory=*/true); auto File = getVirtualTestFilePath("foo.cpp"); Annotations Test(Text); - Server.addDocument(Context::empty(), File, Test.code()); + Server.addDocument(Context::empty(), File, Test.code()).wait(); auto CompletionList = Server.codeComplete(Context::empty(), File, Test.point(), Opts) .get() @@ -506,11 +507,11 @@ TEST(CompletionTest, NoIndex) { Opts.Index = nullptr; auto Results = completions(R"cpp( - namespace ns { class No {}; } + namespace ns { class Local {}; } void f() { ns::^ } )cpp", Opts); - EXPECT_THAT(Results.items, Has("No")); + EXPECT_THAT(Results.items, Has("Local")); } TEST(CompletionTest, StaticAndDynamicIndex) { @@ -538,13 +539,13 @@ TEST(CompletionTest, SimpleIndexBased) { Opts.Index = I.get(); auto Results = completions(R"cpp( - namespace ns { class No {}; } + namespace ns { int local; } void f() { ns::^ } )cpp", Opts); EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class)); EXPECT_THAT(Results.items, Has("foo", CompletionItemKind::Function)); - EXPECT_THAT(Results.items, Not(Has("No"))); + EXPECT_THAT(Results.items, Has("local")); } TEST(CompletionTest, IndexBasedWithFilter) { @@ -585,6 +586,41 @@ TEST(CompletionTest, FullyQualifiedScope) { EXPECT_THAT(Results.items, Has("XYZ", CompletionItemKind::Class)); } +TEST(CompletionTest, IndexSuppressesPreambleCompletions) { + MockFSProvider FS; + MockCompilationDatabase CDB; + IgnoreDiagnostics DiagConsumer; + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true); + + FS.Files[getVirtualTestFilePath("bar.h")] = + R"cpp(namespace ns { int preamble; })cpp"; + auto File = getVirtualTestFilePath("foo.cpp"); + Annotations Test(R"cpp( + #include "bar.h" + namespace ns { int local; } + void f() { ns::^ } + )cpp"); + Server.addDocument(Context::empty(), File, Test.code()).wait(); + clangd::CodeCompleteOptions Opts = {}; + + auto WithoutIndex = + Server.codeComplete(Context::empty(), File, Test.point(), Opts) + .get() + .second.Value; + EXPECT_THAT(WithoutIndex.items, + UnorderedElementsAre(Named("local"), Named("preamble"))); + + auto I = simpleIndexFromSymbols({{"ns::index", index::SymbolKind::Variable}}); + Opts.Index = I.get(); + auto WithIndex = + Server.codeComplete(Context::empty(), File, Test.point(), Opts) + .get() + .second.Value; + EXPECT_THAT(WithIndex.items, + UnorderedElementsAre(Named("local"), Named("index"))); +} + TEST(CompletionTest, ASTIndexMultiFile) { MockFSProvider FS; MockCompilationDatabase CDB; |

