Skip to content

Commit fec040d

Browse files
authored
libSyntax: support generic parameter clause. (#13286)
This patch also performs minor refactoring to align syntax parsing context with the right scope. We start to support the generic clauses because they are necessary pieces to construct struct or function syntax node.
1 parent c9c7d39 commit fec040d

File tree

8 files changed

+44
-22
lines changed

8 files changed

+44
-22
lines changed

include/swift/Parse/Parser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,8 @@ class Parser {
13291329

13301330
ParserResult<GenericParamList> parseGenericParameters();
13311331
ParserResult<GenericParamList> parseGenericParameters(SourceLoc LAngleLoc);
1332+
ParserStatus parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
1333+
SmallVectorImpl<GenericTypeParamDecl *> &GenericParams);
13321334
ParserResult<GenericParamList> maybeParseGenericParams();
13331335
void
13341336
diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams);

lib/Parse/ParseGeneric.cpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,20 @@ using namespace swift::syntax;
3838
/// When parsing the generic parameters, this routine establishes a new scope
3939
/// and adds those parameters to the scope.
4040
ParserResult<GenericParamList> Parser::parseGenericParameters() {
41+
SyntaxParsingContext GPSContext(SyntaxContext, SyntaxKind::GenericParameterClause);
4142
// Parse the opening '<'.
4243
assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
4344
return parseGenericParameters(consumeStartingLess());
4445
}
4546

