@@ -618,10 +618,10 @@ class CompletionContextFinder : public ASTWalker {
618
618
// / If we are completing inside an expression, the \c CodeCompletionExpr that
619
619
// / represents the code completion token.
620
620
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;
625
625
626
626
Expr *InitialExpr = nullptr ;
627
627
DeclContext *InitialDC;
@@ -675,10 +675,13 @@ class CompletionContextFinder : public ASTWalker {
675
675
for (auto &component : KeyPath->getComponents ()) {
676
676
if (component.getKind () ==
677
677
KeyPathExpr::Component::Kind::CodeCompletion) {
678
- CompletionNode = &component ;
678
+ CompletionNode = KeyPath ;
679
679
return std::make_pair (false , nullptr );
680
680
}
681
681
}
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);
682
685
}
683
686
684
687
return std::make_pair (true , E);
@@ -713,12 +716,33 @@ class CompletionContextFinder : public ASTWalker {
713
716
}
714
717
715
718
bool hasCompletionKeyPathComponent () const {
716
- return CompletionNode.dyn_cast <const KeyPathExpr::Component *>() != nullptr ;
719
+ return CompletionNode.dyn_cast <const KeyPathExpr *>() != nullptr ;
717
720
}
718
721
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 {
720
725
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;
722
746
}
723
747
724
748
struct Fallback {
@@ -949,20 +973,27 @@ bool TypeChecker::typeCheckForCodeCompletion(
949
973
if (contextAnalyzer.locatedInMultiStmtClosure ()) {
950
974
auto &solution = solutions.front ();
951
975
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 ());
955
984
}
956
985
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
+ }
966
997
}
967
998
968
999
llvm::for_each (solutions, callback);
0 commit comments