Skip to content

Commit 76bdeb8

Browse files
author
msftbot[bot]
authored
Merge pull request #41639 from CyrusNajmabadi/blockStackFrames
Increase the amount of recursive parsing calls for statements+blocks.
2 parents b73f69c + 29793af commit 76bdeb8

File tree

1 file changed

+49
-56
lines changed

1 file changed

+49
-56
lines changed

src/Compilers/CSharp/Portable/Parser/LanguageParser.cs

Lines changed: 49 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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
{
@@ -6943,54 +6924,66 @@ private bool IsPossibleNewExpression()
69436924
return null;
69446925
}
69456926

6946-
// If "isMethodBody" is true, then this is the immediate body of a method/accessor.
6947-
// In this case, we create a many-child list if the body is not a small single statement.
6948-
// This then allows a "with many weak children" red node when the red node is created.
6949-
// If "isAccessorBody" is true, then we produce a special diagnostic if the open brace is
6950-
// missing. Also, "isMethodBody" must be true.
6951-
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)
69526934
{
6953-
// Check again for incremental re-use, since ParseBlock is called from a bunch of places
6954-
// 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.
69556937
if (this.IsIncrementalAndFactoryContextMatches && this.CurrentNodeKind == SyntaxKind.Block)
6956-
{
69576938
return (BlockSyntax)this.EatNode();
6958-
}
69596939

69606940
// There's a special error code for a missing token after an accessor keyword
6961-
var openBrace = isAccessorBody && this.CurrentToken.Kind != SyntaxKind.OpenBraceToken
6941+
CSharpSyntaxNode openBrace = isAccessorBody && this.CurrentToken.Kind != SyntaxKind.OpenBraceToken
69626942
? this.AddError(
69636943
SyntaxFactory.MissingToken(SyntaxKind.OpenBraceToken),
69646944
IsFeatureEnabled(MessageID.IDS_FeatureExpressionBodiedAccessor)
6965-
? ErrorCode.ERR_SemiOrLBraceOrArrowExpected
6966-
: ErrorCode.ERR_SemiOrLBraceExpected)
6945+
? ErrorCode.ERR_SemiOrLBraceOrArrowExpected
6946+
: ErrorCode.ERR_SemiOrLBraceExpected)
69676947
: this.EatToken(SyntaxKind.OpenBraceToken);
69686948

69696949
var statements = _pool.Allocate<StatementSyntax>();
6970-
try
6971-
{
6972-
CSharpSyntaxNode tmp = openBrace;
6973-
this.ParseStatements(ref tmp, statements, stopOnSwitchSections: false);
6974-
openBrace = (SyntaxToken)tmp;
6975-
var closeBrace = this.EatToken(SyntaxKind.CloseBraceToken);
6950+
this.ParseStatements(ref openBrace, statements, stopOnSwitchSections: false);
69766951

6977-
SyntaxList<StatementSyntax> statementList;
6978-
if (isMethodBody && IsLargeEnoughNonEmptyStatementList(statements))
6979-
{
6980-
// Force creation a many-children list, even if only 1, 2, or 3 elements in the statement list.
6981-
statementList = new SyntaxList<StatementSyntax>(SyntaxList.List(((SyntaxListBuilder)statements).ToArray()));
6982-
}
6983-
else
6984-
{
6985-
statementList = statements;
6986-
}
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));
69876959

6988-
return _syntaxFactory.Block(openBrace, statementList, closeBrace);
6989-
}
6990-
finally
6991-
{
6992-
_pool.Free(statements);
6993-
}
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;
69946987
}
69956988

69966989
// Is this statement list non-empty, and large enough to make using weak children beneficial?

0 commit comments

Comments
 (0)