Skip to content

Commit 0f879c4

Browse files
committed
[CodeCompletion] Avoid prioritizing unavailable in LookupVisibleDecls
rdar://problem/67155695
1 parent 363dc4e commit 0f879c4

File tree

2 files changed

+127
-11
lines changed

2 files changed

+127
-11
lines changed

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -946,17 +946,22 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
946946
/*wouldConflictInSwift5*/nullptr,
947947
/*skipProtocolExtensionCheck*/true)) {
948948
FoundConflicting = true;
949-
// Prefer derived requirements over their witnesses.
950-
if (Reason ==
951-
DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal ||
952-
VD->getFormalAccess() > OtherVD->getFormalAccess() ||
953-
//Prefer available one.
954-
(!AvailableAttr::isUnavailable(VD) &&
955-
AvailableAttr::isUnavailable(OtherVD))) {
956-
FilteredResults.remove(
957-
FoundDeclTy(OtherVD, DeclVisibilityKind::LocalVariable, {}));
958-
FilteredResults.insert(DeclAndReason);
959-
*I = VD;
949+
950+
if (!AvailableAttr::isUnavailable(VD)) {
951+
bool preferVD = (
952+
// Prefer derived requirements over their witnesses.
953+
Reason == DeclVisibilityKind::
954+
MemberOfProtocolDerivedByCurrentNominal ||
955+
// Prefer available one.
956+
AvailableAttr::isUnavailable(OtherVD) ||
957+
// Prefer more accessible one.
958+
VD->getFormalAccess() > OtherVD->getFormalAccess());
959+
if (preferVD) {
960+
FilteredResults.remove(
961+
FoundDeclTy(OtherVD, DeclVisibilityKind::LocalVariable, {}));
962+
FilteredResults.insert(DeclAndReason);
963+
*I = VD;
964+
}
960965
}
961966
}
962967
}

test/IDE/complete_rdar67155695.swift

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PUBLIC | %FileCheck %s --check-prefix=PUBLIC
2+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=INTERNAL | %FileCheck %s --check-prefix=INTERNAL
3+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PRIVATE | %FileCheck %s --check-prefix=PRIVATE
4+
5+
public protocol PubP {}
6+
7+
public extension PubP {
8+
func availableP_availableC() {}
9+
10+
func availableP_unavailableC() {}
11+
12+
@available(*, unavailable)
13+
func unavailableP_availableC() {}
14+
15+
@available(*, unavailable)
16+
func unavailableP_unavailableC() {}
17+
}
18+
19+
struct TestForPubP: PubP {
20+
func availableP_availableC() {}
21+
22+
@available(*, unavailable)
23+
func availableP_unavailableC() {}
24+
25+
func unavailableP_availableC() {}
26+
27+
@available(*, unavailable)
28+
func unavailableP_unavailableC() {}
29+
}
30+
31+
func test(val: TestForPubP) {
32+
val.#^PUBLIC^#
33+
// PUBLIC: Begin completions, 4 items
34+
// PUBLIC-DAG: Keyword[self]/CurrNominal: self[#TestForPubP#];
35+
// PUBLIC-DAG: Decl[InstanceMethod]/CurrNominal: unavailableP_availableC()[#Void#];
36+
// PUBLIC-DAG: Decl[InstanceMethod]/Super: availableP_availableC()[#Void#];
37+
// PUBLIC-DAG: Decl[InstanceMethod]/Super: availableP_unavailableC()[#Void#];
38+
// PUBLIC: End completions
39+
}
40+
41+
protocol InternalP {}
42+
43+
extension InternalP {
44+
func availableP_availableC() {}
45+
46+
func availableP_unavailableC() {}
47+
48+
@available(*, unavailable)
49+
func unavailableP_availableC() {}
50+
51+
@available(*, unavailable)
52+
func unavailableP_unavailableC() {}
53+
}
54+
55+
struct TestForInternalP: InternalP {
56+
func availableP_availableC() {}
57+
58+
@available(*, unavailable)
59+
func availableP_unavailableC() {}
60+
61+
func unavailableP_availableC() {}
62+
63+
@available(*, unavailable)
64+
func unavailableP_unavailableC() {}
65+
}
66+
67+
func test(val: TestForInternalP) {
68+
val.#^INTERNAL^#
69+
// INTERNAL: Begin completions, 4 items
70+
// INTERNAL-DAG: Keyword[self]/CurrNominal: self[#TestForInternalP#];
71+
// INTERNAL-DAG: Decl[InstanceMethod]/CurrNominal: availableP_availableC()[#Void#];
72+
// INTERNAL-DAG: Decl[InstanceMethod]/CurrNominal: unavailableP_availableC()[#Void#];
73+
// INTERNAL-DAG: Decl[InstanceMethod]/Super: availableP_unavailableC()[#Void#];
74+
// INTERNAL: End completions
75+
}
76+
77+
private protocol PrivP {}
78+
79+
private extension PrivP {
80+
func availableP_availableC() {}
81+
82+
func availableP_unavailableC() {}
83+
84+
@available(*, unavailable)
85+
func unavailableP_availableC() {}
86+
87+
@available(*, unavailable)
88+
func unavailableP_unavailableC() {}
89+
}
90+
91+
struct TestForPrivP: PrivP {
92+
func availableP_availableC() {}
93+
94+
@available(*, unavailable)
95+
func availableP_unavailableC() {}
96+
97+
func unavailableP_availableC() {}
98+
99+
@available(*, unavailable)
100+
func unavailableP_unavailableC() {}
101+
}
102+
103+
func test(val: TestForPrivP) {
104+
val.#^PRIVATE^#
105+
// PRIVATE: Begin completions, 4 items
106+
// PRIVATE-DAG: Keyword[self]/CurrNominal: self[#TestForPrivP#];
107+
// PRIVATE-DAG: Decl[InstanceMethod]/CurrNominal: availableP_availableC()[#Void#];
108+
// PRIVATE-DAG: Decl[InstanceMethod]/CurrNominal: unavailableP_availableC()[#Void#];
109+
// PRIVATE-DAG: Decl[InstanceMethod]/Super: availableP_unavailableC()[#Void#];
110+
// PRIVATE-DAG: End completions
111+
}

0 commit comments

Comments
 (0)