@@ -4340,6 +4340,16 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
4340
4340
if (!T->mayHaveMembers ())
4341
4341
return ;
4342
4342
4343
+ if (auto objT = T->getOptionalObjectType ()) {
4344
+ // Add 'nil' keyword with erasing '.' instruction.
4345
+ unsigned bytesToErase = 0 ;
4346
+ auto &SM = CurrDeclContext->getASTContext ().SourceMgr ;
4347
+ if (DotLoc.isValid ())
4348
+ bytesToErase = SM.getByteDistance (DotLoc, SM.getCodeCompletionLoc ());
4349
+ addKeyword (" nil" , T, SemanticContextKind::None,
4350
+ CodeCompletionKeywordKind::kw_nil, bytesToErase);
4351
+ }
4352
+
4343
4353
// We can only say .foo where foo is a static member of the contextual
4344
4354
// type and has the same type (or if the member is a function, then the
4345
4355
// same result type) as the contextual type.
@@ -4378,14 +4388,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
4378
4388
objT = objT->lookThroughAllOptionalTypes ();
4379
4389
if (seenTypes.insert (objT->getCanonicalType ()).second )
4380
4390
getUnresolvedMemberCompletions (objT);
4381
-
4382
- // Add 'nil' keyword with erasing '.' instruction.
4383
- unsigned bytesToErase = 0 ;
4384
- auto &SM = CurrDeclContext->getASTContext ().SourceMgr ;
4385
- if (DotLoc.isValid ())
4386
- bytesToErase = SM.getByteDistance (DotLoc, SM.getCodeCompletionLoc ());
4387
- addKeyword (" nil" , T, SemanticContextKind::None,
4388
- CodeCompletionKeywordKind::kw_nil, bytesToErase);
4389
4391
}
4390
4392
getUnresolvedMemberCompletions (T);
4391
4393
}
@@ -6083,6 +6085,45 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
6083
6085
DCForModules);
6084
6086
}
6085
6087
6088
+ void deliverUnresolvedMemberResults (
6089
+ ArrayRef<UnresolvedMemberTypeCheckCompletionCallback::Result> Results,
6090
+ DeclContext *DC, SourceLoc DotLoc,
6091
+ ide::CodeCompletionContext &CompletionCtx,
6092
+ CodeCompletionConsumer &Consumer) {
6093
+ ASTContext &Ctx = DC->getASTContext ();
6094
+ CompletionLookup Lookup (CompletionCtx.getResultSink (), Ctx, DC,
6095
+ &CompletionCtx);
6096
+
6097
+ assert (DotLoc.isValid ());
6098
+ Lookup.setHaveDot (DotLoc);
6099
+ Lookup.shouldCheckForDuplicates (Results.size () > 1 );
6100
+
6101
+ // Get the canonical versions of the top-level types
6102
+ SmallPtrSet<CanType, 4 > originalTypes;
6103
+ for (auto &Result: Results)
6104
+ originalTypes.insert (Result.ExpectedTy ->getCanonicalType ());
6105
+
6106
+ for (auto &Result: Results) {
6107
+ Lookup.setExpectedTypes ({Result.ExpectedTy },
6108
+ Result.IsSingleExpressionBody ,
6109
+ /* expectsNonVoid*/ true );
6110
+ Lookup.setIdealExpectedType (Result.ExpectedTy );
6111
+
6112
+ // For optional types, also get members of the unwrapped type if it's not
6113
+ // already equivalent to one of the top-level types. Handling it via the top
6114
+ // level type and not here ensures we give the correct type relation
6115
+ // (identical, rather than convertible).
6116
+ if (Result.ExpectedTy ->getOptionalObjectType ()) {
6117
+ Type Unwrapped = Result.ExpectedTy ->lookThroughAllOptionalTypes ();
6118
+ if (originalTypes.insert (Unwrapped->getCanonicalType ()).second )
6119
+ Lookup.getUnresolvedMemberCompletions (Unwrapped);
6120
+ }
6121
+ Lookup.getUnresolvedMemberCompletions (Result.ExpectedTy );
6122
+ }
6123
+ SourceFile *SF = DC->getParentSourceFile ();
6124
+ deliverCompletionResults (CompletionCtx, Lookup, *SF, Consumer);
6125
+ }
6126
+
6086
6127
void deliverDotExprResults (
6087
6128
ArrayRef<DotExprTypeCheckCompletionCallback::Result> Results,
6088
6129
Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
@@ -6158,6 +6199,23 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
6158
6199
Consumer);
6159
6200
return true ;
6160
6201
}
6202
+ case CompletionKind::UnresolvedMember: {
6203
+ assert (CodeCompleteTokenExpr);
6204
+ assert (CurDeclContext);
6205
+
6206
+ UnresolvedMemberTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr);
6207
+ llvm::SaveAndRestore<TypeCheckCompletionCallback*>
6208
+ CompletionCollector (Context.CompletionCallback , &Lookup);
6209
+ typeCheckContextAt (CurDeclContext, CompletionLoc);
6210
+
6211
+ if (!Lookup.gotCallback ())
6212
+ Lookup.fallbackTypeCheck (CurDeclContext);
6213
+
6214
+ addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
6215
+ deliverUnresolvedMemberResults (Lookup.getResults (), CurDeclContext, DotLoc,
6216
+ CompletionContext, Consumer);
6217
+ return true ;
6218
+ }
6161
6219
default :
6162
6220
return false ;
6163
6221
}
@@ -6277,6 +6335,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
6277
6335
switch (Kind) {
6278
6336
case CompletionKind::None:
6279
6337
case CompletionKind::DotExpr:
6338
+ case CompletionKind::UnresolvedMember:
6280
6339
llvm_unreachable (" should be already handled" );
6281
6340
return ;
6282
6341
@@ -6478,15 +6537,6 @@ void CodeCompletionCallbacksImpl::doneParsing() {
6478
6537
Lookup.addImportModuleNames ();
6479
6538
break ;
6480
6539
}
6481
- case CompletionKind::UnresolvedMember: {
6482
- Lookup.setHaveDot (DotLoc);
6483
- ExprContextInfo ContextInfo (CurDeclContext, CodeCompleteTokenExpr);
6484
- Lookup.setExpectedTypes (ContextInfo.getPossibleTypes (),
6485
- ContextInfo.isSingleExpressionBody ());
6486
- Lookup.setIdealExpectedType (CodeCompleteTokenExpr->getType ());
6487
- Lookup.getUnresolvedMemberCompletions (ContextInfo.getPossibleTypes ());
6488
- break ;
6489
- }
6490
6540
case CompletionKind::CallArg: {
6491
6541
ExprContextInfo ContextInfo (CurDeclContext, CodeCompleteTokenExpr);
6492
6542
0 commit comments