@@ -618,10 +618,10 @@ class CompletionContextFinder : public ASTWalker {
618618 // / If we are completing inside an expression, the \c CodeCompletionExpr that
619619 // / represents the code completion token.
620620
621- // / The AST node that represents the code completion token, either as an
622- // / expression or a KeyPath component.
623- llvm::PointerUnion<CodeCompletionExpr *, const KeyPathExpr::Component *>
624- CompletionNode;
621+ // / The AST node that represents the code completion token, either as a
622+ // / \c CodeCompletionExpr or a \c KeyPathExpr which contains a code completion
623+ // / component.
624+ llvm::PointerUnion<CodeCompletionExpr *, const KeyPathExpr *> CompletionNode;
625625
626626 Expr *InitialExpr = nullptr ;
627627 DeclContext *InitialDC;
@@ -675,10 +675,13 @@ class CompletionContextFinder : public ASTWalker {
675675 for (auto &component : KeyPath->getComponents ()) {
676676 if (component.getKind () ==
677677 KeyPathExpr::Component::Kind::CodeCompletion) {
678- CompletionNode = &component ;
678+ CompletionNode = KeyPath ;
679679 return std::make_pair (false , nullptr );
680680 }
681681 }
682+ // Code completion in key paths is modelled by a code completion component
683+ // Don't walk the key path's parsed expressions.
684+ return std::make_pair (false , E);
682685 }
683686
684687 return std::make_pair (true , E);
@@ -713,12 +716,33 @@ class CompletionContextFinder : public ASTWalker {
713716 }
714717
715718 bool hasCompletionKeyPathComponent () const {
716- return CompletionNode.dyn_cast <const KeyPathExpr::Component *>() != nullptr ;
719+ return CompletionNode.dyn_cast <const KeyPathExpr *>() != nullptr ;
717720 }
718721
719- const KeyPathExpr::Component *getCompletionKeyPathComponent () const {
722+ // / If we are completing in a key path, returns the \c KeyPath that contains
723+ // / the code completion component.
724+ const KeyPathExpr *getKeyPathContainingCompletionComponent () const {
720725 assert (hasCompletionKeyPathComponent ());
721- return CompletionNode.get <const KeyPathExpr::Component *>();
726+ return CompletionNode.get <const KeyPathExpr *>();
727+ }
728+
729+ // / If we are completing in a key path, returns the index at which the key
730+ // / path has the code completion component.
731+ size_t getKeyPathCompletionComponentIndex () const {
732+ assert (hasCompletionKeyPathComponent ());
733+ size_t ComponentIndex = 0 ;
734+ auto Components =
735+ getKeyPathContainingCompletionComponent ()->getComponents ();
736+ for (auto &Component : Components) {
737+ if (Component.getKind () == KeyPathExpr::Component::Kind::CodeCompletion) {
738+ break ;
739+ } else {
740+ ComponentIndex++;
741+ }
742+ }
743+ assert (ComponentIndex < Components.size () &&
744+ " No completion component in the key path?" );
745+ return ComponentIndex;
722746 }
723747
724748 struct Fallback {
@@ -949,20 +973,27 @@ bool TypeChecker::typeCheckForCodeCompletion(
949973 if (contextAnalyzer.locatedInMultiStmtClosure ()) {
950974 auto &solution = solutions.front ();
951975
952- if (solution.hasType (contextAnalyzer.getCompletionExpr ())) {
953- llvm::for_each (solutions, callback);
954- return CompletionResult::Ok;
976+ bool HasTypeForCompletionNode = false ;
977+ if (completionExpr) {
978+ HasTypeForCompletionNode = solution.hasType (completionExpr);
979+ } else {
980+ assert (contextAnalyzer.hasCompletionKeyPathComponent ());
981+ HasTypeForCompletionNode = solution.hasType (
982+ contextAnalyzer.getKeyPathContainingCompletionComponent (),
983+ contextAnalyzer.getKeyPathCompletionComponentIndex ());
955984 }
956985
957- // At this point we know the code completion expression wasn't checked
958- // with the closure's surrounding context, so can defer to regular type-
959- // checking for the current call to typeCheckExpression. If that succeeds
960- // we will get a second call to typeCheckExpression for the body of the
961- // closure later and can gather completions then. If it doesn't we rely
962- // on the fallback typechecking in the subclasses of
963- // TypeCheckCompletionCallback that considers in isolation a
964- // sub-expression of the closure that contains the completion location.
965- return CompletionResult::NotApplicable;
986+ if (!HasTypeForCompletionNode) {
987+ // At this point we know the code completion node wasn't checked with
988+ // the closure's surrounding context, so can defer to regular
989+ // type-checking for the current call to typeCheckExpression. If that
990+ // succeeds we will get a second call to typeCheckExpression for the
991+ // body of the closure later and can gather completions then. If it
992+ // doesn't we rely on the fallback typechecking in the subclasses of
993+ // TypeCheckCompletionCallback that considers in isolation a
994+ // sub-expression of the closure that contains the completion location.
995+ return CompletionResult::NotApplicable;
996+ }
966997 }
967998
968999 llvm::for_each (solutions, callback);
0 commit comments