Skip to content

Commit 14107ac

Browse files
author
Nathan Hawes
authored
Merge pull request swiftlang#27983 from nathawes/complete-self-dot-init-in-struct-initializer
[code-completion] Suggest self.init in value type constructors
2 parents 9794b70 + 1317db9 commit 14107ac

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,10 +3025,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
30253025
auto CDC = dyn_cast<ConstructorDecl>(CurrDeclContext);
30263026
if (!CDC)
30273027
return;
3028-
// We do not want 'init' completions for 'self' in non-convenience
3029-
// initializers and for 'super' in convenience initializers.
3030-
if ((IsSelfRefExpr && CDC->isConvenienceInit()) ||
3031-
((IsSuperRefExpr && !CDC->isConvenienceInit())))
3028+
3029+
// For classes, we do not want 'init' completions for 'self' in
3030+
// non-convenience initializers and for 'super' in convenience initializers.
3031+
if (ExprType->is<ClassType>()) {
3032+
if ((IsSelfRefExpr && !CDC->isConvenienceInit()) ||
3033+
(IsSuperRefExpr && CDC->isConvenienceInit()))
3034+
return;
3035+
}
3036+
if (IsSelfRefExpr || IsSuperRefExpr)
30323037
addConstructorCall(CD, Reason, dynamicLookupInfo, None, None,
30333038
/*IsOnType=*/false);
30343039
}

test/IDE/complete_after_self.swift

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SELF_DOT_1 < %t.self.txt
1111
// RUN: %FileCheck %s -check-prefix=COMMON_SELF_DOT_1 < %t.self.txt
1212

13+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONVENIENCE_SELF_DOT_1 > %t.self.txt
14+
// RUN: %FileCheck %s -check-prefix=CONVENIENCE_SELF_DOT_1 < %t.self.txt
15+
// RUN: %FileCheck %s -check-prefix=COMMON_SELF_DOT_1 < %t.self.txt
16+
1317
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONSTRUCTOR_NONSELF_DOT_1 > %t.self.txt
1418
// RUN: %FileCheck %s -check-prefix=COMMON_SELF_DOT_1 < %t.self.txt
1519
// RUN: %FileCheck %s -check-prefix=NO_INIT < %t.self.txt
@@ -49,6 +53,10 @@
4953
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_CONSTRUCTOR_NONSELF_DOT_1 > %t.self.txt
5054
// RUN: %FileCheck %s -check-prefix=NO_INIT < %t.self.txt
5155

56+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=EXTENSION_CONSTRUCTOR_SELF_DOT_1 > %t.self.txt
57+
// RUN: %FileCheck %s -check-prefix=COMMON_SELF_DOT_1 < %t.self.txt
58+
// RUN: %FileCheck %s -check-prefix=EXTENSION_CONSTRUCTOR_SELF_DOT_1 < %t.self.txt
59+
5260
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_SELF_DOT_1 > %t.self.txt
5361
// RUN: %FileCheck %s -check-prefix=NO_INIT < %t.self.txt
5462

@@ -177,16 +185,24 @@ class ThisDerived1 : ThisBase1 {
177185
// NO_INIT-NOT: init()
178186
}
179187

