Skip to content

Commit f5f796b

Browse files
committed
[CodeCompletion] Add code completion for generic parameters' inherited types. rdar://20699515
1 parent a121db8 commit f5f796b

File tree

6 files changed

+82
-22
lines changed

6 files changed

+82
-22
lines changed

include/swift/Parse/Parser.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,9 +1190,9 @@ class Parser {
11901190
//===--------------------------------------------------------------------===//
11911191
// Generics Parsing
11921192

1193-
GenericParamList *parseGenericParameters();
1194-
GenericParamList *parseGenericParameters(SourceLoc LAngleLoc);
1195-
GenericParamList *maybeParseGenericParams();
1193+
ParserResult<GenericParamList> parseGenericParameters();
1194+
ParserResult<GenericParamList> parseGenericParameters(SourceLoc LAngleLoc);
1195+
ParserResult<GenericParamList> maybeParseGenericParams();
11961196
bool parseGenericWhereClause(SourceLoc &WhereLoc,
11971197
SmallVectorImpl<RequirementRepr> &Requirements);
11981198

lib/Parse/ParseDecl.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4051,7 +4051,7 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
40514051
Optional<Scope> GenericsScope;
40524052
GenericsScope.emplace(this, ScopeKind::Generics);
40534053
GenericParamList *GenericParams;
4054-
4054+
bool GPHasCodeCompletion = false;
40554055
// If the name is an operator token that ends in '<' and the following token
40564056
// is an identifier, split the '<' off as a separate token. This allows things
40574057
// like 'func ==<T>(x:T, y:T) {}' to parse as '==' with generic type variable
@@ -4061,10 +4061,16 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
40614061
SimpleName = Context.getIdentifier(SimpleName.str().
40624062
slice(0, SimpleName.str().size() - 1));
40634063
SourceLoc LAngleLoc = NameLoc.getAdvancedLoc(SimpleName.str().size());
4064-
GenericParams = parseGenericParameters(LAngleLoc);
4064+
auto Result = parseGenericParameters(LAngleLoc);
4065+
GenericParams = Result.getPtrOrNull();
4066+
GPHasCodeCompletion |= Result.hasCodeCompletion();
40654067
} else {
4066-
GenericParams = maybeParseGenericParams();
4068+
auto Result = maybeParseGenericParams();
4069+
GenericParams = Result.getPtrOrNull();
4070+
GPHasCodeCompletion |= Result.hasCodeCompletion();
40674071
}
4072+
if (GPHasCodeCompletion && !CodeCompletion)
4073+
return makeParserCodeCompletionStatus();
40684074

40694075
SmallVector<ParameterList*, 8> BodyParams;
40704076

