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

Reply via email to