Skip to content

Commit d389a81

Browse files
committed
[libSyntax] Support parsing postfix type nodes
* OptionalType (?) * ImplicitlyUnwrappedOptional (!) * MetatypeType (.Type, .Protocol)
1 parent 5923e4f commit d389a81

File tree

6 files changed

+72
-27
lines changed

6 files changed

+72
-27
lines changed

include/swift/Parse/Parser.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -964,10 +964,12 @@ class Parser {
964964
/// '[' type ']'
965965
/// '[' type ':' type ']'
966966
SyntaxParserResult<syntax::TypeSyntax, TypeRepr> parseTypeCollection();
967-
ParserResult<OptionalTypeRepr> parseTypeOptional(TypeRepr *Base);
968967

969-
ParserResult<ImplicitlyUnwrappedOptionalTypeRepr>
970-
parseTypeImplicitlyUnwrappedOptional(TypeRepr *Base);
968+
SyntaxParserResult<syntax::TypeSyntax, OptionalTypeRepr>
969+
parseTypeOptional(TypeRepr *Base);
970+
971+
SyntaxParserResult<syntax::TypeSyntax, ImplicitlyUnwrappedOptionalTypeRepr>
972+
parseTypeImplicitlyUnwrappedOptional(TypeRepr *Base);
971973

972974
bool isOptionalToken(const Token &T) const;
973975
SourceLoc consumeOptionalToken();

lib/Parse/ParseType.cpp

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,17 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
244244
checkForInputIncomplete();
245245
return nullptr;
246246
}
247+
248+
auto makeMetatypeTypeSyntax = [&]() {
249+
if (!SyntaxContext->isEnabled())
250+
return;
251+
MetatypeTypeSyntaxBuilder Builder;
252+
Builder
253+
.useTypeOrProtocol(SyntaxContext->popToken())
254+
.usePeriod(SyntaxContext->popToken())
255+
.useBaseType(SyntaxContext->popIf<TypeSyntax>().getValue());
256+
SyntaxContext->addSyntax(Builder.build());
257+
};
247258

248259
// '.Type', '.Protocol', '?', '!', and '[]' still leave us with type-simple.
249260
while (ty.isNonNull()) {
@@ -253,24 +264,32 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
253264
SourceLoc metatypeLoc = consumeToken(tok::identifier);
254265
ty = makeParserResult(ty,
255266
new (Context) MetatypeTypeRepr(ty.get(), metatypeLoc));
267+
makeMetatypeTypeSyntax();
256268
continue;
257269
}
258270
if (peekToken().isContextualKeyword("Protocol")) {
259271
consumeToken();
260272
SourceLoc protocolLoc = consumeToken(tok::identifier);
261273
ty = makeParserResult(ty,
262274
new (Context) ProtocolTypeRepr(ty.get(), protocolLoc));
275+
makeMetatypeTypeSyntax();
263276
continue;
264277
}
265278
}
266279

