From 7f0dcf665dd22be296805bc7a1c71a36243c4e09 Mon Sep 17 00:00:00 2001 From: Kirill Bobyrev Date: Fri, 22 Nov 2019 12:48:06 +0100 Subject: [clangd] Show lambda signature for lambda autocompletions 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. Reviewers: sammccall Reviewed by: sammccall Differential revision: https://reviews.llvm.org/D70445 --- clang/lib/Sema/SemaCodeComplete.cpp | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'clang/lib/Sema/SemaCodeComplete.cpp') diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 81eed4330cd..e75aca4d81e 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -3315,6 +3315,18 @@ CodeCompletionResult::createCodeCompletionStringForOverride( return Result.TakeString(); } +// FIXME: Right now this works well with lambdas. Add support for other functor +// types like std::function. +static const NamedDecl *extractFunctorCallOperator(const NamedDecl *ND) { + const auto *VD = dyn_cast(ND); + if (!VD) + return nullptr; + const auto *RecordDecl = VD->getType()->getAsCXXRecordDecl(); + if (!RecordDecl || !RecordDecl->isLambda()) + return nullptr; + return RecordDecl->getLambdaCallOperator(); +} + CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, bool IncludeBriefComments, const CodeCompletionContext &CCContext, @@ -3339,9 +3351,8 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( for (const auto *I : ND->specific_attrs()) Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation())); - AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result); - - if (const auto *Function = dyn_cast(ND)) { + auto AddFunctionTypeAndResult = [&](const FunctionDecl *Function) { + AddResultTypeChunk(Ctx, Policy, Function, CCContext.getBaseType(), Result); AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); @@ -3349,9 +3360,21 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); + }; + + if (const auto *Function = dyn_cast(ND)) { + AddFunctionTypeAndResult(Function); + return Result.TakeString(); + } + + if (const auto *CallOperator = + dyn_cast_or_null(extractFunctorCallOperator(ND))) { + AddFunctionTypeAndResult(CallOperator); return Result.TakeString(); } + AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result); + if (const FunctionTemplateDecl *FunTmpl = dyn_cast(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, @@ -3417,6 +3440,7 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( Result.AddChunk(CodeCompletionString::CK_RightAngle); return Result.TakeString(); } + if (const auto *Method = dyn_cast(ND)) { Selector Sel = Method->getSelector(); if (Sel.isUnarySelector()) { -- cgit v1.2.3