zyounan updated this revision to Diff 543280. zyounan added a comment. Format
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D155370/new/ https://reviews.llvm.org/D155370 Files: clang-tools-extra/clangd/CodeComplete.cpp clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/member-access.cpp clang/test/Index/complete-qualified.cpp clang/unittests/Sema/CodeCompleteTest.cpp
Index: clang/unittests/Sema/CodeCompleteTest.cpp =================================================================== --- clang/unittests/Sema/CodeCompleteTest.cpp +++ clang/unittests/Sema/CodeCompleteTest.cpp @@ -60,7 +60,10 @@ for (unsigned I = 0; I < NumResults; ++I) { auto R = Results[I]; if (R.Kind == CodeCompletionResult::RK_Declaration) { - if (const auto *FD = llvm::dyn_cast<FunctionDecl>(R.getDeclaration())) { + auto *ND = R.getDeclaration(); + if (auto *Template = llvm::dyn_cast<FunctionTemplateDecl>(ND)) + ND = Template->getTemplatedDecl(); + if (const auto *FD = llvm::dyn_cast<FunctionDecl>(ND)) { CompletedFunctionDecl D; D.Name = FD->getNameAsString(); D.CanBeCall = R.FunctionCanBeCall; @@ -191,6 +194,10 @@ struct Foo { static int staticMethod(); int method() const; + template <typename T, int U> + void generic(T); + template <typename T, int U = 3> + static T staticGeneric(); Foo() { this->$canBeCall^ $canBeCall^ @@ -223,12 +230,16 @@ auto Results = CollectCompletedFunctions(Code.code(), P); EXPECT_THAT(Results, Contains(AllOf(named("method"), isStatic(false), canBeCall(true)))); + EXPECT_THAT(Results, Contains(AllOf(named("generic"), isStatic(false), + canBeCall(true)))); } for (const auto &P : Code.points("cannotBeCall")) { auto Results = CollectCompletedFunctions(Code.code(), P); EXPECT_THAT(Results, Contains(AllOf(named("method"), isStatic(false), canBeCall(false)))); + EXPECT_THAT(Results, Contains(AllOf(named("generic"), isStatic(false), + canBeCall(false)))); } // static method can always be a call @@ -236,6 +247,8 @@ auto Results = CollectCompletedFunctions(Code.code(), P); EXPECT_THAT(Results, Contains(AllOf(named("staticMethod"), isStatic(true), canBeCall(true)))); + EXPECT_THAT(Results, Contains(AllOf(named("staticGeneric"), isStatic(true), + canBeCall(true)))); } } Index: clang/test/Index/complete-qualified.cpp =================================================================== --- clang/test/Index/complete-qualified.cpp +++ clang/test/Index/complete-qualified.cpp @@ -16,5 +16,5 @@ // RUN: c-index-test -code-completion-at=%s:14:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: FieldDecl:{ResultType C<Foo, class Bar>}{TypedText c} (35) // CHECK-CC1: ClassDecl:{TypedText Foo} (35) -// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{LeftParen (}{Placeholder const Foo &}{RightParen )} -// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{LeftParen (}{RightParen )} (80) +// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=} +// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo} (80) Index: clang/test/CodeCompletion/member-access.cpp =================================================================== --- clang/test/CodeCompletion/member-access.cpp +++ clang/test/CodeCompletion/member-access.cpp @@ -171,7 +171,7 @@ template<typename T> void dependentColonColonCompletion() { Template<T>::staticFn(); -// CHECK-CC7: function : [#void#]function() +// CHECK-CC7: function : [#void#]function // CHECK-CC7: Nested : Nested // CHECK-CC7: o1 : [#BaseTemplate<int>#]o1 // CHECK-CC7: o2 : [#BaseTemplate<T>#]o2 Index: clang/lib/Sema/SemaCodeComplete.cpp =================================================================== --- clang/lib/Sema/SemaCodeComplete.cpp +++ clang/lib/Sema/SemaCodeComplete.cpp @@ -1384,7 +1384,11 @@ // dot/arrow member access) and we're not inside that class' scope, // it can't be a call. if (CompletionContext.getKind() == clang::CodeCompletionContext::CCC_Symbol) { - const auto *Method = dyn_cast<CXXMethodDecl>(R.getDeclaration()); + const NamedDecl *ND = R.getDeclaration(); + if (const auto *FuncTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { + ND = FuncTmpl->getTemplatedDecl(); + } + const auto *Method = dyn_cast<CXXMethodDecl>(ND); if (Method && !Method->isStatic()) { // Find the class scope that we're currently in. // We could e.g. be inside a lambda, so walk up the DeclContext until we @@ -3494,6 +3498,10 @@ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); + // We don't emit parameters (and qualifiers) for context where it can't be a + // call. + if (!FunctionCanBeCall) + return; Result.AddChunk(CodeCompletionString::CK_LeftParen); AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); @@ -3550,6 +3558,15 @@ } } + if (!FunctionCanBeCall) { + // If this isn't a call, emit all the template arguments + // to disambiguate the (potential) overloads. + Result.AddChunk(CodeCompletionString::CK_LeftAngle); + AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result); + Result.AddChunk(CodeCompletionString::CK_RightAngle); + return Result.TakeString(); + } + if (LastDeducibleArgument) { // Some of the function template arguments cannot be deduced from a // function call, so we introduce an explicit template argument list Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -532,45 +532,57 @@ struct Foo { static int staticMethod(); int method() const; + template <typename T, int U> + void generic(T); + template <typename T, int U = 3> + static T staticGeneric(); Foo() { - this->$keepSnippet^ - $keepSnippet^ - Foo::$keepSnippet^ + this->$canBeCall^ + $canBeCall^ + Foo::$canBeCall^ } }; struct Derived : Foo { Derived() { - Foo::$keepSnippet^ + Foo::$canBeCall^ } }; struct OtherClass { OtherClass() { Foo f; - f.$keepSnippet^ - &Foo::$noSnippet^ + f.$canBeCall^ + &Foo::$canNotBeCall^ } }; int main() { Foo f; - f.$keepSnippet^ - &Foo::$noSnippet^ + f.$canBeCall^ + &Foo::$canNotBeCall^ } )cpp"); auto TU = TestTU::withCode(Code.code()); - for (const auto &P : Code.points("noSnippet")) { + for (const auto &P : Code.points("canNotBeCall")) { auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts); EXPECT_THAT(Results.Completions, Contains(AllOf(named("method"), snippetSuffix("")))); + EXPECT_THAT( + Results.Completions, + Contains(AllOf(named("generic"), signature("<typename T, int U>"), + snippetSuffix("<${1:typename T}, ${2:int U}>")))); } - for (const auto &P : Code.points("keepSnippet")) { + for (const auto &P : Code.points("canBeCall")) { auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts); EXPECT_THAT(Results.Completions, Contains(AllOf(named("method"), snippetSuffix("()")))); + EXPECT_THAT(Results.Completions, + Contains(AllOf( + named("generic"), signature("<typename T, int U>(T)"), + snippetSuffix("<${1:typename T}, ${2:int U}>(${3:T})")))); } // static method will always keep the snippet @@ -578,6 +590,10 @@ auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts); EXPECT_THAT(Results.Completions, Contains(AllOf(named("staticMethod"), snippetSuffix("()")))); + EXPECT_THAT( + Results.Completions, + Contains(AllOf(named("staticGeneric"), signature("<typename T>()"), + snippetSuffix("<${1:typename T}>()")))); } } Index: clang-tools-extra/clangd/CodeComplete.cpp =================================================================== --- clang-tools-extra/clangd/CodeComplete.cpp +++ clang-tools-extra/clangd/CodeComplete.cpp @@ -438,8 +438,6 @@ if (C.SemaResult) { getSignature(*SemaCCS, &S.Signature, &S.SnippetSuffix, C.SemaResult->Kind, C.SemaResult->CursorKind, &Completion.RequiredQualifier); - if (!C.SemaResult->FunctionCanBeCall) - S.SnippetSuffix.clear(); S.ReturnType = getReturnType(*SemaCCS); } else if (C.IndexResult) { S.Signature = std::string(C.IndexResult->Signature);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits