Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9c2c794
Initial plan
Copilot Nov 16, 2025
bc76ea7
Fix CS1003 error message to suggest '=' when literal follows identifier
Copilot Nov 16, 2025
eb24d70
Add WorkItem attribute to test methods for issue #44292
Copilot Nov 16, 2025
6018aa5
Extend parser fix to handle all expressions and use raw string literals
Copilot Nov 16, 2025
2ed35f5
Update src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
CyrusNajmabadi Nov 16, 2025
05ca746
Remove IsTrueIdentifier check and add OpenBraceToken handling
Copilot Nov 16, 2025
4806bf7
Add documentation for comprehensive manual test verification
Copilot Nov 16, 2025
ba3c97e
Fix comma/semicolon/equals check to apply only for identifiers
Copilot Nov 16, 2025
1affc1b
Remove incorrect comment and add proper manual verification documenta…
Copilot Nov 16, 2025
804703f
Simplify
CyrusNajmabadi Nov 16, 2025
9444e48
Merge branch 'copilot/fix-variable-declaration-issue' of https://gith…
CyrusNajmabadi Nov 16, 2025
138ba72
Fix check
CyrusNajmabadi Nov 16, 2025
a86561d
Add actual tests for unary, binary, and object creation expressions
Copilot Nov 16, 2025
67b2d89
Fix check
CyrusNajmabadi Nov 16, 2025
c823254
Merge branch 'copilot/fix-variable-declaration-issue' of https://gith…
CyrusNajmabadi Nov 16, 2025
f6f16d3
Add testss
CyrusNajmabadi Nov 16, 2025
410ba8a
Fixup
CyrusNajmabadi Nov 16, 2025
6ecd0f5
Simplify impl
CyrusNajmabadi Nov 16, 2025
bb5b40b
Update tests
CyrusNajmabadi Nov 16, 2025
9ec48ac
Update tests
CyrusNajmabadi Nov 16, 2025
c6a0d04
Fix test
CyrusNajmabadi Nov 17, 2025
5abb35e
Update test
CyrusNajmabadi Nov 17, 2025
7dde080
REvert
CyrusNajmabadi Nov 17, 2025
4a2161f
Update src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
CyrusNajmabadi Nov 17, 2025
4c3122b
Add assert
CyrusNajmabadi Nov 17, 2025
6fcd389
Merge branch 'copilot/fix-variable-declaration-issue' of https://gith…
CyrusNajmabadi Nov 17, 2025
cd1b2ff
Fix test
CyrusNajmabadi Nov 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5621,6 +5621,18 @@ private VariableDeclaratorSyntax ParseVariableDeclarator(
break;

default:
Debug.Assert(argumentList is null);
if (looksLikeVariableInitializer())
{
localFunction = null;
return _syntaxFactory.VariableDeclarator(
name,
argumentList: null,
_syntaxFactory.EqualsValueClause(
this.EatToken(SyntaxKind.EqualsToken),
this.ParseVariableInitializer()));
}

if (isConst)
{
name = this.AddError(name, ErrorCode.ERR_ConstValueRequired); // Error here for missing constant initializers
Expand All @@ -5643,6 +5655,40 @@ private VariableDeclaratorSyntax ParseVariableDeclarator(

localFunction = null;
return _syntaxFactory.VariableDeclarator(name, argumentList, initializer);

bool looksLikeVariableInitializer()
{
// 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?
Expand Down
19 changes: 12 additions & 7 deletions src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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);
Expand Down
Loading