diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
index 19b6574e7ba86..57e4eabcdc2dc 100644
--- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
@@ -2450,7 +2450,7 @@ private void ParseBlockAndExpressionBodiesWithSemicolon(
if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken)
{
- blockBody = this.ParseBlock(isMethodBody: true);
+ blockBody = this.ParseMethodOrAccessorBodyBlock(isAccessorBody: false);
}
if (this.CurrentToken.Kind == SyntaxKind.EqualsGreaterThanToken)
@@ -2477,25 +2477,6 @@ private void ParseBlockAndExpressionBodiesWithSemicolon(
}
}
- private void ParseBodyOrSemicolon(out BlockSyntax body, out SyntaxToken semicolon)
- {
- if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken)
- {
- body = this.ParseBlock(isMethodBody: true);
-
- semicolon = null;
- if (this.CurrentToken.Kind == SyntaxKind.SemicolonToken)
- {
- semicolon = this.EatTokenWithPrejudice(ErrorCode.ERR_UnexpectedSemicolon);
- }
- }
- else
- {
- semicolon = this.EatToken(SyntaxKind.SemicolonToken);
- body = null;
- }
- }
-
private bool IsEndOfTypeParameterList()
{
if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken)
@@ -3305,7 +3286,7 @@ private AccessorDeclarationSyntax ParseAccessorDeclaration(bool isEvent)
{
if (!IsTerminator())
{
- blockBody = this.ParseBlock(isMethodBody: true, isAccessorBody: true);
+ blockBody = this.ParseMethodOrAccessorBodyBlock(isAccessorBody: true);
}
else
{
@@ -6941,54 +6922,66 @@ private bool IsPossibleNewExpression()
return null;
}
- // If "isMethodBody" is true, then this is the immediate body of a method/accessor.
- // In this case, we create a many-child list if the body is not a small single statement.
- // This then allows a "with many weak children" red node when the red node is created.
- // If "isAccessorBody" is true, then we produce a special diagnostic if the open brace is
- // missing. Also, "isMethodBody" must be true.
- private BlockSyntax ParseBlock(bool isMethodBody = false, bool isAccessorBody = false)
+ ///
+ /// Used to parse the block-body for a method or accessor. For blocks that appear *inside*
+ /// method bodies, call .
+ ///
+ /// If is true, then we produce a special diagnostic if the
+ /// open brace is missing.
+ private BlockSyntax ParseMethodOrAccessorBodyBlock(bool isAccessorBody)
{
- // Check again for incremental re-use, since ParseBlock is called from a bunch of places
- // other than ParseStatementCore()
+ // Check again for incremental re-use. This way if a method signature is edited we can
+ // still quickly re-sync on the body.
if (this.IsIncrementalAndFactoryContextMatches && this.CurrentNodeKind == SyntaxKind.Block)
- {
return (BlockSyntax)this.EatNode();
- }
// There's a special error code for a missing token after an accessor keyword
- var openBrace = isAccessorBody && this.CurrentToken.Kind != SyntaxKind.OpenBraceToken
+ CSharpSyntaxNode openBrace = isAccessorBody && this.CurrentToken.Kind != SyntaxKind.OpenBraceToken
? this.AddError(
SyntaxFactory.MissingToken(SyntaxKind.OpenBraceToken),
IsFeatureEnabled(MessageID.IDS_FeatureExpressionBodiedAccessor)
- ? ErrorCode.ERR_SemiOrLBraceOrArrowExpected
- : ErrorCode.ERR_SemiOrLBraceExpected)
+ ? ErrorCode.ERR_SemiOrLBraceOrArrowExpected
+ : ErrorCode.ERR_SemiOrLBraceExpected)
: this.EatToken(SyntaxKind.OpenBraceToken);
var statements = _pool.Allocate();
- try
- {
- CSharpSyntaxNode tmp = openBrace;
- this.ParseStatements(ref tmp, statements, stopOnSwitchSections: false);
- openBrace = (SyntaxToken)tmp;
- var closeBrace = this.EatToken(SyntaxKind.CloseBraceToken);
+ this.ParseStatements(ref openBrace, statements, stopOnSwitchSections: false);
- SyntaxList statementList;
- if (isMethodBody && IsLargeEnoughNonEmptyStatementList(statements))
- {
- // Force creation a many-children list, even if only 1, 2, or 3 elements in the statement list.
- statementList = new SyntaxList(SyntaxList.List(((SyntaxListBuilder)statements).ToArray()));
- }
- else
- {
- statementList = statements;
- }
+ var block = _syntaxFactory.Block(
+ (SyntaxToken)openBrace,
+ // Force creation a many-children list, even if only 1, 2, or 3 elements in the statement list.
+ IsLargeEnoughNonEmptyStatementList(statements)
+ ? new SyntaxList(SyntaxList.List(((SyntaxListBuilder)statements).ToArray()))
+ : statements,
+ this.EatToken(SyntaxKind.CloseBraceToken));
- return _syntaxFactory.Block(openBrace, statementList, closeBrace);
- }
- finally
- {
- _pool.Free(statements);
- }
+ _pool.Free(statements);
+ return block;
+ }
+
+ ///
+ /// Used to parse normal blocks that appear inside method bodies. For the top level block
+ /// of a method/accessor use .
+ ///
+ private BlockSyntax ParseBlock()
+ {
+ // Check again for incremental re-use, since ParseBlock is called from a bunch of places
+ // other than ParseStatementCore()
+ if (this.IsIncrementalAndFactoryContextMatches && this.CurrentNodeKind == SyntaxKind.Block)
+ return (BlockSyntax)this.EatNode();
+
+ CSharpSyntaxNode openBrace = this.EatToken(SyntaxKind.OpenBraceToken);
+
+ var statements = _pool.Allocate();
+ this.ParseStatements(ref openBrace, statements, stopOnSwitchSections: false);
+
+ var block = _syntaxFactory.Block(
+ (SyntaxToken)openBrace,
+ statements,
+ this.EatToken(SyntaxKind.CloseBraceToken));
+
+ _pool.Free(statements);
+ return block;
}
// Is this statement list non-empty, and large enough to make using weak children beneficial?