@@ -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 ;
@@ -1330,16 +1341,24 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1330
1341
? ParsedExpr->getLoc ()
1331
1342
: CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ();
1332
1343
1333
- switch (Kind) {
1334
- case CompletionKind::DotExpr: {
1335
- assert (CodeCompleteTokenExpr);
1336
- assert (CurDeclContext);
1337
-
1338
- DotExprTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1339
- CurDeclContext);
1344
+ auto typeCheckWithLookup = [this , &CompletionLoc](
1345
+ TypeCheckCompletionCallback &Lookup) {
1340
1346
llvm::SaveAndRestore<TypeCheckCompletionCallback*>
1341
1347
CompletionCollector (Context.CompletionCallback , &Lookup);
1342
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1348
+ if (AttrWithCompletion) {
1349
+ // / The attribute might not be attached to the AST if there is no var decl
1350
+ // / it could be attached to. Type check it standalone.
1351
+ ASTNode Call = CallExpr::create (
1352
+ CurDeclContext->getASTContext (), AttrWithCompletion->getTypeExpr (),
1353
+ AttrWithCompletion->getArgs (), /* implicit=*/ true );
1354
+ typeCheckContextAt (
1355
+ TypeCheckASTNodeAtLocContext::node (CurDeclContext, Call),
1356
+ CompletionLoc);
1357
+ } else {
1358
+ typeCheckContextAt (
1359
+ TypeCheckASTNodeAtLocContext::declContext (CurDeclContext),
1360
+ CompletionLoc);
1361
+ }
1343
1362
1344
1363
// This (hopefully) only happens in cases where the expression isn't
1345
1364
// typechecked during normal compilation either (e.g. member completion in a
@@ -1348,6 +1367,16 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1348
1367
// tooling in general though.
1349
1368
if (!Lookup.gotCallback ())
1350
1369
Lookup.fallbackTypeCheck (CurDeclContext);
1370
+ };
1371
+
1372
+ switch (Kind) {
1373
+ case CompletionKind::DotExpr: {
1374
+ assert (CodeCompleteTokenExpr);
1375
+ assert (CurDeclContext);
1376
+
1377
+ DotExprTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1378
+ CurDeclContext);
1379
+ typeCheckWithLookup (Lookup);
1351
1380
1352
1381
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
1353
1382
@@ -1362,12 +1391,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1362
1391
1363
1392
UnresolvedMemberTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1364
1393
CurDeclContext);
1365
- llvm::SaveAndRestore<TypeCheckCompletionCallback*>
1366
- CompletionCollector (Context.CompletionCallback , &Lookup);
1367
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1368
-
1369
- if (!Lookup.gotCallback ())
1370
- Lookup.fallbackTypeCheck (CurDeclContext);
1394
+ typeCheckWithLookup (Lookup);
1371
1395
1372
1396
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
1373
1397
Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
@@ -1380,9 +1404,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1380
1404
// so we can safely cast the \c ParsedExpr back to a \c KeyPathExpr.
1381
1405
auto KeyPath = cast<KeyPathExpr>(ParsedExpr);
1382
1406
KeyPathTypeCheckCompletionCallback Lookup (KeyPath);
1383
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1384
- Context.CompletionCallback , &Lookup);
1385
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1407
+ typeCheckWithLookup (Lookup);
1386
1408
1387
1409
Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
1388
1410
return true ;
@@ -1392,13 +1414,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1392
1414
assert (CurDeclContext);
1393
1415
ArgumentTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
1394
1416
CurDeclContext);
1395
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1396
- Context.CompletionCallback , &Lookup);
1397
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1398
-
1399
- if (!Lookup.gotCallback ()) {
1400
- Lookup.fallbackTypeCheck (CurDeclContext);
1401
- }
1417
+ typeCheckWithLookup (Lookup);
1402
1418
1403
1419
Lookup.deliverResults (ShouldCompleteCallPatternAfterParen, CompletionLoc,
1404
1420
CurDeclContext, CompletionContext, Consumer);
@@ -1425,13 +1441,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1425
1441
// need to have a TypeCheckCompletionCallback so we can call
1426
1442
// deliverResults on it to deliver the keyword results from the completion
1427
1443
// context's result sink to the consumer.
1428
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1429
- Context.CompletionCallback , &Lookup);
1430
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1431
-
1432
- if (!Lookup.gotCallback ()) {
1433
- Lookup.fallbackTypeCheck (CurDeclContext);
1434
- }
1444
+ typeCheckWithLookup (Lookup);
1435
1445
}
1436
1446
1437
1447
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
@@ -1446,13 +1456,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
1446
1456
1447
1457
AfterPoundExprCompletion Lookup (CodeCompleteTokenExpr, CurDeclContext,
1448
1458
ParentStmtKind);
1449
- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1450
- Context.CompletionCallback , &Lookup);
1451
- typeCheckContextAt (CurDeclContext, CompletionLoc);
1452
-
1453
- if (!Lookup.gotCallback ()) {
1454
- Lookup.fallbackTypeCheck (CurDeclContext);
1455
- }
1459
+ typeCheckWithLookup (Lookup);
1456
1460
1457
1461
addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
1458
1462
@@ -1522,7 +1526,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
1522
1526
1523
1527
undoSingleExpressionReturn (CurDeclContext);
1524
1528
typeCheckContextAt (
1525
- CurDeclContext,
1529
+ TypeCheckASTNodeAtLocContext::declContext ( CurDeclContext) ,
1526
1530
ParsedExpr
1527
1531
? ParsedExpr->getLoc ()
1528
1532
: CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ());
0 commit comments