From 53cb76e148644233206d45463ad0bd532fe694dd Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 12 Feb 2020 19:25:48 -0800 Subject: [PATCH 1/3] Increase the amount of recursive parsing calls for statements+blocks. --- .../CSharp/Portable/Parser/LanguageParser.cs | 104 +++++++++--------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 19b6574e7ba86..706ff4ce07933 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,19 +6922,18 @@ 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 @@ -6965,30 +6945,48 @@ private BlockSyntax ParseBlock(bool isMethodBody = false, bool isAccessorBody = : 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); - 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; - } + CSharpSyntaxNode tmp = openBrace; + this.ParseStatements(ref tmp, statements, stopOnSwitchSections: false); - return _syntaxFactory.Block(openBrace, statementList, closeBrace); - } - finally - { - _pool.Free(statements); - } + var block = _syntaxFactory.Block( + (SyntaxToken)tmp, + // 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)); + + _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(); + + // There's a special error code for a missing token after an accessor keyword + var openBrace = this.EatToken(SyntaxKind.OpenBraceToken); + + var statements = _pool.Allocate(); + + CSharpSyntaxNode tmp = openBrace; + this.ParseStatements(ref tmp, statements, stopOnSwitchSections: false); + + var block = _syntaxFactory.Block( + (SyntaxToken)tmp, + 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? From 6883b8707c3ba801f561ba5101465e8ca5f1b086 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 12 Feb 2020 20:06:02 -0800 Subject: [PATCH 2/3] Simplify --- .../CSharp/Portable/Parser/LanguageParser.cs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 706ff4ce07933..11e18ac017616 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6936,21 +6936,19 @@ private BlockSyntax ParseMethodOrAccessorBodyBlock(bool isAccessorBody) 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(); - - CSharpSyntaxNode tmp = openBrace; - this.ParseStatements(ref tmp, statements, stopOnSwitchSections: false); + this.ParseStatements(ref openBrace, statements, stopOnSwitchSections: false); var block = _syntaxFactory.Block( - (SyntaxToken)tmp, + (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())) @@ -6973,15 +6971,13 @@ private BlockSyntax ParseBlock() return (BlockSyntax)this.EatNode(); // There's a special error code for a missing token after an accessor keyword - var openBrace = this.EatToken(SyntaxKind.OpenBraceToken); + CSharpSyntaxNode openBrace = this.EatToken(SyntaxKind.OpenBraceToken); var statements = _pool.Allocate(); - - CSharpSyntaxNode tmp = openBrace; - this.ParseStatements(ref tmp, statements, stopOnSwitchSections: false); + this.ParseStatements(ref openBrace, statements, stopOnSwitchSections: false); var block = _syntaxFactory.Block( - (SyntaxToken)tmp, + (SyntaxToken)openBrace, statements, this.EatToken(SyntaxKind.CloseBraceToken)); From 29793af048448746f70ac0be01800cc3d95c696c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 13 Feb 2020 10:09:09 -0800 Subject: [PATCH 3/3] Remove comment --- src/Compilers/CSharp/Portable/Parser/LanguageParser.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 11e18ac017616..57e4eabcdc2dc 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6970,7 +6970,6 @@ private BlockSyntax ParseBlock() 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 CSharpSyntaxNode openBrace = this.EatToken(SyntaxKind.OpenBraceToken); var statements = _pool.Allocate();