Skip to content

Commit 4faa397

Browse files
authored
Merge pull request #36607 from ahoppen/pr/suggest-self-in-where-clause
[CodeComplete] In where clauses, suggest Self and the current type
2 parents 1371789 + 943d7ee commit 4faa397

File tree

3 files changed

+55
-17
lines changed

3 files changed

+55
-17
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4609,7 +4609,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
46094609
}
46104610
}
46114611

4612-
void getGenericRequirementCompletions(DeclContext *DC) {
4612+
void getGenericRequirementCompletions(DeclContext *DC,
4613+
SourceLoc CodeCompletionLoc) {
46134614
auto genericSig = DC->getGenericSignatureOfContext();
46144615
if (!genericSig)
46154616
return;
@@ -4636,6 +4637,18 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
46364637
CurrDeclContext, IncludeInstanceMembers,
46374638
/*includeDerivedRequirements*/false,
46384639
/*includeProtocolExtensionMembers*/true);
4640+
// We not only allow referencing nested types/typealiases directly, but also
4641+
// qualified by the current type. Thus also suggest current self type so the
4642+
// user can do a memberwise lookup on it.
4643+
if (auto SelfType = typeContext->getSelfNominalTypeDecl()) {
4644+
addNominalTypeRef(SelfType, DeclVisibilityKind::LocalVariable,
4645+
DynamicLookupInfo());
4646+
}
4647+
4648+
// Self is also valid in all cases in which it can be used in function
4649+
// bodies. Suggest it if applicable.
4650+
getSelfTypeCompletionInDeclContext(CodeCompletionLoc,
4651+
/*isForResultType=*/false);
46394652
}
46404653

46414654
static bool canUseAttributeOnDecl(DeclAttrKind DAK, bool IsInSil,
@@ -4757,6 +4770,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
47574770
getAttributeDeclParamCompletions(DAK_Available, 0);
47584771
}
47594772

