Author: ibiryukov Date: Mon May 14 03:50:04 2018 New Revision: 332226 URL: http://llvm.org/viewvc/llvm-project?rev=332226&view=rev Log: [clangd] Don't query index when completing inside classes
Summary: We used to query the index when completing after class qualifiers, e.g. 'ClassName::^'. We should not do that for the same reasons we don't query the index for member access expressions. Reviewers: sammccall, ioeric Reviewed By: sammccall Subscribers: klimek, MaskRay, jkorous, cfe-commits Differential Revision: https://reviews.llvm.org/D46795 Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=332226&r1=332225&r2=332226&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original) +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Mon May 14 03:50:04 2018 @@ -759,9 +759,9 @@ bool semaCodeComplete(std::unique_ptr<Co return true; } -// Should we perform index-based completion in this context? +// Should we perform index-based completion in a context of the specified kind? // FIXME: consider allowing completion, but restricting the result types. -bool allowIndex(enum CodeCompletionContext::Kind K) { +bool contextAllowsIndex(enum CodeCompletionContext::Kind K) { switch (K) { case CodeCompletionContext::CCC_TopLevel: case CodeCompletionContext::CCC_ObjCInterface: @@ -803,6 +803,33 @@ bool allowIndex(enum CodeCompletionConte llvm_unreachable("unknown code completion context"); } +// Should we allow index completions in the specified context? +bool allowIndex(CodeCompletionContext &CC) { + if (!contextAllowsIndex(CC.getKind())) + return false; + // We also avoid ClassName::bar (but allow namespace::bar). + auto Scope = CC.getCXXScopeSpecifier(); + if (!Scope) + return true; + NestedNameSpecifier *NameSpec = (*Scope)->getScopeRep(); + if (!NameSpec) + return true; + // We only query the index when qualifier is a namespace. + // If it's a class, we rely solely on sema completions. + switch (NameSpec->getKind()) { + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + return true; + case NestedNameSpecifier::Super: + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + // Unresolved inside a template. + case NestedNameSpecifier::Identifier: + return false; + } +} + } // namespace clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const { @@ -918,7 +945,7 @@ private: } SymbolSlab queryIndex() { - if (!Opts.Index || !allowIndex(Recorder->CCContext.getKind())) + if (!Opts.Index || !allowIndex(Recorder->CCContext)) return SymbolSlab(); trace::Span Tracer("Query index"); SPAN_ATTACH(Tracer, "limit", Opts.Limit); Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp?rev=332226&r1=332225&r2=332226&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Mon May 14 03:50:04 2018 @@ -825,6 +825,67 @@ TEST(CompletionTest, GlobalQualifiedQuer UnorderedElementsAre("")))); } +TEST(CompletionTest, NoIndexCompletionsInsideClasses) { + auto Completions = completions( + R"cpp( + struct Foo { + int SomeNameOfField; + typedef int SomeNameOfTypedefField; + }; + + Foo::^)cpp", + {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")}); + + EXPECT_THAT(Completions.items, + AllOf(Contains(Labeled("SomeNameOfField")), + Contains(Labeled("SomeNameOfTypedefField")), + Not(Contains(Labeled("SomeNameInTheIndex"))))); +} + +TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) { + { + auto Completions = completions( + R"cpp( + template <class T> + void foo() { + T::^ + } + )cpp", + {func("::SomeNameInTheIndex")}); + + EXPECT_THAT(Completions.items, + Not(Contains(Labeled("SomeNameInTheIndex")))); + } + + { + auto Completions = completions( + R"cpp( + template <class T> + void foo() { + T::template Y<int>::^ + } + )cpp", + {func("::SomeNameInTheIndex")}); + + EXPECT_THAT(Completions.items, + Not(Contains(Labeled("SomeNameInTheIndex")))); + } + + { + auto Completions = completions( + R"cpp( + template <class T> + void foo() { + T::foo::^ + } + )cpp", + {func("::SomeNameInTheIndex")}); + + EXPECT_THAT(Completions.items, + Not(Contains(Labeled("SomeNameInTheIndex")))); + } +} + } // namespace } // namespace clangd } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits