Skip to content

Commit 1517ceb

Browse files
authored
Merge pull request #32288 from rintaro/5.3-ide-completion-sself-rdar61307680
[5.3][CodeCompletion] Suggest 'Self' inside struct, enum and classe
2 parents fc20aee + 157c38d commit 1517ceb

File tree

2 files changed

+273
-2
lines changed

2 files changed

+273
-2
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4491,6 +4491,51 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
44914491
getAttributeDeclParamCompletions(DAK_Available, 0);
44924492
}
44934493

4494+
void getSelfTypeCompletionInDeclContext(SourceLoc Loc, bool isForDeclResult) {
4495+
const DeclContext *typeDC = CurrDeclContext->getInnermostTypeContext();
4496+
if (!typeDC)
4497+
return;
4498+
4499+
// For protocols, there's a 'Self' generic parameter.
4500+
if (typeDC->getSelfProtocolDecl())
4501+
return;
4502+
4503+
Type selfType =
4504+
CurrDeclContext->mapTypeIntoContext(typeDC->getSelfInterfaceType());
4505+
4506+
if (typeDC->getSelfClassDecl()) {
4507+
// In classes, 'Self' can be used in result type of func, subscript and
4508+
// computed property, or inside function bodies.
4509+
bool canUseDynamicSelf = false;
4510+
if (isForDeclResult) {
4511+
canUseDynamicSelf = true;
4512+
} else {
4513+
const auto *checkDC = CurrDeclContext;
4514+
if (isa<TypeAliasDecl>(checkDC))
4515+
checkDC = checkDC->getParent();
4516+
4517+
if (const auto *AFD = checkDC->getInnermostMethodContext()) {
4518+
canUseDynamicSelf = Ctx.SourceMgr.rangeContainsTokenLoc(
4519+
AFD->getBodySourceRange(), Loc);
4520+
}
4521+
}
4522+
if (!canUseDynamicSelf)
4523+
return;
4524+
// 'Self' in class is a dynamic type.
4525+
selfType = DynamicSelfType::get(selfType, Ctx);
4526+
} else {
4527+
// In enums and structs, 'Self' is just an alias for the nominal type,
4528+
// and can be used anywhere.
4529+
}
4530+
4531+
CodeCompletionResultBuilder Builder(
4532+
Sink, CodeCompletionResult::ResultKind::Keyword,
4533+
SemanticContextKind::CurrentNominal, expectedTypeContext);
4534+
Builder.addKeyword("Self");
4535+
Builder.setKeywordKind(CodeCompletionKeywordKind::kw_Self);
4536+
addTypeAnnotation(Builder, selfType);
4537+
}
4538+
44944539
void getTypeCompletionsInDeclContext(SourceLoc Loc,
44954540
bool ModuleQualifier = true) {
44964541
Kind = LookupKind::TypeInDeclContext;
@@ -5783,6 +5828,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
57835828
auto DoPostfixExprBeginning = [&] (){
57845829
SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
57855830
Lookup.getValueCompletionsInDeclContext(Loc);
5831+
Lookup.getSelfTypeCompletionInDeclContext(Loc, /*isForDeclResult=*/false);
57865832
};
57875833

57885834
switch (Kind) {
@@ -5933,8 +5979,10 @@ void CodeCompletionCallbacksImpl::doneParsing() {
59335979

59345980
case CompletionKind::TypeDeclResultBeginning:
59355981
case CompletionKind::TypeSimpleBeginning: {
5936-
Lookup.getTypeCompletionsInDeclContext(
5937-
P.Context.SourceMgr.getCodeCompletionLoc());
5982+
auto Loc = Context.SourceMgr.getCodeCompletionLoc();
5983+
Lookup.getTypeCompletionsInDeclContext(Loc);
5984+
Lookup.getSelfTypeCompletionInDeclContext(
5985+
Loc, Kind == CompletionKind::TypeDeclResultBeginning);
59385986
break;
59395987
}
59405988

test/IDE/complete_sself.swift

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_BODY_EXPR | %FileCheck %s --check-prefix=NOSELF
2+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_BODY_TYPE | %FileCheck %s --check-prefix=NOSELF
3+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_VARBODY_EXPR | %FileCheck %s --check-prefix=NOSELF
4+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF
5+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF
6+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=NOSELF
7+
8+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM
9+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM
10+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM
11+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM
12+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_VAR_TYPE | %FileCheck %s --check-prefix=GENERICPARAM
13+
14+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM
15+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=GENERICPARAM
16+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM
17+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM
18+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM
19+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_VAR_TYPE | %FileCheck %s --check-prefix=GENERICPARAM
20+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_BODY_EXPR | %FileCheck %s --check-prefix=GENERICPARAM
21+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_BODY_TYPE | %FileCheck %s --check-prefix=GENERICPARAM
22+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=GENERICPARAM
23+
24+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF
25+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=STATICSELF
26+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF
27+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF
28+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF
29+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_VAR_TYPE | %FileCheck %s --check-prefix=STATICSELF
30+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_BODY_EXPR | %FileCheck %s --check-prefix=STATICSELF
31+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_BODY_TYPE | %FileCheck %s --check-prefix=STATICSELF
32+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_VARBODY_EXPR | %FileCheck %s --check-prefix=STATICSELF
33+
34+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF
35+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=STATICSELF
36+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF
37+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF
38+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF
39+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_VAR_TYPE | %FileCheck %s --check-prefix=STATICSELF
40+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_BODY_EXPR | %FileCheck %s --check-prefix=STATICSELF
41+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_BODY_TYPE | %FileCheck %s --check-prefix=STATICSELF
42+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=STATICSELF
43+
44+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF
45+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF
46+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF
47+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF
48+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF
49+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_VAR_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF
50+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_BODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF
51+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_BODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF
52+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_VARBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF
53+
54+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF
55+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF
56+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF
57+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF
58+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF
59+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_VAR_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF
60+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_BODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF
61+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_BODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF
62+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF
63+
64+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDBODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF
65+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF
66+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_PARAMTYPE | %FileCheck %s --check-prefix=DYNAMICSELF
67+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=DYNAMICSELF
68+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF
69+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_TYPEALIAS_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF
70+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDTYPE_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF
71+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDTYPE_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF
72+
73+
// NOSELF: Begin completions
74+
// NOSELF-NOT: name=Self
75+
// NOSELF: End completions
76+
77+
// GENERICPARAM: Begin completions
78+
// GENERICPARAM: Decl[GenericTypeParam]/Local: Self[#Self#];
79+
80+
// STATICSELF: Begin completions
81+
// STATICSELF: Keyword[Self]/CurrNominal: Self[#S#];
82+
83+
// DYNAMICSELF: Begin completions
84+
// DYNAMICSELF: Keyword[Self]/CurrNominal: Self[#Self#];
85+
86+
func freeFunc() {
87+
#^GLOBAL_BODY_EXPR^#
88+
let _: #^GLOBAL_BODY_TYPE^#
89+
}
90+
var freeVar: String {
91+
"\(#^GLOBAL_VARBODY_EXPR^#)"
92+
}
93+
func freeFunc(x: #^GLOBAL_FUNC_PARAMTYPE^#) {}
94+
func freeFunc(x: Int = #^GLOBAL_FUNC_DEFAULTEXPR^#) {}
95+
func freeFunc(x: Int) -> #^GLOBAL_FUNC_RESULTTYPE^# {}
96+
97+
var x: ^#GLOBAL_VAR_TYPE^#
98+
99+
func sync() {}
100+
101+
protocol P {
102+
func protoMeth(x: #^PROTOCOL_FUNC_PARAMTYPE^#)
103+
func protoMeth(x: Int) -> #^PROTOCOL_FUNC_RESULTTYPE^#
104+
105+
subscript(x: #^PROTOCOL_SUBSCRIPT_PARAMTYPE^#) -> Int { get }
106+
subscript(y: Int) -> #^PROTOCOL_SUBSCRIPT_RESULTTYPE^# { get }
107+
108+
var x: #^PROTOCOL_VAR_TYPE^#
109+
}
110+
extension P {
111+
func method(x: #^PROTOEXT_FUNC_PARAMTYPE^#) { }
112+
func method(x: Int = #^PROTOEXT_FUNC_DEFAULTEXPR^#) { }
113+
func method(x: Int) -> #^PROTOEXT_FUNC_RESULTTYPE^# { }
114+
115+
subscript(x: #^PROTOEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { }
116+
subscript(y: Int) -> #^PROTOEXT_SUBSCRIPT_RESULTTYPE^# { }
117+
118+
var x: #^PROTOEXT_VAR_TYPE^# { }
119+
120+
func bodyTest() {
121+
#^PROTOEXT_BODY_EXPR^#
122+
let _: #^PROTOEXT_BODY_TYPE^#
123+
}
124+
var varTest: String {
125+
"\(#^PROTOEXT_VARBODY_EXPR^#)"
126+
}
127+
}
128+
129+
struct S {
130+
func method(x: #^STRUCT_FUNC_PARAMTYPE^#)
131+
func method(x: Int = #^STRUCT_FUNC_DEFAULTEXPR^#) { }
132+
func method(x: Int) -> #^STRUCT_FUNC_RESULTTYPE^#
133+
134+
subscript(x: #^STRUCT_SUBSCRIPT_PARAMTYPE^#) -> Int { get }
135+
subscript(y: Int) -> #^STRUCT_SUBSCRIPT_RESULTTYPE^# { get }
136+
137+
var x: #^STRUCT_VAR_TYPE^#
138+
139+
func bodyTest() {
140+
#^STRUCT_BODY_EXPR^#
141+
let _: #^STRUCT_BODY_TYPE^#
142+
}
143+
var varTest: String {
144+
"\(#^STRUCT_VARBODY_EXPR^#)"
145+
}
146+
}
147+
extension S {
148+
func method(x: #^STRUCTEXT_FUNC_PARAMTYPE^#)
149+
func method(x: Int = #^STRUCTEXT_FUNC_DEFAULTEXPR^#) { }
150+
func method(x: Int) -> #^STRUCTEXT_FUNC_RESULTTYPE^#
151+
152+
subscript(x: #^STRUCTEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { get }
153+
subscript(y: Int) -> #^STRUCTEXT_SUBSCRIPT_RESULTTYPE^# { get }
154+
155+
var x: #^STRUCTEXT_VAR_TYPE^#
156+
157+
func bodyTest() {
158+
#^STRUCTEXT_BODY_EXPR^#
159+
let _: #^STRUCTEXT_BODY_TYPE^#
160+
}
161+
var varTest: String {
162+
"\(#^STRUCTEXT_VARBODY_EXPR^#)"
163+
}
164+
}
165+
166+
class C {
167+
func method(x: #^CLASS_FUNC_PARAMTYPE^#)
168+
func method(x: Int = #^CLASS_FUNC_DEFAULTEXPR^#) { }
169+
func method(x: Int) -> #^CLASS_FUNC_RESULTTYPE^#
170+
171+
subscript(x: #^CLASS_SUBSCRIPT_PARAMTYPE^#) -> Int { get }
172+
subscript(y: Int) -> #^CLASS_SUBSCRIPT_RESULTTYPE^# { get }
173+
174+
var x: #^CLASS_VAR_TYPE^#
175+
176+
func bodyTest() {
177+
#^CLASS_BODY_EXPR^#
178+
let _: #^CLASS_BODY_TYPE^#
179+
}
180+
var varTest: String {
181+
"\(#^CLASS_VARBODY_EXPR^#)"
182+
}
183+
}
184+
class CC {}
185+
extension CC {
186+
func method(x: #^CLASSEXT_FUNC_PARAMTYPE^#)
187+
func method(x: Int = #^CLASSEXT_FUNC_DEFAULTEXPR^#) { }
188+
func method(x: Int) -> #^CLASSEXT_FUNC_RESULTTYPE^#
189+
190+
subscript(x: #^CLASSEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { get }
191+
subscript(y: Int) -> #^CLASSEXT_SUBSCRIPT_RESULTTYPE^# { get }
192+
193+
var x: #^CLASSEXT_VAR_TYPE^#
194+
195+
func bodyTest() {
196+
#^CLASSEXT_BODY_EXPR^#
197+
let _: #^CLASSEXT_BODY_TYPE^#
198+
}
199+
var varTest: String {
200+
"\(#^CLASSEXT_VARBODY_EXPR^#)"
201+
}
202+
}
203+
204+
class CCC {
205+
func bodyTest() {
206+
func inner() {
207+
#^CLASS_NESTEDBODY_EXPR^#
208+
let _: #^CLASS_NESTEDBODY_TYPE^#
209+
}
210+
211+
func inner(x: #^CLASS_NESTEDFUNC_PARAMTYPE^#) {}
212+
func inner(y: Int = #^CLASS_NESTEDFUNC_DEFAULTEXPR^#) {}
213+
func inner() -> #^CLASS_NESTEDFUNC_RESULTTYPE^# {}
214+
215+
typealias A<T> = #^CLASS_TYPEALIAS_TYPE^#
216+
}
217+
class Inner {
218+
func method() {
219+
#^CLASS_NESTEDTYPE_EXPR^#
220+
let _: #^CLASS_NESTEDTYPE_TYPE^#
221+
}
222+
}
223+
}

0 commit comments

Comments
 (0)