@@ -4108,6 +4108,69 @@ static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
4108
4108
Results.ExitScope ();
4109
4109
}
4110
4110
4111
+ // / Try to find a corresponding FunctionProtoType for function-like types (e.g.
4112
+ // / function pointers, std::function, etc).
4113
+ static const FunctionProtoType *TryDeconstructFunctionLike (QualType T) {
4114
+ assert (!T.isNull ());
4115
+ // Try to extract first template argument from std::function<> and similar.
4116
+ // Note we only handle the sugared types, they closely match what users wrote.
4117
+ // We explicitly choose to not handle ClassTemplateSpecializationDecl.
4118
+ if (auto *Specialization = T->getAs <TemplateSpecializationType>()) {
4119
+ if (Specialization->getNumArgs () != 1 )
4120
+ return nullptr ;
4121
+ const TemplateArgument &Argument = Specialization->getArg (0 );
4122
+ if (Argument.getKind () != TemplateArgument::Type)
4123
+ return nullptr ;
4124
+ return Argument.getAsType ()->getAs <FunctionProtoType>();
4125
+ }
4126
+ // Handle other cases.
4127
+ if (T->isPointerType ())
4128
+ T = T->getPointeeType ();
4129
+ return T->getAs <FunctionProtoType>();
4130
+ }
4131
+
4132
+ // / Adds a pattern completion for a lambda expression with the specified
4133
+ // / parameter types and placeholders for parameter names.
4134
+ static void AddLambdaCompletion (ResultBuilder &Results,
4135
+ llvm::ArrayRef<QualType> Parameters,
4136
+ const LangOptions &LangOpts) {
4137
+ CodeCompletionBuilder Completion (Results.getAllocator (),
4138
+ Results.getCodeCompletionTUInfo ());
4139
+ // [](<parameters>) {}
4140
+ Completion.AddChunk (CodeCompletionString::CK_LeftBracket);
4141
+ Completion.AddPlaceholderChunk (" =" );
4142
+ Completion.AddChunk (CodeCompletionString::CK_RightBracket);
4143
+ if (!Parameters.empty ()) {
4144
+ Completion.AddChunk (CodeCompletionString::CK_LeftParen);
4145
+ bool First = true ;
4146
+ for (auto Parameter : Parameters) {
4147
+ if (!First)
4148
+ Completion.AddChunk (CodeCompletionString::ChunkKind::CK_Comma);
4149
+ else
4150
+ First = false ;
4151
+
4152
+ constexpr llvm::StringLiteral NamePlaceholder = " !#!NAME_GOES_HERE!#!" ;
4153
+ std::string Type = NamePlaceholder;
4154
+ Parameter.getAsStringInternal (Type, PrintingPolicy (LangOpts));
4155
+ llvm::StringRef Prefix, Suffix;
4156
+ std::tie (Prefix, Suffix) = llvm::StringRef (Type).split (NamePlaceholder);
4157
+ Prefix = Prefix.rtrim ();
4158
+ Suffix = Suffix.ltrim ();
4159
+
4160
+ Completion.AddTextChunk (Completion.getAllocator ().CopyString (Prefix));
4161
+ Completion.AddChunk (CodeCompletionString::CK_HorizontalSpace);
4162
+ Completion.AddPlaceholderChunk (" parameter" );
4163
+ Completion.AddTextChunk (Completion.getAllocator ().CopyString (Suffix));
4164
+ };
4165
+ Completion.AddChunk (CodeCompletionString::CK_RightParen);
4166
+ }
4167
+ Completion.AddChunk (CodeCompletionString::CK_LeftBrace);
4168
+ Completion.AddPlaceholderChunk (" body" );
4169
+ Completion.AddChunk (CodeCompletionString::CK_RightBrace);
4170
+
4171
+ Results.AddResult (Completion.TakeString ());
4172
+ }
4173
+
4111
4174
// / Perform code-completion in an expression context when we know what
4112
4175
// / type we're looking for.
4113
4176
void Sema::CodeCompleteExpression (Scope *S,
@@ -4169,6 +4232,14 @@ void Sema::CodeCompleteExpression(Scope *S,
4169
4232
if (CodeCompleter->includeMacros ())
4170
4233
AddMacroResults (PP, Results, CodeCompleter->loadExternal (), false ,
4171
4234
PreferredTypeIsPointer);
4235
+
4236
+ // Complete a lambda expression when preferred type is a function.
4237
+ if (!Data.PreferredType .isNull () && getLangOpts ().CPlusPlus11 ) {
4238
+ if (const FunctionProtoType *F =
4239
+ TryDeconstructFunctionLike (Data.PreferredType ))
4240
+ AddLambdaCompletion (Results, F->getParamTypes (), getLangOpts ());
4241
+ }
4242
+
4172
4243
HandleCodeCompleteResults (this , CodeCompleter, Results.getCompletionContext (),
4173
4244
Results.data (), Results.size ());
4174
4245
}
0 commit comments