@@ -622,10 +622,10 @@ class CompletionContextFinder : public ASTWalker {
622
622
// / If we are completing inside an expression, the \c CodeCompletionExpr that
623
623
// / represents the code completion token.
624
624
625
- // / The AST node that represents the code completion token, either as an
626
- // / expression or a KeyPath component.
627
- llvm::PointerUnion<CodeCompletionExpr *, const KeyPathExpr::Component *>
628
- CompletionNode;
625
+ // / The AST node that represents the code completion token, either as a
626
+ // / \c CodeCompletionExpr or a \c KeyPathExpr which contains a code completion
627
+ // / component.
628
+ llvm::PointerUnion<CodeCompletionExpr *, const KeyPathExpr *> CompletionNode;
629
629
630
630
Expr *InitialExpr = nullptr ;
631
631
DeclContext *InitialDC;
@@ -679,10 +679,13 @@ class CompletionContextFinder : public ASTWalker {
679
679
for (auto &component : KeyPath->getComponents ()) {
680
680
if (component.getKind () ==
681
681
KeyPathExpr::Component::Kind::CodeCompletion) {
682
- CompletionNode = &component ;
682
+ CompletionNode = KeyPath ;
683
683
return std::make_pair (false , nullptr );
684
684
}
685
685
}
686
+ // Code completion in key paths is modelled by a code completion component
687
+ // Don't walk the key path's parsed expressions.
688
+ return std::make_pair (false , E);
686
689
}
687
690
688
691
return std::make_pair (true , E);
@@ -717,12 +720,33 @@ class CompletionContextFinder : public ASTWalker {
717
720
}
718
721
719
722
bool hasCompletionKeyPathComponent () const {
720
- return CompletionNode.dyn_cast <const KeyPathExpr::Component *>() != nullptr ;
723
+ return CompletionNode.dyn_cast <const KeyPathExpr *>() != nullptr ;
721
724
}
722
725
723
- const KeyPathExpr::Component *getCompletionKeyPathComponent () const {
726
+ // / If we are completing in a key path, returns the \c KeyPath that contains
727
+ // / the code completion component.
728
+ const KeyPathExpr *getKeyPathContainingCompletionComponent () const {
724
729
assert (hasCompletionKeyPathComponent ());
725
- return CompletionNode.get <const KeyPathExpr::Component *>();
730
+ return CompletionNode.get <const KeyPathExpr *>();
731
+ }
732
+
733
+ // / If we are completing in a key path, returns the index at which the key
734
+ // / path has the code completion component.
735
+ size_t getKeyPathCompletionComponentIndex () const {
736
+ assert (hasCompletionKeyPathComponent ());
737
+ size_t ComponentIndex = 0 ;
738
+ auto Components =
739
+ getKeyPathContainingCompletionComponent ()->getComponents ();
740
+ for (auto &Component : Components) {
741
+ if (Component.getKind () == KeyPathExpr::Component::Kind::CodeCompletion) {
742
+ break ;
743
+ } else {
744
+ ComponentIndex++;
745
+ }
746
+ }
747
+ assert (ComponentIndex < Components.size () &&
748
+ " No completion component in the key path?" );
749
+ return ComponentIndex;
726
750
}
727
751
728
752
struct Fallback {
@@ -953,20 +977,27 @@ bool TypeChecker::typeCheckForCodeCompletion(
953
977
if (contextAnalyzer.locatedInMultiStmtClosure ()) {
954
978
auto &solution = solutions.front ();
955
979
956
- if (solution.hasType (contextAnalyzer.getCompletionExpr ())) {
957
- llvm::for_each (solutions, callback);
958
- return CompletionResult::Ok;
980
+ bool HasTypeForCompletionNode = false ;
981
+ if (completionExpr) {
982
+ HasTypeForCompletionNode = solution.hasType (completionExpr);
983
+ } else {
984
+ assert (contextAnalyzer.hasCompletionKeyPathComponent ());
985
+ HasTypeForCompletionNode = solution.hasType (
986
+ contextAnalyzer.getKeyPathContainingCompletionComponent (),
987
+ contextAnalyzer.getKeyPathCompletionComponentIndex ());
959
988
}
960
989
961
- // At this point we know the code completion expression wasn't checked
962
- // with the closure's surrounding context, so can defer to regular type-
963
- // checking for the current call to typeCheckExpression. If that succeeds
964
- // we will get a second call to typeCheckExpression for the body of the
965
- // closure later and can gather completions then. If it doesn't we rely
966
- // on the fallback typechecking in the subclasses of
967
- // TypeCheckCompletionCallback that considers in isolation a
968
- // sub-expression of the closure that contains the completion location.
969
- return CompletionResult::NotApplicable;
990
+ if (!HasTypeForCompletionNode) {
991
+ // At this point we know the code completion node wasn't checked with
992
+ // the closure's surrounding context, so can defer to regular
993
+ // type-checking for the current call to typeCheckExpression. If that
994
+ // succeeds we will get a second call to typeCheckExpression for the
995
+ // body of the closure later and can gather completions then. If it
996
+ // doesn't we rely on the fallback typechecking in the subclasses of
997
+ // TypeCheckCompletionCallback that considers in isolation a
998
+ // sub-expression of the closure that contains the completion location.
999
+ return CompletionResult::NotApplicable;
1000
+ }
970
1001
}
971
1002
972
1003
llvm::for_each (solutions, callback);
0 commit comments