@@ -115,6 +115,12 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
115
115
DeclContext *CurDeclContext = nullptr ;
116
116
DeclAttrKind AttrKind;
117
117
118
+ // / When the code completion token occurs in a custom attribute, the attribute
119
+ // / it occurs in. Used so we can complete inside the attribute even if it's
120
+ // / not attached to the AST, e.g. because there is no var decl it could be
121
+ // / attached to.
122
+ CustomAttr *AttrWithCompletion = nullptr ;
123
+
118
124
// / In situations when \c SyntaxKind hints or determines
119
125
// / completions, i.e. a precedence group attribute, this
120
126
// / can be set and used to control the code completion scenario.
@@ -227,6 +233,11 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
227
233
AttTargetDK = DK;
228
234
}
229
235
236
+ void setCompletingInAttribute (CustomAttr *Attr) override {
237
+ AttrWithCompletion = Attr;
238
+ CurDeclContext = P.CurDeclContext ;
239
+ }
240
+
230
241
void completeDotExpr (CodeCompletionExpr *E, SourceLoc DotLoc) override ;
231
242
void completeStmtOrExpr (CodeCompletionExpr *E) override ;
232
243
void completePostfixExprBeginning (CodeCompletionExpr *E) override ;
@@ -1358,16 +1369,24 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1358
1369
? ParsedExpr->getLoc ()
1359
1370
: CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ();
1360
1371
1361
- switch (Kind) {
1362
- case CompletionKind::DotExpr: {
1363
- assert (CodeCompleteTokenExpr);
1364
- assert (CurDeclContext);
1365
-
1366
- DotExprTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1367
- CurDeclContext);
1372
+ auto typeCheckWithLookup = [this , &CompletionLoc](
1373
+ TypeCheckCompletionCallback &Lookup) {
1368
1374
llvm::SaveAndRestore<TypeCheckCompletionCallback*>
1369
1375
CompletionCollector (Context.CompletionCallback , &Lookup);
1370
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1376
+ if (AttrWithCompletion) {
1377
+ // / The attribute might not be attached to the AST if there is no var decl
1378
+ // / it could be attached to. Type check it standalone.
1379
+ ASTNode Call = CallExpr::create (
1380
+ CurDeclContext->getASTContext (), AttrWithCompletion->getTypeExpr (),
1381
+ AttrWithCompletion->getArgs (), /* implicit=*/ true );
1382
+ typeCheckContextAt (
1383
+ TypeCheckASTNodeAtLocContext::node (CurDeclContext, Call),
1384
+ CompletionLoc);
1385
+ } else {
1386
+ typeCheckContextAt (
1387
+ TypeCheckASTNodeAtLocContext::declContext (CurDeclContext),
1388
+ CompletionLoc);
1389
+ }
1371
1390
1372
1391
// This (hopefully) only happens in cases where the expression isn't
1373
1392
// typechecked during normal compilation either (e.g. member completion in a
@@ -1376,6 +1395,16 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1376
1395
// tooling in general though.
1377
1396
if (!Lookup.gotCallback ())
1378
1397
Lookup.fallbackTypeCheck (CurDeclContext);
1398
+ };
1399
+
1400
+ switch (Kind) {
1401
+ case CompletionKind::DotExpr: {
1402
+ assert (CodeCompleteTokenExpr);
1403
+ assert (CurDeclContext);
1404
+
1405
+ DotExprTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1406
+ CurDeclContext);
1407
+ typeCheckWithLookup (Lookup);
1379
1408
1380
1409
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
1381
1410
@@ -1390,12 +1419,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1390
1419
1391
1420
UnresolvedMemberTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1392
1421
CurDeclContext);
1393
- llvm::SaveAndRestore<TypeCheckCompletionCallback*>
1394
- CompletionCollector (Context.CompletionCallback , &Lookup);
1395
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1396
-
1397
- if (!Lookup.gotCallback ())
1398
- Lookup.fallbackTypeCheck (CurDeclContext);
1422
+ typeCheckWithLookup (Lookup);
1399
1423
1400
1424
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
1401
1425
Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
@@ -1408,9 +1432,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1408
1432
// so we can safely cast the \c ParsedExpr back to a \c KeyPathExpr.
1409
1433
auto KeyPath = cast<KeyPathExpr>(ParsedExpr);
1410
1434
KeyPathTypeCheckCompletionCallback Lookup (KeyPath);
1411
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1412
- Context.CompletionCallback , &Lookup);
1413
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1435
+ typeCheckWithLookup (Lookup);
1414
1436
1415
1437
Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
1416
1438
return true ;
@@ -1420,13 +1442,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1420
1442
assert (CurDeclContext);
1421
1443
ArgumentTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1422
1444
CurDeclContext);
1423
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1424
- Context.CompletionCallback , &Lookup);
1425
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1426
-
1427
- if (!Lookup.gotCallback ()) {
1428
- Lookup.fallbackTypeCheck (CurDeclContext);
1429
- }
1445
+ typeCheckWithLookup (Lookup);
1430
1446
1431
1447
Lookup.deliverResults (ShouldCompleteCallPatternAfterParen, CompletionLoc,
1432
1448
CurDeclContext, CompletionContext, Consumer);
@@ -1453,13 +1469,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1453
1469
// need to have a TypeCheckCompletionCallback so we can call
1454
1470
// deliverResults on it to deliver the keyword results from the completion
1455
1471
// context's result sink to the consumer.
1456
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1457
- Context.CompletionCallback , &Lookup);
1458
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1459
-
1460
- if (!Lookup.gotCallback ()) {
1461
- Lookup.fallbackTypeCheck (CurDeclContext);
1462
- }
1472
+ typeCheckWithLookup (Lookup);
1463
1473
}
1464
1474
1465
1475
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
@@ -1474,13 +1484,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1474
1484
1475
1485
AfterPoundExprCompletion Lookup (CodeCompleteTokenExpr, CurDeclContext,
1476
1486
ParentStmtKind);
1477
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1478
- Context.CompletionCallback , &Lookup);
1479
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1480
-
1481
- if (!Lookup.gotCallback ()) {
1482
- Lookup.fallbackTypeCheck (CurDeclContext);
1483
- }
1487
+ typeCheckWithLookup (Lookup);
1484
1488
1485
1489
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
1486
1490
@@ -1550,7 +1554,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
1550
1554
1551
1555
undoSingleExpressionReturn (CurDeclContext);
1552
1556
typeCheckContextAt (
1553
- CurDeclContext,
1557
+ TypeCheckASTNodeAtLocContext::declContext ( CurDeclContext) ,
1554
1558
ParsedExpr
1555
1559
? ParsedExpr->getLoc ()
1556
1560
: CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ());
0 commit comments