@@ -282,11 +282,17 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
282
282
bool IsDynamicRef;
283
283
// / The declaration that is being referenced. Will never be \c nullptr.
284
284
ValueDecl *ReferencedDecl;
285
+ // / The interface type of the referenced declaration. This might not be
286
+ // / stored in `ReferencedDecl->getInterfaceType()` if the declaration's
287
+ // / type hasn't been applied to the AST.
288
+ Type SolutionSpecificInterfaceType;
285
289
286
290
bool operator ==(const CursorInfoDeclReference &Other) const {
287
291
return nullableTypesEqual (BaseType, Other.BaseType ) &&
288
292
IsDynamicRef == Other.IsDynamicRef &&
289
- ReferencedDecl == Other.ReferencedDecl ;
293
+ ReferencedDecl == Other.ReferencedDecl &&
294
+ nullableTypesEqual (SolutionSpecificInterfaceType,
295
+ Other.SolutionSpecificInterfaceType );
290
296
}
291
297
};
292
298
@@ -302,24 +308,43 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
302
308
303
309
SmallVector<CursorInfoDeclReference, 1 > Results;
304
310
305
- Expr * getExprToResolve () {
311
+ void sawSolutionImpl ( const Solution &S) override {
306
312
NodeFinder Finder (DC, ResolveLoc);
307
313
Finder.resolve ();
308
314
auto Result = Finder.takeResult ();
309
- if (!Result || Result->getKind () != NodeFinderResultKind::Expr) {
310
- return nullptr ;
315
+ if (!Result) {
316
+ return ;
317
+ }
318
+ switch (Result->getKind ()) {
319
+ case NodeFinderResultKind::Decl: {
320
+ ValueDecl *DeclToResolve =
321
+ cast<NodeFinderDeclResult>(Result.get ())->getDecl ();
322
+ addCursorInfoResultForDecl (DeclToResolve, S);
323
+ break ;
324
+ }
325
+ case NodeFinderResultKind::Expr: {
326
+ Expr *ExprToResolve = cast<NodeFinderExprResult>(Result.get ())->getExpr ();
327
+ addCursorInfoResultForExpr (ExprToResolve, S);
328
+ break ;
329
+ }
311
330
}
312
- return cast<NodeFinderExprResult>(Result.get ())->getExpr ();
313
331
}
314
332
315
- void sawSolutionImpl (const Solution &S) override {
316
- auto &CS = S.getConstraintSystem ();
317
- auto ResolveExpr = getExprToResolve ();
318
- if (!ResolveExpr) {
333
+ void addCursorInfoResultForDecl (ValueDecl *DeclToResolve, const Solution &S) {
334
+ if (!S.hasType (DeclToResolve)) {
319
335
return ;
320
336
}
337
+ Type SolutionInterfaceTy =
338
+ S.simplifyType (S.getType (DeclToResolve))->mapTypeOutOfContext ();
339
+
340
+ addResult ({/* BaseType=*/ nullptr , /* IsDynamicRef=*/ false , DeclToResolve,
341
+ SolutionInterfaceTy});
342
+ }
343
+
344
+ void addCursorInfoResultForExpr (Expr *ExprToResolve, const Solution &S) {
345
+ auto &CS = S.getConstraintSystem ();
321
346
322
- auto Locator = CS.getConstraintLocator (ResolveExpr );
347
+ auto Locator = CS.getConstraintLocator (ExprToResolve );
323
348
auto CalleeLocator = S.getCalleeLocator (Locator);
324
349
auto OverloadInfo = getSelectedOverloadInfo (S, CalleeLocator);
325
350
if (!OverloadInfo.ValueRef ) {
@@ -337,9 +362,11 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
337
362
[&S](Expr *E) { return S.getResolvedType (E); });
338
363
}
339
364
340
- CursorInfoDeclReference NewResult = {OverloadInfo.BaseTy , IsDynamicRef,
341
- OverloadInfo.getValue ()};
365
+ addResult ({OverloadInfo.BaseTy , IsDynamicRef, OverloadInfo.getValue (),
366
+ /* SolutionSpecificInterfaceType=*/ Type ()});
367
+ }
342
368
369
+ void addResult (const CursorInfoDeclReference &NewResult) {
343
370
if (llvm::any_of (Results, [&](const CursorInfoDeclReference &R) {
344
371
return R == NewResult;
345
372
})) {
@@ -367,47 +394,38 @@ class CursorInfoDoneParsingCallback : public DoneParsingCallback {
367
394
SourceLoc RequestedLoc)
368
395
: DoneParsingCallback(), Consumer(Consumer), RequestedLoc(RequestedLoc) {}
369
396
370
- std::vector<ResolvedCursorInfoPtr>
371
- getDeclResult (NodeFinderDeclResult *DeclResult, SourceFile *SrcFile,
372
- NodeFinder &Finder) const {
373
- typeCheckDeclAndParentClosures (DeclResult->getDecl ());
374
- auto CursorInfo = new ResolvedValueRefCursorInfo (
375
- SrcFile, RequestedLoc, DeclResult->getDecl (),
376
- /* CtorTyRef=*/ nullptr ,
377
- /* ExtTyRef=*/ nullptr , /* IsRef=*/ false , /* Ty=*/ Type (),
378
- /* ContainerType=*/ Type (),
379
- /* CustomAttrRef=*/ std::nullopt,
380
- /* IsKeywordArgument=*/ false ,
381
- /* IsDynamic=*/ false ,
382
- /* ReceiverTypes=*/ {},
383
- Finder.getShorthandShadowedDecls (DeclResult->getDecl ()));
384
- return {CursorInfo};
385
- }
386
-
387
- std::vector<ResolvedCursorInfoPtr>
388
- getExprResult (NodeFinderExprResult *ExprResult, SourceFile *SrcFile,
389
- NodeFinder &Finder) const {
390
- Expr *E = ExprResult->getExpr ();
391
- DeclContext *DC = ExprResult->getDeclContext ();
392
-
397
+ private:
398
+ // / Shared core of `getExprResult` and `getDeclResult`.
399
+ std::vector<ResolvedCursorInfoPtr> getResult (ASTNode Node, DeclContext *DC,
400
+ SourceFile *SrcFile,
401
+ NodeFinder &Finder) const {
393
402
// Type check the statemnt containing E and listen for solutions.
394
403
CursorInfoTypeCheckSolutionCallback Callback (*DC, RequestedLoc);
395
404
{
396
405
llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
397
406
DC->getASTContext ().SolutionCallback , &Callback);
398
- typeCheckASTNodeAtLoc (TypeCheckASTNodeAtLocContext::declContext (DC),
399
- E->getLoc ());
407
+ if (ValueDecl *VD = getAsDecl<ValueDecl>(Node)) {
408
+ typeCheckDeclAndParentClosures (VD);
409
+ } else {
410
+ typeCheckASTNodeAtLoc (TypeCheckASTNodeAtLocContext::declContext (DC),
411
+ Node.getStartLoc ());
412
+ }
400
413
}
401
414
402
415
if (Callback.getResults ().empty ()) {
403
416
// No results.
404
417
return {};
405
418
}
406
419
407
- for (auto Info : Callback.getResults ()) {
408
- // Type check the referenced decls so that all their parent closures are
409
- // type-checked (see comment in typeCheckDeclAndParentClosures).
410
- typeCheckDeclAndParentClosures (Info.ReferencedDecl );
420
+ if (Node.is <Expr *>()) {
421
+ // If we are performing cursor info on an expression, type check the
422
+ // referenced decls so that all their parent closures are type-checked
423
+ // (see comment in typeCheckDeclAndParentClosures).
424
+ // When doing cursor info on a declaration, we already type checked the
425
+ // decl above while listening to the solution callbacks.
426
+ for (auto Info : Callback.getResults ()) {
427
+ typeCheckDeclAndParentClosures (Info.ReferencedDecl );
428
+ }
411
429
}
412
430
413
431
// Deliver results
@@ -434,7 +452,8 @@ class CursorInfoDoneParsingCallback : public DoneParsingCallback {
434
452
auto CursorInfo = new ResolvedValueRefCursorInfo (
435
453
SrcFile, RequestedLoc, Res.ReferencedDecl ,
436
454
/* CtorTyRef=*/ nullptr ,
437
- /* ExtTyRef=*/ nullptr , /* IsRef=*/ true , /* Ty=*/ Type (),
455
+ /* ExtTyRef=*/ nullptr , /* IsRef=*/ true ,
456
+ Res.SolutionSpecificInterfaceType ,
438
457
/* ContainerType=*/ Res.BaseType ,
439
458
/* CustomAttrRef=*/ std::nullopt,
440
459
/* IsKeywordArgument=*/ false , Res.IsDynamicRef , ReceiverTypes,
@@ -444,6 +463,43 @@ class CursorInfoDoneParsingCallback : public DoneParsingCallback {
444
463
return Results;
445
464
}
446
465
466
+ public:
467
+ std::vector<ResolvedCursorInfoPtr>
468
+ getDeclResult (NodeFinderDeclResult *DeclResult, SourceFile *SrcFile,
469
+ NodeFinder &Finder) const {
470
+ std::vector<ResolvedCursorInfoPtr> Results =
471
+ getResult (DeclResult->getDecl (),
472
+ DeclResult->getDecl ()->getDeclContext (), SrcFile, Finder);
473
+
474
+ if (!Results.empty ()) {
475
+ return Results;
476
+ }
477
+
478
+ // If we didn't get any solution from the constraint system, try getting the
479
+ // type from the decl itself. This may happen if the decl is in an inactive
480
+ // branch of a `#if` clause.
481
+ auto CursorInfo = new ResolvedValueRefCursorInfo (
482
+ SrcFile, RequestedLoc, DeclResult->getDecl (),
483
+ /* CtorTyRef=*/ nullptr ,
484
+ /* ExtTyRef=*/ nullptr ,
485
+ /* IsRef=*/ false ,
486
+ /* SolutionSpecificInterfaceType=*/ Type (),
487
+ /* ContainerType=*/ Type (),
488
+ /* CustomAttrRef=*/ std::nullopt,
489
+ /* IsKeywordArgument=*/ false ,
490
+ /* IsDynamic=*/ false ,
491
+ /* ReceiverTypes=*/ {},
492
+ Finder.getShorthandShadowedDecls (DeclResult->getDecl ()));
493
+ return {CursorInfo};
494
+ }
495
+
496
+ std::vector<ResolvedCursorInfoPtr>
497
+ getExprResult (NodeFinderExprResult *ExprResult, SourceFile *SrcFile,
498
+ NodeFinder &Finder) const {
499
+ return getResult (ExprResult->getExpr (), ExprResult->getDeclContext (),
500
+ SrcFile, Finder);
501
+ }
502
+
447
503
void doneParsing (SourceFile *SrcFile) override {
448
504
if (!SrcFile) {
449
505
return ;
0 commit comments