Skip to content

Commit bfa385c

Browse files
committed
[CodeCompletion] Update for SE-0249 KeyPath as functions
If the context type is a function type that receives one argument, infer the key path expressions root type from the context. rdar://problem/59302416
1 parent 1d2d8d4 commit bfa385c

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5296,12 +5296,20 @@ void CodeCompletionCallbacksImpl::doneParsing() {
52965296
for (auto T : ContextInfo.getPossibleTypes()) {
52975297
if (auto unwrapped = T->getOptionalObjectType())
52985298
T = unwrapped;
5299-
if (!T->getAnyNominal() || !T->getAnyNominal()->getKeyPathTypeKind() ||
5300-
T->hasUnresolvedType() || !T->is<BoundGenericType>())
5301-
continue;
5302-
// Use the first KeyPath context type found.
5303-
baseType = T->castTo<BoundGenericType>()->getGenericArgs()[0];
5304-
break;
5299+
5300+
// If the context type is any of the KeyPath types, use it.
5301+
if (T->getAnyNominal() && T->getAnyNominal()->getKeyPathTypeKind() &&
5302+
!T->hasUnresolvedType() && T->is<BoundGenericType>()) {
5303+
baseType = T->castTo<BoundGenericType>()->getGenericArgs()[0];
5304+
break;
5305+
}
5306+
5307+
// KeyPath can be used as a function that receives its root type.
5308+
if (T->is<AnyFunctionType>() &&
5309+
T->castTo<AnyFunctionType>()->getNumParams() == 1) {
5310+
baseType = T->castTo<AnyFunctionType>()->getParams()[0].getOldType();
5311+
break;
5312+
}
53055313
}
53065314
}
53075315
if (!OnRoot && KPE->getComponents().back().getKind() ==

test/IDE/complete_swift_key_path.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONTEXT_GENERIC_RESULT | %FileCheck %s -check-prefix=PERSONTYPE-DOT
2626
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONTEXT_GENERIC_RESULT_OPTIONAL | %FileCheck %s -check-prefix=PERSONTYPE-DOT
2727

28+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONTEXT_FUNC | %FileCheck %s -check-prefix=PERSONTYPE-DOT
29+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONTEXT_FUNC_GENERICRESULT | %FileCheck %s -check-prefix=PERSONTYPE-DOT
30+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONTEXT_FUNC_ROOT | %FileCheck %s -check-prefix=PERSONTYPE-DOT
31+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONTEXT_FUNC_NONROOT | %FileCheck %s -check-prefix=OBJ-DOT
32+
2833
class Person {
2934
var name: String
3035
var friends: [Person] = []
@@ -149,3 +154,19 @@ func recvExplicitKPWithGenericResultOpt<Result>(_ kp: KeyPath<Person, Result>?)
149154
recvExplicitKPWithGenericResult(\.#^CONTEXT_GENERIC_RESULT_OPTIONAL^#
150155
// Same as TYPE_DOT.
151156
}
157+
func recvFunc(_ fn: (Person) -> String) {
158+
recvFunc(\.#^CONTEXT_FUNC^#)
159+
}
160+
func recvFuncGeneric<T>(_ fn: (Person) -> T) {
161+
recvFunc(\.#^CONTEXT_FUNC_GENERICRESULT^#)
162+
}
163+
164+
struct Wrap<T> {
165+
func map<U>(_ fn: (T) -> U) -> U { fatalError() }
166+
}
167+
func testKeyPathAsFunctions(wrapped: Wrap<Person>) {
168+
let _ = wrapped.map(\.#^CONTEXT_FUNC_ROOT^#)
169+
// Same as TYPE_DOT.
170+
let _ = wrapped.map(\.friends[0].#^CONTEXT_FUNC_NONROOT^#)
171+
// Same as OBJ_DOT.
172+
}

0 commit comments

Comments
 (0)