@@ -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 ;
@@ -1330,16 +1341,24 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13301341 ? ParsedExpr->getLoc ()
13311342 : CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ();
13321343
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) {
13401346 llvm::SaveAndRestore<TypeCheckCompletionCallback*>
13411347 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+ }
13431362
13441363 // This (hopefully) only happens in cases where the expression isn't
13451364 // typechecked during normal compilation either (e.g. member completion in a
@@ -1348,6 +1367,16 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13481367 // tooling in general though.
13491368 if (!Lookup.gotCallback ())
13501369 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);
13511380
13521381 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
13531382
@@ -1362,12 +1391,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13621391
13631392 UnresolvedMemberTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
13641393 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);
13711395
13721396 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
13731397 Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
@@ -1380,9 +1404,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13801404 // so we can safely cast the \c ParsedExpr back to a \c KeyPathExpr.
13811405 auto KeyPath = cast<KeyPathExpr>(ParsedExpr);
13821406 KeyPathTypeCheckCompletionCallback Lookup (KeyPath);
1383- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1384- Context.CompletionCallback , &Lookup);
1385- typeCheckContextAt (CurDeclContext, CompletionLoc);
1407+ typeCheckWithLookup (Lookup);
13861408
13871409 Lookup.deliverResults (CurDeclContext, DotLoc, CompletionContext, Consumer);
13881410 return true ;
@@ -1392,13 +1414,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
13921414 assert (CurDeclContext);
13931415 ArgumentTypeCheckCompletionCallback Lookup (CodeCompleteTokenExpr,
13941416 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);
14021418
14031419 Lookup.deliverResults (ShouldCompleteCallPatternAfterParen, CompletionLoc,
14041420 CurDeclContext, CompletionContext, Consumer);
@@ -1422,13 +1438,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14221438 // need to have a TypeCheckCompletionCallback so we can call
14231439 // deliverResults on it to deliver the keyword results from the completion
14241440 // context's result sink to the consumer.
1425- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1426- Context.CompletionCallback , &Lookup);
1427- typeCheckContextAt (CurDeclContext, CompletionLoc);
1428-
1429- if (!Lookup.gotCallback ()) {
1430- Lookup.fallbackTypeCheck (CurDeclContext);
1431- }
1441+ typeCheckWithLookup (Lookup);
14321442 }
14331443
14341444 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
@@ -1443,13 +1453,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14431453
14441454 AfterPoundExprCompletion Lookup (CodeCompleteTokenExpr, CurDeclContext,
14451455 ParentStmtKind);
1446- llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector (
1447- Context.CompletionCallback , &Lookup);
1448- typeCheckContextAt (CurDeclContext, CompletionLoc);
1449-
1450- if (!Lookup.gotCallback ()) {
1451- Lookup.fallbackTypeCheck (CurDeclContext);
1452- }
1456+ typeCheckWithLookup (Lookup);
14531457
14541458 addKeywords (CompletionContext.getResultSink (), MaybeFuncBody);
14551459
@@ -1519,7 +1523,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
15191523
15201524 undoSingleExpressionReturn (CurDeclContext);
15211525 typeCheckContextAt (
1522- CurDeclContext,
1526+ TypeCheckASTNodeAtLocContext::declContext ( CurDeclContext) ,
15231527 ParsedExpr
15241528 ? ParsedExpr->getLoc ()
15251529 : CurDeclContext->getASTContext ().SourceMgr .getCodeCompletionLoc ());
0 commit comments