diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 6550d229bb5c4..4629412b4891b 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -5506,9 +5506,6 @@ private VariableDeclaratorSyntax ParseVariableDeclarator( // specifically treats it as a variable name, even if it could be interpreted as a // keyword. var name = this.ParseIdentifierToken(); - BracketedArgumentListSyntax argumentList = null; - EqualsValueClauseSyntax initializer = null; - TerminatorState saveTerm = _termState; bool isFixed = (flags & VariableFlags.Fixed) != 0; bool isConst = (flags & VariableFlags.Const) != 0; bool isLocalOrField = (flags & VariableFlags.LocalOrField) != 0; @@ -5524,125 +5521,206 @@ private VariableDeclaratorSyntax ParseVariableDeclarator( name = this.AddError(name, ErrorCode.ERR_MultiTypeInDeclaration); } - switch (this.CurrentToken.Kind) + return this.CurrentToken.Kind switch { - case SyntaxKind.EqualsToken: - if (isFixed) - { - goto default; - } + SyntaxKind.EqualsToken when !isFixed => parseNonFixedVariableDeclaratorWithEqualsToken(name, argumentList: null, out localFunction), + SyntaxKind.LessThanToken => parseVariableDeclaratorWithLessThanToken(name, out localFunction), + SyntaxKind.OpenParenToken => parseVariableDeclaratorWithOpenParenToken(name, out localFunction), + SyntaxKind.OpenBracketToken => parseVariableDeclaratorWithOpenBracketToken(name, out localFunction), + _ => parseVariableDeclaratorDefault(name, out localFunction), + }; - var equals = this.EatToken(); + VariableDeclaratorSyntax parseNonFixedVariableDeclaratorWithEqualsToken( + SyntaxToken name, BracketedArgumentListSyntax argumentList, out LocalFunctionStatementSyntax localFunction) + { + Debug.Assert(this.CurrentToken.Kind == SyntaxKind.EqualsToken); + Debug.Assert(!isFixed, "Should only be called in the non fixed-statement/fixed-size-buffer case"); - // check for lambda expression with explicit ref return type: `ref int () => { ... }` - var refKeyword = isLocalOrField && !isConst && this.CurrentToken.Kind == SyntaxKind.RefKeyword && !this.IsPossibleLambdaExpression(Precedence.Expression) - ? this.EatToken() - : null; + var equals = this.EatToken(); - var init = this.ParseVariableInitializer(); - initializer = _syntaxFactory.EqualsValueClause( - equals, - refKeyword == null ? init : _syntaxFactory.RefExpression(refKeyword, init)); - break; + // check for lambda expression with explicit ref return type: `ref int () => { ... }` + var refKeyword = isLocalOrField && !isConst && this.CurrentToken.Kind == SyntaxKind.RefKeyword && !this.IsPossibleLambdaExpression(Precedence.Expression) + ? this.EatToken() + : null; - case SyntaxKind.LessThanToken: - if (allowLocalFunctions && isFirst) - { - localFunction = TryParseLocalFunctionStatementBody(attributes, mods, parentType, name); - if (localFunction != null) - { - return null; - } - } - goto default; + var init = this.ParseVariableInitializer(); + var initializer = _syntaxFactory.EqualsValueClause( + equals, + refKeyword == null ? init : _syntaxFactory.RefExpression(refKeyword, init)); - case SyntaxKind.OpenParenToken: - if (allowLocalFunctions && isFirst) + localFunction = null; + return _syntaxFactory.VariableDeclarator(name, argumentList, initializer); + } + + VariableDeclaratorSyntax parseVariableDeclaratorWithLessThanToken(SyntaxToken name, out LocalFunctionStatementSyntax localFunction) + { + if (allowLocalFunctions && isFirst) + { + Debug.Assert(!isFixed, "Both the fixed-size-buffer and fixed-statement codepaths pass through allowLocalFunctions=false"); + localFunction = TryParseLocalFunctionStatementBody(attributes, mods, parentType, name); + if (localFunction != null) { - localFunction = TryParseLocalFunctionStatementBody(attributes, mods, parentType, name); - if (localFunction != null) - { - return null; - } + return null; } + } - // Special case for accidental use of C-style constructors - // Fake up something to hold the arguments. - _termState |= TerminatorState.IsPossibleEndOfVariableDeclaration; - argumentList = this.ParseBracketedArgumentList(); - _termState = saveTerm; - argumentList = this.AddError(argumentList, ErrorCode.ERR_BadVarDecl); - break; + return parseVariableDeclaratorDefault(name, out localFunction); + } - case SyntaxKind.OpenBracketToken: - bool sawNonOmittedSize; - _termState |= TerminatorState.IsPossibleEndOfVariableDeclaration; - var specifier = this.ParseArrayRankSpecifier(sawNonOmittedSize: out sawNonOmittedSize); - _termState = saveTerm; - var open = specifier.OpenBracketToken; - var sizes = specifier.Sizes; - var close = specifier.CloseBracketToken; - if (isFixed && !sawNonOmittedSize) + VariableDeclaratorSyntax parseVariableDeclaratorWithOpenParenToken( + SyntaxToken name, out LocalFunctionStatementSyntax localFunction) + { + if (allowLocalFunctions && isFirst) + { + Debug.Assert(!isFixed, "Both the fixed-size-buffer and fixed-statement codepaths pass through allowLocalFunctions=false"); + localFunction = TryParseLocalFunctionStatementBody(attributes, mods, parentType, name); + if (localFunction != null) { - close = this.AddError(close, ErrorCode.ERR_ValueExpected); + return null; } + } - var args = _pool.AllocateSeparated(); - var withSeps = sizes.GetWithSeparators(); - foreach (var item in withSeps) - { - if (item is ExpressionSyntax expression) - { - bool isOmitted = expression.Kind == SyntaxKind.OmittedArraySizeExpression; - if (!isFixed && !isOmitted) - { - expression = this.AddError(expression, ErrorCode.ERR_ArraySizeInDeclaration); - } + // Special case for accidental use of C-style constructors + // Fake up something to hold the arguments. + var saveTerm = _termState; + _termState |= TerminatorState.IsPossibleEndOfVariableDeclaration; + var argumentList = this.ParseBracketedArgumentList(); + _termState = saveTerm; + argumentList = this.AddError(argumentList, ErrorCode.ERR_BadVarDecl); - args.Add(_syntaxFactory.Argument(null, refKindKeyword: null, expression)); - } - else - { - args.AddSeparator((SyntaxToken)item); - } - } + localFunction = null; + return _syntaxFactory.VariableDeclarator(name, argumentList, initializer: null); + } - argumentList = _syntaxFactory.BracketedArgumentList(open, _pool.ToListAndFree(args), close); - if (!isFixed) + VariableDeclaratorSyntax parseVariableDeclaratorWithOpenBracketToken( + SyntaxToken name, out LocalFunctionStatementSyntax localFunction) + { + var saveTerm = _termState; + _termState |= TerminatorState.IsPossibleEndOfVariableDeclaration; + var specifier = this.ParseArrayRankSpecifier(sawNonOmittedSize: out var sawNonOmittedSize); + _termState = saveTerm; + var open = specifier.OpenBracketToken; + var sizes = specifier.Sizes; + var close = specifier.CloseBracketToken; + if (isFixed && !sawNonOmittedSize) + { + close = this.AddError(close, ErrorCode.ERR_ValueExpected); + } + + var args = _pool.AllocateSeparated(); + var withSeps = specifier.Sizes.GetWithSeparators(); + foreach (var item in withSeps) + { + if (item is ExpressionSyntax expression) { - argumentList = this.AddError(argumentList, ErrorCode.ERR_CStyleArray); - // If we have "int x[] = new int[10];" then parse the initializer. - if (this.CurrentToken.Kind == SyntaxKind.EqualsToken) + bool isOmitted = expression.Kind == SyntaxKind.OmittedArraySizeExpression; + if (!isFixed && !isOmitted) { - goto case SyntaxKind.EqualsToken; + expression = this.AddError(expression, ErrorCode.ERR_ArraySizeInDeclaration); } + + args.Add(_syntaxFactory.Argument(null, refKindKeyword: null, expression)); + } + else + { + args.AddSeparator((SyntaxToken)item); } + } - break; + var argumentList = _syntaxFactory.BracketedArgumentList(open, _pool.ToListAndFree(args), close); + if (!isFixed) + { + argumentList = this.AddError(argumentList, ErrorCode.ERR_CStyleArray); + // If we have "int x[] = new int[10];" then parse the initializer. + if (this.CurrentToken.Kind == SyntaxKind.EqualsToken) + return parseNonFixedVariableDeclaratorWithEqualsToken(name, argumentList, out localFunction); + } - default: - if (isConst) + localFunction = null; + return _syntaxFactory.VariableDeclarator(name, argumentList, initializer: null); + } + + VariableDeclaratorSyntax parseVariableDeclaratorDefault( + SyntaxToken name, out LocalFunctionStatementSyntax localFunction) + { + // Note: it is ok that we do this work prior to the isConst/isFixed checks below. If it looks like + // a variable initializer, that means we're missing at least an equals and we'll report that error + // here. So it's fine to not report the other errors related to const/fixed as they can be fixed up + // once the user adds the '='. + if (looksLikeVariableInitializer()) + { + localFunction = null; + return _syntaxFactory.VariableDeclarator( + name, + argumentList: null, + _syntaxFactory.EqualsValueClause( + this.EatToken(SyntaxKind.EqualsToken), + this.ParseVariableInitializer())); + } + + if (isConst) + { + // Error here for missing constant initializers. Note: this error would be better suited in the + // binder as we do not need to make an syntax tree with diagnostics here. + name = this.AddError(name, ErrorCode.ERR_ConstValueRequired); + } + else if (isFixed) + { + if (parentType.Kind == SyntaxKind.ArrayType) { - name = this.AddError(name, ErrorCode.ERR_ConstValueRequired); // Error here for missing constant initializers + // They accidentally put the array before the identifier + name = this.AddError(name, ErrorCode.ERR_FixedDimsRequired); } - else if (isFixed) + else { - if (parentType.Kind == SyntaxKind.ArrayType) - { - // They accidentally put the array before the identifier - name = this.AddError(name, ErrorCode.ERR_FixedDimsRequired); - } - else - { - goto case SyntaxKind.OpenBracketToken; - } + return parseVariableDeclaratorWithOpenBracketToken(name, out localFunction); } + } - break; + localFunction = null; + return _syntaxFactory.VariableDeclarator(name, argumentList: null, initializer: null); } - localFunction = null; - return _syntaxFactory.VariableDeclarator(name, argumentList, initializer); + bool looksLikeVariableInitializer() + { + // Note: this check is redundant, as CanStartExpression will return false for an equals-token. However, + // we want to guarantee that this always holds true, and thus the caller will *always* report an error + // when trying to consume the equals token. That ensures that we it's then ok to skip other syntax + // errors that are reported with variable declarators. + if (this.CurrentToken.Kind == SyntaxKind.EqualsToken) + return false; + + // If we see a token that can start an expression after the identifier (e.g., "int value 5;"), + // treat it as a missing '=' and parse the initializer. + // + // Do this except for cases that are better served by saying we have a missing comma. Specifically: + // + // Type t1 t2 t3 + // Type t1 t2, + // Type t1 t2 = ... + // Type t1 t2; + // Type t1 t2) // likely an incorrect tuple. + var shouldParseAsNextDeclarator = + this.CurrentToken.Kind == SyntaxKind.IdentifierToken && + this.PeekToken(1).Kind is SyntaxKind.IdentifierToken or SyntaxKind.CommaToken or SyntaxKind.EqualsToken or SyntaxKind.SemicolonToken or SyntaxKind.CloseParenToken or SyntaxKind.EndOfFileToken; + if (shouldParseAsNextDeclarator) + return false; + + if (ContainsErrorDiagnostic(name)) + return false; + + if (!CanStartExpression()) + return false; + + using var _ = this.GetDisposableResetPoint(resetOnDispose: true); + var initializer = this.ParseExpressionCore(); + + // If we see a type following, then prefer to view this as a declarator for the next variable. + if (initializer is TypeSyntax) + return false; + + return !ContainsErrorDiagnostic(initializer); + } } // Is there a local function after an eaten identifier? diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index a5e11eec192c2..4606385df7015 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -22156,6 +22156,9 @@ void M() }"; comp = CreateCompilation(source); comp.VerifyDiagnostics( + // (1,12): error CS8983: A 'struct' with field initializers must include an explicitly declared constructor. + // ref struct R + Diagnostic(ErrorCode.ERR_StructHasInitializersAndNoDeclaredConstructor, "R").WithLocation(1, 12), // (3,9): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) // ref scoped R M() => throw null; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 9), @@ -22168,16 +22171,18 @@ void M() // (3,16): warning CS0169: The field 'R.R' is never used // ref scoped R M() => throw null; Diagnostic(ErrorCode.WRN_UnreferencedField, "R").WithArguments("R.R").WithLocation(3, 16), - // (3,18): error CS1002: ; expected + // (3,18): error CS1003: Syntax error, '=' expected // ref scoped R M() => throw null; - Diagnostic(ErrorCode.ERR_SemicolonExpected, "M").WithLocation(3, 18), - // (3,18): error CS1520: Method must have a return type + Diagnostic(ErrorCode.ERR_SyntaxError, "M").WithArguments("=").WithLocation(3, 18), + // (3,18): error CS8172: Cannot initialize a by-reference variable with a value // ref scoped R M() => throw null; - Diagnostic(ErrorCode.ERR_MemberNeedsType, "M").WithLocation(3, 18), - // (3,18): error CS8958: The parameterless struct constructor must be 'public'. + Diagnostic(ErrorCode.ERR_InitializeByReferenceVariableWithValue, "M() => throw null").WithLocation(3, 18), + // (3,18): error CS0246: The type or namespace name 'M' could not be found (are you missing a using directive or an assembly reference?) // ref scoped R M() => throw null; - Diagnostic(ErrorCode.ERR_NonPublicParameterlessStructConstructor, "M").WithLocation(3, 18) - ); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "M").WithArguments("M").WithLocation(3, 18), + // (3,18): error CS1510: A ref or out value must be an assignable variable + // ref scoped R M() => throw null; + Diagnostic(ErrorCode.ERR_RefLvalueExpected, "M() => throw null").WithLocation(3, 18)); source = @" delegate void M(ref scoped R parameter); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs index b8632c6150a87..05a91066845a8 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs @@ -13857,5 +13857,4060 @@ class C<[] public class D {} } EOF(); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals() + { + var tree = UsingTree(""" + class C { + int value 5; + } + """, + // (2,13): error CS1003: Syntax error, '=' expected + // int value 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments("=").WithLocation(2, 13)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_StringLiteral() + { + var tree = UsingTree(""" + class C { + string value "hello"; + } + """, + // (2,16): error CS1003: Syntax error, '=' expected + // string value "hello"; + Diagnostic(ErrorCode.ERR_SyntaxError, """ + "hello" + """).WithArguments("=").WithLocation(2, 16)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.StringLiteralExpression); + { + N(SyntaxKind.StringLiteralToken, @"""hello"""); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_BoolLiteral() + { + var tree = UsingTree(""" + class C { + bool value true; + } + """, + // (2,14): error CS1003: Syntax error, '=' expected + // bool value true; + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=").WithLocation(2, 14)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.BoolKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_NullLiteral() + { + var tree = UsingTree(""" + class C { + object value null; + } + """, + // (2,16): error CS1003: Syntax error, '=' expected + // object value null; + Diagnostic(ErrorCode.ERR_SyntaxError, "null").WithArguments("=").WithLocation(2, 16)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_UnaryExpression() + { + var tree = UsingTree(""" + class C { + int x -y; + } + """, + // (2,9): error CS1003: Syntax error, '=' expected + // int x -y; + Diagnostic(ErrorCode.ERR_SyntaxError, "-").WithArguments("=").WithLocation(2, 9)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryMinusExpression); + { + N(SyntaxKind.MinusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_BinaryExpression() + { + var tree = UsingTree(""" + class C { + int x + y; + } + """, + // (2,9): error CS1003: Syntax error, '=' expected + // int x + y; + Diagnostic(ErrorCode.ERR_SyntaxError, "+").WithArguments("=").WithLocation(2, 9)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryPlusExpression); + { + N(SyntaxKind.PlusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_ObjectCreationExpression() + { + var tree = UsingTree(""" + class C { + C x new C(); + } + """, + // (2,7): error CS1003: Syntax error, '=' expected + // C x new C(); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(2, 7)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_ImplicitObjectCreation() + { + var tree = UsingTree(""" + class C { + C x new(); + } + """, + // (2,9): error CS1003: Syntax error, '=' expected + // C x new(); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(2, 9)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_CollectionExpression() + { + // Error recovery isn't great here as we have existing logic that looks for `C x[` and reports a misplaced + // array declarator For C/C++ style users. + var tree = UsingTree(""" + class C { + C x [1, 2, 3]; + } + """, + // (2,7): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_CStyleArray, "[1, 2, 3]").WithLocation(2, 7), + // (2,8): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "1").WithLocation(2, 8), + // (2,11): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2").WithLocation(2, 11), + // (2,14): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "3").WithLocation(2, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "3"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_InvocationExpression() + { + var tree = UsingTree(""" + class C { + C x X.Y; + } + """, + // (2,7): error CS1003: Syntax error, '=' expected + // C x X.Y; + Diagnostic(ErrorCode.ERR_SyntaxError, "X").WithArguments("=").WithLocation(2, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_CastExpression() + { + // Error recovery isn't great here as `C x(` looks like the start of a method. + var tree = UsingTree(""" + class C { + C x (int)0; + } + """, + // (2,11): error CS1001: Identifier expected + // C x (int)0; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(2, 11), + // (2,12): error CS1002: ; expected + // C x (int)0; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "0").WithLocation(2, 12), + // (2,12): error CS1519: Invalid token '0' in a member declaration + // C x (int)0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "0").WithArguments("0").WithLocation(2, 12)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_SimpleLambda() + { + var tree = UsingTree(""" + class C { + C x a => b; + } + """, + // (2,7): error CS1003: Syntax error, '=' expected + // C x a => b; + Diagnostic(ErrorCode.ERR_SyntaxError, "a").WithArguments("=").WithLocation(2, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleLambdaExpression); + { + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_ParenthesizedLambda() + { + var tree = UsingTree(""" + class C { + C x (a) => b; + } + """, + // (2,9): error CS1001: Identifier expected + // C x (a) => b; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(2, 9)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_DefaultLiteral() + { + var tree = UsingTree(""" + class C { + C x default; + } + """, + // (2,7): error CS1003: Syntax error, '=' expected + // C x default; + Diagnostic(ErrorCode.ERR_SyntaxError, "default").WithArguments("=").WithLocation(2, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_QueryExpression() + { + var tree = UsingTree(""" + class C { + C x from int x in y select x; + } + """, + // (2,7): error CS1003: Syntax error, '=' expected + // C x from int x in y select x; + Diagnostic(ErrorCode.ERR_SyntaxError, "from").WithArguments("=").WithLocation(2, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.QueryExpression); + { + N(SyntaxKind.FromClause); + { + N(SyntaxKind.FromKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.QueryBody); + { + N(SyntaxKind.SelectClause); + { + N(SyntaxKind.SelectKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_PrimitiveVariableFollows1() + { + // In this case, even though 'int' can start an expression, we want to prefer to treat this as two field + // declarations missing an semicolon. + var tree = UsingTree(""" + class C { + C x int y; + } + """, + // (2,7): error CS1002: ; expected + // C x int y; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "int").WithLocation(2, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFieldDeclarationWithMissingEquals_PrimitiveVariableFollows2() + { + var tree = UsingTree(""" + class C { + C x int.MaxValue; + } + """, + // (2,7): error CS1003: Syntax error, '=' expected + // C x int.MaxValue; + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments("=").WithLocation(2, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "MaxValue"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals() + { + UsingStatement(""" + int value 5; + """, + // (1,11): error CS1003: Syntax error, '=' expected + // int value 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments("=").WithLocation(1, 11)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_StringLiteral() + { + UsingStatement(""" + string value "hello"; + """, + // (1,14): error CS1003: Syntax error, '=' expected + // string value "hello"; + Diagnostic(ErrorCode.ERR_SyntaxError, @"""hello""").WithArguments("=").WithLocation(1, 14)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.StringLiteralExpression); + { + N(SyntaxKind.StringLiteralToken, "\"hello\""); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_BoolLiteral() + { + UsingStatement(""" + bool value true; + """, + // (1,12): error CS1003: Syntax error, '=' expected + // bool value true; + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=").WithLocation(1, 12)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.BoolKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_NullLiteral() + { + UsingStatement(""" + object value null; + """, + // (1,14): error CS1003: Syntax error, '=' expected + // object value null; + Diagnostic(ErrorCode.ERR_SyntaxError, "null").WithArguments("=").WithLocation(1, 14)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_UnaryExpression() + { + UsingStatement(""" + int x -y; + """, + // (1,7): error CS1003: Syntax error, '=' expected + // int x -y; + Diagnostic(ErrorCode.ERR_SyntaxError, "-").WithArguments("=").WithLocation(1, 7)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryMinusExpression); + { + N(SyntaxKind.MinusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_BinaryExpression() + { + UsingStatement(""" + int x + y; + """, + // (1,7): error CS1003: Syntax error, '=' expected + // int x + y; + Diagnostic(ErrorCode.ERR_SyntaxError, "+").WithArguments("=").WithLocation(1, 7)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryPlusExpression); + { + N(SyntaxKind.PlusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_ObjectCreationExpression() + { + UsingStatement(""" + C x new C(); + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x new C(); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_ImplicitObjectCreation() + { + UsingStatement(""" + C x new(); + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x new(); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_CollectionExpression() + { + // Error recovery isn't great here as we have existing logic that looks for `C x[` and reports a misplaced + // array declarator For C/C++ style users. + UsingStatement(""" + C x [1, 2, 3]; + """, + // (1,5): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_CStyleArray, "[1, 2, 3]").WithLocation(1, 5), + // (1,6): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "1").WithLocation(1, 6), + // (1,9): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2").WithLocation(1, 9), + // (1,12): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "3").WithLocation(1, 12)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "3"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_MemberAccess() + { + UsingStatement(""" + C x X.Y; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x X.Y; + Diagnostic(ErrorCode.ERR_SyntaxError, "X").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_CastExpression() + { + // Error recovery isn't great here as `C x(` looks like the start of a method. + UsingStatement(""" + C x (int)0; + """, + // (1,1): error CS1073: Unexpected token '0' + // C x (int)0; + Diagnostic(ErrorCode.ERR_UnexpectedToken, "C x (int)").WithArguments("0").WithLocation(1, 1), + // (1,9): error CS1001: Identifier expected + // C x (int)0; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(1, 9), + // (1,10): error CS1002: ; expected + // C x (int)0; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "0").WithLocation(1, 10)); + + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_SimpleLambda() + { + UsingStatement(""" + C x a => b; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x a => b; + Diagnostic(ErrorCode.ERR_SyntaxError, "a").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleLambdaExpression); + { + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_ParenthesizedLambda() + { + UsingStatement(""" + C x (a) => b; + """, + // (1,7): error CS1001: Identifier expected + // C x (a) => b; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(1, 7)); + + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_DefaultLiteral() + { + UsingStatement(""" + C x default; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x default; + Diagnostic(ErrorCode.ERR_SyntaxError, "default").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_QueryExpression() + { + UsingStatement(""" + C x from int x in y select x; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x from int x in y select x; + Diagnostic(ErrorCode.ERR_SyntaxError, "from").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.QueryExpression); + { + N(SyntaxKind.FromClause); + { + N(SyntaxKind.FromKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.QueryBody); + { + N(SyntaxKind.SelectClause); + { + N(SyntaxKind.SelectKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_PrimitiveVariableFollows1() + { + // In this case, even though 'int' can start an expression, we want to prefer to treat this as two field + // declarations missing an semicolon. + UsingStatement(""" + C x int y; + """, + // (1,5): error CS1003: Syntax error, ',' expected + // C x int y; + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestLocalDeclarationWithMissingEquals_PrimitiveVariableFollows2() + { + UsingStatement(""" + C x int.MaxValue; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x int.MaxValue; + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "MaxValue"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals() + { + UsingTree(""" + int value 5; + """, + // (1,11): error CS1003: Syntax error, '=' expected + // int value 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments("=").WithLocation(1, 11)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_StringLiteral() + { + UsingTree(""" + string value "hello"; + """, + // (1,14): error CS1003: Syntax error, '=' expected + // string value "hello"; + Diagnostic(ErrorCode.ERR_SyntaxError, @"""hello""").WithArguments("=").WithLocation(1, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.StringLiteralExpression); + { + N(SyntaxKind.StringLiteralToken, "\"hello\""); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_BoolLiteral() + { + UsingTree(""" + bool value true; + """, + // (1,12): error CS1003: Syntax error, '=' expected + // bool value true; + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=").WithLocation(1, 12)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.BoolKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_NullLiteral() + { + UsingTree(""" + object value null; + """, + // (1,14): error CS1003: Syntax error, '=' expected + // object value null; + Diagnostic(ErrorCode.ERR_SyntaxError, "null").WithArguments("=").WithLocation(1, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_UnaryExpression() + { + UsingTree(""" + int x -y; + """, + // (1,7): error CS1003: Syntax error, '=' expected + // int x -y; + Diagnostic(ErrorCode.ERR_SyntaxError, "-").WithArguments("=").WithLocation(1, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryMinusExpression); + { + N(SyntaxKind.MinusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_BinaryExpression() + { + UsingTree(""" + int x + y; + """, + // (1,7): error CS1003: Syntax error, '=' expected + // int x + y; + Diagnostic(ErrorCode.ERR_SyntaxError, "+").WithArguments("=").WithLocation(1, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryPlusExpression); + { + N(SyntaxKind.PlusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_ObjectCreationExpression() + { + UsingTree(""" + C x new C(); + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x new C(); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_ImplicitObjectCreation() + { + UsingTree(""" + C x new(); + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x new(); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_CollectionExpression() + { + // Error recovery isn't great here as we have existing logic that looks for `C x[` and reports a misplaced + // array declarator For C/C++ style users. + UsingTree(""" + C x [1, 2, 3]; + """, + // (1,5): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_CStyleArray, "[1, 2, 3]").WithLocation(1, 5), + // (1,6): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "1").WithLocation(1, 6), + // (1,9): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2").WithLocation(1, 9), + // (1,12): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // C x [1, 2, 3]; + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "3").WithLocation(1, 12)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "3"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_MemberAccess() + { + UsingTree(""" + C x X.Y; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x X.Y; + Diagnostic(ErrorCode.ERR_SyntaxError, "X").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_CastExpression() + { + // Error recovery isn't great here as `C x(` looks like the start of a method. + UsingTree(""" + C x (int)0; + """, + // (1,9): error CS1001: Identifier expected + // C x (int)0; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(1, 9), + // (1,10): error CS1002: ; expected + // C x (int)0; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "0").WithLocation(1, 10)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_SimpleLambda() + { + UsingTree(""" + C x a => b; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x a => b; + Diagnostic(ErrorCode.ERR_SyntaxError, "a").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleLambdaExpression); + { + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_ParenthesizedLambda() + { + UsingTree(""" + C x (a) => b; + """, + // (1,7): error CS1001: Identifier expected + // C x (a) => b; + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(1, 7)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_DefaultLiteral() + { + UsingTree(""" + C x default; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x default; + Diagnostic(ErrorCode.ERR_SyntaxError, "default").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_QueryExpression() + { + UsingTree(""" + C x from int x in y select x; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x from int x in y select x; + Diagnostic(ErrorCode.ERR_SyntaxError, "from").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.QueryExpression); + { + N(SyntaxKind.FromClause); + { + N(SyntaxKind.FromKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.QueryBody); + { + N(SyntaxKind.SelectClause); + { + N(SyntaxKind.SelectKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_PrimitiveVariableFollows1() + { + // In this case, even though 'int' can start an expression, we want to prefer to treat this as two field + // declarations missing an semicolon. + UsingTree(""" + C x int y; + """, + // (1,5): error CS1003: Syntax error, ',' expected + // C x int y; + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestTopLevelLocalDeclarationWithMissingEquals_PrimitiveVariableFollows2() + { + UsingTree(""" + C x int.MaxValue; + """, + // (1,5): error CS1003: Syntax error, '=' expected + // C x int.MaxValue; + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments("=").WithLocation(1, 5)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "MaxValue"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals() + { + UsingStatement(""" + for (int value 5;;); + """, + // (1,16): error CS1003: Syntax error, '=' expected + // for (int value 5;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments("=").WithLocation(1, 16)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_StringLiteral() + { + UsingStatement(""" + for (string value "hello";;); + """, + // (1,19): error CS1003: Syntax error, '=' expected + // for (string value "hello";;); + Diagnostic(ErrorCode.ERR_SyntaxError, @"""hello""").WithArguments("=").WithLocation(1, 19)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.StringLiteralExpression); + { + N(SyntaxKind.StringLiteralToken, "\"hello\""); + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_BoolLiteral() + { + UsingStatement(""" + for (bool value true;;); + """, + // (1,17): error CS1003: Syntax error, '=' expected + // for (bool value true;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=").WithLocation(1, 17)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.BoolKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_NullLiteral() + { + UsingStatement(""" + for (object value null;;); + """, + // (1,19): error CS1003: Syntax error, '=' expected + // for (object value null;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "null").WithArguments("=").WithLocation(1, 19)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_UnaryExpression() + { + UsingStatement(""" + for (int x -y;;); + """, + // (1,12): error CS1003: Syntax error, '=' expected + // for (int x -y;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "-").WithArguments("=").WithLocation(1, 12)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryMinusExpression); + { + N(SyntaxKind.MinusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_BinaryExpression() + { + UsingStatement(""" + for (int x + y;;); + """, + // (1,12): error CS1003: Syntax error, '=' expected + // for (int x + y;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "+").WithArguments("=").WithLocation(1, 12)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.UnaryPlusExpression); + { + N(SyntaxKind.PlusToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_ObjectCreationExpression() + { + UsingStatement(""" + for (C x new C();;); + """, + // (1,10): error CS1003: Syntax error, '=' expected + // for (C x new C();;); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_ImplicitObjectCreation() + { + UsingStatement(""" + for (C x new();;); + """, + // (1,10): error CS1003: Syntax error, '=' expected + // for (C x new();;); + Diagnostic(ErrorCode.ERR_SyntaxError, "new").WithArguments("=").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ImplicitObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_CollectionExpression() + { + // Error recovery isn't great here as we have existing logic that looks for `C x[` and reports a misplaced + // array declarator For C/C++ style users. + UsingStatement(""" + for (C x [1, 2, 3];;); + """, + // (1,10): error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. + // for (C x [1, 2, 3];;); + Diagnostic(ErrorCode.ERR_CStyleArray, "[1, 2, 3]").WithLocation(1, 10), + // (1,11): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // for (C x [1, 2, 3];;); + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "1").WithLocation(1, 11), + // (1,14): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // for (C x [1, 2, 3];;); + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "2").WithLocation(1, 14), + // (1,17): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // for (C x [1, 2, 3];;); + Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "3").WithLocation(1, 17)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "2"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "3"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_MemberAccess() + { + UsingStatement(""" + for (C x X.Y;;); + """, + // (1,10): error CS1003: Syntax error, '=' expected + // for (C x X.Y;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "X").WithArguments("=").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_CastExpression() + { + // Error recovery isn't great here as `C x(` looks like the start of a method. + UsingStatement(""" + for (C x (int)0;;); + """, + // (1,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // for (C x (int)0;;); + Diagnostic(ErrorCode.ERR_BadVarDecl, "(int").WithLocation(1, 10), + // (1,10): error CS1003: Syntax error, '[' expected + // for (C x (int)0;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[").WithLocation(1, 10), + // (1,11): error CS1525: Invalid expression term 'int' + // for (C x (int)0;;); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(1, 11), + // (1,14): error CS1003: Syntax error, ']' expected + // for (C x (int)0;;); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]").WithLocation(1, 14), + // (1,15): error CS1003: Syntax error, ',' expected + // for (C x (int)0;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "0").WithArguments(",").WithLocation(1, 15)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.BracketedArgumentList); + { + M(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + M(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_SimpleLambda() + { + UsingStatement(""" + for (C x a => b;;); + """, + // (1,10): error CS1003: Syntax error, '=' expected + // for (C x a => b;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "a").WithArguments("=").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleLambdaExpression); + { + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_ParenthesizedLambda() + { + UsingStatement(""" + for (C x (a) => b;;); + """, + // (1,10): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // for (C x (a) => b;;); + Diagnostic(ErrorCode.ERR_BadVarDecl, "(a").WithLocation(1, 10), + // (1,10): error CS1003: Syntax error, '[' expected + // for (C x (a) => b;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[").WithLocation(1, 10), + // (1,12): error CS1003: Syntax error, ']' expected + // for (C x (a) => b;;); + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]").WithLocation(1, 12), + // (1,14): error CS1003: Syntax error, ',' expected + // for (C x (a) => b;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "=>").WithArguments(",").WithLocation(1, 14)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.BracketedArgumentList); + { + M(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + M(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_DefaultLiteral() + { + UsingStatement(""" + for (C x default;;); + """, + // (1,10): error CS1003: Syntax error, '=' expected + // for (C x default;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "default").WithArguments("=").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_QueryExpression() + { + UsingStatement(""" + for (C x from int x in y select x;;); + """, + // (1,10): error CS1003: Syntax error, '=' expected + // for (C x from int x in y select x;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "from").WithArguments("=").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.QueryExpression); + { + N(SyntaxKind.FromClause); + { + N(SyntaxKind.FromKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.QueryBody); + { + N(SyntaxKind.SelectClause); + { + N(SyntaxKind.SelectKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_PrimitiveVariableFollows1() + { + // In this case, even though 'int' can start an expression, we want to prefer to treat this as two field + // declarations missing an semicolon. + UsingStatement(""" + for (C x int y;;); + """, + // (1,10): error CS1003: Syntax error, ',' expected + // for (C x int y;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestForStatementDeclarationWithMissingEquals_PrimitiveVariableFollows2() + { + UsingStatement(""" + for (C x int.MaxValue;;); + """, + // (1,10): error CS1003: Syntax error, '=' expected + // for (C x int.MaxValue;;); + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments("=").WithLocation(1, 10)); + + N(SyntaxKind.ForStatement); + { + N(SyntaxKind.ForKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "MaxValue"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.EmptyStatement); + { + N(SyntaxKind.SemicolonToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestConstFieldDeclarationWithMissingEquals() + { + var tree = UsingTree(""" + class C { + const int value 5; + } + """, + // (2,21): error CS1003: Syntax error, '=' expected + // const int value 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments("=").WithLocation(2, 21)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.ConstKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedFieldDeclarationWithMissingEquals1() + { + var tree = UsingTree(""" + class C { + fixed int value 5; + } + """, + // (2,21): error CS1003: Syntax error, '=' expected + // fixed int value 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments("=").WithLocation(2, 21)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.FixedKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedFieldDeclarationWithMissingEquals2() + { + var tree = UsingTree(""" + class C { + fixed int[] value 5; + } + """, + // (2,23): error CS1003: Syntax error, '=' expected + // fixed int[] value 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments("=").WithLocation(2, 23)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.FixedKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedFieldDeclarationWithEquals1() + { + var tree = UsingTree(""" + class C { + fixed int value = 5; + } + """, + // (2,21): error CS1003: Syntax error, '[' expected + // fixed int value = 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "=").WithArguments("[").WithLocation(2, 21), + // (2,21): error CS1525: Invalid expression term '=' + // fixed int value = 5; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(2, 21), + // (2,24): error CS1003: Syntax error, ',' expected + // fixed int value = 5; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(2, 24), + // (2,24): error CS0443: Syntax error; value expected + // fixed int value = 5; + Diagnostic(ErrorCode.ERR_ValueExpected, "").WithLocation(2, 24), + // (2,24): error CS1003: Syntax error, ']' expected + // fixed int value = 5; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments("]").WithLocation(2, 24)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.FixedKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.BracketedArgumentList); + { + M(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.SimpleAssignmentExpression); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + M(SyntaxKind.CommaToken); + M(SyntaxKind.Argument); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedFieldDeclarationWithEquals2() + { + var tree = UsingTree(""" + class C { + fixed int[] value = 5; + } + """, + // (2,17): error CS1641: A fixed size buffer field must have the array size specifier after the field name + // fixed int[] value = 5; + Diagnostic(ErrorCode.ERR_FixedDimsRequired, "value").WithLocation(2, 17), + // (2,23): error CS1003: Syntax error, ',' expected + // fixed int[] value = 5; + Diagnostic(ErrorCode.ERR_SyntaxError, "=").WithArguments(",").WithLocation(2, 23)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.FixedKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedLocalFunction1() + { + var tree = UsingTree(""" + class C { + void M() { + fixed int value() { } + } + } + """, + // (3,15): error CS1003: Syntax error, '(' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments("(").WithLocation(3, 15), + // (3,24): error CS1026: ) expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_CloseParenExpected, "<").WithLocation(3, 24), + // (3,24): error CS1525: Invalid expression term '<' + // fixed int value() { } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(3, 24), + // (3,28): error CS1525: Invalid expression term ')' + // fixed int value() { } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(3, 28), + // (3,30): error CS1002: ; expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(3, 30)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FixedStatement); + { + N(SyntaxKind.FixedKeyword); + M(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + } + } + M(SyntaxKind.CloseParenToken); + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.GreaterThanExpression); + { + N(SyntaxKind.LessThanExpression); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + } + N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.ParenthesizedExpression); + { + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedLocalFunction2() + { + var tree = UsingTree(""" + class C { + void M() { + fixed int value() { } + } + } + """, + // (3,15): error CS1003: Syntax error, '(' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments("(").WithLocation(3, 15), + // (3,24): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // fixed int value() { } + Diagnostic(ErrorCode.ERR_BadVarDecl, "(").WithLocation(3, 24), + // (3,24): error CS1003: Syntax error, '[' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[").WithLocation(3, 24), + // (3,25): error CS1003: Syntax error, ']' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]").WithLocation(3, 25), + // (3,27): error CS1026: ) expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_CloseParenExpected, "{").WithLocation(3, 27)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FixedStatement); + { + N(SyntaxKind.FixedKeyword); + M(SyntaxKind.OpenParenToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + M(SyntaxKind.BracketedArgumentList); + { + M(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + } + } + M(SyntaxKind.CloseParenToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedFieldFunction1() + { + var tree = UsingTree(""" + struct C { + fixed int value() { } + } + """, + // (2,20): error CS1003: Syntax error, '[' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "<").WithArguments("[").WithLocation(2, 20), + // (2,20): error CS1525: Invalid expression term '<' + // fixed int value() { } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(2, 20), + // (2,24): error CS1525: Invalid expression term ')' + // fixed int value() { } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(2, 24), + // (2,26): error CS1003: Syntax error, ',' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments(",").WithLocation(2, 26), + // (2,26): error CS1003: Syntax error, ',' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments(",").WithLocation(2, 26), + // (2,28): error CS0443: Syntax error; value expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_ValueExpected, "").WithLocation(2, 28), + // (2,28): error CS1003: Syntax error, ']' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "}").WithArguments("]").WithLocation(2, 28), + // (2,28): error CS1002: ; expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "}").WithLocation(2, 28), + // (3,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(3, 1)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.FixedKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + N(SyntaxKind.BracketedArgumentList); + { + M(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.GreaterThanExpression); + { + N(SyntaxKind.LessThanExpression); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + } + N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.ParenthesizedExpression); + { + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + } + } + M(SyntaxKind.CommaToken); + M(SyntaxKind.Argument); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CloseBracketToken); + } + } + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44292")] + public void TestFixedFieldFunction2() + { + var tree = UsingTree(""" + struct C { + fixed int value() { } + } + """, + // (2,20): error CS1528: Expected ; or = (cannot specify constructor arguments in declaration) + // fixed int value() { } + Diagnostic(ErrorCode.ERR_BadVarDecl, "(").WithLocation(2, 20), + // (2,20): error CS1003: Syntax error, '[' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("[").WithLocation(2, 20), + // (2,21): error CS1003: Syntax error, ']' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments("]").WithLocation(2, 21), + // (2,23): error CS1003: Syntax error, ',' expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments(",").WithLocation(2, 23), + // (2,25): error CS1002: ; expected + // fixed int value() { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "}").WithLocation(2, 25), + // (3,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(3, 1)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.FixedKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "value"); + M(SyntaxKind.BracketedArgumentList); + { + M(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + } + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs index 6740c40c0c393..2af1953c35c0b 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs @@ -274,10 +274,9 @@ public void Method_05() { string source = "ref scoped R F() => default;"; UsingDeclaration(source, TestOptions.Regular11, - // (1,14): error CS1003: Syntax error, ',' expected + // (1,14): error CS1003: Syntax error, '=' expected // ref scoped R F() => default; - Diagnostic(ErrorCode.ERR_SyntaxError, "F").WithArguments(",").WithLocation(1, 14) - ); + Diagnostic(ErrorCode.ERR_SyntaxError, "F").WithArguments("=").WithLocation(1, 14)); N(SyntaxKind.FieldDeclaration); { @@ -294,6 +293,27 @@ public void Method_05() N(SyntaxKind.VariableDeclarator); { N(SyntaxKind.IdentifierToken, "R"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } } } N(SyntaxKind.SemicolonToken); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs index b268f7cf681a4..359921704fd2c 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs @@ -9997,8 +9997,68 @@ public void GlobalStatementSeparators_Missing() int a Console.Goo() "; - ParseAndValidate(test, - new ErrorDescription { Code = (int)ErrorCode.ERR_SemicolonExpected, Line = 3, Column = 6 }); + + UsingTree(test, + // (3,6): error CS1003: Syntax error, '=' expected + // int a + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=").WithLocation(3, 6), + // (4,14): error CS1002: ; expected + // Console.Goo() + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 14)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "System"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "a"); + N(SyntaxKind.EqualsValueClause); + { + M(SyntaxKind.EqualsToken); + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Console"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + } + } + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); } #endregion diff --git a/src/Features/CSharpTest/ExtractMethod/ExtractMethodCodeRefactoringTests.cs b/src/Features/CSharpTest/ExtractMethod/ExtractMethodCodeRefactoringTests.cs index f7ad916eca3da..6477f61f6177c 100644 --- a/src/Features/CSharpTest/ExtractMethod/ExtractMethodCodeRefactoringTests.cs +++ b/src/Features/CSharpTest/ExtractMethod/ExtractMethodCodeRefactoringTests.cs @@ -3626,7 +3626,7 @@ class C { private Task DoSomethingAsync() => Task.FromResult(""); - public Task async M() + public async Task M() { [|string? x = await DoSomethingAsync();|] x = null; @@ -3644,7 +3644,7 @@ class C { private Task DoSomethingAsync() => Task.FromResult(""); - public Task async M() + public async Task M() { string? x = await {|Rename:NewMethod|}(); x = null;