-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Fix CS1003 error message when expression follows identifier without '=' #81285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
9c2c794
bc76ea7
eb24d70
6018aa5
2ed35f5
05ca746
4806bf7
ba3c97e
1affc1b
804703f
9444e48
138ba72
a86561d
67b2d89
c823254
f6f16d3
410ba8a
6ecd0f5
bb5b40b
9ec48ac
c6a0d04
5abb35e
7dde080
4a2161f
4c3122b
6fcd389
cd1b2ff
a89f601
99a6f66
1d31995
f346c3b
6c49f4d
b87edba
f86f217
e4bc551
7cdc933
f2168e5
ca928a9
82b95b8
1d136b8
f94459c
66a348e
97420a5
1ae65b6
525ec6f
8c55e30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5621,7 +5621,22 @@ | |
| break; | ||
|
|
||
| default: | ||
| if (isConst) | ||
| // 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. However, we need to exclude tokens | ||
| // that can legally appear in ParseVariableDeclarator: | ||
| // - IdentifierToken: handled by ERR_MultiTypeInDeclaration check above | ||
| // - CommaToken, SemicolonToken: end of declarator | ||
| // - EqualsToken, LessThanToken, OpenParenToken, OpenBracketToken: handled by cases above | ||
| if (!isFixed && | ||
|
Check failure on line 5630 in src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
|
||
| this.CurrentToken.Kind is not SyntaxKind.CommaToken and not SyntaxKind.SemicolonToken && | ||
| !this.IsTrueIdentifier() && | ||
|
||
| this.IsPossibleExpression()) | ||
| { | ||
| var missingEquals = this.EatToken(SyntaxKind.EqualsToken); | ||
| var initExpr = this.ParseVariableInitializer(); | ||
| initializer = _syntaxFactory.EqualsValueClause(missingEquals, initExpr); | ||
| } | ||
CyrusNajmabadi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| else if (isConst) | ||
| { | ||
| name = this.AddError(name, ErrorCode.ERR_ConstValueRequired); // Error here for missing constant initializers | ||
| } | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Think we also should add variations for
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider also having some variations on the 2 locals tests, like
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @CyrusNajmabadi I don't see any added tests for using statements, only using local declarations.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah. Tests added for that. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12950,6 +12950,200 @@ public void AnonymousDelegateNoParameters_TopLevel() | |
| 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(); | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot we need tests for
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 4806bf7. All requested cases have been manually verified with the compiler and produce the correct CS1003 error:
Comprehensive manual verification documented in test file comments. |
||
|
|
||
| [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23877")] | ||
| public void TestParseAttributeArgumentListWithInvalidString() | ||
| { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.