Skip to content

Commit 79b0cd6

Browse files
committed
[Sema] Skip adding solutions to completion callback if needed
If `CompletionContextFinder` fails to find a `CompletionNode`, skip trying to filter and add solutions to the completion callback. This prevents an assertion/crash in `filterSolutionsForCodeCompletion` which assumes `CompletionNode` is non-null (either an expression or keypath). Resolves rdar://99966094.
1 parent 453fd22 commit 79b0cd6

File tree

4 files changed

+10
-7
lines changed

4 files changed

+10
-7
lines changed

include/swift/Sema/CompletionContextFinder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class CompletionContextFinder : public ASTWalker {
9191
return CompletionNode.dyn_cast<const KeyPathExpr *>() != nullptr;
9292
}
9393

94+
bool hasCompletion() const {
95+
return !CompletionNode.isNull();
96+
}
97+
9498
/// If we are completing in a key path, returns the \c KeyPath that contains
9599
/// the code completion component.
96100
const KeyPathExpr *getKeyPathContainingCompletionComponent() const {

lib/Sema/BuilderTransform.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,9 +2361,11 @@ Optional<BraceStmt *> TypeChecker::applyResultBuilderBodyTransform(
23612361
cs.solveForCodeCompletion(solutions);
23622362

23632363
CompletionContextFinder analyzer(func, func->getDeclContext());
2364-
filterSolutionsForCodeCompletion(solutions, analyzer);
2365-
for (const auto &solution : solutions) {
2366-
cs.getASTContext().CompletionCallback->sawSolution(solution);
2364+
if (analyzer.hasCompletion()) {
2365+
filterSolutionsForCodeCompletion(solutions, analyzer);
2366+
for (const auto &solution : solutions) {
2367+
cs.getASTContext().CompletionCallback->sawSolution(solution);
2368+
}
23672369
}
23682370
return nullptr;
23692371
}

lib/Sema/CompletionContextFinder.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ CompletionContextFinder::walkToExprPost(Expr *E) {
7171
}
7272

7373
size_t CompletionContextFinder::getKeyPathCompletionComponentIndex() const {
74-
assert(hasCompletionKeyPathComponent());
7574
size_t ComponentIndex = 0;
7675
auto Components = getKeyPathContainingCompletionComponent()->getComponents();
7776
for (auto &Component : Components) {

lib/Sema/TypeCheckCodeCompletion.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,6 @@ static bool hasTypeForCompletion(Solution &solution,
518518
if (contextAnalyzer.hasCompletionExpr()) {
519519
return solution.hasType(contextAnalyzer.getCompletionExpr());
520520
} else {
521-
assert(contextAnalyzer.hasCompletionKeyPathComponent());
522521
return solution.hasType(
523522
contextAnalyzer.getKeyPathContainingCompletionComponent(),
524523
contextAnalyzer.getKeyPathCompletionComponentIndex());
@@ -578,8 +577,7 @@ bool TypeChecker::typeCheckForCodeCompletion(
578577

579578
// If there was no completion expr (e.g. if the code completion location was
580579
// among tokens that were skipped over during parser error recovery) bail.
581-
if (!contextAnalyzer.hasCompletionExpr() &&
582-
!contextAnalyzer.hasCompletionKeyPathComponent())
580+
if (!contextAnalyzer.hasCompletion())
583581
return false;
584582

585583
// Interpolation components are type-checked separately.

0 commit comments

Comments
 (0)