From 410596efd99096dfa35df6304d440a01cfed8159 Mon Sep 17 00:00:00 2001 From: Suyash Srijan Date: Wed, 5 Aug 2020 03:47:11 +0100 Subject: [PATCH] [ExprContextAnalysis] Look into base type of optional as well when collecting callees for unresolved member --- lib/IDE/ExprContextAnalysis.cpp | 16 ++++++++++++---- test/IDE/complete_call_arg.swift | 6 ++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 04eb5f543c6af..7f8b7a0efe70d 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -669,11 +669,9 @@ static bool collectPossibleCalleesForUnresolvedMember( SmallVectorImpl &candidates) { auto currModule = DC.getParentModule(); - // Get the context of the expression itself. - ExprContextInfo contextInfo(&DC, unresolvedMemberExpr); - for (auto expectedTy : contextInfo.getPossibleTypes()) { + auto collectMembers = [&](Type expectedTy) { if (!expectedTy->mayHaveMembers()) - continue; + return; SmallVector members; collectPossibleCalleesByQualifiedLookup(DC, MetatypeType::get(expectedTy), unresolvedMemberExpr->getName(), @@ -683,6 +681,16 @@ static bool collectPossibleCalleesForUnresolvedMember( member.Decl)) candidates.push_back(member); } + }; + + // Get the context of the expression itself. + ExprContextInfo contextInfo(&DC, unresolvedMemberExpr); + for (auto expectedTy : contextInfo.getPossibleTypes()) { + collectMembers(expectedTy); + // If this is an optional type, let's also check its base type. + if (auto baseTy = expectedTy->getOptionalObjectType()) { + collectMembers(baseTy->lookThroughAllOptionalTypes()); + } } return !candidates.empty(); } diff --git a/test/IDE/complete_call_arg.swift b/test/IDE/complete_call_arg.swift index 609b1847543ce..1d0c56fe0b6a1 100644 --- a/test/IDE/complete_call_arg.swift +++ b/test/IDE/complete_call_arg.swift @@ -80,6 +80,7 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC_METHOD_SKIPPED | %FileCheck %s -check-prefix=STATIC_METHOD_SKIPPED // 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 // 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 +// 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 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_SECOND | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SECOND // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_SKIPPED | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SKIPPED // 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() { // IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Literal[Integer]/None/TypeRelation[Identical]: 0[#Int#]; // IMPLICIT_MEMBER_AFTERPAREN_2: End completions + let _: TestStaticMemberCall? = .create1(#^IMPLICIT_MEMBER_AFTERPAREN_3^#) +// IMPLICIT_MEMBER_AFTERPAREN_3: Begin completions, 1 items +// IMPLICIT_MEMBER_AFTERPAREN_3: Decl[StaticMethod]/CurrNominal: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int +// IMPLICIT_MEMBER_AFTERPAREN_3: End completions + let _: TestStaticMemberCall = .create2(1, #^IMPLICIT_MEMBER_SECOND^#) // IMPLICIT_MEMBER_SECOND: Begin completions, 3 items // IMPLICIT_MEMBER_SECOND: Pattern/ExprSpecific: {#arg2: Int#}[#Int#];