@@ -3362,6 +3362,8 @@ public static bool IsComplete(CSharpSyntaxNode node)
33623362 return true;
33633363 }
33643364
3365+ #nullable enable
3366+
33653367 private ConstructorDeclarationSyntax ParseConstructorDeclaration(
33663368 SyntaxList<AttributeListSyntax> attributes, SyntaxListBuilder modifiers)
33673369 {
@@ -3371,9 +3373,7 @@ private ConstructorDeclarationSyntax ParseConstructorDeclaration(
33713373 try
33723374 {
33733375 var paramList = this.ParseParenthesizedParameterList(forExtension: false);
3374- var initializer = this.CurrentToken.Kind == SyntaxKind.ColonToken
3375- ? this.ParseConstructorInitializer()
3376- : null;
3376+ var initializer = this.TryParseConstructorInitializer();
33773377
33783378 this.ParseBlockAndExpressionBodiesWithSemicolon(out var body, out var expressionBody, out var semicolon);
33793379
@@ -3385,38 +3385,48 @@ private ConstructorDeclarationSyntax ParseConstructorDeclaration(
33853385 }
33863386 }
33873387
3388- private ConstructorInitializerSyntax ParseConstructorInitializer ()
3388+ private ConstructorInitializerSyntax? TryParseConstructorInitializer ()
33893389 {
3390- var colon = this.EatToken(SyntaxKind.ColonToken);
3390+ var currentTokenKind = this.CurrentToken.Kind;
3391+ var shouldParse = currentTokenKind is SyntaxKind.ColonToken ||
3392+ (currentTokenKind is SyntaxKind.EqualsGreaterThanToken &&
3393+ this.PeekToken(1).Kind is SyntaxKind.ThisKeyword or SyntaxKind.BaseKeyword &&
3394+ this.PeekToken(2).Kind is SyntaxKind.OpenParenToken);
33913395
3392- var reportError = true;
3393- var kind = this.CurrentToken.Kind == SyntaxKind.BaseKeyword
3394- ? SyntaxKind.BaseConstructorInitializer
3395- : SyntaxKind.ThisConstructorInitializer;
3396+ if (!shouldParse)
3397+ return null;
33963398
3397- SyntaxToken token;
3398- if (this.CurrentToken.Kind is SyntaxKind.BaseKeyword or SyntaxKind.ThisKeyword)
3399- {
3400- token = this.EatToken();
3401- }
3402- else
3403- {
3404- token = this.EatToken(SyntaxKind.ThisKeyword, ErrorCode.ERR_ThisOrBaseExpected);
3399+ return ParseConstructorInitializer();
3400+ }
34053401
3406- // No need to report further errors at this point:
3407- reportError = false;
3408- }
3402+ private ConstructorInitializerSyntax ParseConstructorInitializer()
3403+ {
3404+ // Normally called for `:` but also in some error recovery circumstances for `=>`. EatTokenAsKind handles
3405+ // both cases properly, producing the right errors we need in the latter case, and always consuming
3406+ // whichever token we're coming into this method on.
3407+ Debug.Assert(this.CurrentToken.Kind is SyntaxKind.ColonToken or SyntaxKind.EqualsGreaterThanToken);
3408+ var colon = this.EatTokenAsKind(SyntaxKind.ColonToken);
3409+
3410+ var token = this.CurrentToken.Kind is SyntaxKind.BaseKeyword or SyntaxKind.ThisKeyword
3411+ ? this.EatToken()
3412+ : this.EatToken(SyntaxKind.ThisKeyword, ErrorCode.ERR_ThisOrBaseExpected);
34093413
34103414 var argumentList = this.CurrentToken.Kind == SyntaxKind.OpenParenToken
34113415 ? this.ParseParenthesizedArgumentList()
34123416 : _syntaxFactory.ArgumentList(
3413- this.EatToken(SyntaxKind.OpenParenToken, reportError),
3417+ this.EatToken(SyntaxKind.OpenParenToken, reportError: !token.ContainsDiagnostics ),
34143418 arguments: default,
3415- this.EatToken(SyntaxKind.CloseParenToken, reportError));
3419+ this.EatToken(SyntaxKind.CloseParenToken, reportError: !token.ContainsDiagnostics ));
34163420
3417- return _syntaxFactory.ConstructorInitializer(kind, colon, token, argumentList);
3421+ return _syntaxFactory.ConstructorInitializer(
3422+ token.Kind == SyntaxKind.BaseKeyword
3423+ ? SyntaxKind.BaseConstructorInitializer
3424+ : SyntaxKind.ThisConstructorInitializer,
3425+ colon, token, argumentList);
34183426 }
34193427
3428+ #nullable disable
3429+
34203430 private DestructorDeclarationSyntax ParseDestructorDeclaration(SyntaxList<AttributeListSyntax> attributes, SyntaxListBuilder modifiers)
34213431 {
34223432 Debug.Assert(this.CurrentToken.Kind == SyntaxKind.TildeToken);
0 commit comments