Skip to content

Commit 8c5dcc0

Browse files
authored
Merge pull request #27485 from rintaro/syntaxparse-decltypealias
[SyntaxParse] Parse typealias declaration
2 parents af5eda5 + 5914325 commit 8c5dcc0

File tree

8 files changed

+225
-107
lines changed

8 files changed

+225
-107
lines changed

include/swift/Parse/ASTGen.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class ASTGen {
5656
Decl *generate(const syntax::DeclSyntax &Decl, const SourceLoc Loc);
5757
TypeDecl *generate(const syntax::AssociatedtypeDeclSyntax &Decl,
5858
const SourceLoc Loc);
59+
TypeDecl *generate(const syntax::TypealiasDeclSyntax &Decl,
60+
const SourceLoc Loc);
5961

6062
TrailingWhereClause *generate(const syntax::GenericWhereClauseSyntax &syntax,
6163
const SourceLoc Loc);
@@ -70,6 +72,11 @@ class ASTGen {
7072
const Optional<syntax::ModifierListSyntax> &modifiers,
7173
SourceLoc Loc, bool includeComments);
7274

75+
void generateFreeStandingGenericWhereClause(
76+
const syntax::GenericWhereClauseSyntax &syntax,
77+
const SourceLoc Loc,
78+
GenericParamList *genericParams);
79+
7380
public:
7481
//===--------------------------------------------------------------------===//
7582
// Expressions.

include/swift/Parse/Parser.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,11 @@ class Parser {
10131013
Optional<ParsedAttributeListSyntax> attrs,
10141014
Optional<ParsedModifierListSyntax> modifiers);
10151015

1016+
ParsedSyntaxResult<ParsedDeclSyntax>
1017+
parseDeclTypeAliasSyntax(ParseDeclOptions flags,
1018+
Optional<ParsedAttributeListSyntax> attrs,
1019+
Optional<ParsedModifierListSyntax> modifiers);
1020+
10161021
ParserResult<TypeDecl> parseDeclTypeAlias(ParseDeclOptions Flags,
10171022
DeclAttributes &Attributes,
10181023
SourceLoc leadingLoc);
@@ -1628,6 +1633,9 @@ class Parser {
16281633
SmallVectorImpl<GenericTypeParamDecl *> &GenericParams);
16291634
ParserResult<GenericParamList> maybeParseGenericParams();
16301635
void
1636+
diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams,
1637+
SourceLoc whereLoc);
1638+
void
16311639
diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams);
16321640

