Skip to content

Commit ea68861

Browse files
committed
[CodeCompletion] Generalize generic requirement completion
Align completion logics for all 'where' clauses.
1 parent e5cdbb7 commit ea68861

File tree

4 files changed

+70
-13
lines changed

4 files changed

+70
-13
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3959,7 +3959,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39593959
}
39603960

39613961
void getGenericRequirementCompletions(DeclContext *DC) {
3962-
39633962
auto genericSig = DC->getGenericSignatureOfContext();
39643963
if (!genericSig)
39653964
return;
@@ -3968,8 +3967,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39683967
addGenericTypeParamRef(GPT->getDecl(),
39693968
DeclVisibilityKind::GenericParameter, {});
39703969
}
3971-
3972-
auto selfTy = DC->getSelfTypeInContext();
3970+
3971+
auto typeContext = DC->getInnermostTypeContext();
3972+
if (!typeContext)
3973+
return;
3974+
3975+
auto selfTy = typeContext->getSelfTypeInContext();
39733976
Kind = LookupKind::GenericRequirement;
39743977
this->BaseType = selfTy;
39753978
NeedLeadingDot = false;

lib/Parse/ParseDecl.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4638,9 +4638,7 @@ Parser::parseDeclExtension(ParseDeclOptions Flags, DeclAttributes &Attributes) {
46384638
firstTypeInComplete);
46394639
if (whereStatus.hasCodeCompletion()) {
46404640
if (isCodeCompletionFirstPass())
4641-
return makeParserCodeCompletionStatus();
4642-
if (firstTypeInComplete && CodeCompletion)
4643-
CodeCompletion->completeGenericRequirement();
4641+
return whereStatus;
46444642
trailingWhereHadCodeCompletion = true;
46454643
}
46464644

@@ -7086,12 +7084,16 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) {
70867084
}
70877085

70887086
TrailingWhereClause *TrailingWhere = nullptr;
7087+
bool whereClauseHadCodeCompletion = false;
70897088
// Parse a 'where' clause if present.
70907089
if (Tok.is(tok::kw_where)) {
70917090
auto whereStatus = parseProtocolOrAssociatedTypeWhereClause(
70927091
TrailingWhere, /*isProtocol=*/true);
7093-
if (whereStatus.shouldStopParsing())
7094-
return whereStatus;
7092+
if (whereStatus.hasCodeCompletion()) {
7093+
if (isCodeCompletionFirstPass())
7094+
return whereStatus;
7095+
whereClauseHadCodeCompletion = true;
7096+
}
70957097
}
70967098

