Skip to content
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

WIP: Add WithElement syntax #76003

Draft
wants to merge 19 commits into
base: features/dictionary-expressions
Choose a base branch
from
Draft
18 changes: 18 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5199,6 +5199,16 @@ private BoundExpression BindCollectionExpression(CollectionExpressionSyntax synt

MessageID.IDS_FeatureCollectionExpressions.CheckFeatureAvailability(diagnostics, syntax, syntax.OpenBracketToken.GetLocation());

for (int i = 1, n = syntax.Elements.Count - 1; i < n; i++)
{
var element = syntax.Elements[i];
if (element is WithElementSyntax withElement)
{
Error(diagnostics, ErrorCode.ERR_WithElementMustBeFirst, withElement.WithKeyword.GetLocation());
break;
}
}

foreach (var element in syntax.Elements)
{
if (element is KeyValuePairElementSyntax keyValuePairElement)
Expand All @@ -5209,6 +5219,14 @@ private BoundExpression BindCollectionExpression(CollectionExpressionSyntax synt
Error(diagnostics, ErrorCode.ERR_SyntaxError, keyValuePairElement.ColonToken, ",");
return new BoundBadExpression(syntax, LookupResultKind.Empty, symbols: [], childBoundNodes: [], CreateErrorType());
}
else if (element is WithElementSyntax withElement)
{
MessageID.IDS_FeatureCollectionExpressionConstructionArguments.CheckFeatureAvailability(diagnostics, syntax, withElement.WithKeyword.GetLocation());

// PROTOTYPE: Error for now. Flesh this out when we do the binding for `with(...)` arguments.
Error(diagnostics, ErrorCode.ERR_SyntaxError, withElement.WithKeyword, ",");
return new BoundBadExpression(syntax, LookupResultKind.Empty, symbols: [], childBoundNodes: [], CreateErrorType());
}
}

var builder = ArrayBuilder<BoundNode>.GetInstance(syntax.Elements.Count);
Expand Down
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6832,6 +6832,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="IDS_FeatureDictionaryExpressions" xml:space="preserve">
<value>dictionary expressions</value>
</data>
<data name="IDS_FeatureCollectionExpressionConstructionArguments" xml:space="preserve">
<value>collection expression construction arguments</value>
</data>
<data name="ERR_CollectionExpressionTargetTypeNotConstructible" xml:space="preserve">
<value>Cannot initialize type '{0}' with a collection expression because the type is not constructible.</value>
</data>
Expand Down Expand Up @@ -8020,4 +8023,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_IteratorRefLikeElementType" xml:space="preserve">
<value>Element type of an iterator may not be a ref struct or a type parameter allowing ref structs</value>
</data>
<data name="ERR_WithElementMustBeFirst" xml:space="preserve">
<value>'with(...)' element must be first element in collection expression</value>
</data>
</root>
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,7 @@ internal enum ErrorCode
WRN_AccessorDoesNotUseBackingField = 9266,

ERR_IteratorRefLikeElementType = 9267,
ERR_WithElementMustBeFirst = 9268,

// Note: you will need to do the following after adding errors:
// 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2467,6 +2467,7 @@ or ErrorCode.WRN_UninitializedNonNullableBackingField
or ErrorCode.WRN_UnassignedInternalRefField
or ErrorCode.WRN_AccessorDoesNotUseBackingField
or ErrorCode.ERR_IteratorRefLikeElementType
or ErrorCode.ERR_WithElementMustBeFirst
=> false,
};
#pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value.
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ internal enum MessageID

IDS_FeatureFirstClassSpan = MessageBase + 12849,
IDS_FeatureDictionaryExpressions = MessageBase + 12850,
IDS_FeatureCollectionExpressionConstructionArguments = MessageBase + 12851,
}

// Message IDs may refer to strings that need to be localized.
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6767,6 +6767,82 @@ internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
=> new KeyValuePairElementSyntax(this.Kind, this.keyExpression, this.colonToken, this.valueExpression, GetDiagnostics(), annotations);
}

