[PATCH] D70445: [clangd] Show lambda signature for lambda autocompletions

Kirill Bobyrev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 19 07:56:26 PST 2019


kbobyrev created this revision.
kbobyrev added a reviewer: sammccall.
kbobyrev added projects: clang, clang-tools-extra.
Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay.

The original bug report can be found here <https://github.com/clangd/clangd/issues/85>.

Given the following code:

  c++
  void function() {
    auto Lambda = [](int a, double &b) {return 1.f;};
    La^
  }

Triggering the completion at `^` would show `(lambda)` before this patch and would show signature `(int a, double &b) const`, build a snippet etc with this patch.


Repository:
  rC Clang

https://reviews.llvm.org/D70445

Files:
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang/lib/Sema/SemaCodeComplete.cpp


Index: clang/lib/Sema/SemaCodeComplete.cpp
===================================================================
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -3327,6 +3327,26 @@
   return Result.TakeString();
 }
 
+namespace {
+const CXXMethodDecl *extractLambdaCallOperator(const NamedDecl *ND) {
+  const auto *VD = dyn_cast<VarDecl>(ND);
+  if (!VD)
+    return nullptr;
+  const auto *LambdaType = VD->getType().getTypePtr();
+  if (const auto *SugaredType = dyn_cast<AutoType>(LambdaType))
+    LambdaType = SugaredType->desugar().getTypePtr();
+  LambdaType = dyn_cast<RecordType>(LambdaType);
+  if (!LambdaType)
+    return nullptr;
+  const auto *RecordDecl = LambdaType->getAsCXXRecordDecl();
+  // FIXME: Don't ignore generic lambdas.
+  return (RecordDecl && RecordDecl->isLambda() &&
+          !RecordDecl->isGenericLambda())
+             ? RecordDecl->getLambdaCallOperator()
+             : nullptr;
+}
+} // namespace
+
 CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
     Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
     bool IncludeBriefComments, const CodeCompletionContext &CCContext,
@@ -3351,19 +3371,30 @@
   for (const auto *I : ND->specific_attrs<AnnotateAttr>())
     Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
 
-  AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
-
-  if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
-    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
-                                   Ctx, Policy);
+  auto handleFunctionlike = [&](const FunctionDecl *Function,
+                                bool AddQualifier = true) {
+    AddResultTypeChunk(Ctx, Policy, Function, CCContext.getBaseType(), Result);
+    if (AddQualifier)
+      AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+                                     Ctx, Policy);
     AddTypedNameChunk(Ctx, Policy, ND, Result);
     Result.AddChunk(CodeCompletionString::CK_LeftParen);
     AddFunctionParameterChunks(PP, Policy, Function, Result);
     Result.AddChunk(CodeCompletionString::CK_RightParen);
     AddFunctionTypeQualsToCompletionString(Result, Function);
     return Result.TakeString();
+  };
+
+  if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
+    return handleFunctionlike(Function);
   }
 
+  if (const auto *CallOperator = extractLambdaCallOperator(ND)) {
+    return handleFunctionlike(CallOperator, false);
+  }
+
+  AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
+
   if (const FunctionTemplateDecl *FunTmpl =
           dyn_cast<FunctionTemplateDecl>(ND)) {
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2471,6 +2471,26 @@
   EXPECT_THAT(C, ElementsAre(SnippetSuffix("")));
 }
 
+TEST(CompletionTest, Lambda) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+    void function() {
+      auto Lambda = [](int a, const double &b) {return 1.f;};
+      Lam^
+    }
+  )cpp", {}, Opts);
+
+  EXPECT_EQ(Results.Completions.size(), 1u);
+  const auto A = Results.Completions.front();
+  EXPECT_EQ(A.Name, "Lambda");
+  EXPECT_EQ(A.Signature, "(int a, const double &b) const");
+  EXPECT_EQ(A.Kind, CompletionItemKind::Variable);
+  EXPECT_EQ(A.ReturnType, "float");
+  EXPECT_EQ(A.SnippetSuffix, "(${1:int a}, ${2:const double &b})");
+}
+
 TEST(CompletionTest, ObjectiveCMethodOneArgument) {
   auto Results = completions(R"objc(
       @interface Foo


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70445.230072.patch
Type: text/x-patch
Size: 3868 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191119/665bbfd5/attachment-0001.bin>


More information about the cfe-commits mailing list