Skip to content

Commit 6c18230

Browse files
authored
Merge pull request #13143 from rintaro/syntax-parse-type-collection
[libSyntax] Support parsing several type kinds
2 parents 4ab6e76 + d389a81 commit 6c18230

File tree

7 files changed

+142
-65
lines changed

7 files changed

+142
-65
lines changed

include/swift/Parse/Parser.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -963,11 +963,13 @@ class Parser {
963963
/// type-simple:
964964
/// '[' type ']'
965965
/// '[' type ':' type ']'
966-
ParserResult<TypeRepr> parseTypeCollection();
967-
ParserResult<OptionalTypeRepr> parseTypeOptional(TypeRepr *Base);
966+
SyntaxParserResult<syntax::TypeSyntax, TypeRepr> parseTypeCollection();
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();

include/swift/Parse/SyntaxParserResult.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ template <typename Syntax, typename AST> class SyntaxParserResult {
2424
public:
2525
SyntaxParserResult(std::nullptr_t = nullptr)
2626
: SyntaxNode(None), ASTResult(nullptr) {}
27+
SyntaxParserResult(ParserStatus Status)
28+
: SyntaxNode(None), ASTResult(Status) {}
2729
SyntaxParserResult(llvm::Optional<Syntax> SyntaxNode, AST *ASTNode)
2830
: SyntaxNode(SyntaxNode), ASTResult(ASTNode) {}
2931
SyntaxParserResult(ParserStatus Status, llvm::Optional<Syntax> SyntaxNode,

lib/Parse/ParseType.cpp

Lines changed: 96 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,13 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
215215
// Eat the code completion token because we handled it.
216216
consumeToken(tok::code_complete);
217217
return makeParserCodeCompletionResult<TypeRepr>();
218-
case tok::l_square:
219-
ty = parseTypeCollection();
218+
case tok::l_square: {
219+
auto Result = parseTypeCollection();
220+
if (Result.hasSyntax())
221+
SyntaxContext->addSyntax(Result.getSyntax());
222+
ty = Result.getASTResult();
220223
break;
224+
}
221225
case tok::kw_protocol:
222226
if (startsWithLess(peekToken())) {
223227
ty = parseOldStyleProtocolComposition();
@@ -240,6 +244,17 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
240244
checkForInputIncomplete();
241245
return nullptr;
242246
}
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+
};
243258

244259
// '.Type', '.Protocol', '?', '!', and '[]' still leave us with type-simple.
245260
while (ty.isNonNull()) {
@@ -249,24 +264,32 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
249264
SourceLoc metatypeLoc = consumeToken(tok::identifier);
250265
ty = makeParserResult(ty,
251266
new (Context) MetatypeTypeRepr(ty.get(), metatypeLoc));
267+
makeMetatypeTypeSyntax();
252268
continue;
253269
}
254270
if (peekToken().isContextualKeyword("Protocol")) {
255271
consumeToken();
256272
SourceLoc protocolLoc = consumeToken(tok::identifier);
257273
ty = makeParserResult(ty,
258274
new (Context) ProtocolTypeRepr(ty.get(), protocolLoc));
275+
makeMetatypeTypeSyntax();
259276
continue;
260277
}
261278
}
262279

263280
if (!Tok.isAtStartOfLine()) {
264281
if (isOptionalToken(Tok)) {
265-
ty = parseTypeOptional(ty.get());
282+
auto Result = parseTypeOptional(ty.get());
283+
if (Result.hasSyntax())
284+
SyntaxContext->addSyntax(Result.getSyntax());
285+
ty = Result.getASTResult();
266286
continue;
267287
}
268288
if (isImplicitlyUnwrappedOptionalToken(Tok)) {
269-
ty = parseTypeImplicitlyUnwrappedOptional(ty.get());
289+
auto Result = parseTypeImplicitlyUnwrappedOptional(ty.get());
290+
if (Result.hasSyntax())
291+
SyntaxContext->addSyntax(Result.getSyntax());
292+
ty = Result.getASTResult();
270293
continue;
271294
}
272295
// Parse legacy array types for migration.
@@ -730,6 +753,7 @@ Parser::parseAnyType() {
730753
/// type-identifier
731754
/// type-composition-list-deprecated ',' type-identifier
732755
ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
756+
SyntaxParsingContext TypeContext(SyntaxContext, SyntaxContextKind::Type);
733757
assert(Tok.is(tok::kw_protocol) && startsWithLess(peekToken()));
734758

735759
// Start a context for creating type syntax.
@@ -839,6 +863,7 @@ ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
839863
/// identifier ':' type
840864
/// type
841865
ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
866+
SyntaxParsingContext TypeContext(SyntaxContext, SyntaxContextKind::Type);
842867
Parser::StructureMarkerRAII ParsingTypeTuple(*this, Tok);
843868
SourceLoc RPLoc, LPLoc = consumeToken(tok::l_paren);
844869
SourceLoc EllipsisLoc;
@@ -1051,14 +1076,16 @@ ParserResult<TypeRepr> Parser::parseTypeArray(TypeRepr *Base) {
10511076
return makeParserResult(ATR);
10521077
}
10531078

1054-
ParserResult<TypeRepr> Parser::parseTypeCollection() {
1079+
SyntaxParserResult<TypeSyntax, TypeRepr> Parser::parseTypeCollection() {
1080+
ParserStatus Status;
10551081
// Parse the leading '['.
10561082
assert(Tok.is(tok::l_square));
10571083
Parser::StructureMarkerRAII parsingCollection(*this, Tok);
10581084
SourceLoc lsquareLoc = consumeToken();
10591085

10601086
// Parse the element type.
10611087
ParserResult<TypeRepr> firstTy = parseType(diag::expected_element_type);
1088+
Status |= firstTy;
10621089

10631090
// If there is a ':', this is a dictionary type.
10641091
SourceLoc colonLoc;
@@ -1068,36 +1095,57 @@ ParserResult<TypeRepr> Parser::parseTypeCollection() {
10681095

10691096
// Parse the second type.
10701097
secondTy = parseType(diag::expected_dictionary_value_type);
1098+
Status |= secondTy;
10711099
}
10721100

10731101
// Parse the closing ']'.
10741102
SourceLoc rsquareLoc;
1075-
parseMatchingToken(tok::r_square, rsquareLoc,
1076-
colonLoc.isValid()
1077-
? diag::expected_rbracket_dictionary_type
1078-
: diag::expected_rbracket_array_type,
1079-
lsquareLoc);
1103+
if (parseMatchingToken(tok::r_square, rsquareLoc,
1104+
colonLoc.isValid()
1105+
? diag::expected_rbracket_dictionary_type
1106+
: diag::expected_rbracket_array_type,
1107+
lsquareLoc))
1108+
Status.setIsParseError();
10801109

1081-
if (firstTy.hasCodeCompletion() || secondTy.hasCodeCompletion())
1082-
return makeParserCodeCompletionStatus();
1110+
if (Status.hasCodeCompletion())
1111+
return Status;
10831112

10841113
// If we couldn't parse anything for one of the types, propagate the error.
1085-
if (firstTy.isNull() || (colonLoc.isValid() && secondTy.isNull()))
1114+
if (Status.isError())
10861115
return makeParserError();
10871116

1088-
// Form the dictionary type.
1117+
TypeRepr *TyR;
1118+
llvm::Optional<TypeSyntax> SyntaxNode;
1119+
10891120
SourceRange brackets(lsquareLoc, rsquareLoc);
1090-
if (colonLoc.isValid())
1091-
return makeParserResult(ParserStatus(firstTy) | ParserStatus(secondTy),
1092-
new (Context) DictionaryTypeRepr(firstTy.get(),
1093-
secondTy.get(),
1094-
colonLoc,
1095-
brackets));
1121+
if (colonLoc.isValid()) {
1122+
// Form the dictionary type.
1123+
TyR = new (Context)
1124+
DictionaryTypeRepr(firstTy.get(), secondTy.get(), colonLoc, brackets);
1125+
if (SyntaxContext->isEnabled()) {
1126+
DictionaryTypeSyntaxBuilder Builder;
1127+
Builder
1128+
.useRightSquareBracket(SyntaxContext->popToken())
1129+
.useValueType(SyntaxContext->popIf<TypeSyntax>().getValue())
1130+
.useColon(SyntaxContext->popToken())
1131+
.useKeyType(SyntaxContext->popIf<TypeSyntax>().getValue())
1132+
.useLeftSquareBracket(SyntaxContext->popToken());
1133+
SyntaxNode.emplace(Builder.build());
1134+
}
1135+
} else {
1136+
// Form the array type.
1137+
TyR = new (Context) ArrayTypeRepr(firstTy.get(), brackets);
1138+
if (SyntaxContext->isEnabled()) {
1139+
ArrayTypeSyntaxBuilder Builder;
1140+
Builder
1141+
.useRightSquareBracket(SyntaxContext->popToken())
1142+
.useElementType(SyntaxContext->popIf<TypeSyntax>().getValue())
1143+
.useLeftSquareBracket(SyntaxContext->popToken());
1144+
SyntaxNode.emplace(Builder.build());
1145+
}
1146+
}
10961147

1097-
// Form the array type.
1098-
return makeParserResult(firstTy,
1099-
new (Context) ArrayTypeRepr(firstTy.get(),
1100-
brackets));
1148+
return makeSyntaxResult(Status, SyntaxNode, TyR);
11011149
}
11021150

11031151
bool Parser::isOptionalToken(const Token &T) const {
@@ -1142,19 +1190,37 @@ SourceLoc Parser::consumeImplicitlyUnwrappedOptionalToken() {
11421190

11431191
/// Parse a single optional suffix, given that we are looking at the
11441192
/// question mark.
1145-
ParserResult<OptionalTypeRepr> Parser::parseTypeOptional(TypeRepr *base) {
1193+
SyntaxParserResult<TypeSyntax, OptionalTypeRepr>
1194+
Parser::parseTypeOptional(TypeRepr *base) {
11461195
SourceLoc questionLoc = consumeOptionalToken();
1147-
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);
11481206
}
11491207

11501208
/// Parse a single implicitly unwrapped optional suffix, given that we
11511209
/// are looking at the exclamation mark.
1152-
ParserResult<ImplicitlyUnwrappedOptionalTypeRepr>
1210+
SyntaxParserResult<TypeSyntax, ImplicitlyUnwrappedOptionalTypeRepr>
11531211
Parser::parseTypeImplicitlyUnwrappedOptional(TypeRepr *base) {
11541212
SourceLoc exclamationLoc = consumeImplicitlyUnwrappedOptionalToken();
1155-
return makeParserResult(
1156-
new (Context) ImplicitlyUnwrappedOptionalTypeRepr(
1157-
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);
11581224
}
11591225

11601226
//===----------------------------------------------------------------------===//

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,7 @@ class C {
5858

5959
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>)
61+
typealias C = <ArrayType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>]</ArrayType>
62+
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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,7 @@ class C {
5858

5959
typealias A = Any
6060
typealias B = (Array<Array<Any>>.Element)
61+
typealias C = [Int]
62+
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: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@
3434
is_optional=True),
3535
]),
3636

37+
# array-type -> '[' type ']'
38+
Node('ArrayType', kind='Type',
39+
children=[
40+
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
41+
Child('ElementType', kind='Type'),
42+
Child('RightSquareBracket', kind='RightSquareBracketToken'),
43+
]),
44+
45+
# dictionary-type -> '[' type ':' type ']'
46+
Node('DictionaryType', kind='Type',
47+
children=[
48+
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
49+
Child('KeyType', kind='Type'),
50+
Child('Colon', kind='ColonToken'),
51+
Child('ValueType', kind='Type'),
52+
Child('RightSquareBracket', kind='RightSquareBracketToken'),
53+
]),
3754

3855
# metatype-type -> type '.' 'Type'
3956
# | type '.' 'Protocol
@@ -48,14 +65,18 @@
4865
]),
4966
]),
5067