internal sealed partial class WithElementSyntax : CollectionElementSyntax
{
internal readonly SyntaxToken withKeyword;
internal readonly ArgumentListSyntax argumentList;

internal WithElementSyntax(SyntaxKind kind, SyntaxToken withKeyword, ArgumentListSyntax argumentList, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
: base(kind, diagnostics, annotations)
{
this.SlotCount = 2;
this.AdjustFlagsAndWidth(withKeyword);
this.withKeyword = withKeyword;
this.AdjustFlagsAndWidth(argumentList);
this.argumentList = argumentList;
}

internal WithElementSyntax(SyntaxKind kind, SyntaxToken withKeyword, ArgumentListSyntax argumentList, SyntaxFactoryContext context)
: base(kind)
{
this.SetFactoryContext(context);
this.SlotCount = 2;
this.AdjustFlagsAndWidth(withKeyword);
this.withKeyword = withKeyword;
this.AdjustFlagsAndWidth(argumentList);
this.argumentList = argumentList;
}

internal WithElementSyntax(SyntaxKind kind, SyntaxToken withKeyword, ArgumentListSyntax argumentList)
: base(kind)
{
this.SlotCount = 2;
this.AdjustFlagsAndWidth(withKeyword);
this.withKeyword = withKeyword;
this.AdjustFlagsAndWidth(argumentList);
this.argumentList = argumentList;
}

public SyntaxToken WithKeyword => this.withKeyword;
public ArgumentListSyntax ArgumentList => this.argumentList;

internal override GreenNode? GetSlot(int index)
=> index switch
{
0 => this.withKeyword,
1 => this.argumentList,
_ => null,
};

internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.WithElementSyntax(this, parent, position);

public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitWithElement(this);
public override TResult Accept<TResult>(CSharpSyntaxVisitor<TResult> visitor) => visitor.VisitWithElement(this);

public WithElementSyntax Update(SyntaxToken withKeyword, ArgumentListSyntax argumentList)
{
if (withKeyword != this.WithKeyword || argumentList != this.ArgumentList)
{
var newNode = SyntaxFactory.WithElement(withKeyword, argumentList);
var diags = GetDiagnostics();
if (diags?.Length > 0)
newNode = newNode.WithDiagnosticsGreen(diags);
var annotations = GetAnnotations();
if (annotations?.Length > 0)
newNode = newNode.WithAnnotationsGreen(annotations);
return newNode;
}

return this;
}

internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics)
=> new WithElementSyntax(this.Kind, this.withKeyword, this.argumentList, diagnostics, GetAnnotations());

internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
=> new WithElementSyntax(this.Kind, this.withKeyword, this.argumentList, GetDiagnostics(), annotations);
}