4773+
/// \p Loc is the location of the code completin token.
4774+
/// \p isForDeclResult determines if were are spelling out the result type
4775+
/// of a declaration.
47604776
void getSelfTypeCompletionInDeclContext(SourceLoc Loc, bool isForDeclResult) {
47614777
const DeclContext *typeDC = CurrDeclContext->getInnermostTypeContext();
47624778
if (!typeDC)
@@ -6924,9 +6940,11 @@ void CodeCompletionCallbacksImpl::doneParsing() {
69246940
break;
69256941
}
69266942

6927-
case CompletionKind::GenericRequirement:
6928-
Lookup.getGenericRequirementCompletions(CurDeclContext);
6943+
case CompletionKind::GenericRequirement: {
6944+
auto Loc = Context.SourceMgr.getCodeCompletionLoc();
6945+
Lookup.getGenericRequirementCompletions(CurDeclContext, Loc);
69296946
break;
6947+
}
69306948
case CompletionKind::PrecedenceGroup:
69316949
Lookup.getPrecedenceGroupCompletions(SyntxKind);
69326950
break;

test/IDE/complete_annotation.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,9 @@ func testArchetypeAnnotations<T>(arg: TestArchetypeAnnotations<T>) {
132132
struct TestGenericParamAnnotations<T> {
133133
func foo1<U>(u: U) where #^WHERE^#
134134
}
135-
// WHERE: Begin completions, 2 items
136-
// WHERE-NEXT: Decl[GenericTypeParam]/Local: <name>T</name>; typename=<typeid.user>T</typeid.user>; name=T
137-
// WHERE-NEXT: Decl[GenericTypeParam]/Local: <name>U</name>; typename=<typeid.user>U</typeid.user>; name=U
135+
// WHERE: Begin completions, 4 items
136+
// WHERE-DAG: Decl[GenericTypeParam]/Local: <name>T</name>; typename=<typeid.user>T</typeid.user>; name=T
137+
// WHERE-DAG: Decl[GenericTypeParam]/Local: <name>U</name>; typename=<typeid.user>U</typeid.user>; name=U
138+
// WHERE-DAG: Decl[Struct]/Local: <name>TestGenericParamAnnotations</name>;
139+
// WHERE-DAG: Keyword[Self]/CurrNominal: <keyword>Self</keyword>;
138140
// WHERE: End completions

test/IDE/complete_where_clause.swift

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_2_ASSOC | %FileCheck %s -check-prefix=GEN_T_ASSOC_DOT
1212
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_3 | %FileCheck %s -check-prefix=GEN_T
1313
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_4 | %FileCheck %s -check-prefix=GEN_T_DOT
14-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_5 | %FileCheck %s -check-prefix=GEN_T
14+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_5 | %FileCheck %s -check-prefix=GEN_T_S1
1515
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_6 | %FileCheck %s -check-prefix=GEN_T_DOT
16-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=SUBSCRIPT_1 | %FileCheck %s -check-prefix=GEN_T
16+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=SUBSCRIPT_1 | %FileCheck %s -check-prefix=GEN_T_S1
1717
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=SUBSCRIPT_2 | %FileCheck %s -check-prefix=GEN_T_DOT
18-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_1 | %FileCheck %s -check-prefix=GEN_T
18+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_1 | %FileCheck %s -check-prefix=GEN_T_S1
1919
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_2 | %FileCheck %s -check-prefix=GEN_T_DOT
20-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ALIAS_1 | %FileCheck %s -check-prefix=GEN_T
20+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ALIAS_1 | %FileCheck %s -check-prefix=GEN_T_S1
2121
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ALIAS_2 | %FileCheck %s -check-prefix=GEN_T_DOT
2222
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_1 | %FileCheck %s -check-prefix=GEN_T_NOMINAL
2323
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_2 | %FileCheck %s -check-prefix=GEN_T_DOT
@@ -64,8 +64,10 @@ extension A1 where T1.#^GP6^# {}
6464
// A1-DAG: Decl[GenericTypeParam]/Local: T1[#T1#]; name=T1
6565
// A1-DAG: Decl[GenericTypeParam]/Local: T2[#T2#]; name=T2
6666
// A1-DAG: Decl[GenericTypeParam]/Local: T3[#T3#]; name=T3
67+
// A1-DAG: Decl[Class]/Local: A1[#A1#]; name=A1
6768
// A1-NOT: T4
6869
// A1-NOT: T5
70+
// A1-NOT: Self
6971

7072
// TYPE1: Begin completions
7173
// TYPE1-DAG: Decl[Protocol]/CurrModule: P1[#P1#]; name=P1
@@ -76,6 +78,7 @@ extension A1 where T1.#^GP6^# {}
7678
// TYPE1-NOT: T3
7779
// TYPE1-NOT: T4
7880
// TYPE1-NOT: T5
81+
// TYPE1-NOT: Self
7982

8083
// EMPTY: Begin completions, 1 items
8184
// EMPTY-DAG: Keyword/None: Type[#T1.Type#]; name=Type
@@ -125,6 +128,11 @@ struct S1 {
125128
typealias TA1<T> = A1<T, T, T> where #^ALIAS_1^#
126129
typealias TA2<T> = A1<T, T, T> where T.#^ALIAS_2^#
127130
}
131+
// GEN_T_S1: Begin completions, 3 items
132+
// GEN_T_S1-DAG: Decl[GenericTypeParam]/Local: T[#T#];
133+
// GEN_T_S1-DAG: Decl[Struct]/Local: S1[#S1#];
134+
// GEN_T_S1-DAG: Keyword[Self]/CurrNominal: Self[#S1#];
135+
// GEN_T_S1: End completions
128136

129137
struct S2<T> where #^STRUCT_1^# {}
130138
struct S3<T> where T.#^STRUCT_2^# {}
@@ -149,10 +157,11 @@ protocol P2 {
149157
associatedtype U: Assoc where U.#^ASSOC_2^#
150158
}
151159

152-
// P2: Begin completions, 3 items
153-
// P2-DAG: Decl[GenericTypeParam]/Local: Self[#Self#];
160+
// P2: Begin completions, 4 items
161+
// P2-DAG: Decl[GenericTypeParam]/Local: Self[#Self#];
154162
// P2-DAG: Decl[AssociatedType]/{{Super|CurrNominal}}: T;
155163
// P2-DAG: Decl[AssociatedType]/{{Super|CurrNominal}}: U;
164+
// P2-DAG: Decl[Protocol]/Local: P2[#P2#]
156165
// P2: End completions
157166

158167
// U_DOT: Begin completions, 2 items
@@ -165,10 +174,11 @@ protocol P3 where #^PROTOCOL^# {
165174
typealias U = T.Q
166175
typealias IntAlias = Int
167176
}
168-
// PROTOCOL: Begin completions, 3 items
177+
// PROTOCOL: Begin completions, 4 items
169178
// PROTOCOL-DAG: Decl[GenericTypeParam]/Local: Self[#Self#];
170179
// PROTOCOL-DAG: Decl[AssociatedType]/CurrNominal: T;
171180
// PROTOCOL-DAG: Decl[TypeAlias]/CurrNominal: U[#Self.T.Q#];
181+
// PROTOCOL-DAG: Decl[Protocol]/Local: P3[#P3#];
172182
// PROTOCOL: End completions
173183

174184
extension P3 where #^PROTOCOL_EXT^# {
@@ -180,7 +190,7 @@ protocol P4 where Self.#^PROTOCOL_SELF^# {
180190
typealias U = T.Q
181191
typealias IntAlias = Int
182192
}
183-
// PROTOCOL_SELF: Begin completions, 4 items
193+
// PROTOCOL_SELF: Begin completions
184194
// PROTOCOL_SELF-DAG: Decl[AssociatedType]/CurrNominal: T;
185195
// PROTOCOL_SELF-DAG: Decl[TypeAlias]/CurrNominal: U[#Self.T.Q#];
186196
// PROTOCOL_SELF-DAG: Decl[TypeAlias]/CurrNominal: IntAlias[#Int#];
@@ -194,9 +204,11 @@ struct TA1<T: Assoc> where #^NOMINAL_TYPEALIAS^# {
194204
// NOMINAL_TYPEALIAS-DAG: Decl[GenericTypeParam]/Local: T[#T#];
195205
// NOMINAL_TYPEALIAS: End completions
196206
extension TA1 where #^NOMINAL_TYPEALIAS_EXT^# { }
197-
// NOMINAL_TYPEALIAS_EXT: Begin completions, 2 items
207+
// NOMINAL_TYPEALIAS_EXT: Begin completions, 4 items
198208
// NOMINAL_TYPEALIAS_EXT-DAG: Decl[GenericTypeParam]/Local: T[#T#];
199209
// NOMINAL_TYPEALIAS_EXT-DAG: Decl[TypeAlias]/CurrNominal: U[#T.Q#];
210+
// NOMINAL_TYPEALIAS_EXT-DAG: Decl[Struct]/Local: TA1[#TA1#];
211+
// NOMINAL_TYPEALIAS_EXT-DAG: Keyword[Self]/CurrNominal: Self[#TA1<T>#];
200212
// NOMINAL_TYPEALIAS_EXT: End completions
201213

