Skip to content

Commit 0f2b748

Browse files
committed
Parser: Teach canParseType about member types with non-identifier qualifiers
1 parent fe047b9 commit 0f2b748

File tree

3 files changed

+294
-65
lines changed

3 files changed

+294
-65
lines changed

include/swift/Parse/Parser.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,10 +1566,7 @@ class Parser {
15661566
/// \verbatim
15671567
/// simple-type-identifier: identifier generic-argument-list?
15681568
/// \endverbatim
1569-
bool canParseSimpleTypeIdentifier();
1570-
15711569
bool canParseTypeIdentifier();
1572-
bool canParseTypeIdentifierOrTypeComposition();
15731570
bool canParseOldStyleProtocolComposition();
15741571
bool canParseTypeTupleBody();
15751572
bool canParseTypeAttribute();

lib/Parse/ParseType.cpp

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,15 +1520,13 @@ bool Parser::canParseType() {
15201520
switch (Tok.getKind()) {
15211521
case tok::kw_Self:
15221522
case tok::kw_Any:
1523+
case tok::identifier:
15231524
case tok::code_complete:
15241525
if (!canParseTypeIdentifier())
15251526
return false;
15261527
break;
1527-
case tok::kw_protocol: // Deprecated composition syntax
1528-
case tok::identifier:
1529-
if (!canParseTypeIdentifierOrTypeComposition())
1530-
return false;
1531-
break;
1528+
case tok::kw_protocol:
1529+
return canParseOldStyleProtocolComposition();
15321530
case tok::l_paren: {
15331531
consumeToken();
15341532
if (!canParseTypeTupleBody())
@@ -1561,14 +1559,22 @@ bool Parser::canParseType() {
15611559
return false;
15621560
}
15631561

1564-
// '.Type', '.Protocol', '?', and '!' still leave us with type-simple.
1562+
// A member type, '.Type', '.Protocol', '?', and '!' still leave us with
1563+
// type-simple.
15651564
while (true) {
1566-
if ((Tok.is(tok::period) || Tok.is(tok::period_prefix)) &&
1567-
(peekToken().isContextualKeyword("Type")
1568-
|| peekToken().isContextualKeyword("Protocol"))) {
1565+
if (Tok.isAny(tok::period_prefix, tok::period)) {
15691566
consumeToken();
1570-
consumeToken(tok::identifier);
1571-
continue;
1567+
1568+
if (Tok.isContextualKeyword("Type") ||
1569+
Tok.isContextualKeyword("Protocol")) {
1570+
consumeToken();
1571+
continue;
1572+
}
1573+
1574+
if (canParseTypeIdentifier())
1575+
continue;
1576+
1577+
return false;
15721578
}
15731579
if (isOptionalToken(Tok)) {
15741580
consumeOptionalToken();
@@ -1581,6 +1587,13 @@ bool Parser::canParseType() {
15811587
break;
15821588
}
15831589

1590+
while (Tok.isContextualPunctuator("&")) {
1591+
consumeToken();
1592+
// FIXME: Should be 'canParseTypeSimple', but we don't have one.
1593+
if (!canParseType())
1594+
return false;
1595+
}
1596+
15841597
if (isAtFunctionTypeArrow()) {
15851598
// Handle type-function if we have an '->' with optional
15861599
// 'async' and/or 'throws'.
@@ -1605,25 +1618,10 @@ bool Parser::canParseType() {
16051618
return true;
16061619
}
16071620

1608-
bool Parser::canParseTypeIdentifierOrTypeComposition() {
1609-
if (Tok.is(tok::kw_protocol))
1610-
return canParseOldStyleProtocolComposition();
1611-
1612-
while (true) {
1613-
if (!canParseTypeIdentifier())
1614-
return false;
1615-
1616-
if (Tok.isContextualPunctuator("&")) {
1617-
consumeToken();
1618-
continue;
1619-
} else {
1620-
return true;
1621-
}
1622-
}
1623-
}
1624-
1625-
bool Parser::canParseSimpleTypeIdentifier() {
1621+
bool Parser::canParseTypeIdentifier() {
16261622
// Parse an identifier.
1623+
//
1624+
// FIXME: We should expect e.g. 'X.var'. Almost any keyword is a valid member component.
16271625
if (!Tok.isAny(tok::identifier, tok::kw_Self, tok::kw_Any, tok::code_complete))
16281626
return false;
16291627
consumeToken();
@@ -1635,28 +1633,11 @@ bool Parser::canParseSimpleTypeIdentifier() {
16351633
return true;
16361634
}
16371635

1638-
bool Parser::canParseTypeIdentifier() {
1639-
while (true) {
1640-
if (!canParseSimpleTypeIdentifier())
1641-
return false;
1642-
1643-
// Treat 'Foo.<anything>' as an attempt to write a dotted type
1644-
// unless <anything> is 'Type' or 'Protocol'.
1645-
if ((Tok.is(tok::period) || Tok.is(tok::period_prefix)) &&
1646-
!peekToken().isContextualKeyword("Type") &&
1647-
!peekToken().isContextualKeyword("Protocol")) {
1648-
consumeToken();
1649-
} else {
1650-
return true;
1651-
}
1652-
}
1653-
}
1654-
16551636
bool Parser::canParseBaseTypeForQualifiedDeclName() {
16561637
BacktrackingScope backtrack(*this);
16571638

16581639
// Parse a simple type identifier.
1659-
if (!canParseSimpleTypeIdentifier())
1640+
if (!canParseTypeIdentifier())
16601641
return false;
16611642

16621643
// Qualified name base types must be followed by a period.

0 commit comments

Comments
 (0)