Skip to content

Commit e8b08de

Browse files
authored
Merge pull request #16868 from AnthonyLatsis/code-compl-missing-init-dotexpr
[CodeCompletion] Missing init completions for dotExpr
2 parents 7b69302 + ff4d061 commit e8b08de

File tree

6 files changed

+168
-58
lines changed

6 files changed

+168
-58
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,7 +2586,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25862586

25872587
void addConstructorCall(const ConstructorDecl *CD, DeclVisibilityKind Reason,
25882588
Optional<Type> BaseType, Optional<Type> Result,
2589-
bool IsOnMetatype = true,
2589+
bool IsOnType = true,
25902590
Identifier addName = Identifier()) {
25912591
foundFunction(CD);
25922592
Type MemberType = getTypeOfMember(CD, BaseType);
@@ -2596,14 +2596,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25962596
->castTo<AnyFunctionType>();
25972597

25982598
bool needInit = false;
2599-
if (!IsOnMetatype) {
2599+
if (!IsOnType) {
26002600
assert(addName.empty());
2601-
assert(isa<ConstructorDecl>(CurrDeclContext) &&
2602-
"can call super.init only inside a constructor");
26032601
needInit = true;
2604-
} else if (addName.empty() && HaveDot &&
2605-
Reason == DeclVisibilityKind::MemberOfCurrentNominal) {
2606-
// This case is querying the init function as member
2602+
} else if (addName.empty() && HaveDot) {
26072603
needInit = true;
26082604
}
26092605

@@ -2633,7 +2629,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26332629
addTypeAnnotation(Builder, MemberType);
26342630
return;
26352631
}
2636-
assert(ConstructorType);
26372632

26382633
if (!HaveLParen)
26392634
Builder.addLeftParen();
@@ -2687,7 +2682,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26872682
if (shouldHideDeclFromCompletionResults(init))
26882683
continue;
26892684
addConstructorCall(cast<ConstructorDecl>(init), Reason, type, None,
2690-
/*IsOnMetatype=*/true, name);
2685+
/*IsOnType=*/true, name);
26912686
}
26922687
}
26932688
}
@@ -2938,43 +2933,40 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
29382933
return;
29392934
}
29402935

