Skip to content

Commit 59f1e28

Browse files
committed
Add DeclNameRef to syntax tree
1 parent 9f71ee1 commit 59f1e28

31 files changed

+722
-646
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -435,16 +435,19 @@ ERROR(deprecated_operator_body_use_group,PointsToFirstBadToken,
435435
"use a precedence group instead", ())
436436
ERROR(operator_decl_no_fixity,none,
437437
"operator must be declared as 'prefix', 'postfix', or 'infix'", ())
438-
ERROR(operator_decl_expected_precedencegroup, none,
439-
"expected precedence group name after ':' in operator declaration", ())
440438

441439
WARNING(operator_decl_remove_designated_types,none,
442440
"designated types are no longer used by the compiler; please remove "
443441
"the designated type list from this operator declaration", ())
444442

445-
// PrecedenceGroup
446443
ERROR(precedencegroup_not_infix,none,
447444
"only infix operators may declare a precedence", ())
445+
ERROR(precedencegroup_too_many,none,
446+
"infix operators may declare only one precedence", ())
447+
ERROR(expected_group_name_in_precedencegroup_list,none,
448+
"expected name in precedence group list", ())
449+
450+
// PrecedenceGroup
448451
ERROR(expected_precedencegroup_name,none,
449452
"expected identifier after 'precedencegroup'", ())
450453
ERROR(expected_precedencegroup_lbrace,none,
@@ -463,9 +466,6 @@ ERROR(expected_precedencegroup_associativity,none,
463466
"expected 'none', 'left', or 'right' after 'associativity'", ())
464467
ERROR(expected_precedencegroup_assignment,none,
465468
"expected 'true' or 'false' after 'assignment'", ())
466-
ERROR(expected_precedencegroup_relation,none,
467-
"expected name of related precedence group after '%0'",
468-
(StringRef))
469469

470470
// SIL
471471
ERROR(expected_sil_keyword,none,
@@ -1856,5 +1856,9 @@ ERROR(expected_closure_literal,none,
18561856
ERROR(expected_multiple_closures_block_rbrace,none,
18571857
"expected '}' at the end of a trailing closures block", ())
18581858

1859+
ERROR(impossible_parse,none,
1860+
"parser entered impossible state; please file a bug report with this "
1861+
"source file", ())
1862+
18591863
#define UNDEFINE_DIAGNOSTIC_MACROS
18601864
#include "DefineDiagnosticMacros.h"

include/swift/Parse/Parser.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,13 +1623,19 @@ class Parser {
16231623

16241624
/// If passed, compound names with empty argument lists are allowed.
16251625
AllowZeroArgCompoundNames = AllowCompoundNames | 1 << 5,
1626+
1627+
/// If passed, `$0` etc. are allowed.
1628+
AllowAnonymousParamNames = 1 << 6,
16261629
};
16271630
using DeclNameOptions = OptionSet<DeclNameFlag>;
16281631

16291632
friend DeclNameOptions operator|(DeclNameFlag flag1, DeclNameFlag flag2) {
16301633
return DeclNameOptions(flag1) | flag2;
16311634
}
16321635

1636+
/// Parse a declaration name that results in a `DeclNameRef` in the syntax
1637+
/// tree.
1638+
///
16331639
/// Without \c DeclNameFlag::AllowCompoundNames, parse an
16341640
/// unqualified-decl-base-name.
16351641
///

include/swift/Syntax/SyntaxFactory.h.gyb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ public:
126126
llvm::Optional<TokenSyntax> TrailingComma
127127
);
128128

129+
/// Creates a DeclNameRef with the indicated module selector (if any) and base
130+
/// name.
131+
DeclNameRefSyntax makeDeclNameRef(
132+
llvm::Optional<StringRef> ModuleName,
133+
StringRef BaseName,
134+
StringRef LeadingTrivia,
135+
StringRef TrailingTrivia);
136+
129137
/// Creates a TypeIdentifierSyntax with the provided name and leading/trailing
130138
/// trivia.
131139
TypeSyntax makeTypeIdentifier(

lib/Parse/ParseDecl.cpp

Lines changed: 87 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,6 @@ bool Parser::parseSpecializeAttributeArguments(
665665
}
666666
if (ParamLabel == "target") {
667667
if (!parseSILTargetName(*this)) {
668-
SyntaxParsingContext ContentContext(SyntaxContext,
669-
SyntaxKind::DeclName);
670668
DeclNameLoc loc;
671669
targetFunction = parseDeclNameRef(
672670
loc, diag::attr_specialize_expected_function,
@@ -2482,17 +2480,13 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
24822480
return false;
24832481
}
24842482
consumeToken(tok::colon);
2485-
{
2486-
SyntaxParsingContext ContentContext(SyntaxContext,
2487-
SyntaxKind::DeclName);
2488-
2489-
DeclNameLoc loc;
2490-
replacedFunction = parseDeclNameRef(loc,
2491-
diag::attr_dynamic_replacement_expected_function,
2492-
DeclNameFlag::AllowZeroArgCompoundNames |
2493-
DeclNameFlag::AllowKeywordsUsingSpecialNames |
2494-
DeclNameFlag::AllowOperators);
2495-
}
2483+
2484+
DeclNameLoc loc;
2485+
replacedFunction = parseDeclNameRef(loc,
2486+
diag::attr_dynamic_replacement_expected_function,
2487+
DeclNameFlag::AllowZeroArgCompoundNames |
2488+
DeclNameFlag::AllowKeywordsUsingSpecialNames |
2489+
DeclNameFlag::AllowOperators);
24962490
}
24972491

24982492
// Parse the matching ')'.
@@ -8104,6 +8098,42 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
81048098
return DCC.fixupParserResult(Result);
81058099
}
81068100

8101+
template <typename Fn>
8102+
static ParserStatus
8103+
parsePrecedenceGroupNameList(Parser &P, Fn takeGroupName) {
8104+
SourceLoc prevCommaLoc;
8105+
do {
8106+
SyntaxParsingContext NameCtxt(P.SyntaxContext,
8107+
SyntaxKind::PrecedenceGroupNameElement);
8108+
if (P.Tok.is(tok::code_complete)) {
8109+
if (P.CodeCompletion)
8110+
// FIXME: weird that we use PrecedenceGroupRelation, not NameElement.
8111+
P.CodeCompletion->
8112+
completeInPrecedenceGroup(SyntaxKind::PrecedenceGroupRelation);
8113+
P.consumeToken();
8114+
return makeParserCodeCompletionStatus();
8115+
}
8116+
8117+
DeclNameLoc nameLoc;
8118+
auto name = P.parseDeclNameRef(nameLoc,
8119+
diag::expected_group_name_in_precedencegroup_list, {});
8120+
if (!name)
8121+
return makeParserError();
8122+
8123+
takeGroupName(prevCommaLoc, name, nameLoc);
8124+
8125+
if (P.Tok.is(tok::code_complete)
8126+
&& P.getEndOfPreviousLoc() == P.Tok.getLoc()) {
8127+
P.consumeToken();
8128+
return makeParserCodeCompletionStatus();
8129+
}
8130+
if (!P.consumeIf(tok::comma, prevCommaLoc))
8131+
break;
8132+
} while (true);
8133+
P.SyntaxContext->collectNodesInPlace(SyntaxKind::PrecedenceGroupNameList);
8134+
return makeParserSuccess();
8135+
}
8136+
81078137
ParserResult<OperatorDecl>
81088138
Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
81098139
SourceLoc NameLoc, DeclAttributes &Attributes) {
@@ -8131,56 +8161,58 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
81318161
return makeParserCodeCompletionResult<OperatorDecl>();
81328162
}
81338163

8134-
SyntaxParsingContext ListCtxt(SyntaxContext, SyntaxKind::IdentifierList);
8135-
8136-
(void)parseIdentifier(groupName, groupLoc,
8137-
diag::operator_decl_expected_precedencegroup,
8138-
/*diagnoseDollarPrefix=*/false);
8164+
// Although we parse this as a list, we actually only want there to be zero
8165+
// (prefix/postfix) or one (infix) elements. These SourceLocs point to the
8166+
// ends of the elements that should not be there (including the introducer
8167+
// token for the first one) so that we can diagnose them all at once. If
8168+
// `typesEndLoc` never becomes valid, we didn't find any excess elements.
8169+
SourceLoc excessStartLoc = isInfix ? SourceLoc() : colonLoc;
8170+
SourceLoc excessEndLoc;
8171+
8172+
ParserStatus listStatus = parsePrecedenceGroupNameList(*this,
8173+
[&](SourceLoc prevCommaLoc, DeclNameRef name, DeclNameLoc nameLoc) {
8174+
if (!isPrefix && !isPostfix && groupName.empty()) {
8175+
// For infix operator declarations, the first element is assumed to be
8176+
// a real precedence group.
8177+
groupName = name.getBaseIdentifier();
8178+
groupLoc = nameLoc.getBaseNameLoc();
8179+
} else {
8180+
// This is an excess element. Update excessStartLoc and excessEndLoc to
8181+
// include it in the range to diagnose.
8182+
if (excessStartLoc.isInvalid())
8183+
excessStartLoc = prevCommaLoc;
8184+
excessEndLoc = nameLoc.getEndLoc();
8185+
}
8186+
});
81398187

8140-
if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) {
8141-
// Designated types have been removed; consume the list (mainly for source
8142-
// compatibility with old swiftinterfaces) and emit a warning.
8188+
if (listStatus.isErrorOrHasCompletion())
8189+
return makeParserResult<OperatorDecl>(listStatus, nullptr);
81438190

8144-
// These SourceLocs point to the ends of the designated type list. If
8145-
// `typesEndLoc` never becomes valid, we didn't find any designated types.
8146-
SourceLoc typesStartLoc = Tok.getLoc();
8147-
SourceLoc typesEndLoc;
8191+
// Nothing to complete here, simply consume the token.
8192+
if (Tok.is(tok::code_complete))
8193+
consumeToken();
81488194

8149-
if (isPrefix || isPostfix) {
8150-
// These have no precedence group, so we already parsed the first entry
8151-
// in the designated types list. Retroactively include it in the range.
8152-
typesStartLoc = colonLoc;
8153-
typesEndLoc = groupLoc;
8154-
}
8195+
if (excessEndLoc.isValid()) {
8196+
auto diagID = !isPrefix && !isPostfix ? diag::precedencegroup_too_many
8197+
: diag::precedencegroup_not_infix;
81558198

8156-
while (consumeIf(tok::comma, typesEndLoc)) {
8157-
if (Tok.isNot(tok::eof))
8158-
typesEndLoc = consumeToken();
8159-
}
8199+
if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes)
8200+
diagID = diag::operator_decl_remove_designated_types;
81608201

8161-
if (typesEndLoc.isValid())
8162-
diagnose(typesStartLoc, diag::operator_decl_remove_designated_types)
8163-
.fixItRemove({typesStartLoc, typesEndLoc});
8164-
} else {
8165-
if (isPrefix || isPostfix) {
8166-
diagnose(colonLoc, diag::precedencegroup_not_infix)
8167-
.fixItRemove({colonLoc, groupLoc});
8168-
}
8169-
// Nothing to complete here, simply consume the token.
8170-
if (Tok.is(tok::code_complete))
8171-
consumeToken();
8202+
diagnose(excessStartLoc, diagID)
8203+
.fixItRemove({excessStartLoc, excessEndLoc});
81728204
}
81738205
}
81748206

