@@ -115,6 +115,12 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
115115 DeclContext *CurDeclContext = nullptr ;
116116 DeclAttrKind AttrKind;
117117
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+
118124 // / In situations when \c SyntaxKind hints or determines
119125 // / completions, i.e. a precedence group attribute, this
120126 // / can be set and used to control the code completion scenario.
@@ -227,6 +233,11 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
227233 AttTargetDK = DK;
228234 }
229235
236+ void setCompletingInAttribute (CustomAttr *Attr) override {
237+ AttrWithCompletion = Attr;
238+ CurDeclContext = P.CurDeclContext ;
239+ }
240+
230241 void completeDotExpr (CodeCompletionExpr *E, SourceLoc DotLoc) override ;
231242 void completeStmtOrExpr (CodeCompletionExpr *E) override ;
232243 void completePostfixExprBeginning (CodeCompletionExpr *E) override ;
@@ -1358,16 +1369,24 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13581369 ? ParsedExpr->getLoc ()
13591370 : CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ();
13601371
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) {
13681374 llvm::SaveAndRestore<TypeCheckCompletionCallback*>
13691375 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+ }
13711390
13721391 // This (hopefully) only happens in cases where the expression isn't
13731392 // typechecked during normal compilation either (e.g. member completion in a
@@ -1376,6 +1395,16 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13761395 // tooling in general though.
13771396 if (!Lookup.gotCallback ())
13781397 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);
13791408
13801409 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
13811410
@@ -1390,12 +1419,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13901419
13911420 UnresolvedMemberTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
13921421 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);
13991423
14001424 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
14011425 Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
@@ -1408,9 +1432,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14081432 // so we can safely cast the \c ParsedExpr back to a \c KeyPathExpr.
14091433 auto KeyPath = cast<KeyPathExpr>(ParsedExpr);
14101434 KeyPathTypeCheckCompletionCallback Lookup (KeyPath);
1411- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1412- Context.CompletionCallback , &Lookup);
1413- typeCheckContextAt (CurDeclContext, CompletionLoc);
1435+ typeCheckWithLookup (Lookup);
14141436
14151437 Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
14161438 return true ;
@@ -1420,13 +1442,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14201442 assert (CurDeclContext);
14211443 ArgumentTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
14221444 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);
14301446
14311447 Lookup.deliverResults (ShouldCompleteCallPatternAfterParen, CompletionLoc,
14321448 CurDeclContext, CompletionContext, Consumer);
@@ -1453,13 +1469,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14531469 // need to have a TypeCheckCompletionCallback so we can call
14541470 // deliverResults on it to deliver the keyword results from the completion
14551471 // 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);
14631473 }
14641474
14651475 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
@@ -1474,13 +1484,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14741484
14751485 AfterPoundExprCompletion Lookup (CodeCompleteTokenExpr, CurDeclContext,
14761486 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);
14841488
14851489 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
14861490
@@ -1550,7 +1554,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
15501554
15511555 undoSingleExpressionReturn (CurDeclContext);
15521556 typeCheckContextAt (
1553- CurDeclContext,
1557+ TypeCheckASTNodeAtLocContext::declContext ( CurDeclContext) ,
15541558 ParsedExpr
15551559 ? ParsedExpr->getLoc ()
15561560 : CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ());
0 commit comments