Skip to content

Commit 7cb2c9b

Browse files
authored
Merge pull request #21249 from rintaro/ide-completion-rdar46657585
[CodeCompletion] Unresolved member completion at type parameter position
2 parents 09c15c3 + 4b39c20 commit 7cb2c9b

File tree

2 files changed

+134
-10
lines changed

2 files changed

+134
-10
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,10 +1523,10 @@ static Type getReturnTypeFromContext(const DeclContext *DC) {
15231523
if (FD->getDeclContext()->isTypeContext())
15241524
Ty = FD->getMethodInterfaceType();
15251525
if (auto FT = Ty->getAs<AnyFunctionType>())
1526-
return FT->getResult();
1526+
return DC->mapTypeIntoContext(FT->getResult());
15271527
}
15281528
} else if (auto ACE = dyn_cast<AbstractClosureExpr>(DC)) {
1529-
if (ACE->getType())
1529+
if (ACE->getType() && !ACE->getType()->hasError())
15301530
return ACE->getResultType();
15311531
if (auto CE = dyn_cast<ClosureExpr>(ACE)) {
15321532
if (CE->hasExplicitResultType())
@@ -3670,9 +3670,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
36703670
}
36713671

36723672
void getUnresolvedMemberCompletions(Type T) {
3673-
if (!T->getNominalOrBoundGenericNominal())
3673+
if (!T->mayHaveMembers())
36743674
return;
36753675

3676+
ModuleDecl *CurrModule = CurrDeclContext->getParentModule();
3677+
36763678
// We can only say .foo where foo is a static member of the contextual
36773679
// type and has the same type (or if the member is a function, then the
36783680
// same result type) as the contextual type.
@@ -3704,8 +3706,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
37043706
}
37053707

37063708
// Otherwise, check the result type matches the contextual type.
3707-
auto declTy = getTypeOfMember(VD, T);
3708-
if (declTy->hasError())
3709+
auto declTy = T->getTypeOfMember(CurrModule, VD);
3710+
if (declTy->is<ErrorType>())
37093711
return false;
37103712

37113713
DeclContext *DC = const_cast<DeclContext *>(CurrDeclContext);
@@ -5174,6 +5176,7 @@ class CodeCompletionTypeContextAnalyzer {
51745176
void recordPossibleType(Type ty) {
51755177
if (!ty || ty->is<ErrorType>())
51765178
return;
5179+
51775180
PossibleTypes.push_back(ty->getRValueType());
51785181
}
51795182

@@ -5212,6 +5215,10 @@ class CodeCompletionTypeContextAnalyzer {
52125215
SmallPtrSet<TypeBase *, 4> seenTypes;
52135216
SmallPtrSet<Identifier, 4> seenNames;
52145217
for (auto &typeAndDecl : Candidates) {
5218+
DeclContext *memberDC = nullptr;
5219+
if (typeAndDecl.second)
5220+
memberDC = typeAndDecl.second->getInnermostDeclContext();
5221+
52155222
auto Params = typeAndDecl.first->getParams();
52165223
if (Position >= Params.size())
52175224
continue;
@@ -5220,8 +5227,11 @@ class CodeCompletionTypeContextAnalyzer {
52205227
if (seenNames.insert(Param.getLabel()).second)
52215228
recordPossibleName(Param.getLabel().str());
52225229
} else {
5223-
if (seenTypes.insert(Param.getOldType().getPointer()).second)
5224-
recordPossibleType(Param.getOldType());
5230+
Type ty = Param.getOldType();
5231+
if (memberDC && ty->hasTypeParameter())
5232+
ty = memberDC->mapTypeIntoContext(ty);
5233+
if (seenTypes.insert(ty.getPointer()).second)
5234+
recordPossibleType(ty);
52255235
}
52265236
}
52275237
}
@@ -5302,8 +5312,11 @@ class CodeCompletionTypeContextAnalyzer {
53025312
if (auto type = destExpr->getType()) {
53035313
recordPossibleType(type);
53045314
} else if (auto *DRE = dyn_cast<DeclRefExpr>(destExpr)) {
5305-
if (auto *decl = DRE->getDecl())
5306-
recordPossibleType(decl->getInterfaceType());
5315+
if (auto *decl = DRE->getDecl()) {
5316+
if (decl->hasInterfaceType())
5317+
recordPossibleType(decl->getDeclContext()->mapTypeIntoContext(
5318+
decl->getInterfaceType()));
5319+
}
53075320
}
53085321
}
53095322
break;
@@ -5398,7 +5411,8 @@ class CodeCompletionTypeContextAnalyzer {
53985411
auto ExprPat = cast<ExprPattern>(P);
53995412
if (auto D = ExprPat->getMatchVar()) {
54005413
if (D->hasInterfaceType())
5401-
recordPossibleType(D->getInterfaceType());
5414+
recordPossibleType(
5415+
D->getDeclContext()->mapTypeIntoContext(D->getInterfaceType()));
54025416
}
54035417
break;
54045418
}

test/IDE/complete_unresolved_members.swift

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,28 @@
7878
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOADED_INIT_1 | %FileCheck %s -check-prefix=OVERLOADED_METHOD_1
7979
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOADED_INIT_2 | %FileCheck %s -check-prefix=OVERLOADED_METHOD_1
8080

81+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_1 | %FileCheck %s -check-prefix=GENERICPARAM_1
82+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_2 | %FileCheck %s -check-prefix=GENERICPARAM_1
83+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_3 | %FileCheck %s -check-prefix=GENERICPARAM_1
84+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_4 | %FileCheck %s -check-prefix=GENERICPARAM_1
85+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_5 | %FileCheck %s -check-prefix=GENERICPARAM_1
86+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_6 | %FileCheck %s -check-prefix=GENERICPARAM_1
87+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_7 | %FileCheck %s -check-prefix=GENERICPARAM_1
88+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_8 | %FileCheck %s -check-prefix=GENERICPARAM_1
89+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_9 | %FileCheck %s -check-prefix=GENERICPARAM_1
90+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_10 | %FileCheck %s -check-prefix=GENERICPARAM_1
91+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_11 | %FileCheck %s -check-prefix=GENERICPARAM_1
92+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_12 | %FileCheck %s -check-prefix=GENERICPARAM_1
93+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_13 | %FileCheck %s -check-prefix=GENERICPARAM_1
94+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_14 | %FileCheck %s -check-prefix=GENERICPARAM_1
95+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_15 | %FileCheck %s -check-prefix=GENERICPARAM_1
96+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_16 | %FileCheck %s -check-prefix=GENERICPARAM_1
97+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_17 | %FileCheck %s -check-prefix=GENERICPARAM_1
98+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_18 | %FileCheck %s -check-prefix=GENERICPARAM_1
99+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_19 | %FileCheck %s -check-prefix=GENERICPARAM_1
100+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_20 | %FileCheck %s -check-prefix=GENERICPARAM_1
101+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_21 | %FileCheck %s -check-prefix=GENERICPARAM_1
102+
81103
enum SomeEnum1 {
82104
case South
83105
case North
@@ -535,3 +557,91 @@ func testOverload(val: HasOverloaded) {
535557
let _ = HasOverloaded(e: .#^OVERLOADED_INIT_2^#)
536558
// Same as OVERLOADED_METHOD_1.
537559
}
560+
561+
protocol HasStatic {
562+
static var instance: Self { get }
563+
}
564+
func receiveHasStatic<T: HasStatic>(x: T) {}
565+
func testingGenericParam1<T: HasStatic>(x: inout T, fn: (T) -> Void) -> T {
566+
x = .#^GENERICPARAM_1^#
567+
// GENERICPARAM_1: Begin completions, 1 items
568+
// GENERICPARAM_1: Decl[StaticVar]/CurrNominal: instance[#HasStatic#]; name=instance
569+
// GENERICPARAM_1: End completions
570+
571+
/* Parser sync. */;
572+
573+
let _: (Int, T) = (1, .#^GENERICPARAM_2^#)
574+
// Same as GENERICPARAM_1.
575+
576+
(_, x) = (1, .#^GENERICPARAM_3^#)
577+
// Same as GENERICPARAM_1.
578+
579+
let _ = fn(.#^GENERICPARAM_4^#)
580+
// Same as GENERICPARAM_1.
581+
582+
let _ = receiveHasStatic(x: .#^GENERICPARAM_5^#)
583+
// Same as GENERICPARAM_1.
584+
585+
let _ = { () -> T in
586+
return .#^GENERICPARAM_6^#
587+
// Same as GENERICPARAM_1.
588+
}
589+
let _: () -> T = {
590+
return .#^GENERICPARAM_7^#
591+
// Same as GENERICPARAM_1.
592+
}
593+
let _ = { (_: InvalidTy) -> T in
594+
return .#^GENERICPARAM_8^#
595+
// Same as GENERICPARAM_1.
596+
}
597+
598+
if case .#^GENERICPARAM_9^# = x {}
599+
// Same as GENERICPARAM_1.
600+
601+
return .#^GENERICPARAM_10^#
602+
// Same as GENERICPARAM_1.
603+
}
604+
605+
class C<T: HasStatic> {
606+
607+
var t: T = .instance
608+
609+
func foo(x: T) -> T {
610+
return .#^GENERICPARAM_11^#
611+
// Same as GENERICPARAM_1.
612+
}
613+
func bar<U: HasStatic>(x: U) -> U {
614+
return .#^GENERICPARAM_12^#
615+
// Same as GENERICPARAM_1.
616+
}
617+
618+
func testing() {
619+
let _ = foo(x: .#^GENERICPARAM_13^#)
620+
// Same as GENERICPARAM_1.
621+
let _ = bar(x: .#^GENERICPARAM_14^#)
622+
// Same as GENERICPARAM_1.
623+
624+
t = .#^GENERICPARAM_15^#
625+
// Same as GENERICPARAM_1.
626+
627+
/* Parser sync. */; func sync1() {}
628+
self.t = .#^GENERICPARAM_16^#
629+
// Same as GENERICPARAM_1.
630+
631+
/* Parser sync. */; func sync2() {}
632+
(_, t) = (1, .#^GENERICPARAM_17^#)
633+
// Same as GENERICPARAM_1.
634+
635+
(_, self.t) = (1, .#^GENERICPARAM_18^#)
636+
// Same as GENERICPARAM_1.
637+
}
638+
}
639+
640+
func testingGenericParam2<X>(obj: C<X>) {
641+
let _ = obj.foo(x: .#^GENERICPARAM_19^#)
642+
// Same as GENERICPARAM_1.
643+
let _ = obj.bar(x: .#^GENERICPARAM_20^#)
644+
// Same as GENERICPARAM_1.
645+
obj.t = .#^GENERICPARAM_21^#
646+
// Same as GENERICPARAM_1.
647+
}

0 commit comments

Comments
 (0)