81758207
// Diagnose deprecated operator body syntax `operator + { ... }`.
8208+
SourceLoc lastGoodLoc = PreviousLoc;
81768209
SourceLoc lBraceLoc;
81778210
if (consumeIf(tok::l_brace, lBraceLoc)) {
81788211
if (isInfix && !Tok.is(tok::r_brace)) {
81798212
diagnose(lBraceLoc, diag::deprecated_operator_body_use_group);
81808213
} else {
81818214
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
81828215
if (Tok.is(tok::r_brace)) {
8183-
SourceLoc lastGoodLoc = groupLoc.isValid() ? groupLoc : NameLoc;
81848216
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
81858217
lastGoodLoc);
81868218
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
@@ -8420,28 +8452,14 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
84208452
: higherThanKeywordLoc);
84218453
auto &relations = (isLowerThan ? lowerThan : higherThan);
84228454

8423-
do {
8424-
SyntaxParsingContext NameCtxt(SyntaxContext,
8425-
SyntaxKind::PrecedenceGroupNameElement);
8426-
if (checkCodeCompletion(SyntaxKind::PrecedenceGroupRelation)) {
8427-
return abortBody(/*hasCodeCompletion*/true);
8428-
}
8429-
8430-
if (Tok.isNot(tok::identifier)) {
8431-
diagnose(Tok, diag::expected_precedencegroup_relation, attrName);
8432-
return abortBody();
8433-
}
8434-
Identifier name;
8435-
SourceLoc nameLoc = consumeIdentifier(name,
8436-
/*diagnoseDollarPrefix=*/false);
8437-
relations.push_back({nameLoc, name, nullptr});
8438-
8439-
if (skipUnspacedCodeCompleteToken())
8440-
return abortBody(/*hasCodeCompletion*/true);
8441-
if (!consumeIf(tok::comma))
8442-
break;
8443-
} while (true);
8444-
SyntaxContext->collectNodesInPlace(SyntaxKind::PrecedenceGroupNameList);
8455+
ParserStatus listStatus = parsePrecedenceGroupNameList(*this,
8456+
[&](SourceLoc prevCommaLoc, DeclNameRef name, DeclNameLoc nameLoc) {
8457+
relations.push_back({nameLoc.getBaseNameLoc(), name.getBaseIdentifier(),
8458+
nullptr});
8459+
});
8460+
if (listStatus.isErrorOrHasCompletion()) {
8461+
return abortBody(listStatus.hasCodeCompletion());
8462+
}
84458463
continue;
84468464
}
84478465

