Skip to content

Commit a577a87

Browse files
authored
[ExprContextAnalysis] Look into base type of optional as well when collecting callees for unresolved member (#33292)
1 parent 57d5c4d commit a577a87

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -669,11 +669,9 @@ static bool collectPossibleCalleesForUnresolvedMember(
669669
SmallVectorImpl<FunctionTypeAndDecl> &candidates) {
670670
auto currModule = DC.getParentModule();
671671

672-
// Get the context of the expression itself.
673-
ExprContextInfo contextInfo(&DC, unresolvedMemberExpr);
674-
for (auto expectedTy : contextInfo.getPossibleTypes()) {
672+
auto collectMembers = [&](Type expectedTy) {
675673
if (!expectedTy->mayHaveMembers())
676-
continue;
674+
return;
677675
SmallVector<FunctionTypeAndDecl, 2> members;
678676
collectPossibleCalleesByQualifiedLookup(DC, MetatypeType::get(expectedTy),
679677
unresolvedMemberExpr->getName(),
@@ -683,6 +681,16 @@ static bool collectPossibleCalleesForUnresolvedMember(
683681
member.Decl))
684682
candidates.push_back(member);
685683
}
684+
};
685+
686+
// Get the context of the expression itself.
687+
ExprContextInfo contextInfo(&DC, unresolvedMemberExpr);
688+
for (auto expectedTy : contextInfo.getPossibleTypes()) {
689+
collectMembers(expectedTy);
690+
// If this is an optional type, let's also check its base type.
691+
if (auto baseTy = expectedTy->getOptionalObjectType()) {
692+
collectMembers(baseTy->lookThroughAllOptionalTypes());
693+
}
686694
}
687695
return !candidates.empty();
688696
}

test/IDE/complete_call_arg.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC_METHOD_SKIPPED | %FileCheck %s -check-prefix=STATIC_METHOD_SKIPPED
8181
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_AFTERPAREN_1 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_1
8282
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_AFTERPAREN_2 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_2
83+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_AFTERPAREN_3 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_3
8384
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_SECOND | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SECOND
8485
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_SKIPPED | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SKIPPED
8586
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_1_AFTERPAREN_1 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_1
@@ -707,6 +708,11 @@ func testImplicitMember() {
707708
// IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Literal[Integer]/None/TypeRelation[Identical]: 0[#Int#];
708709
// IMPLICIT_MEMBER_AFTERPAREN_2: End completions
709710

711+
let _: TestStaticMemberCall? = .create1(#^IMPLICIT_MEMBER_AFTERPAREN_3^#)
712+
// IMPLICIT_MEMBER_AFTERPAREN_3: Begin completions, 1 items
713+
// IMPLICIT_MEMBER_AFTERPAREN_3: Decl[StaticMethod]/CurrNominal: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int
714+
// IMPLICIT_MEMBER_AFTERPAREN_3: End completions
715+
710716
let _: TestStaticMemberCall = .create2(1, #^IMPLICIT_MEMBER_SECOND^#)
711717
// IMPLICIT_MEMBER_SECOND: Begin completions, 3 items
712718
// IMPLICIT_MEMBER_SECOND: Pattern/ExprSpecific: {#arg2: Int#}[#Int#];

0 commit comments

Comments
 (0)