180-
init(a : Int) {
188+
init(a: Int) {
181189
self.#^CONSTRUCTOR_SELF_DOT_1^#
182190
// CONSTRUCTOR_SELF_DOT_1: Begin completions, 16 items
183191
// CONSTRUCTOR_SELF_DOT_1-NOT: Decl[Constructor]
184-
185192
// CONSTRUCTOR_SELF_DOT_1: End completions
186193
let d: ThisDerived1
187194
d.#^CONSTRUCTOR_NONSELF_DOT_1^#
188195
}
189196

197+
convenience init(conv: Int) {
198+
self.#^CONVENIENCE_SELF_DOT_1^#
199+
// CONVENIENCE_SELF_DOT_1: Begin completions, 20 items
200+
// CONVENIENCE_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init()[#ThisDerived1#]; name=init()
201+
// CONVENIENCE_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init({#a: Int#})[#ThisDerived1#]; name=init(a: Int)
202+
// CONVENIENCE_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init({#conv: Int#})[#ThisDerived1#]; name=init(conv: Int)
203+
// CONVENIENCE_SELF_DOT_1: End completions
204+
}
205+
190206
deinit {
191207
self#^DESTRUCTOR_SELF_NO_DOT_1^#
192208
// DESTRUCTOR_SELF_NO_DOT_1: Begin completions, 21 items
@@ -217,6 +233,7 @@ class ThisDerived1 : ThisBase1 {
217233
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: .derivedStaticFunc0()[#Void#]
218234
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: .init()[#ThisDerived1#]
219235
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: .init({#a: Int#})[#ThisDerived1#]
236+
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: .init({#conv: Int#})[#ThisDerived1#]
220237
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: .test1({#(self): ThisDerived1#})[#() -> Void#]
221238
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: .test2({#(self): ThisDerived1#})[#() -> Void#]
222239
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: .staticTest1()[#Void#]
@@ -251,6 +268,7 @@ class ThisDerived1 : ThisBase1 {
251268
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: derivedStaticFunc0()[#Void#]
252269
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Constructor]/CurrNominal: init()[#ThisDerived1#]
253270
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Constructor]/CurrNominal: init({#a: Int#})[#ThisDerived1#]
271+
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Constructor]/CurrNominal: init({#conv: Int#})[#ThisDerived1#]
254272
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: test1({#(self): ThisDerived1#})[#() -> Void#]
255273
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: test2({#(self): ThisDerived1#})[#() -> Void#]
256274
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: staticTest1()[#Void#]
@@ -312,17 +330,24 @@ extension ThisDerived1 {
312330

313331
convenience init(someExtensionArg: Int) {
314332
self.#^EXTENSION_CONSTRUCTOR_SELF_DOT_1^#
333+
// EXTENSION_CONSTRUCTOR_SELF_DOT_1: Begin completions, 20 items
334+
// EXTENSION_CONSTRUCTOR_SELF_DOT_1: Decl[Constructor]/CurrNominal: init()[#ThisDerived1#]; name=init()
335+
// EXTENSION_CONSTRUCTOR_SELF_DOT_1: Decl[Constructor]/CurrNominal: init({#a: Int#})[#ThisDerived1#]; name=init(a: Int)
336+
// EXTENSION_CONSTRUCTOR_SELF_DOT_1: Decl[Constructor]/CurrNominal: init({#someExtensionArg: Int#})[#ThisDerived1#]; name=init(someExtensionArg: Int)
337+
// EXTENSION_CONSTRUCTOR_SELF_DOT_1: End completions
338+
315339
}
316340
}
317341

318342
struct S1 {
319343
init() {}
320344
init(x: Int) {
321345
self.#^STRUCT_CONSTRUCTOR_SELF_DOT_1^#
322-
// STRUCT_CONSTRUCTOR_SELF_DOT_1: Begin completions, 2 items
323-
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Keyword[self]/CurrNominal: self[#S1#]; name=self
324-
// STRUCT_CONSTRUCTOR_SELF_DOT_1-NOT: Decl[Constructor]
325-
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: f()[#Void#];
346+
// STRUCT_CONSTRUCTOR_SELF_DOT_1: Begin completions, 4 items
347+
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Keyword[self]/CurrNominal: self[#S1#]; name=self
348+
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init()[#S1#]; name=init()
349+
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init({#x: Int#})[#S1#]; name=init(x: Int)
350+
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: f()[#Void#]; name=f()
326351
// STRUCT_CONSTRUCTOR_SELF_DOT_1: End completions
327352
let s: S1
328353
s.#^STRUCT_CONSTRUCTOR_NONSELF_DOT_1^#

0 commit comments

Comments
 (0)