@@ -4119,7 +4125,11 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
41194125
// Add the attributes here so if we need them while parsing the body
41204126
// they are available.
41214127
FD->getAttrs() = Attributes;
4122-
4128+
4129+
// Code completion for the generic type params.
4130+
if (GPHasCodeCompletion)
4131+
CodeCompletion->setDelayedParsedDecl(FD);
4132+
41234133
// Pass the function signature to code completion.
41244134
if (SignatureStatus.hasCodeCompletion())
41254135
CodeCompletion->setDelayedParsedDecl(FD);
@@ -4242,7 +4252,10 @@ ParserResult<EnumDecl> Parser::parseDeclEnum(ParseDeclOptions Flags,
42424252
GenericParamList *GenericParams = nullptr;
42434253
{
42444254
Scope S(this, ScopeKind::Generics);
4245-
GenericParams = maybeParseGenericParams();
4255+
auto Result = maybeParseGenericParams();
4256+
GenericParams = Result.getPtrOrNull();
4257+
if (Result.hasCodeCompletion())
4258+
return makeParserCodeCompletionStatus();
42464259
}
42474260

42484261
EnumDecl *UD = new (Context) EnumDecl(EnumLoc, EnumName, EnumNameLoc,
@@ -4508,7 +4521,10 @@ ParserResult<StructDecl> Parser::parseDeclStruct(ParseDeclOptions Flags,
45084521
GenericParamList *GenericParams = nullptr;
45094522
{
45104523
Scope S(this, ScopeKind::Generics);
4511-
GenericParams = maybeParseGenericParams();
4524+
auto Result = maybeParseGenericParams();
4525+
GenericParams = Result.getPtrOrNull();
4526+
if (Result.hasCodeCompletion())
4527+
return makeParserCodeCompletionStatus();
45124528
}
45134529

45144530
StructDecl *SD = new (Context) StructDecl(StructLoc, StructName,
@@ -4588,7 +4604,10 @@ ParserResult<ClassDecl> Parser::parseDeclClass(SourceLoc ClassLoc,
45884604
GenericParamList *GenericParams = nullptr;
45894605
{
45904606
Scope S(this, ScopeKind::Generics);
4591-
GenericParams = maybeParseGenericParams();
4607+
auto Result = maybeParseGenericParams();
4608+
GenericParams = Result.getPtrOrNull();
4609+
if (Result.hasCodeCompletion())
4610+
return makeParserCodeCompletionStatus();
45924611
}
45934612

45944613
// Create the class.
@@ -4865,7 +4884,10 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
48654884

48664885
// Parse the generic-params, if present.
48674886
Scope S(this, ScopeKind::Generics);
4868-
GenericParamList *GenericParams = maybeParseGenericParams();
4887+
auto GPResult = maybeParseGenericParams();
4888+
GenericParamList *GenericParams = GPResult.getPtrOrNull();
4889+
if (GPResult.hasCodeCompletion())
4890+
return makeParserCodeCompletionStatus();
48694891

48704892
// Parse the parameters.
48714893
// FIXME: handle code completion in Arguments.

lib/Parse/ParseGeneric.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ using namespace swift;
3232
///
3333
/// When parsing the generic parameters, this routine establishes a new scope
3434
/// and adds those parameters to the scope.
35-
GenericParamList *Parser::parseGenericParameters() {
35+
ParserResult<GenericParamList> Parser::parseGenericParameters() {
3636
// Parse the opening '<'.
3737
assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
3838
return parseGenericParameters(consumeStartingLess());
3939
}
4040

41-
GenericParamList *Parser::parseGenericParameters(SourceLoc LAngleLoc) {
41+
ParserResult<GenericParamList> Parser::parseGenericParameters(SourceLoc LAngleLoc) {
4242
// Parse the generic parameter list.
4343
SmallVector<GenericTypeParamDecl *, 4> GenericParams;
4444
bool Invalid = false;
@@ -56,7 +56,8 @@ GenericParamList *Parser::parseGenericParameters(SourceLoc LAngleLoc) {
5656
if (Tok.is(tok::colon)) {
5757
(void)consumeToken();
5858
ParserResult<TypeRepr> Ty;
59-
if (Tok.getKind() == tok::identifier) {
59+
if (Tok.getKind() == tok::identifier ||
60+
Tok.getKind() == tok::code_complete) {
6061
Ty = parseTypeIdentifier();
6162
} else if (Tok.getKind() == tok::kw_protocol) {
6263
Ty = parseTypeComposition();
@@ -65,7 +66,9 @@ GenericParamList *Parser::parseGenericParameters(SourceLoc LAngleLoc) {
6566
Invalid = true;
6667
}
6768

68-
// FIXME: code completion not handled.
69+
if (Ty.hasCodeCompletion())
70+
return makeParserCodeCompletionStatus();
71+
6972
if (Ty.isNonNull())
7073
Inherited.push_back(Ty.get());
7174
}
@@ -117,11 +120,12 @@ GenericParamList *Parser::parseGenericParameters(SourceLoc LAngleLoc) {
117120
if (GenericParams.empty())
118121
return nullptr;
119122

120-
return GenericParamList::create(Context, LAngleLoc, GenericParams,
121-
WhereLoc, Requirements, RAngleLoc);
123+
return makeParserResult(GenericParamList::create(Context, LAngleLoc,
124+
GenericParams, WhereLoc,
125+
Requirements, RAngleLoc));
122126
}
123127

124-
GenericParamList *Parser::maybeParseGenericParams() {
128+
ParserResult<GenericParamList> Parser::maybeParseGenericParams() {
125129
if (!startsWithLess(Tok))
126130
return nullptr;
127131

@@ -132,15 +136,15 @@ GenericParamList *Parser::maybeParseGenericParams() {
132136
// first one being the outmost generic parameter list.
133137
GenericParamList *gpl = nullptr, *outer_gpl = nullptr;
134138
do {
135-
gpl = parseGenericParameters();
139+
gpl = parseGenericParameters().getPtrOrNull();
136140
if (!gpl)
137141
return nullptr;
138142

139143
if (outer_gpl)
140144
gpl->setOuterParameters(outer_gpl);
141145
outer_gpl = gpl;
142146
} while(startsWithLess(Tok));
143-
return gpl;
147+
return makeParserResult(gpl);
144148
}
145149

146150
/// parseGenericWhereClause - Parse a 'where' clause, which places additional

lib/Parse/ParseSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4099,7 +4099,7 @@ ProtocolConformance *SILParser::parseProtocolConformance(
40994099
if (localScope)
41004100
GenericsScope.emplace(&P, ScopeKind::Generics);
41014101

4102-
generics = P.maybeParseGenericParams();
4102+
generics = P.maybeParseGenericParams().getPtrOrNull();
41034103
if (generics) {
41044104
generics->setBuilder(&builder);
41054105
SmallVector<ArchetypeBuilder *, 1> builders(1, &builder);

lib/Parse/ParseType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
156156
// body.
157157
GenericParamList *generics = nullptr;
158158
if (isInSILMode()) {
159-
generics = maybeParseGenericParams();
159+
generics = maybeParseGenericParams().getPtrOrNull();
160160
}
161161

162162
ParserResult<TypeRepr> ty = parseTypeSimple(MessageID, HandleCodeCompletion);

test/IDE/complete_generic_param.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT1 | FileCheck %s -check-prefix=INHERIT
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT2 | FileCheck %s -check-prefix=INHERIT
3+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT3 | FileCheck %s -check-prefix=INHERIT
4+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT4 | FileCheck %s -check-prefix=INHERIT
5+
6+
class C1{}
7+
protocol P1{}
8+
struct S1{}
9+
10+
let ValueInt1 = 1
11+
let ValueString2 = ""
12+
func TopLevelFunc() {}
13+
14+
func f1<S : #^INHERIT1^#>(p : S) {}
15+
func f2<S : #^INHERIT2^#
16+
17+
class C2 {
18+
func f1<S : #^INHERIT3^#>(p : S) {}
19+
func f2<S : #^INHERIT4^#
20+
}
21+
22+
class C3 {
23+
func f1<S1: P1, S2 : #^INHERIT5^#>(p : S1) {}
24+
func f2<S1: P1, S2 : #^INHERIT6^#
25+
}
26+
27+
// INHERIT-DAG: Decl[Class]/CurrModule: C1[#C1#]{{; name=.+$}}
28+
29+
// FIXME: Exclude struct type. rdar://24110708
30+
// INHERIT-DAG: Decl[Struct]/CurrModule: S1[#S1#]{{; name=.+$}}
31+
// INHERIT-DAG: Decl[Protocol]/CurrModule: P1[#P1#]{{; name=.+$}}
32+
// INHERIT-NOT: ValueInt1
33+
// INHERIT-NOT: ValueString2
34+
// INHERIT-NOT: TopLevelFunc

0 commit comments

Comments
 (0)