46-
ParserResult<GenericParamList>
47-
Parser::parseGenericParameters(SourceLoc LAngleLoc) {
48-
// Parse the generic parameter list.
49-
SmallVector<GenericTypeParamDecl *, 4> GenericParams;
50-
bool Invalid = false;
47+
ParserStatus
48+
Parser::parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
49+
SmallVectorImpl<GenericTypeParamDecl *> &GenericParams) {
50+
ParserStatus Result;
51+
SyntaxParsingContext GPSContext(SyntaxContext, SyntaxKind::GenericParameterList);
52+
bool HasNextParam;
5153
do {
54+
SyntaxParsingContext GParamContext(SyntaxContext, SyntaxKind::GenericParameter);
5255
// Note that we're parsing a declaration.
5356
StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(),
5457
StructureMarkerKind::Declaration);
@@ -65,7 +68,7 @@ Parser::parseGenericParameters(SourceLoc LAngleLoc) {
6568
SourceLoc NameLoc;
6669
if (parseIdentifier(Name, NameLoc,
6770
diag::expected_generics_parameter_name)) {
68-
Invalid = true;
71+
Result.setIsParseError();
6972
break;
7073
}
7174

@@ -74,18 +77,19 @@ Parser::parseGenericParameters(SourceLoc LAngleLoc) {
7477
if (Tok.is(tok::colon)) {
7578
(void)consumeToken();
7679
ParserResult<TypeRepr> Ty;
77-
78-
if (Tok.isAny(tok::identifier, tok::code_complete, tok::kw_protocol, tok::kw_Any)) {
80+
81+
if (Tok.isAny(tok::identifier, tok::code_complete, tok::kw_protocol,
82+
tok::kw_Any)) {
7983
Ty = parseType();
8084
} else if (Tok.is(tok::kw_class)) {
8185
diagnose(Tok, diag::unexpected_class_constraint);
8286
diagnose(Tok, diag::suggest_anyobject)
83-
.fixItReplace(Tok.getLoc(), "AnyObject");
87+
.fixItReplace(Tok.getLoc(), "AnyObject");
8488
consumeToken();
85-
Invalid = true;
89+
Result.setIsParseError();
8690
} else {
8791
diagnose(Tok, diag::expected_generics_type_restriction, Name);
88-
Invalid = true;
92+
Result.setIsParseError();
8993
}
9094

9195
if (Ty.hasCodeCompletion())
@@ -98,10 +102,9 @@ Parser::parseGenericParameters(SourceLoc LAngleLoc) {
98102
// We always create generic type parameters with an invalid depth.
99103
// Semantic analysis fills in the depth when it processes the generic
100104
// parameter list.
101-
auto Param = new (Context) GenericTypeParamDecl(
102-
CurDeclContext, Name, NameLoc,
103-
GenericTypeParamDecl::InvalidDepth,
104-
GenericParams.size());
105+
auto Param = new (Context) GenericTypeParamDecl(CurDeclContext, Name, NameLoc,
106+
GenericTypeParamDecl::InvalidDepth,
107+
GenericParams.size());
105108
if (!Inherited.empty())
106109
Param->setInherited(Context.AllocateCopy(Inherited));
107110
GenericParams.push_back(Param);
@@ -113,7 +116,22 @@ Parser::parseGenericParameters(SourceLoc LAngleLoc) {
113116
addToScope(Param);
114117

115118
// Parse the comma, if the list continues.
116-
} while (consumeIf(tok::comma));
119+
HasNextParam = consumeIf(tok::comma);
120+
} while (HasNextParam);
121+
122+
return Result;
123+
}
124+
125+
ParserResult<GenericParamList>
126+
Parser::parseGenericParameters(SourceLoc LAngleLoc) {
127+
// Parse the generic parameter list.
128+
SmallVector<GenericTypeParamDecl *, 4> GenericParams;
129+
auto Result = parseGenericParametersBeforeWhere(LAngleLoc, GenericParams);
130+
131+
// Return early if there was code completion token.
132+
if (Result.hasCodeCompletion())
133+
return Result;
134+
auto Invalid = Result.isError();
117135

118136
// Parse the optional where-clause.
119137
SourceLoc WhereLoc;

lib/Syntax/SyntaxFactory.cpp.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ TupleTypeElementSyntax SyntaxFactory::makeTupleTypeElement(TypeSyntax Type,
308308
GenericParameterSyntax
309309
SyntaxFactory::makeGenericParameter(TokenSyntax Name,
310310
llvm::Optional<TokenSyntax> TrailingComma) {
311-
return makeGenericParameter(Name, None, None, TrailingComma);
311+
return makeGenericParameter(None, Name, None, None, TrailingComma);
312312
}
313313

314314
TypeSyntax SyntaxFactory::makeTypeIdentifier(OwnedString TypeName,

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,4 @@ struct foo <MemberDeclBlock>{<Attribute>
8585
}
8686
}</MemberDeclBlock>
8787

88-
struct S<A, B, C, D> <GenericWhereClause>where <ConformanceRequirement><SimpleTypeIdentifier>A</SimpleTypeIdentifier>:<SimpleTypeIdentifier>B</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><SimpleTypeIdentifier>B</SimpleTypeIdentifier>==<SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><SimpleTypeIdentifier>A </SimpleTypeIdentifier>: <SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>B</SimpleTypeIdentifier>.C </MemberTypeIdentifier>== <MemberTypeIdentifier><SimpleTypeIdentifier>D</SimpleTypeIdentifier>.A</MemberTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>A</SimpleTypeIdentifier>.B</MemberTypeIdentifier>: <MemberTypeIdentifier><SimpleTypeIdentifier>C</SimpleTypeIdentifier>.D </MemberTypeIdentifier></ConformanceRequirement></GenericWhereClause><MemberDeclBlock>{}</MemberDeclBlock>
88+
struct S<GenericParameterClause><<GenericParameter>A, </GenericParameter><GenericParameter>B, </GenericParameter><GenericParameter>C, </GenericParameter><GenericParameter><Attribute>@objc </Attribute>D</GenericParameter>> </GenericParameterClause><GenericWhereClause>where <ConformanceRequirement><SimpleTypeIdentifier>A</SimpleTypeIdentifier>:<SimpleTypeIdentifier>B</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><SimpleTypeIdentifier>B</SimpleTypeIdentifier>==<SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><SimpleTypeIdentifier>A </SimpleTypeIdentifier>: <SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>B</SimpleTypeIdentifier>.C </MemberTypeIdentifier>== <MemberTypeIdentifier><SimpleTypeIdentifier>D</SimpleTypeIdentifier>.A</MemberTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>A</SimpleTypeIdentifier>.B</MemberTypeIdentifier>: <MemberTypeIdentifier><SimpleTypeIdentifier>C</SimpleTypeIdentifier>.D </MemberTypeIdentifier></ConformanceRequirement></GenericWhereClause><MemberDeclBlock>{}</MemberDeclBlock>

test/Syntax/round_trip_parse_gen.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,4 @@ struct foo {
8585
}
8686
}
8787

88-
struct S<A, B, C, D> where A:B, B==C, A : C, B.C == D.A, A.B: C.D {}
88+
struct S<A, B, C, @objc D> where A:B, B==C, A : C, B.C == D.A, A.B: C.D {}

tools/SwiftSyntax/SyntaxFactory.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public enum SyntaxFactory {
139139

140140
public static func makeGenericParameter(name: TokenSyntax,
141141
trailingComma: TokenSyntax) -> GenericParameterSyntax {
142-
return makeGenericParameter(name: name, colon: nil,
142+
return makeGenericParameter(attributes: nil, name: name, colon: nil,
143143
inheritedType: nil,
144144
trailingComma: trailingComma)
145145
}

unittests/Syntax/DeclSyntaxTests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ TEST(DeclSyntaxTests, TypealiasMakeAPIs) {
8282
auto Subsequence = SyntaxFactory::makeIdentifier("MyCollection", {}, {});
8383
auto ElementName = SyntaxFactory::makeIdentifier("Element", {}, {});
8484
auto ElementParam =
85-
SyntaxFactory::makeGenericParameter(ElementName, None, None, None);
85+
SyntaxFactory::makeGenericParameter(None, ElementName, None, None, None);
8686
auto LeftAngle = SyntaxFactory::makeLeftAngleToken({}, {});
8787
auto RightAngle = SyntaxFactory::makeRightAngleToken({}, Trivia::spaces(1));
8888
auto GenericParams = GenericParameterClauseSyntaxBuilder()
@@ -119,7 +119,7 @@ TEST(DeclSyntaxTests, TypealiasWithAPIs) {
119119
auto MyCollection = SyntaxFactory::makeIdentifier("MyCollection", {}, {});
120120
auto ElementName = SyntaxFactory::makeIdentifier("Element", {}, {});
121121
auto ElementParam =
122-
SyntaxFactory::makeGenericParameter(ElementName, None, None, None);
122+
SyntaxFactory::makeGenericParameter(None, ElementName, None, None, None);
123123
auto LeftAngle = SyntaxFactory::makeLeftAngleToken({}, {});
124124
auto RightAngle =
125125
SyntaxFactory::makeRightAngleToken({}, { Trivia::spaces(1) });

utils/gyb_syntax_support/GenericNodes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
# | type-name : protocol-composition-type
3636
Node('GenericParameter', kind='Syntax',
3737
children=[
38+
Child('Attributes', kind='AttributeList',
39+
is_optional=True),
3840
Child('Name', kind='IdentifierToken'),
3941
Child('Colon', kind='ColonToken',
4042
is_optional=True),

0 commit comments

Comments
 (0)