267280
if (!Tok.isAtStartOfLine()) {
268281
if (isOptionalToken(Tok)) {
269-
ty = parseTypeOptional(ty.get());
282+
auto Result = parseTypeOptional(ty.get());
283+
if (Result.hasSyntax())
284+
SyntaxContext->addSyntax(Result.getSyntax());
285+
ty = Result.getASTResult();
270286
continue;
271287
}
272288
if (isImplicitlyUnwrappedOptionalToken(Tok)) {
273-
ty = parseTypeImplicitlyUnwrappedOptional(ty.get());
289+
auto Result = parseTypeImplicitlyUnwrappedOptional(ty.get());
290+
if (Result.hasSyntax())
291+
SyntaxContext->addSyntax(Result.getSyntax());
292+
ty = Result.getASTResult();
274293
continue;
275294
}
276295
// Parse legacy array types for migration.
@@ -734,6 +753,7 @@ Parser::parseAnyType() {
734753
/// type-identifier
735754
/// type-composition-list-deprecated ',' type-identifier
736755
ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
756+
SyntaxParsingContext TypeContext(SyntaxContext, SyntaxContextKind::Type);
737757
assert(Tok.is(tok::kw_protocol) && startsWithLess(peekToken()));
738758

739759
// Start a context for creating type syntax.
@@ -843,6 +863,7 @@ ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
843863
/// identifier ':' type
844864
/// type
845865
ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
866+
SyntaxParsingContext TypeContext(SyntaxContext, SyntaxContextKind::Type);
846867
Parser::StructureMarkerRAII ParsingTypeTuple(*this, Tok);
847868
SourceLoc RPLoc, LPLoc = consumeToken(tok::l_paren);
848869
SourceLoc EllipsisLoc;
@@ -1169,19 +1190,37 @@ SourceLoc Parser::consumeImplicitlyUnwrappedOptionalToken() {
11691190

11701191
/// Parse a single optional suffix, given that we are looking at the
11711192
/// question mark.
1172-
ParserResult<OptionalTypeRepr> Parser::parseTypeOptional(TypeRepr *base) {
1193+
SyntaxParserResult<TypeSyntax, OptionalTypeRepr>
1194+
Parser::parseTypeOptional(TypeRepr *base) {
11731195
SourceLoc questionLoc = consumeOptionalToken();
1174-
return makeParserResult(new (Context) OptionalTypeRepr(base, questionLoc));
1196+
auto TyR = new (Context) OptionalTypeRepr(base, questionLoc);
1197+
llvm::Optional<TypeSyntax> SyntaxNode;
1198+
if (SyntaxContext->isEnabled()) {
1199+
OptionalTypeSyntaxBuilder Builder;
1200+
Builder
1201+
.useQuestionMark(SyntaxContext->popToken())
1202+
.useWrappedType(SyntaxContext->popIf<TypeSyntax>().getValue());
1203+
SyntaxNode.emplace(Builder.build());
1204+
}
1205+
return makeSyntaxResult(SyntaxNode, TyR);
11751206
}
11761207

11771208
/// Parse a single implicitly unwrapped optional suffix, given that we
11781209
/// are looking at the exclamation mark.
1179-
ParserResult<ImplicitlyUnwrappedOptionalTypeRepr>
1210+
SyntaxParserResult<TypeSyntax, ImplicitlyUnwrappedOptionalTypeRepr>
11801211
Parser::parseTypeImplicitlyUnwrappedOptional(TypeRepr *base) {
11811212
SourceLoc exclamationLoc = consumeImplicitlyUnwrappedOptionalToken();
1182-
return makeParserResult(
1183-
new (Context) ImplicitlyUnwrappedOptionalTypeRepr(
1184-
base, exclamationLoc));
1213+
auto TyR =
1214+
new (Context) ImplicitlyUnwrappedOptionalTypeRepr(base, exclamationLoc);
1215+
llvm::Optional<TypeSyntax> SyntaxNode;
1216+
if (SyntaxContext->isEnabled()) {
1217+
ImplicitlyUnwrappedOptionalTypeSyntaxBuilder Builder;
1218+
Builder
1219+
.useExclamationMark(SyntaxContext->popToken())
1220+
.useWrappedType(SyntaxContext->popIf<TypeSyntax>().getValue());
1221+
SyntaxNode.emplace(Builder.build());
1222+
}
1223+
return makeSyntaxResult(SyntaxNode, TyR);
11851224
}
11861225

11871226
//===----------------------------------------------------------------------===//

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,5 @@ typealias A = <SimpleTypeIdentifier>Any</SimpleTypeIdentifier>
6060
typealias B = (<MemberTypeIdentifier><SimpleTypeIdentifier>Array<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Array<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Any</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier>.Element</MemberTypeIdentifier>)
6161
typealias C = <ArrayType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>]</ArrayType>
6262
typealias D = <DictionaryType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier>]</DictionaryType>
63+
typealias E = <MetatypeType><OptionalType><SimpleTypeIdentifier>Int</SimpleTypeIdentifier>?</OptionalType>.Protocol</MetatypeType>
64+
typealias F = <MetatypeType><ImplicitlyUnwrappedOptionalType><ArrayType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>]</ArrayType>!</ImplicitlyUnwrappedOptionalType>.Type</MetatypeType>

test/Syntax/round_trip_parse_gen.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,5 @@ typealias A = Any
6060
typealias B = (Array<Array<Any>>.Element)
6161
typealias C = [Int]
6262
typealias D = [Int: String]
63+
typealias E = Int?.Protocol
64+
typealias F = [Int]!.Type

unittests/Syntax/TypeSyntaxTests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ TEST(TypeSyntaxTests, OptionalTypeWithAPIs) {
313313
auto StringType = SyntaxFactory::makeTypeIdentifier("String",
314314
Trivia::spaces(1), {});
315315
SyntaxFactory::makeBlankOptionalType()
316-
.withValueType(StringType)
316+
.withWrappedType(StringType)
317317
.withQuestionMark(SyntaxFactory::makePostfixQuestionMarkToken({}, {}))
318318
.print(OS);
319319
ASSERT_EQ(OS.str(), " String?");
@@ -341,7 +341,7 @@ TEST(TypeSyntaxTests, ImplicitlyUnwrappedOptionalTypeWithAPIs) {
341341
{ Trivia::spaces(1) },
342342
{});
343343
SyntaxFactory::makeBlankImplicitlyUnwrappedOptionalType()
344-
.withValueType(StringType)
344+
.withWrappedType(StringType)
345345
.withExclamationMark(SyntaxFactory::makeExclamationMarkToken({}, {}))
346346
.print(OS);
347347
ASSERT_EQ(OS.str(), " String!");

utils/gyb_syntax_support/TypeNodes.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@
6565
]),
6666
]),
6767