202214
struct TA2<T: Assoc> {
@@ -217,17 +229,23 @@ struct TA2<T: Assoc> {
217229
// NOMINAL_TYPEALIAS_NESTED2: End completions
218230
}
219231
extension TA2.Inner1 where #^NOMINAL_TYPEALIAS_NESTED1_EXT^# {}
220-
// NOMINAL_TYPEALIAS_NESTED1_EXT: Begin completions, 4 items
232+
// NOMINAL_TYPEALIAS_NESTED1_EXT: Begin completions, 6 items
221233
// NOMINAL_TYPEALIAS_NESTED1_EXT-DAG: Decl[GenericTypeParam]/Local: T[#T#];
222234
// NOMINAL_TYPEALIAS_NESTED1_EXT-DAG: Decl[GenericTypeParam]/Local: U[#U#];
223235
// NOMINAL_TYPEALIAS_NESTED1_EXT-DAG: Decl[TypeAlias]/CurrNominal: X1[#T#];
224236
// NOMINAL_TYPEALIAS_NESTED1_EXT-DAG: Decl[TypeAlias]/CurrNominal: X2[#T.Q#];
237+
// FIXME : We shouldn't be suggesting Inner1 because it's not fully-qualified
238+
// NOMINAL_TYPEALIAS_NESTED1_EXT-DAG: Decl[Struct]/Local: Inner1[#TA2.Inner1#];
239+
// NOMINAL_TYPEALIAS_NESTED1_EXT-DAG: Keyword[Self]/CurrNominal: Self[#TA2<T>.Inner1<U>#];
225240
// NOMINAL_TYPEALIAS_NESTED1_EXT: End completions
226241
extension TA2.Inner2 where #^NOMINAL_TYPEALIAS_NESTED2_EXT^# {}
227-
// NOMINAL_TYPEALIAS_NESTED2_EXT: Begin completions, 3 items
242+
// NOMINAL_TYPEALIAS_NESTED2_EXT: Begin completions, 5 items
228243
// NOMINAL_TYPEALIAS_NESTED2_EXT-DAG: Decl[GenericTypeParam]/Local: T[#T#];
229244
// NOMINAL_TYPEALIAS_NESTED2_EXT-DAG: Decl[TypeAlias]/CurrNominal: X1[#T#];
230245
// NOMINAL_TYPEALIAS_NESTED2_EXT-DAG: Decl[TypeAlias]/CurrNominal: X2[#T.Q#];
246+
// FIXME : We shouldn't be suggesting Inner2 because it's not fully-qualified
247+
// NOMINAL_TYPEALIAS_NESTED2_EXT-DAG: Decl[Struct]/Local: Inner2[#TA2.Inner2#];
248+
// NOMINAL_TYPEALIAS_NESTED2_EXT-DAG: Keyword[Self]/CurrNominal: Self[#TA2<T>.Inner2#];
231249
// NOMINAL_TYPEALIAS_NESTED2_EXT: End completions
232250

233251
protocol WithAssoc {

0 commit comments

Comments
 (0)