@@ -2450,7 +2450,7 @@ private void ParseBlockAndExpressionBodiesWithSemicolon(
24502450
24512451 if ( this . CurrentToken . Kind == SyntaxKind . OpenBraceToken )
24522452 {
2453- blockBody = this . ParseBlock ( isMethodBody : true ) ;
2453+ blockBody = this . ParseMethodOrAccessorBodyBlock ( isAccessorBody : false ) ;
24542454 }
24552455
24562456 if ( this . CurrentToken . Kind == SyntaxKind . EqualsGreaterThanToken )
@@ -2477,25 +2477,6 @@ private void ParseBlockAndExpressionBodiesWithSemicolon(
24772477 }
24782478 }
24792479
2480- private void ParseBodyOrSemicolon ( out BlockSyntax body , out SyntaxToken semicolon )
2481- {
2482- if ( this . CurrentToken . Kind == SyntaxKind . OpenBraceToken )
2483- {
2484- body = this . ParseBlock ( isMethodBody : true ) ;
2485-
2486- semicolon = null ;
2487- if ( this . CurrentToken . Kind == SyntaxKind . SemicolonToken )
2488- {
2489- semicolon = this . EatTokenWithPrejudice ( ErrorCode . ERR_UnexpectedSemicolon ) ;
2490- }
2491- }
2492- else
2493- {
2494- semicolon = this . EatToken ( SyntaxKind . SemicolonToken ) ;
2495- body = null ;
2496- }
2497- }
2498-
24992480 private bool IsEndOfTypeParameterList ( )
25002481 {
25012482 if ( this . CurrentToken . Kind == SyntaxKind . OpenParenToken )
@@ -3305,7 +3286,7 @@ private AccessorDeclarationSyntax ParseAccessorDeclaration(bool isEvent)
33053286 {
33063287 if ( ! IsTerminator ( ) )
33073288 {
3308- blockBody = this . ParseBlock ( isMethodBody : true , isAccessorBody : true ) ;
3289+ blockBody = this . ParseMethodOrAccessorBodyBlock ( isAccessorBody : true ) ;
33093290 }
33103291 else
33113292 {
@@ -6421,8 +6402,10 @@ private StatementSyntax ParseStatementNoDeclaration(bool allowAnyExpression)
64216402 case SyntaxKind . GotoKeyword :
64226403 return this . ParseGotoStatement ( ) ;
64236404 case SyntaxKind . IfKeyword :
6424- case SyntaxKind . ElseKeyword : // Including 'else' keyword to handle 'else without if' error cases
64256405 return this . ParseIfStatement ( ) ;
6406+ case SyntaxKind . ElseKeyword :
6407+ // Including 'else' keyword to handle 'else without if' error cases
6408+ return this . ParseMisplacedElse ( ) ;
64266409 case SyntaxKind . LockKeyword :
64276410 return this . ParseLockStatement ( ) ;
64286411 case SyntaxKind . ReturnKeyword :
@@ -6941,54 +6924,66 @@ private bool IsPossibleNewExpression()
69416924 return null ;
69426925 }
69436926
6944- // If "isMethodBody" is true, then this is the immediate body of a method/accessor.
6945- // In this case, we create a many-child list if the body is not a small single statement.
6946- // This then allows a "with many weak children" red node when the red node is created.
6947- // If "isAccessorBody" is true, then we produce a special diagnostic if the open brace is
6948- // missing. Also, "isMethodBody" must be true.
6949- private BlockSyntax ParseBlock ( bool isMethodBody = false , bool isAccessorBody = false )
6927+ /// <summary>
6928+ /// Used to parse the block-body for a method or accessor. For blocks that appear *inside*
6929+ /// method bodies, call <see cref="ParseBlock"/>.
6930+ /// </summary>
6931+ /// <param name="isAccessorBody">If is true, then we produce a special diagnostic if the
6932+ /// open brace is missing.</param>
6933+ private BlockSyntax ParseMethodOrAccessorBodyBlock ( bool isAccessorBody )
69506934 {
6951- // Check again for incremental re-use, since ParseBlock is called from a bunch of places
6952- // other than ParseStatementCore()
6935+ // Check again for incremental re-use. This way if a method signature is edited we can
6936+ // still quickly re-sync on the body.
69536937 if ( this . IsIncrementalAndFactoryContextMatches && this . CurrentNodeKind == SyntaxKind . Block )
6954- {
69556938 return ( BlockSyntax ) this . EatNode ( ) ;
6956- }
69576939
69586940 // There's a special error code for a missing token after an accessor keyword
6959- var openBrace = isAccessorBody && this . CurrentToken . Kind != SyntaxKind . OpenBraceToken
6941+ CSharpSyntaxNode openBrace = isAccessorBody && this . CurrentToken . Kind != SyntaxKind . OpenBraceToken
69606942 ? this . AddError (
69616943 SyntaxFactory . MissingToken ( SyntaxKind . OpenBraceToken ) ,
69626944 IsFeatureEnabled ( MessageID . IDS_FeatureExpressionBodiedAccessor )
6963- ? ErrorCode . ERR_SemiOrLBraceOrArrowExpected
6964- : ErrorCode . ERR_SemiOrLBraceExpected )
6945+ ? ErrorCode . ERR_SemiOrLBraceOrArrowExpected
6946+ : ErrorCode . ERR_SemiOrLBraceExpected )
69656947 : this . EatToken ( SyntaxKind . OpenBraceToken ) ;
69666948
69676949 var statements = _pool . Allocate < StatementSyntax > ( ) ;
6968- try
6969- {
6970- CSharpSyntaxNode tmp = openBrace ;
6971- this . ParseStatements ( ref tmp , statements , stopOnSwitchSections : false ) ;
6972- openBrace = ( SyntaxToken ) tmp ;
6973- var closeBrace = this . EatToken ( SyntaxKind . CloseBraceToken ) ;
6950+ this . ParseStatements ( ref openBrace , statements , stopOnSwitchSections : false ) ;
69746951
6975- SyntaxList < StatementSyntax > statementList ;
6976- if ( isMethodBody && IsLargeEnoughNonEmptyStatementList ( statements ) )
6977- {
6978- // Force creation a many-children list, even if only 1, 2, or 3 elements in the statement list.
6979- statementList = new SyntaxList < StatementSyntax > ( SyntaxList . List ( ( ( SyntaxListBuilder ) statements ) . ToArray ( ) ) ) ;
6980- }
6981- else
6982- {
6983- statementList = statements ;
6984- }
6952+ var block = _syntaxFactory . Block (
6953+ ( SyntaxToken ) openBrace ,
6954+ // Force creation a many-children list, even if only 1, 2, or 3 elements in the statement list.
6955+ IsLargeEnoughNonEmptyStatementList ( statements )
6956+ ? new SyntaxList < StatementSyntax > ( SyntaxList . List ( ( ( SyntaxListBuilder ) statements ) . ToArray ( ) ) )
6957+ : statements ,
6958+ this . EatToken ( SyntaxKind . CloseBraceToken ) ) ;
69856959
6986- return _syntaxFactory . Block ( openBrace , statementList , closeBrace ) ;
6987- }
6988- finally
6989- {
6990- _pool . Free ( statements ) ;
6991- }
6960+ _pool . Free ( statements ) ;
6961+ return block ;
6962+ }
6963+
6964+ /// <summary>
6965+ /// Used to parse normal blocks that appear inside method bodies. For the top level block
6966+ /// of a method/accessor use <see cref="ParseMethodOrAccessorBodyBlock"/>.
6967+ /// </summary>
6968+ private BlockSyntax ParseBlock ( )
6969+ {
6970+ // Check again for incremental re-use, since ParseBlock is called from a bunch of places
6971+ // other than ParseStatementCore()
6972+ if ( this . IsIncrementalAndFactoryContextMatches && this . CurrentNodeKind == SyntaxKind . Block )
6973+ return ( BlockSyntax ) this . EatNode ( ) ;
6974+
6975+ CSharpSyntaxNode openBrace = this . EatToken ( SyntaxKind . OpenBraceToken ) ;
6976+
6977+ var statements = _pool . Allocate < StatementSyntax > ( ) ;
6978+ this . ParseStatements ( ref openBrace , statements , stopOnSwitchSections : false ) ;
6979+
6980+ var block = _syntaxFactory . Block (
6981+ ( SyntaxToken ) openBrace ,
6982+ statements ,
6983+ this . EatToken ( SyntaxKind . CloseBraceToken ) ) ;
6984+
6985+ _pool . Free ( statements ) ;
6986+ return block ;
69926987 }
69936988
69946989 // Is this statement list non-empty, and large enough to make using weak children beneficial?
@@ -7686,19 +7681,28 @@ private GotoStatementSyntax ParseGotoStatement()
76867681
76877682 private IfStatementSyntax ParseIfStatement ( )
76887683 {
7689- Debug . Assert ( this . CurrentToken . Kind == SyntaxKind . IfKeyword || this . CurrentToken . Kind == SyntaxKind . ElseKeyword ) ;
7684+ Debug . Assert ( this . CurrentToken . Kind == SyntaxKind . IfKeyword ) ;
76907685
7691- bool firstTokenIsElse = this . CurrentToken . Kind == SyntaxKind . ElseKeyword ;
7692- var @if = firstTokenIsElse
7693- ? this . EatToken ( SyntaxKind . IfKeyword , ErrorCode . ERR_ElseCannotStartStatement )
7694- : this . EatToken ( SyntaxKind . IfKeyword ) ;
7695- var openParen = this . EatToken ( SyntaxKind . OpenParenToken ) ;
7696- var condition = this . ParseExpressionCore ( ) ;
7697- var closeParen = this . EatToken ( SyntaxKind . CloseParenToken ) ;
7698- var statement = firstTokenIsElse ? this . ParseExpressionStatement ( ) : this . ParseEmbeddedStatement ( ) ;
7699- var elseClause = this . ParseElseClauseOpt ( ) ;
7686+ return _syntaxFactory . IfStatement (
7687+ this . EatToken ( SyntaxKind . IfKeyword ) ,
7688+ this . EatToken ( SyntaxKind . OpenParenToken ) ,
7689+ this . ParseExpressionCore ( ) ,
7690+ this . EatToken ( SyntaxKind . CloseParenToken ) ,
7691+ this . ParseEmbeddedStatement ( ) ,
7692+ this . ParseElseClauseOpt ( ) ) ;
7693+ }
7694+
7695+ private IfStatementSyntax ParseMisplacedElse ( )
7696+ {
7697+ Debug . Assert ( this . CurrentToken . Kind == SyntaxKind . ElseKeyword ) ;
77007698
7701- return _syntaxFactory . IfStatement ( @if , openParen , condition , closeParen , statement , elseClause ) ;
7699+ return _syntaxFactory . IfStatement (
7700+ this . EatToken ( SyntaxKind . IfKeyword , ErrorCode . ERR_ElseCannotStartStatement ) ,
7701+ this . EatToken ( SyntaxKind . OpenParenToken ) ,
7702+ this . ParseExpressionCore ( ) ,
7703+ this . EatToken ( SyntaxKind . CloseParenToken ) ,
7704+ this . ParseExpressionStatement ( ) ,
7705+ this . ParseElseClauseOpt ( ) ) ;
77027706 }
77037707
77047708 private ElseClauseSyntax ParseElseClauseOpt ( )
0 commit comments