68+
# optional-type -> type '?'
69+
Node('OptionalType', kind='Type',
70+
children=[
71+
Child('WrappedType', kind='Type'),
72+
Child('QuestionMark', kind='PostfixQuestionMarkToken'),
73+
]),
74+
75+
# implicitly-unwrapped-optional-type -> type '!'
76+
Node('ImplicitlyUnwrappedOptionalType', kind='Type',
77+
children=[
78+
Child('WrappedType', kind='Type'),
79+
Child('ExclamationMark', kind='ExclamationMarkToken'),
80+
]),
81+
6882
# throwing-specifier -> 'throws' | 'rethrows'
6983
# function-type -> attribute-list '(' function-type-argument-list ')'
7084
# throwing-specifier? '->'? type?
@@ -124,13 +138,6 @@
124138
Node('TupleTypeElementList', kind='SyntaxCollection',
125139
element='TupleTypeElement'),
126140

127-
# implicitly-unwrapped-optional-type -> type '!'
128-
Node('ImplicitlyUnwrappedOptionalType', kind='Type',
129-
children=[
130-
Child('ValueType', kind='Type'),
131-
Child('ExclamationMark', kind='ExclamationMarkToken'),
132-
]),
133-
134141
# protocol-composition-element -> type-identifier '&'
135142
Node('ProtocolCompositionElement', kind='Syntax',
136143
children=[
@@ -176,13 +183,6 @@
176183
is_optional=True),
177184
]),
178185

179-
# optional-type -> type '?'
180-
Node('OptionalType', kind='Type',
181-
children=[
182-
Child('ValueType', kind='Type'),
183-
Child('QuestionMark', kind='PostfixQuestionMarkToken'),
184-
]),
185-
186186
# function-type-argument-list -> function-type-argument
187187
# function-type-argument-list?
188188
Node('FunctionTypeArgumentList', kind='SyntaxCollection',

0 commit comments

Comments
 (0)