51-
# dictionary-type -> '[' type ':' type ']'
52-
Node('DictionaryType', kind='Type',
68+
# optional-type -> type '?'
69+
Node('OptionalType', kind='Type',
5370
children=[
54-
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
55-
Child('KeyType', kind='Type'),
56-
Child('Colon', kind='ColonToken'),
57-
Child('ValueType', kind='Type'),
58-
Child('RightSquareBracket', kind='RightSquareBracketToken'),
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'),
5980
]),
6081

6182
# throwing-specifier -> 'throws' | 'rethrows'
@@ -99,14 +120,6 @@
99120
is_optional=True),
100121
]),
101122

102-
# array-type -> '[' type ']'
103-
Node('ArrayType', kind='Type',
104-
children=[
105-
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
106-
Child('ElementType', kind='Type'),
107-
Child('RightSquareBracket', kind='RightSquareBracketToken'),
108-
]),
109-
110123
# type-annotation -> attribute-list 'inout'? type
111124
Node('TypeAnnotation', kind='Syntax',
112125
children=[
@@ -125,13 +138,6 @@
125138
Node('TupleTypeElementList', kind='SyntaxCollection',
126139
element='TupleTypeElement'),
127140

128-
# implicitly-unwrapped-optional-type -> type '!'
129-
Node('ImplicitlyUnwrappedOptionalType', kind='Type',
130-
children=[
131-
Child('ValueType', kind='Type'),
132-
Child('ExclamationMark', kind='ExclamationMarkToken'),
133-
]),
134-
135141
# protocol-composition-element -> type-identifier '&'
136142
Node('ProtocolCompositionElement', kind='Syntax',
137143
children=[
@@ -177,13 +183,6 @@
177183
is_optional=True),
178184
]),
179185

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

0 commit comments

Comments
 (0)