16331641
enum class WhereClauseKind : unsigned {

lib/Parse/ASTGen.cpp

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/Basic/SourceManager.h"
1919
#include "swift/Parse/CodeCompletionCallbacks.h"
2020
#include "swift/Parse/Parser.h"
21+
#include "swift/Parse/Scope.h"
2122

2223
using namespace swift;
2324
using namespace swift::syntax;
@@ -46,6 +47,8 @@ Decl *ASTGen::generate(const DeclSyntax &D, const SourceLoc Loc) {
4647

4748
if (auto associatedTypeDecl = D.getAs<AssociatedtypeDeclSyntax>()) {
4849
DeclAST = generate(*associatedTypeDecl, Loc);
50+
} else if (auto typealiasDecl = D.getAs<TypealiasDeclSyntax>()) {
51+
DeclAST = generate(*typealiasDecl, Loc);
4952
} else {
5053
llvm_unreachable("unsupported decl kind");
5154
}
@@ -105,8 +108,8 @@ TypeDecl *ASTGen::generate(const AssociatedtypeDeclSyntax &D,
105108
return nullptr;
106109

107110
auto keywordLoc = advanceLocBegin(Loc, D.getAssociatedtypeKeyword());
108-
auto name = Context.getIdentifier(idToken.getIdentifierText());
109-
auto nameLoc = advanceLocBegin(Loc, idToken);
111+
Identifier name;
112+
SourceLoc nameLoc = generateIdentifierDeclName(idToken, Loc, name);
110113

111114
DeclAttributes attrs =
112115
generateDeclAttributes(D, D.getAttributes(), D.getModifiers(), Loc, true);
@@ -136,6 +139,89 @@ TypeDecl *ASTGen::generate(const AssociatedtypeDeclSyntax &D,
136139
return assocType;
137140
}
138141

142+
TypeDecl *ASTGen::generate(const TypealiasDeclSyntax &D, const SourceLoc Loc) {
143+
auto idToken = D.getIdentifier();
144+
if (idToken.isMissing())
145+
return nullptr;
146+
147+
auto keywordLoc = advanceLocBegin(Loc, D.getTypealiasKeyword());
148+
Identifier name;
149+
SourceLoc nameLoc = generateIdentifierDeclName(idToken, Loc, name);
150+
auto attrs =
151+
generateDeclAttributes(D, D.getAttributes(), D.getModifiers(), Loc, true);
152+
SourceLoc equalLoc;
153+
154+
DebuggerContextChange DCC(P, name, DeclKind::TypeAlias);
155+
156+
Optional<Scope> GenericScope;
157+
GenericParamList *genericParams = nullptr;
158+
GenericScope.emplace(&P, ScopeKind::Generics);
159+
if (auto clause = D.getGenericParameterClause())
160+
genericParams = generate(*clause, Loc);
161+
162+
auto *TAD = new (Context) TypeAliasDecl(keywordLoc, equalLoc, name, nameLoc,
163+
genericParams, P.CurDeclContext);
164+
P.setLocalDiscriminator(TAD);
165+
TAD->getAttrs() = attrs;
166+
167+
TypeRepr *underlyingType = nullptr;
168+
SourceLoc typeEndLoc;
169+
if (auto init = D.getInitializer()) {
170+
Parser::ContextChange CC(P, TAD);
171+
equalLoc = generate(init->getEqual(), Loc);
172+
underlyingType = generate(init->getValue(), Loc);
173+
if (auto lastToken = init->getLastToken())
174+
typeEndLoc = generate(*lastToken, Loc);
175+
}
176+
TAD->setUnderlyingTypeRepr(underlyingType);
177+
178+
SourceLoc whereLoc;
179+
if (auto clause = D.getGenericWhereClause()) {
180+
whereLoc = advanceLocBegin(Loc, clause->getWhereKeyword());
181+
Parser::ContextChange CC(P, TAD);
182+
generateFreeStandingGenericWhereClause(*clause, Loc, genericParams);
183+
}
184+
P.diagnoseWhereClauseInGenericParamList(genericParams, whereLoc);
185+
186+
if (equalLoc.isInvalid())
187+
return nullptr;
188+
189+
GenericScope.reset();
190+
191+
addToScope(TAD);
192+
return DCC.fixupParserResult(TAD).getPtrOrNull();
193+
}
194+
195+
void ASTGen::generateFreeStandingGenericWhereClause(
196+
const syntax::GenericWhereClauseSyntax &syntax, const SourceLoc Loc,
197+
GenericParamList *genericParams) {
198+
199+
SourceLoc whereLoc = generate(syntax.getWhereKeyword(), Loc);
200+
201+
if (!genericParams) {
202+
P.diagnose(whereLoc, diag::where_without_generic_params,
203+
unsigned(Parser::WhereClauseKind::Declaration));
204+
return;
205+
}
206+
207+
// Push the generic parameters back into a local scope so that references
208+
// will find them.
209+
Scope S(&P, ScopeKind::Generics);
210+
for (auto pd : genericParams->getParams())
211+
addToScope(pd);
212+
213+
SmallVector<RequirementRepr, 4> requirements;
214+
requirements.reserve(syntax.getRequirementList().size());
215+
for (auto elem : syntax.getRequirementList()) {
216+
if (auto req = generate(elem, Loc))
217+
requirements.push_back(*req);
218+
}
219+
if (requirements.empty())
220+
return;
221+
222+
genericParams->addTrailingWhereClause(Context, whereLoc, requirements);
223+
}
224+
139225
TrailingWhereClause *ASTGen::generate(const GenericWhereClauseSyntax &syntax,
140226
const SourceLoc Loc) {
141227
SourceLoc whereLoc = advanceLocBegin(Loc, syntax.getWhereKeyword());

lib/Parse/ParseDecl.cpp

Lines changed: 83 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,7 +2782,6 @@ Parser::parseDecl(ParseDeclOptions Flags,
27822782
break;
27832783
}
27842784
case tok::kw_typealias:
2785-
DeclParsingContext.setCreateSyntax(SyntaxKind::TypealiasDecl);
27862785
DeclResult = parseDeclTypeAlias(Flags, Attributes, leadingLoc);
27872786
MayNeedOverrideCompletion = true;
27882787
break;
@@ -3977,115 +3976,126 @@ ParserStatus Parser::parseLineDirective(bool isLine) {
39773976

39783977
/// Parse a typealias decl.
39793978
///
3980-
/// \verbatim
39813979
/// decl-typealias:
3982-
/// 'typealias' identifier generic-params? '=' type requirement-clause?
3983-
/// \endverbatim
3984-
ParserResult<TypeDecl>
3985-
Parser::parseDeclTypeAlias(Parser::ParseDeclOptions Flags,
3986-
DeclAttributes &Attributes, SourceLoc leadingLoc) {
3980+
/// 'typealias' identifier generic-params? '=' type
3981+
/// generic-where-clause?
3982+
ParsedSyntaxResult<ParsedDeclSyntax>
3983+
Parser::parseDeclTypeAliasSyntax(Parser::ParseDeclOptions Flags,
3984+
Optional<ParsedAttributeListSyntax> attrs,
3985+
Optional<ParsedModifierListSyntax> modifiers) {
39873986
ParserPosition startPosition = getParserPosition();
39883987
llvm::Optional<SyntaxParsingContext> TmpCtxt;
39893988
TmpCtxt.emplace(SyntaxContext);
39903989
TmpCtxt->setBackTracking();
39913990

3992-
SourceLoc TypeAliasLoc = consumeToken(tok::kw_typealias);
3993-
SourceLoc EqualLoc;
3994-
Identifier Id;
3995-
SourceLoc IdLoc;
3996-
ParserStatus Status;
3991+
auto typealiasKeyword = consumeTokenSyntax(tok::kw_typealias);
39973992

3998-
Status |= parseIdentifierDeclName(
3999-
*this, Id, IdLoc, "typealias",
4000-
[](const Token &next) { return next.isAny(tok::colon, tok::equal); });
4001-
if (Status.isError()) {
4002-
TmpCtxt->setTransparent();
4003-
return nullptr;
4004-
}
3993+
ParserStatus status;
40053994

4006-
DebuggerContextChange DCC(*this, Id, DeclKind::TypeAlias);
3995+
auto applyIntroducer = [&](ParsedTypealiasDeclSyntaxBuilder &builder) {
3996+
if (attrs)
3997+
builder.useAttributes(std::move(*attrs));
3998+
if (modifiers)
3999+
builder.useModifiers(std::move(*modifiers));
4000+
builder.useTypealiasKeyword(std::move(typealiasKeyword));
4001+
};
40074002

4008-
Optional<Scope> GenericsScope;
4009-
GenericsScope.emplace(this, ScopeKind::Generics);
4003+
// Parse the name.
4004+
auto name =
4005+
parseIdentifierDeclNameSyntax(*this, "typealias", [](const Token &next) {
4006+
return next.isAny(tok::colon, tok::equal);
4007+
});
4008+
if (name.isNull()) {
4009+
TmpCtxt->setTransparent();
4010+
TmpCtxt.reset();
4011+
ParsedTypealiasDeclSyntaxBuilder builder(*SyntaxContext);
4012+
applyIntroducer(builder);
4013+
return makeParsedError(builder.build());
4014+
}
40104015

4011-
// Parse a generic parameter list if it is present.
4012-
GenericParamList *genericParams = nullptr;
4016+
// Parse optional generic parameters.
4017+
Optional<ParsedGenericParameterClauseSyntax> genericParams;
40134018
if (startsWithLess(Tok)) {
4014-
auto Result = parseGenericParameters();
4015-
if (Result.hasCodeCompletion() && !CodeCompletion)
4016-
return makeParserCodeCompletionStatus();
4017-
genericParams = Result.getPtrOrNull();
4018-
4019-
if (!genericParams) {
4020-
// If the parser returned null, it is an already diagnosed parse error.
4021-
} else if (!genericParams->getRequirements().empty()) {
4022-
// Reject a where clause.
4023-
diagnose(genericParams->getWhereLoc(),
4024-
diag::associated_type_generic_parameter_list)
4025-
.highlight(genericParams->getWhereClauseSourceRange());
4026-
}
4019+
auto result = parseGenericParameterClauseSyntax();
4020+
status |= result.getStatus();
4021+
if (!result.isNull())
4022+
genericParams = result.get();
40274023
}
40284024

40294025
if (Flags.contains(PD_InProtocol) && !genericParams && !Tok.is(tok::equal)) {
4026+
// If we're in a protocol and don't see an '=' this looks like leftover
4027+
// Swift 2 code intending to be an associatedtype.
40304028
TmpCtxt.reset();
4031-
// If we're in a protocol and don't see an '=' this looks like leftover Swift 2
4032-
// code intending to be an associatedtype.
40334029
backtrackToPosition(startPosition);
4034-
return parseDeclAssociatedType(Flags, Attributes, leadingLoc);
4030+
return parseDeclAssociatedTypeSyntax(Flags, std::move(attrs),
4031+
std::move(modifiers));
40354032
}
4033+
40364034
TmpCtxt->setTransparent();
40374035
TmpCtxt.reset();
40384036

4039-
auto *TAD = new (Context) TypeAliasDecl(TypeAliasLoc, EqualLoc, Id, IdLoc,
4040-
genericParams, CurDeclContext);
4041-
setLocalDiscriminator(TAD);
4042-
ParserResult<TypeRepr> UnderlyingTy;
4037+
ParsedTypealiasDeclSyntaxBuilder builder(*SyntaxContext);
4038+
applyIntroducer(builder);
4039+
builder.useIdentifier(name.get());
4040+
if (genericParams)
4041+
builder.useGenericParameterClause(std::move(*genericParams));
40434042

4044-
if (Tok.is(tok::colon) || Tok.is(tok::equal)) {
4045-
ContextChange CC(*this, TAD);
4043+
// Parse underlying type clause.
4044+
if (Tok.isAny(tok::equal, tok::colon)) {
4045+
ParsedTypeInitializerClauseSyntaxBuilder initBuilder(*SyntaxContext);
40464046

4047-
SyntaxParsingContext InitCtx(SyntaxContext,
4048-
SyntaxKind::TypeInitializerClause);
4047+
// Parse '='.
40494048
if (Tok.is(tok::colon)) {
40504049
// It is a common mistake to write "typealias A : Int" instead of = Int.
40514050
// Recognize this and produce a fixit.
40524051
diagnose(Tok, diag::expected_equal_in_typealias)
40534052
.fixItReplace(Tok.getLoc(), " = ");
4054-
EqualLoc = consumeToken(tok::colon);
4053+
ignoreToken(tok::colon);
40554054
} else {
4056-
EqualLoc = consumeToken(tok::equal);
4055+
initBuilder.useEqual(consumeTokenSyntax());
40574056
}
40584057

4059-
UnderlyingTy = parseType(diag::expected_type_in_typealias);
4060-
TAD->setTypeEndLoc(PreviousLoc);
4061-
Status |= UnderlyingTy;
4058+
// Parse the underlying type.
4059+
auto underlyingType = parseTypeSyntax(diag::expected_type_in_typealias);
4060+
status |= underlyingType.getStatus();
4061+
if (!underlyingType.isNull()) {
4062+
initBuilder.useValue(underlyingType.get());
4063+
} else {
4064+
initBuilder.useValue(
4065+
ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext));
4066+
}
4067+
builder.useInitializer(initBuilder.build());
4068+
} else {
4069+
diagnose(Tok, diag::expected_equal_in_typealias);
4070+
status.setIsParseError();
40624071
}
40634072

4064-
TAD->setUnderlyingTypeRepr(UnderlyingTy.getPtrOrNull());
4065-
TAD->getAttrs() = Attributes;
4066-
4067-
// Parse a 'where' clause if present, adding it to our GenericParamList.
4073+
// Parse optional where clause.
40684074
if (Tok.is(tok::kw_where)) {
4069-
ContextChange CC(*this, TAD);
4070-
Status |= parseFreestandingGenericWhereClause(genericParams);
4075+
bool FirstTypeInComplete = false;
4076+
auto whereClause = parseGenericWhereClauseSyntax(FirstTypeInComplete);
4077+
status |= whereClause.getStatus();
4078+
builder.useGenericWhereClause(whereClause.get());
40714079
}
40724080

4073-
if (UnderlyingTy.isNull()) {
4074-
// If there is an attempt to do code completion
4075-
// inside of typealias type, let's just return
4076-
// because we've seen required '=' token.
4077-
if (EqualLoc.isInvalid()) {
4078-
diagnose(Tok, diag::expected_equal_in_typealias);
4079-
Status.setIsParseError();
4080-
return Status;
4081-
}
4082-
}
4081+
return makeParsedResult(builder.build(), status);
4082+
}
40834083

4084-
// Exit the scope introduced for the generic parameters.
4085-
GenericsScope.reset();
4084+
ParserResult<TypeDecl>
4085+
Parser::parseDeclTypeAlias(Parser::ParseDeclOptions Flags,
4086+
DeclAttributes &Attributes, SourceLoc leadingLoc) {
4087+
auto modifiers = SyntaxContext->popIf<ParsedModifierListSyntax>();
4088+
auto attrs = SyntaxContext->popIf<ParsedAttributeListSyntax>();
4089+
4090+
auto parsed =
4091+
parseDeclTypeAliasSyntax(Flags, std::move(attrs), std::move(modifiers));
4092+
assert(!parsed.isNull());
40864093

4087-
addToScope(TAD);
4088-
return DCC.fixupParserResult(Status, TAD);
4094+
SyntaxContext->addSyntax(parsed.get());
4095+
auto syntax = SyntaxContext->topNode<DeclSyntax>();
4096+
TypeDecl *result =
4097+
cast_or_null<TypeDecl>(Generator.generate(syntax, leadingLoc));
4098+
return makeParserResult(parsed.getStatus(), result);
40894099
}
40904100

40914101
/// Parse an associatedtype decl.

0 commit comments

Comments
 (0)