Merge pull request #13625 from rintaro/syntax-cleanup
[Syntax] Fix miscellaneous round trip failures
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index f72e0c4..2f49325 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -925,9 +925,9 @@
SourceLoc &LAngleLoc,
SourceLoc &RAngleLoc);
- SyntaxParserResult<syntax::TypeSyntax, TypeRepr> parseTypeIdentifier();
+ ParserResult<TypeRepr> parseTypeIdentifier();
ParserResult<TypeRepr> parseOldStyleProtocolComposition();
- SyntaxParserResult<syntax::TypeSyntax, CompositionTypeRepr> parseAnyType();
+ ParserResult<CompositionTypeRepr> parseAnyType();
ParserResult<TypeRepr> parseSILBoxType(GenericParamList *generics,
const TypeAttributes &attrs,
Optional<Scope> &GenericsScope);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 7c537a7..244c4b6 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -272,8 +272,10 @@
InPoundLineEnvironment);
// If we are done parsing the whole file, finalize the token receiver.
- if (Tok.is(tok::eof))
+ if (Tok.is(tok::eof)) {
+ SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
TokReceiver->finalize();
+ }
return FoundTopLevelCodeToExecute;
}
@@ -1606,13 +1608,13 @@
SyntaxParsingContext TokListContext(SyntaxContext, SyntaxKind::TokenList);
if (Tok.is(tok::l_paren) && getEndOfPreviousLoc() == Tok.getLoc()) {
- ParserPosition LParenPosition = getParserPosition();
+ BacktrackingScope backtrack(*this);
skipSingle();
// If we found '->', or 'throws' after paren, it's likely a parameter
// of function type.
- if (Tok.isAny(tok::arrow, tok::kw_throws, tok::kw_rethrows,
+ if (Tok.isNot(tok::arrow, tok::kw_throws, tok::kw_rethrows,
tok::kw_throw))
- backtrackToPosition(LParenPosition);
+ backtrack.cancelBacktrack();
}
return true;
}
@@ -3236,6 +3238,10 @@
ParserResult<TypeDecl> Parser::
parseDeclTypeAlias(Parser::ParseDeclOptions Flags, DeclAttributes &Attributes) {
ParserPosition startPosition = getParserPosition();
+ llvm::Optional<SyntaxParsingContext> TmpCtxt;
+ TmpCtxt.emplace(SyntaxContext);
+ TmpCtxt->setTransparent();
+
SourceLoc TypeAliasLoc = consumeToken(tok::kw_typealias);
SourceLoc EqualLoc;
Identifier Id;
@@ -3271,11 +3277,14 @@
}
if (Flags.contains(PD_InProtocol) && !genericParams && !Tok.is(tok::equal)) {
+ TmpCtxt->setDiscard();
+ TmpCtxt.reset();
// If we're in a protocol and don't see an '=' this looks like leftover Swift 2
// code intending to be an associatedtype.
backtrackToPosition(startPosition);
return parseDeclAssociatedType(Flags, Attributes);
}
+ TmpCtxt.reset();
ParserResult<TypeRepr> UnderlyingTy;
@@ -3873,9 +3882,13 @@
// attributes might not be appertaining to the accessor, but to the first
// declaration inside the implicit getter, we need to save the parser
// position and restore it later.
+ llvm::Optional<SyntaxParsingContext> BacktrackCtxt;
ParserPosition BeginParserPosition;
- if (Tok.is(tok::at_sign))
+ if (Tok.is(tok::at_sign)) {
BeginParserPosition = getParserPosition();
+ BacktrackCtxt.emplace(SyntaxContext);
+ BacktrackCtxt->setTransparent();
+ }
// Parse any leading attributes.
DeclAttributes Attributes;
@@ -3912,6 +3925,8 @@
// that the diagnostics point to correct tokens.
if (BeginParserPosition.isValid()) {
backtrackToPosition(BeginParserPosition);
+ BacktrackCtxt->setDiscard();
+ BacktrackCtxt.reset();
Attributes = DeclAttributes();
}
if (!IsFirstAccessor) {
@@ -3925,6 +3940,8 @@
TheDeclPtr = &accessors.Get;
isImplicitGet = true;
}
+ if (BacktrackCtxt)
+ BacktrackCtxt.reset();
// Set the contextual keyword kind properly.
if (AccessorKeywordLoc.isValid()) {
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 49a5b07..8276a53 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -576,15 +576,14 @@
if (startsWithSymbol(Tok, '.')) {
llvm::SaveAndRestore<Expr*> S(SwiftKeyPathRoot, rootResult.getPtrOrNull());
+ auto dotLoc = Tok.getLoc();
// For uniformity, \.foo is parsed as if it were MAGIC.foo, so we need to
// make sure the . is there, but parsing the ? in \.? as .? doesn't make
// sense. This is all made more complicated by .?. being considered an
// operator token, and a single one at that (which means
// peekToken().is(tok::identifier) is incorrect: it is true for .?.foo).
- auto position = getParserPosition();
- auto dotLoc = consumeStartingCharacterOfCurrentToken(tok::period);
- if (Tok.is(tok::identifier))
- backtrackToPosition(position);
+ if (Tok.getLength() != 1 || !peekToken().is(tok::identifier))
+ consumeStartingCharacterOfCurrentToken(tok::period);
auto inner = makeParserResult(new (Context) KeyPathDotExpr(dotLoc));
bool unusedHasBindOptional = false;
@@ -1590,13 +1589,9 @@
break;
case tok::kw_Any: { // Any
- auto SynResult = parseAnyType();
- auto expr = new (Context) TypeExpr(TypeLoc(SynResult.getAST()));
- if (SynResult.hasSyntax()) {
- TypeExprSyntaxBuilder Builder;
- Builder.useType(SynResult.getSyntax());
- SyntaxContext->addSyntax(Builder.build());
- }
+ SyntaxParsingContext ExprContext(SyntaxContext, SyntaxKind::TypeExpr);
+ auto TyR = parseAnyType();
+ auto expr = new (Context) TypeExpr(TypeLoc(TyR.get()));
Result = makeParserResult(expr);
break;
}
@@ -2089,6 +2084,8 @@
return baseName;
}
+ // TODO: Support compound name in libSyntax.
+
// Try to parse a compound name.
BacktrackingScope backtrack(*this);
@@ -2097,11 +2094,6 @@
SourceLoc lparenLoc = consumeToken(tok::l_paren);
SourceLoc rparenLoc;
while (true) {
- // The following code may backtrack; so we disable the syntax tree creation
- // in this scope.
- SyntaxParsingContext DisabledContext(SyntaxContext);
- SyntaxContext->disable();
-
// Terminate at ')'.
if (Tok.is(tok::r_paren)) {
rparenLoc = consumeToken(tok::r_paren);
diff --git a/lib/Parse/ParseGeneric.cpp b/lib/Parse/ParseGeneric.cpp
index 0d79088..36c8120 100644
--- a/lib/Parse/ParseGeneric.cpp
+++ b/lib/Parse/ParseGeneric.cpp
@@ -276,10 +276,7 @@
do {
SyntaxParsingContext ReqContext(SyntaxContext, SyntaxContextKind::Syntax);
// Parse the leading type-identifier.
- auto FirstTypeResult = parseTypeIdentifier();
- if (FirstTypeResult.hasSyntax())
- SyntaxContext->addSyntax(FirstTypeResult.getSyntax());
- ParserResult<TypeRepr> FirstType = FirstTypeResult.getASTResult();
+ ParserResult<TypeRepr> FirstType = parseTypeIdentifier();
if (FirstType.hasCodeCompletion()) {
Status.setHasCodeCompletion();
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index a81f93c..d252ad7 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -186,10 +186,7 @@
case tok::kw_Self:
case tok::kw_Any:
case tok::identifier: {
- auto Result = parseTypeIdentifier();
- if (Result.hasSyntax())
- SyntaxContext->addSyntax(Result.getSyntax());
- ty = Result.getASTResult();
+ ty = parseTypeIdentifier();
break;
}
case tok::l_paren:
@@ -547,7 +544,7 @@
/// type-identifier:
/// identifier generic-args? ('.' identifier generic-args?)*
///
-SyntaxParserResult<TypeSyntax, TypeRepr> Parser::parseTypeIdentifier() {
+ParserResult<TypeRepr> Parser::parseTypeIdentifier() {
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_Self)) {
// is this the 'Any' type
if (Tok.is(tok::kw_Any)) {
@@ -557,7 +554,7 @@
CodeCompletion->completeTypeSimpleBeginning();
// Eat the code completion token because we handled it.
consumeToken(tok::code_complete);
- return makeSyntaxCodeCompletionResult<TypeSyntax, IdentTypeRepr>();
+ return makeParserCodeCompletionResult<IdentTypeRepr>();
}
diagnose(Tok, diag::expected_identifier_for_type);
@@ -569,10 +566,10 @@
return nullptr;
}
+ SyntaxParsingContext IdentTypeCtxt(SyntaxContext, SyntaxContextKind::Type);
ParserStatus Status;
SmallVector<ComponentIdentTypeRepr *, 4> ComponentsR;
- llvm::Optional<TypeSyntax> SyntaxNode;
SourceLoc EndLoc;
while (true) {
SourceLoc Loc;
@@ -604,27 +601,10 @@
else
CompT = new (Context) SimpleIdentTypeRepr(Loc, Name);
ComponentsR.push_back(CompT);
-
- if (SyntaxContext->isEnabled()) {
- if (SyntaxNode) {
- MemberTypeIdentifierSyntaxBuilder Builder;
- Builder.useBaseType(*SyntaxNode);
- if (auto Args =
- SyntaxContext->popIf<GenericArgumentClauseSyntax>())
- Builder.useGenericArgumentClause(*Args);
- Builder.useName(SyntaxContext->popToken());
- Builder.usePeriod(SyntaxContext->popToken());
- SyntaxNode.emplace(Builder.build());
- } else {
- SimpleTypeIdentifierSyntaxBuilder Builder;
- if (auto Args =
- SyntaxContext->popIf<GenericArgumentClauseSyntax>())
- Builder.useGenericArgumentClause(*Args);
- Builder.useName(SyntaxContext->popToken());
- SyntaxNode.emplace(Builder.build());
- }
- }
}
+ SyntaxContext->createNodeInPlace(ComponentsR.size() == 1
+ ? SyntaxKind::SimpleTypeIdentifier
+ : SyntaxKind::MemberTypeIdentifier);
// Treat 'Foo.<anything>' as an attempt to write a dotted type
// unless <anything> is 'Type'.
@@ -669,7 +649,7 @@
consumeToken(tok::code_complete);
}
- return makeSyntaxResult(Status, SyntaxNode, ITR);
+ return makeParserResult(Status, ITR);
}
/// parseTypeSimpleOrComposition
@@ -740,18 +720,13 @@
Context, Types, FirstTypeLoc, {FirstAmpersandLoc, PreviousLoc}));
}
-SyntaxParserResult<TypeSyntax, CompositionTypeRepr>
+ParserResult<CompositionTypeRepr>
Parser::parseAnyType() {
+ SyntaxParsingContext IdentTypeCtxt(SyntaxContext,
+ SyntaxKind::SimpleTypeIdentifier);
auto Loc = consumeToken(tok::kw_Any);
auto TyR = CompositionTypeRepr::createEmptyComposition(Context, Loc);
- llvm::Optional<TypeSyntax> SyntaxNode;
-
- if (SyntaxContext->isEnabled()) {
- auto builder = SimpleTypeIdentifierSyntaxBuilder();
- builder.useName(SyntaxContext->popToken());
- SyntaxNode.emplace(builder.build());
- }
- return makeSyntaxResult(SyntaxNode, TyR);
+ return makeParserResult(TyR);
}
/// parseOldStyleProtocolComposition
@@ -779,10 +754,7 @@
if (!IsEmpty) {
do {
// Parse the type-identifier.
- auto Result = parseTypeIdentifier();
- if (Result.hasSyntax())
- SyntaxContext->addSyntax(Result.getSyntax());
- ParserResult<TypeRepr> Protocol = Result.getASTResult();
+ ParserResult<TypeRepr> Protocol = parseTypeIdentifier();
Status |= Protocol;
if (auto *ident =
dyn_cast_or_null<IdentTypeRepr>(Protocol.getPtrOrNull()))
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index f09cf19..28c22a5 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -467,9 +467,6 @@
}
Parser::~Parser() {
- if (Tok.is(tok::eof))
- SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
-
delete L;
delete TokReceiver;
delete SyntaxContext;
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index 4b7dfb8..795201f 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -122,6 +122,8 @@
createNodeInPlace(Kind, Pair.first);
break;
}
+ case SyntaxKind::SimpleTypeIdentifier:
+ case SyntaxKind::MemberTypeIdentifier:
case SyntaxKind::FunctionCallExpr:
case SyntaxKind::SubscriptExpr:
case SyntaxKind::ExprList: {
diff --git a/test/Syntax/round_trip_misc.swift b/test/Syntax/round_trip_misc.swift
new file mode 100644
index 0000000..1b78860
--- /dev/null
+++ b/test/Syntax/round_trip_misc.swift
@@ -0,0 +1,30 @@
+// RUN: %round-trip-syntax-test --swift-syntax-test %swift-syntax-test --file %s
+
+class C {
+ // Erroneous typealias decl.
+ typealias Inner: Foo = Int
+
+ // Implict accessor with attribute at the top of its body.
+ var x: Int {
+ @objc
+ func f() {}
+ }
+}
+
+// Orphan '}' at top level
+}
+
+// Compound name.
+foo(x:y:)()
+
+// Type identifier with erroneous component.
+let a: Int.)
+
+// Type with unknown attribute followed by parentheses.
+typealias b = @foobar() -> Void
+typealias c = @foobar(a) () -> Void
+
+// keypath expressions.
+let d = \.foo
+let e = \.[1]
+let f = \.?.bar