lib/Parse/ParseExpr.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,9 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
11261126
// Handle "x.42" - a tuple index.
11271127
if (Tok.is(tok::integer_literal)) {
11281128
DeclNameRef name(Context.getIdentifier(Tok.getText()));
1129-
SourceLoc nameLoc = consumeToken(tok::integer_literal);
1129+
SourceLoc nameLoc =
1130+
(SyntaxParsingContext(SyntaxContext, SyntaxKind::DeclNameRef),
1131+
consumeToken(tok::integer_literal));
11301132
SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);
11311133

11321134
// Don't allow '.<integer literal>' following a numeric literal
@@ -2250,13 +2252,19 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
22502252
DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc,
22512253
const Diagnostic &diag,
22522254
DeclNameOptions flags) {
2255+
SyntaxParsingContext declNameRefCtxt(SyntaxContext, SyntaxKind::DeclNameRef);
2256+
22532257
// Consume the base name.
22542258
DeclBaseName baseName;
22552259
SourceLoc baseNameLoc;
22562260
if (Tok.isAny(tok::identifier, tok::kw_Self, tok::kw_self)) {
22572261
Identifier baseNameId;
22582262
baseNameLoc = consumeIdentifier(baseNameId, /*diagnoseDollarPrefix=*/false);
22592263
baseName = baseNameId;
2264+
} else if (flags.contains(DeclNameFlag::AllowAnonymousParamNames)
2265+
&& Tok.is(tok::dollarident)) {
2266+
baseName = Context.getIdentifier(Tok.getText());
2267+
baseNameLoc = consumeToken(tok::dollarident);
22602268
} else if (flags.contains(DeclNameFlag::AllowOperators) &&
22612269
Tok.isAnyOperator()) {
22622270
baseName = Context.getIdentifier(Tok.getText());
@@ -3005,8 +3013,14 @@ ParserResult<Expr> Parser::parseExprClosure() {
30053013
/// dollarident
30063014
Expr *Parser::parseExprAnonClosureArg() {
30073015
SyntaxParsingContext ExprContext(SyntaxContext, SyntaxKind::IdentifierExpr);
3008-
StringRef Name = Tok.getText();
3009-
SourceLoc Loc = consumeToken(tok::dollarident);
3016+
3017+
DeclNameLoc nameLoc;
3018+
DeclNameRef nameRef =
3019+
parseDeclNameRef(nameLoc, diag::impossible_parse,
3020+
DeclNameFlag::AllowAnonymousParamNames);
3021+
3022+
StringRef Name = nameRef.getBaseIdentifier().str();
3023+
SourceLoc Loc = nameLoc.getBaseNameLoc();
30103024
assert(Name[0] == '$' && "Not a dollarident");
30113025

30123026
// We know from the lexer that this is all-numeric.

lib/Parse/ParseType.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,8 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason) {
889889
ParserResult<TypeRepr> Parser::parseAnyType() {
890890
SyntaxParsingContext IdentTypeCtxt(SyntaxContext,
891891
SyntaxKind::SimpleTypeIdentifier);
892+
SyntaxParsingContext DeclNameRefCtxt(SyntaxContext, SyntaxKind::DeclNameRef);
893+
892894
auto Loc = consumeToken(tok::kw_Any);
893895
auto TyR = CompositionTypeRepr::createEmptyComposition(Context, Loc);
894896
return makeParserResult(TyR);

lib/Syntax/SyntaxFactory.cpp.gyb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,12 +270,19 @@ SyntaxFactory::makeGenericParameter(TokenSyntax Name,
270270
return makeGenericParameter(None, Name, None, None, TrailingComma);
271271
}
272272

273+
DeclNameRefSyntax SyntaxFactory::makeDeclNameRef(Optional<StringRef> ModuleName,
274+
StringRef BaseName,
275+
StringRef LeadingTrivia,
276+
StringRef TrailingTrivia) {
277+
auto baseNameIdent = makeIdentifier(BaseName, LeadingTrivia, TrailingTrivia);
278+
return makeDeclNameRef(baseNameIdent, None);
279+
}
280+
273281
TypeSyntax SyntaxFactory::makeTypeIdentifier(StringRef TypeName,
274282
StringRef LeadingTrivia,
275283
StringRef TrailingTrivia) {
276-
auto identifier =
277-
makeIdentifier(TypeName, LeadingTrivia, TrailingTrivia);
278-
return makeSimpleTypeIdentifier(identifier, None);
284+
auto nameRef = makeDeclNameRef(None, TypeName, LeadingTrivia, TrailingTrivia);
285+
return makeSimpleTypeIdentifier(nameRef, None);
279286
}
280287

281288
TypeSyntax SyntaxFactory::makeAnyTypeIdentifier(StringRef LeadingTrivia,

0 commit comments

Comments
 (0)