2941-
if (auto MT = ExprType->getRValueType()->getAs<AnyMetatypeType>()) {
2942-
if (HaveDot) {
2943-
Type Ty;
2944-
for (Ty = MT; Ty && Ty->is<AnyMetatypeType>();
2945-
Ty = Ty->getAs<AnyMetatypeType>()->getInstanceType());
2946-
assert(Ty && "Cannot find instance type.");
2947-
2948-
// Add init() as member of the metatype.
2949-
if (Reason == DeclVisibilityKind::MemberOfCurrentNominal) {
2950-
if (IsStaticMetatype || CD->isRequired() ||
2951-
!Ty->is<ClassType>())
2952-
addConstructorCall(CD, Reason, None, None);
2953-
}
2954-
return;
2955-
}
2956-
}
2957-
29582936
if (auto MT = ExprType->getAs<AnyMetatypeType>()) {
2959-
if (HaveDot)
2960-
return;
2937+
Type Ty = MT->getInstanceType();
2938+
assert(Ty && "Cannot find instance type.");
29612939

2962-
// If instance type is type alias, showing users that the constructed
2940+
// If instance type is type alias, show users that the constructed
29632941
// type is the typealias instead of the underlying type of the alias.
29642942
Optional<Type> Result = None;
2965-
if (auto AT = MT->getInstanceType()) {
2966-
if (!CD->getInterfaceType()->is<ErrorType>() &&
2967-
(isa<NameAliasType>(AT.getPointer()) &&
2968-
AT->getDesugaredType() ==
2969-
CD->getResultInterfaceType().getPointer()))
2970-
Result = AT;
2943+
if (!CD->getInterfaceType()->is<ErrorType>() &&
2944+
isa<NameAliasType>(Ty.getPointer()) &&
2945+
Ty->getDesugaredType() ==
2946+
CD->getResultInterfaceType().getPointer()) {
2947+
Result = Ty;
29712948
}
2972-
addConstructorCall(CD, Reason, None, Result);
2949+
// If the expression type is not a static metatype or an archetype, the base
2950+
// is not a type. Direct call syntax is illegal on values, so we only add
2951+
// initializer completions if we do not have a left parenthesis and either
2952+
// the initializer is required, the base type's instance type is not a class,
2953+
// or this is a 'self' or 'super' reference.
2954+
if (IsStaticMetatype || Ty->is<ArchetypeType>())
2955+
addConstructorCall(CD, Reason, None, Result, /*isOnType*/true);
2956+
else if ((IsSelfRefExpr || IsSuperRefExpr || !Ty->is<ClassType>() ||
2957+
CD->isRequired()) && !HaveLParen)
2958+
addConstructorCall(CD, Reason, None, Result, /*isOnType*/false);
2959+
return;
29732960
}
2974-
if (IsSuperRefExpr || IsSelfRefExpr) {
2975-
if (!isa<ConstructorDecl>(CurrDeclContext))
2961+
if (!HaveLParen) {
2962+
auto CDC = dyn_cast<ConstructorDecl>(CurrDeclContext);
2963+
if (!CDC)
29762964
return;
2977-
addConstructorCall(CD, Reason, None, None, /*IsOnMetatype=*/false);
2965+
// We do not want 'init' completions for 'self' in non-convenience
2966+
// initializers and for 'super' in convenience initializers.
2967+
if ((IsSelfRefExpr && CDC->isConvenienceInit()) ||
2968+
((IsSuperRefExpr && !CDC->isConvenienceInit())))
2969+
addConstructorCall(CD, Reason, None, None, /*IsOnType=*/false);
29782970
}
29792971
return;
29802972
}

test/IDE/complete_after_self.swift

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
// RUN: %FileCheck %s -check-prefix=COMMON_SELF_NO_DOT_1 < %t.self.txt
3030
// RUN: %FileCheck %s -check-prefix=NO_INIT < %t.self.txt
3131

32+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC_SELF_PAREN > %t.self.txt
33+
// RUN: %FileCheck %s -check-prefix=STATIC_SELF_PAREN < %t.self.txt
34+
3235
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_SELF_DOT_1 > %t.self.txt
3336
// RUN: %FileCheck %s -check-prefix=FUNC_SELF_DOT_1 < %t.self.txt
3437
// RUN: %FileCheck %s -check-prefix=COMMON_SELF_DOT_1 < %t.self.txt
@@ -166,9 +169,8 @@ class ThisDerived1 : ThisBase1 {
166169

167170
init() {
168171
self#^CONSTRUCTOR_SELF_NO_DOT_1^#
169-
// CONSTRUCTOR_SELF_NO_DOT_1: Begin completions, 24 items
170-
// CONSTRUCTOR_SELF_NO_DOT_1-DAG: Decl[Constructor]/CurrNominal: .init()[#ThisDerived1#];
171-
// CONSTRUCTOR_SELF_NO_DOT_1-DAG: Decl[Constructor]/CurrNominal: .init({#a: Int#})[#ThisDerived1#];
172+
// CONSTRUCTOR_SELF_NO_DOT_1: Begin completions, 21 items
173+
// CONSTRUCTOR_SELF_NO_DOT_1-NOT: Decl[Constructor]
172174
// CONSTRUCTOR_SELF_NO_DOT_1: End completions
173175
let d: ThisDerived1
174176
d#^CONSTRUCTOR_NONSELF_NO_DOT_1^#
@@ -177,9 +179,8 @@ class ThisDerived1 : ThisBase1 {
177179

178180
init(a : Int) {
179181
self.#^CONSTRUCTOR_SELF_DOT_1^#
180-
// CONSTRUCTOR_SELF_DOT_1: Begin completions, 19 items
181-
// CONSTRUCTOR_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init()[#ThisDerived1#];
182-
// CONSTRUCTOR_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init({#a: Int#})[#ThisDerived1#];
182+
// CONSTRUCTOR_SELF_DOT_1: Begin completions, 16 items
183+
// CONSTRUCTOR_SELF_DOT_1-NOT: Decl[Constructor]
183184

184185
// CONSTRUCTOR_SELF_DOT_1: End completions
185186
let d: ThisDerived1
@@ -214,8 +215,8 @@ class ThisDerived1 : ThisBase1 {
214215
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: .derivedFunc0({#self: ThisDerived1#})[#() -> Void#]
215216
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[StaticVar]/CurrNominal: .derivedStaticVar[#Int#]
216217
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: .derivedStaticFunc0()[#Void#]
217-
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: ()[#ThisDerived1#]
218-
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: ({#a: Int#})[#ThisDerived1#]
218+
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: .init()[#ThisDerived1#]
219+
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: .init({#a: Int#})[#ThisDerived1#]
219220
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: .test1({#self: ThisDerived1#})[#() -> Void#]
220221
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: .test2({#self: ThisDerived1#})[#() -> Void#]
221222
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: .staticTest1()[#Void#]
@@ -226,7 +227,7 @@ class ThisDerived1 : ThisBase1 {
226227
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Class]/CurrNominal: .DerivedExtNestedClass[#ThisDerived1.DerivedExtNestedClass#]
227228
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Enum]/CurrNominal: .DerivedExtNestedEnum[#ThisDerived1.DerivedExtNestedEnum#]
228229
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[TypeAlias]/CurrNominal: .DerivedExtNestedTypealias[#Int#]
229-
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: ({#someExtensionArg: Int#})[#ThisDerived1#]
230+
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[Constructor]/CurrNominal: .init({#someExtensionArg: Int#})[#ThisDerived1#]
230231
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[InstanceMethod]/Super: .baseFunc0({#self: ThisBase1#})[#() -> Void#]
231232
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[InstanceMethod]/Super: .baseFunc1({#self: ThisBase1#})[#(Int) -> Void#]
232233
// FUNC_STATIC_SELF_NO_DOT_1-NEXT: Decl[StaticVar]/Super: .baseStaticVar[#Int#]
@@ -248,6 +249,8 @@ class ThisDerived1 : ThisBase1 {
248249
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: derivedFunc0({#self: ThisDerived1#})[#() -> Void#]
249250
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[StaticVar]/CurrNominal: derivedStaticVar[#Int#]
250251
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: derivedStaticFunc0()[#Void#]
252+
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Constructor]/CurrNominal: init()[#ThisDerived1#]
253+
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Constructor]/CurrNominal: init({#a: Int#})[#ThisDerived1#]
251254
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: test1({#self: ThisDerived1#})[#() -> Void#]
252255
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[InstanceMethod]/CurrNominal: test2({#self: ThisDerived1#})[#() -> Void#]
253256
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[StaticMethod]/CurrNominal: staticTest1()[#Void#]
@@ -258,6 +261,7 @@ class ThisDerived1 : ThisBase1 {
258261
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Class]/CurrNominal: DerivedExtNestedClass[#ThisDerived1.DerivedExtNestedClass#]
259262
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Enum]/CurrNominal: DerivedExtNestedEnum[#ThisDerived1.DerivedExtNestedEnum#]
260263
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[TypeAlias]/CurrNominal: DerivedExtNestedTypealias[#Int#]
264+
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[Constructor]/CurrNominal: init({#someExtensionArg: Int#})[#ThisDerived1#]
261265
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[InstanceMethod]/Super: baseFunc0({#self: ThisBase1#})[#() -> Void#]
262266
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[InstanceMethod]/Super: baseFunc1({#self: ThisBase1#})[#(Int) -> Void#]
263267
// FUNC_STATIC_SELF_DOT_1-NEXT: Decl[StaticVar]/Super: baseStaticVar[#Int#]
@@ -272,6 +276,11 @@ class ThisDerived1 : ThisBase1 {
272276
}
273277
}
274278

279+
class func staticTest3() {
280+
self(#^STATIC_SELF_PAREN^#
281+
// STATIC_SELF_PAREN-NOT: Decl[Constructor]
282+
}
283+
275284
extension ThisDerived1 {
276285
var derivedExtProp : Int {
277286
get {
@@ -310,10 +319,9 @@ struct S1 {
310319
init() {}
311320
init(x: Int) {
312321
self.#^STRUCT_CONSTRUCTOR_SELF_DOT_1^#
313-
// STRUCT_CONSTRUCTOR_SELF_DOT_1: Begin completions, 4 items
322+
// STRUCT_CONSTRUCTOR_SELF_DOT_1: Begin completions, 2 items
314323
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Keyword[self]/CurrNominal: self[#S1#]; name=self
315-
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init()[#S1#];
316-
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Decl[Constructor]/CurrNominal: init({#x: Int#})[#S1#];
324+
// STRUCT_CONSTRUCTOR_SELF_DOT_1-NOT: Decl[Constructor]
317325
// STRUCT_CONSTRUCTOR_SELF_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: f()[#Void#];
318326
// STRUCT_CONSTRUCTOR_SELF_DOT_1: End completions
319327
let s: S1

test/IDE/complete_after_super.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@
99
// RUN: %FileCheck %s -check-prefix=COMMON_BASE_A_DOT < %t.super.txt
1010
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SUPER_DOT_1 < %t.super.txt
1111

12+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONV_CONSTRUCTOR_SUPER_DOT > %t.super.txt
13+
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SUPER_NOINIT < %t.super.txt
14+
15+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONV_CONSTRUCTOR_SUPER_NO_DOT > %t.super.txt
16+
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SUPER_NOINIT < %t.super.txt
17+
18+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONV_CONSTRUCTOR_SUPER_PAREN > %t.super.txt
19+
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SUPER_NOINIT < %t.super.txt
20+
21+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONSTRUCTOR_SUPER_PAREN > %t.super.txt
22+
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SUPER_NOINIT < %t.super.txt
23+
24+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_SUPER_PAREN > %t.super.txt
25+
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SUPER_NOINIT < %t.super.txt
26+
1227
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONSTRUCTOR_SUPER_INIT_1 > %t.super.txt
1328
// RUN: %FileCheck %s -check-prefix=CONSTRUCTOR_SUPER_INIT_1 < %t.super.txt
1429

@@ -64,6 +79,11 @@
6479
// RUN: %FileCheck %s -check-prefix=FUNC_SUPER_DOT_2 < %t.super.txt
6580
// RUN: %FileCheck %s -check-prefix=NO_CONSTRUCTORS < %t.super.txt
6681

82+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_SUPER_NODOT > %t.super.txt
83+
// RUN: %FileCheck %s -check-prefix=CLASS_FUNC_SUPER < %t.super.txt
84+
85+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_SUPER_DOT > %t.super.txt
86+
// RUN: %FileCheck %s -check-prefix=CLASS_FUNC_SUPER < %t.super.txt
6787

6888
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=SEMANTIC_CONTEXT_OVERRIDDEN_DECL_1 > %t.super.txt
6989
// RUN: %FileCheck %s -check-prefix=SEMANTIC_CONTEXT_OVERRIDDEN_DECL_1 < %t.super.txt
@@ -221,11 +241,19 @@ class SuperDerivedA : SuperBaseA {
221241

222242
init(a: Int) {
223243
super.#^CONSTRUCTOR_SUPER_DOT_1^#
244+
super(#^CONSTRUCTOR_SUPER_PAREN^#
224245
// CONSTRUCTOR_SUPER_DOT_1: Begin completions, 7 items
225246
// CONSTRUCTOR_SUPER_DOT_1-DAG: Decl[Constructor]/CurrNominal: init()[#SuperBaseA#]{{; name=.+$}}
226247
// CONSTRUCTOR_SUPER_DOT_1: End completions
227248
}
228249

250+
convenience init(foo1: Int) {
251+
super.#^CONV_CONSTRUCTOR_SUPER_DOT^#
252+
super#^CONV_CONSTRUCTOR_SUPER_NO_DOT^#
253+
super(#^CONV_CONSTRUCTOR_SUPER_PAREN^#
254+
// CONSTRUCTOR_SUPER_NOINIT-NOT: Decl[Constructor]
255+
}
256+
229257
init (a: Float) {
230258
super.init#^CONSTRUCTOR_SUPER_INIT_1^#
231259
// CONSTRUCTOR_SUPER_INIT_1: Begin completions
@@ -411,6 +439,19 @@ class SuperDerivedB : SuperBaseB {
411439
// FUNC_SUPER_DOT_2: Begin completions, 6 items
412440
// FUNC_SUPER_DOT_2: End completions
413441
}
442+
443+
class func test3() {
444+
super#^CLASS_FUNC_SUPER_NODOT^#
445+
}
446+
class func test4() {
447+
super.#^CLASS_FUNC_SUPER_DOT^#
448+
}
449+
class func test5() {
450+
super(#^CLASS_FUNC_SUPER_PAREN^#
451+
}
452+
// CLASS_FUNC_SUPER: Decl[Constructor]/CurrNominal: {{.init|init}}()[#SuperBaseB#]
453+
// CLASS_FUNC_SUPER: Decl[Constructor]/CurrNominal: {{.init|init}}({#a: Double#})[#SuperBaseB#]
454+
// CLASS_FUNC_SUPER: Decl[Constructor]/CurrNominal: {{.init|init}}({#int: Int#})[#SuperBaseB#]
414455
}
415456

416457
//===--- Check that we assign a special semantic context to the overridden decl.

0 commit comments

Comments
 (0)