70977099
ProtocolDecl *Proto = new (Context)
@@ -7100,6 +7102,8 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) {
71007102
// No need to setLocalDiscriminator: protocols can't appear in local contexts.
71017103

71027104
Proto->getAttrs() = Attributes;
7105+
if (whereClauseHadCodeCompletion && CodeCompletion)
7106+
CodeCompletion->setParsedDecl(Proto);
71037107

71047108
ContextChange CC(*this, Proto);
71057109
Scope ProtocolBodyScope(this, ScopeKind::ProtocolBody);

lib/Parse/ParseGeneric.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,14 @@ ParserStatus Parser::parseGenericWhereClause(
279279
Optional<SyntaxParsingContext> BodyContext;
280280
BodyContext.emplace(SyntaxContext);
281281

282+
if (Tok.is(tok::code_complete)) {
283+
if (CodeCompletion)
284+
CodeCompletion->completeGenericRequirement();
285+
consumeToken(tok::code_complete);
286+
Status.setHasCodeCompletion();
287+
break;
288+
}
289+
282290
// Parse the leading type. It doesn't necessarily have to be just a type
283291
// identifier if we're dealing with a same-type constraint.
284292
ParserResult<TypeRepr> FirstType = parseType();

test/IDE/complete_where_clause.swift

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GP3 | %FileCheck %s -check-prefix=A1
44
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GP4 | %FileCheck %s -check-prefix=TYPE1
55
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GP5 | %FileCheck %s -check-prefix=TYPE1
6-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GP6 | %FileCheck %s -check-prefix=A1
6+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GP6 | %FileCheck %s -check-prefix=EMPTY
77
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_ASSOC_NODUP_1 | %FileCheck %s -check-prefix=GEN_T_ASSOC_E
88
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_ASSOC_NODUP_2 | %FileCheck %s -check-prefix=GEN_T_ASSOC_E
99
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FUNC_1 | %FileCheck %s -check-prefix=GEN_T
@@ -21,14 +21,17 @@
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
24-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_3 | %FileCheck %s -check-prefix=GEN_T_NOMINAL
24+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_3 | %FileCheck %s -check-prefix=ANYTYPE
2525
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_4 | %FileCheck %s -check-prefix=GEN_T_DOT
2626
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_1 | %FileCheck %s -check-prefix=GEN_T_NOMINAL
2727
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_2 | %FileCheck %s -check-prefix=GEN_T_DOT
2828
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_1 | %FileCheck %s -check-prefix=GEN_T_NOMINAL
2929
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_2 | %FileCheck %s -check-prefix=GEN_T_DOT
3030
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ASSOC_1 | %FileCheck %s -check-prefix=P2
3131
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ASSOC_2 | %FileCheck %s -check-prefix=U_DOT
32+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL | %FileCheck %s -check-prefix=PROTOCOL
33+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT | %FileCheck %s -check-prefix=PROTOCOL
34+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SELF | %FileCheck %s -check-prefix=PROTOCOL_SELF
3235

3336
class A1<T1, T2, T3> {}
3437

@@ -65,6 +68,10 @@ extension A1 where T1.#^GP6^# {}
6568
// TYPE1-NOT: T4
6669
// TYPE1-NOT: T5
6770

71+
// EMPTY: Begin completions, 1 items
72+
// EMPTY-DAG: Keyword/None: Type[#T1.Type#]; name=Type
73+
// EMPTY: End completions
74+
6875
protocol A {associatedtype E}
6976
protocol B {associatedtype E}
7077

@@ -118,20 +125,55 @@ class C1<T> where #^CLASS_1^# {}
118125
class C2<T> where T.#^CLASS_2^# {}
119126
enum E1<T> where #^ENUM_1^# {}
120127
enum E2<T> where T.#^ENUM_2^# {}
128+
// GEN_T_NOMINAL: Begin completions, 1 items
121129
// GEN_T_NOMINAL: Decl[GenericTypeParam]/Local: T[#T#]; name=T
130+
// GEN_T_NOMINAL: End completions
131+
132+
// ANYTYPE: Begin completions
133+
// ANYTYPE-DAG: Decl[GenericTypeParam]/Local: T[#T#];
134+
// ANYTYPE-DAG: Decl[Class]/CurrModule: A1[#A1#];
135+
// ANYTYPE-DAG: Decl[Struct]/OtherModule[Swift]: Int[#Int#];
136+
// ANYTYPE: End completions
122137

123138
protocol P2 {
124139
associatedtype T where #^ASSOC_1^#
125140
associatedtype U: Assoc where U.#^ASSOC_2^#
126141
}
127142

128-
// P2: Begin completions
143+
// P2: Begin completions, 3 items
129144
// P2-DAG: Decl[GenericTypeParam]/Local: Self[#Self#];
130145
// P2-DAG: Decl[AssociatedType]/{{Super|CurrNominal}}: T;
131146
// P2-DAG: Decl[AssociatedType]/{{Super|CurrNominal}}: U;
132147
// P2: End completions
133148

134-
// U_DOT: Begin completions
135-
// FIXME: Should complete Q from Assoc.
149+
// U_DOT: Begin completions, 2 items
136150
// U_DOT-DAG: Keyword/None: Type[#Self.U.Type#];
151+
// U_DOT-DAG: Decl[AssociatedType]/CurrNominal: Q;
137152
// U_DOT: End completions
153+
154+
protocol P3 where #^PROTOCOL^# {
155+
associatedtype T: Assoc
156+
typealias U = T.Q
157+
typealias IntAlias = Int
158+
}
159+
// PROTOCOL: Begin completions, 3 items
160+
// PROTOCOL-DAG: Decl[GenericTypeParam]/Local: Self[#Self#];
161+
// PROTOCOL-DAG: Decl[AssociatedType]/CurrNominal: T;
162+
// PROTOCOL-DAG: Decl[TypeAlias]/CurrNominal: U[#Self.T.Q#];
163+
// PROTOCOL: End completions
164+
165+
extension P3 where #^PROTOCOL_EXT^# {
166+
// Same as PROTOCOL
167+
}
168+
169+
protocol P4 where Self.#^PROTOCOL_SELF^# {
170+
associatedtype T: Assoc
171+
typealias U = T.Q
172+
typealias IntAlias = Int
173+
}
174+
// PROTOCOL_SELF: Begin completions, 4 items
175+
// PROTOCOL_SELF-DAG: Decl[AssociatedType]/CurrNominal: T;
176+
// PROTOCOL_SELF-DAG: Decl[TypeAlias]/CurrNominal: U[#Self.T.Q#];
177+
// PROTOCOL_SELF-DAG: Decl[TypeAlias]/CurrNominal: IntAlias[#Int#];
178+
// PROTOCOL_SELF-DAG: Keyword/None: Type[#Self.Type#];
179+
// PROTOCOL_SELF: End completions

0 commit comments

Comments
 (0)