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