internal abstract partial class QueryClauseSyntax : CSharpSyntaxNode
{
internal QueryClauseSyntax(SyntaxKind kind, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
Expand Down Expand Up @@ -26641,6 +26717,7 @@ internal partial class CSharpSyntaxVisitor<TResult>
public virtual TResult VisitExpressionElement(ExpressionElementSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitSpreadElement(SpreadElementSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitKeyValuePairElement(KeyValuePairElementSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitQueryExpression(QueryExpressionSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitQueryBody(QueryBodySyntax node) => this.DefaultVisit(node);
public virtual TResult VisitFromClause(FromClauseSyntax node) => this.DefaultVisit(node);
Expand Down Expand Up @@ -26890,6 +26967,7 @@ internal partial class CSharpSyntaxVisitor
public virtual void VisitExpressionElement(ExpressionElementSyntax node) => this.DefaultVisit(node);
public virtual void VisitSpreadElement(SpreadElementSyntax node) => this.DefaultVisit(node);
public virtual void VisitKeyValuePairElement(KeyValuePairElementSyntax node) => this.DefaultVisit(node);
public virtual void VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node);
public virtual void VisitQueryExpression(QueryExpressionSyntax node) => this.DefaultVisit(node);
public virtual void VisitQueryBody(QueryBodySyntax node) => this.DefaultVisit(node);
public virtual void VisitFromClause(FromClauseSyntax node) => this.DefaultVisit(node);
Expand Down Expand Up @@ -27283,6 +27361,9 @@ public override CSharpSyntaxNode VisitSpreadElement(SpreadElementSyntax node)
public override CSharpSyntaxNode VisitKeyValuePairElement(KeyValuePairElementSyntax node)
=> node.Update((ExpressionSyntax)Visit(node.KeyExpression), (SyntaxToken)Visit(node.ColonToken), (ExpressionSyntax)Visit(node.ValueExpression));

public override CSharpSyntaxNode VisitWithElement(WithElementSyntax node)
=> node.Update((SyntaxToken)Visit(node.WithKeyword), (ArgumentListSyntax)Visit(node.ArgumentList));

public override CSharpSyntaxNode VisitQueryExpression(QueryExpressionSyntax node)
=> node.Update((FromClauseSyntax)Visit(node.FromClause), (QueryBodySyntax)Visit(node.Body));

Expand Down Expand Up @@ -29435,6 +29516,27 @@ public KeyValuePairElementSyntax KeyValuePairElement(ExpressionSyntax keyExpress
return result;
}

public WithElementSyntax WithElement(SyntaxToken withKeyword, ArgumentListSyntax argumentList)
{
#if DEBUG
if (withKeyword == null) throw new ArgumentNullException(nameof(withKeyword));
if (withKeyword.Kind != SyntaxKind.WithKeyword) throw new ArgumentException(nameof(withKeyword));
if (argumentList == null) throw new ArgumentNullException(nameof(argumentList));
#endif

int hash;
var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.WithElement, withKeyword, argumentList, this.context, out hash);
if (cached != null) return (WithElementSyntax)cached;

var result = new WithElementSyntax(SyntaxKind.WithElement, withKeyword, argumentList, this.context);
if (hash >= 0)
{
SyntaxNodeCache.AddNode(result, hash);
}

return result;
}

public QueryExpressionSyntax QueryExpression(FromClauseSyntax fromClause, QueryBodySyntax body)
{
#if DEBUG
Expand Down Expand Up @@ -34725,6 +34827,27 @@ public static KeyValuePairElementSyntax KeyValuePairElement(ExpressionSyntax key
return result;
}

public static WithElementSyntax WithElement(SyntaxToken withKeyword, ArgumentListSyntax argumentList)
{
#if DEBUG
if (withKeyword == null) throw new ArgumentNullException(nameof(withKeyword));
if (withKeyword.Kind != SyntaxKind.WithKeyword) throw new ArgumentException(nameof(withKeyword));
if (argumentList == null) throw new ArgumentNullException(nameof(argumentList));
#endif

int hash;
var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.WithElement, withKeyword, argumentList, out hash);
if (cached != null) return (WithElementSyntax)cached;

var result = new WithElementSyntax(SyntaxKind.WithElement, withKeyword, argumentList);
if (hash >= 0)
{
SyntaxNodeCache.AddNode(result, hash);
}

return result;
}

public static QueryExpressionSyntax QueryExpression(FromClauseSyntax fromClause, QueryBodySyntax body)
{
#if DEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@
/// <summary>Called when the visitor visits a KeyValuePairElementSyntax node.</summary>
public virtual TResult? VisitKeyValuePairElement(KeyValuePairElementSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a WithElementSyntax node.</summary>
public virtual TResult? VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a QueryExpressionSyntax node.</summary>
public virtual TResult? VisitQueryExpression(QueryExpressionSyntax node) => this.DefaultVisit(node);

Expand Down Expand Up @@ -969,6 +972,9 @@
/// <summary>Called when the visitor visits a KeyValuePairElementSyntax node.</summary>
public virtual void VisitKeyValuePairElement(KeyValuePairElementSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a WithElementSyntax node.</summary>
public virtual void VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a QueryExpressionSyntax node.</summary>
public virtual void VisitQueryExpression(QueryExpressionSyntax node) => this.DefaultVisit(node);

Expand Down Expand Up @@ -1707,6 +1713,9 @@
public override SyntaxNode? VisitKeyValuePairElement(KeyValuePairElementSyntax node)
=> node.Update((ExpressionSyntax?)Visit(node.KeyExpression) ?? throw new ArgumentNullException("keyExpression"), VisitToken(node.ColonToken), (ExpressionSyntax?)Visit(node.ValueExpression) ?? throw new ArgumentNullException("valueExpression"));

public override SyntaxNode? VisitWithElement(WithElementSyntax node)
=> node.Update(VisitToken(node.WithKeyword), (ArgumentListSyntax?)Visit(node.ArgumentList) ?? throw new ArgumentNullException("argumentList"));

public override SyntaxNode? VisitQueryExpression(QueryExpressionSyntax node)
=> node.Update((FromClauseSyntax?)Visit(node.FromClause) ?? throw new ArgumentNullException("fromClause"), (QueryBodySyntax?)Visit(node.Body) ?? throw new ArgumentNullException("body"));

Expand Down Expand Up @@ -3439,6 +3448,18 @@
public static KeyValuePairElementSyntax KeyValuePairElement(ExpressionSyntax keyExpression, ExpressionSyntax valueExpression)
=> SyntaxFactory.KeyValuePairElement(keyExpression, SyntaxFactory.Token(SyntaxKind.ColonToken), valueExpression);

/// <summary>Creates a new WithElementSyntax instance.</summary>
public static WithElementSyntax WithElement(SyntaxToken withKeyword, ArgumentListSyntax argumentList)
{
if (withKeyword.Kind() != SyntaxKind.WithKeyword) throw new ArgumentException(nameof(withKeyword));
if (argumentList == null) throw new ArgumentNullException(nameof(argumentList));
return (WithElementSyntax)Syntax.InternalSyntax.SyntaxFactory.WithElement((Syntax.InternalSyntax.SyntaxToken)withKeyword.Node!, (Syntax.InternalSyntax.ArgumentListSyntax)argumentList.Green).CreateRed();
}

/// <summary>Creates a new WithElementSyntax instance.</summary>
public static WithElementSyntax WithElement(ArgumentListSyntax? argumentList = default)

Check failure on line 3460 in src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs

View check run for this annotation

Azure Pipelines / roslyn-CI (Correctness Correctness_Analyzers)

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs#L3460

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs(3460,37): error RS0027: (NETCORE_ENGINEERING_TELEMETRY=Build) 'WithElement' violates the backcompat requirement: 'API with optional parameter(s) should have the most parameters amongst its public overloads'. See 'https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md' for details. (https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md)

Check failure on line 3460 in src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs

View check run for this annotation

Azure Pipelines / roslyn-CI (Correctness Correctness_Analyzers)

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs#L3460

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs(3460,37): error RS0027: (NETCORE_ENGINEERING_TELEMETRY=Build) 'WithElement' violates the backcompat requirement: 'API with optional parameter(s) should have the most parameters amongst its public overloads'. See 'https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md' for details. (https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md)

Check failure on line 3460 in src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs

View check run for this annotation

Azure Pipelines / roslyn-CI (Correctness Correctness_Analyzers)

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs#L3460

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs(3460,37): error RS0027: (NETCORE_ENGINEERING_TELEMETRY=Build) 'WithElement' violates the backcompat requirement: 'API with optional parameter(s) should have the most parameters amongst its public overloads'. See 'https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md' for details. (https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md)

Check failure on line 3460 in src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs

View check run for this annotation

Azure Pipelines / roslyn-CI

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs#L3460

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs(3460,37): error RS0027: (NETCORE_ENGINEERING_TELEMETRY=Build) 'WithElement' violates the backcompat requirement: 'API with optional parameter(s) should have the most parameters amongst its public overloads'. See 'https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md' for details. (https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md)

Check failure on line 3460 in src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs

View check run for this annotation

Azure Pipelines / roslyn-CI

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs#L3460

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs(3460,37): error RS0027: (NETCORE_ENGINEERING_TELEMETRY=Build) 'WithElement' violates the backcompat requirement: 'API with optional parameter(s) should have the most parameters amongst its public overloads'. See 'https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md' for details. (https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md)

Check failure on line 3460 in src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs

View check run for this annotation

Azure Pipelines / roslyn-CI

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs#L3460

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs(3460,37): error RS0027: (NETCORE_ENGINEERING_TELEMETRY=Build) 'WithElement' violates the backcompat requirement: 'API with optional parameter(s) should have the most parameters amongst its public overloads'. See 'https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md' for details. (https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md)
=> SyntaxFactory.WithElement(SyntaxFactory.Token(SyntaxKind.WithKeyword), argumentList ?? SyntaxFactory.ArgumentList());

/// <summary>Creates a new QueryExpressionSyntax instance.</summary>
public static QueryExpressionSyntax QueryExpression(FromClauseSyntax fromClause, QueryBodySyntax body)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4331,6 +4331,50 @@ public KeyValuePairElementSyntax Update(ExpressionSyntax keyExpression, SyntaxTo
public KeyValuePairElementSyntax WithValueExpression(ExpressionSyntax valueExpression) => Update(this.KeyExpression, this.ColonToken, valueExpression);
}

/// <remarks>
/// <para>This node is associated with the following syntax kinds:</para>
/// <list type="bullet">
/// <item><description><see cref="SyntaxKind.WithElement"/></description></item>
/// </list>
/// </remarks>
public sealed partial class WithElementSyntax : CollectionElementSyntax
{
private ArgumentListSyntax? argumentList;

internal WithElementSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
: base(green, parent, position)
{
}

public SyntaxToken WithKeyword => new SyntaxToken(this, ((InternalSyntax.WithElementSyntax)this.Green).withKeyword, Position, 0);

public ArgumentListSyntax ArgumentList => GetRed(ref this.argumentList, 1)!;

internal override SyntaxNode? GetNodeSlot(int index) => index == 1 ? GetRed(ref this.argumentList, 1)! : null;

internal override SyntaxNode? GetCachedSlot(int index) => index == 1 ? this.argumentList : null;

public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitWithElement(this);
public override TResult? Accept<TResult>(CSharpSyntaxVisitor<TResult> visitor) where TResult : default => visitor.VisitWithElement(this);

public WithElementSyntax Update(SyntaxToken withKeyword, ArgumentListSyntax argumentList)
{
if (withKeyword != this.WithKeyword || argumentList != this.ArgumentList)
{
var newNode = SyntaxFactory.WithElement(withKeyword, argumentList);
var annotations = GetAnnotations();
return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode;
}

return this;
}

public WithElementSyntax WithWithKeyword(SyntaxToken withKeyword) => Update(withKeyword, this.ArgumentList);
public WithElementSyntax WithArgumentList(ArgumentListSyntax argumentList) => Update(this.WithKeyword, argumentList);

public WithElementSyntax AddArgumentListArguments(params ArgumentSyntax[] items) => WithArgumentList(this.ArgumentList.WithArguments(this.ArgumentList.Arguments.AddRange(items)));
}

public abstract partial class QueryClauseSyntax : CSharpSyntaxNode
{
internal QueryClauseSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
Expand Down
10 changes: 6 additions & 4 deletions src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12718,6 +12718,9 @@ private bool IsPossibleCollectionElement()

private CollectionElementSyntax ParseCollectionElement()
{
if (this.CurrentToken.ContextualKind == SyntaxKind.WithKeyword && this.PeekToken(1).Kind == SyntaxKind.OpenParenToken)
return _syntaxFactory.WithElement(this.EatContextualToken(SyntaxKind.WithKeyword), this.ParseParenthesizedArgumentList());

if (this.IsAtDotDotToken())
return _syntaxFactory.SpreadElement(this.EatDotDotToken(), this.ParseExpressionCore());

Expand All @@ -12727,10 +12730,9 @@ private CollectionElementSyntax ParseCollectionElement()
: this.ParseExpressionCore();

var colonToken = this.TryEatToken(SyntaxKind.ColonToken);
if (colonToken != null)
return _syntaxFactory.KeyValuePairElement(expression, colonToken, this.ParseExpressionCore());

return _syntaxFactory.ExpressionElement(expression);
return colonToken != null
? _syntaxFactory.KeyValuePairElement(expression, colonToken, this.ParseExpressionCore())
: _syntaxFactory.ExpressionElement(expression);
}

private bool IsAnonymousType()
Expand Down
Loading
Loading