ioeric created this revision. ioeric added a reviewer: kadircet. Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, ilya-biryukov.
E.g. allow injected "A::A" in `using A::A^` but not in "A^". Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D55065 Files: clangd/CodeComplete.cpp unittests/clangd/CodeCompleteTests.cpp Index: unittests/clangd/CodeCompleteTests.cpp =================================================================== --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -416,6 +416,11 @@ Has("X")); } +TEST(CompletionTest, SkipInjectedWhenUnqualified) { + EXPECT_THAT(completions("struct X { void f() { X^ }};").Completions, + ElementsAre(Named("X"), Named("~X"))); +} + TEST(CompletionTest, Snippets) { clangd::CodeCompleteOptions Opts; auto Results = completions( Index: clangd/CodeComplete.cpp =================================================================== --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -656,6 +656,13 @@ llvm_unreachable("unknown code completion context"); } +static bool isInjectedClass(const NamedDecl &D) { + if (auto *R = dyn_cast_or_null<RecordDecl>(&D)) + if (R->isInjectedClassName()) + return true; + return false; +} + // Some member calls are blacklisted because they're so rarely useful. static bool isBlacklistedMember(const NamedDecl &D) { // Destructor completion is rarely useful, and works inconsistently. @@ -663,9 +670,8 @@ if (D.getKind() == Decl::CXXDestructor) return true; // Injected name may be useful for A::foo(), but who writes A::A::foo()? - if (auto *R = dyn_cast_or_null<RecordDecl>(&D)) - if (R->isInjectedClassName()) - return true; + if (isInjectedClass(D)) + return true; // Explicit calls to operators are also rare. auto NameKind = D.getDeclName().getNameKind(); if (NameKind == DeclarationName::CXXOperatorName || @@ -744,6 +750,11 @@ !Context.getBaseType().isNull() // is this a member-access context? && isBlacklistedMember(*Result.Declaration)) continue; + // Skip injected class name when no class scope is not explicitly set. + // E.g. show injected A::A in `using A::A^` but not in "A^". + if (Result.Declaration && !Context.getCXXScopeSpecifier().hasValue() && + isInjectedClass(*Result.Declaration)) + continue; // We choose to never append '::' to completion results in clangd. Result.StartsNestedNameSpecifier = false; Results.push_back(Result);
Index: unittests/clangd/CodeCompleteTests.cpp =================================================================== --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -416,6 +416,11 @@ Has("X")); } +TEST(CompletionTest, SkipInjectedWhenUnqualified) { + EXPECT_THAT(completions("struct X { void f() { X^ }};").Completions, + ElementsAre(Named("X"), Named("~X"))); +} + TEST(CompletionTest, Snippets) { clangd::CodeCompleteOptions Opts; auto Results = completions( Index: clangd/CodeComplete.cpp =================================================================== --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -656,6 +656,13 @@ llvm_unreachable("unknown code completion context"); } +static bool isInjectedClass(const NamedDecl &D) { + if (auto *R = dyn_cast_or_null<RecordDecl>(&D)) + if (R->isInjectedClassName()) + return true; + return false; +} + // Some member calls are blacklisted because they're so rarely useful. static bool isBlacklistedMember(const NamedDecl &D) { // Destructor completion is rarely useful, and works inconsistently. @@ -663,9 +670,8 @@ if (D.getKind() == Decl::CXXDestructor) return true; // Injected name may be useful for A::foo(), but who writes A::A::foo()? - if (auto *R = dyn_cast_or_null<RecordDecl>(&D)) - if (R->isInjectedClassName()) - return true; + if (isInjectedClass(D)) + return true; // Explicit calls to operators are also rare. auto NameKind = D.getDeclName().getNameKind(); if (NameKind == DeclarationName::CXXOperatorName || @@ -744,6 +750,11 @@ !Context.getBaseType().isNull() // is this a member-access context? && isBlacklistedMember(*Result.Declaration)) continue; + // Skip injected class name when no class scope is not explicitly set. + // E.g. show injected A::A in `using A::A^` but not in "A^". + if (Result.Declaration && !Context.getCXXScopeSpecifier().hasValue() && + isInjectedClass(*Result.Declaration)) + continue; // We choose to never append '::' to completion results in clangd. Result.StartsNestedNameSpecifier = false; Results.push_back(Result);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits