Collection expression argument parsing ([with(x, y, z), a, b, c]).#76003
Conversation
|
This PR modifies public API files. Please follow the instructions at https://github.com/dotnet/roslyn/blob/main/docs/contributing/API%20Review%20Process.md for ensuring all public APIs are reviewed before merging. |
| var element = syntax.Elements[i]; | ||
| if (element is WithElementSyntax withElement) | ||
| { | ||
| Error(diagnostics, ErrorCode.ERR_WithElementMustBeFirst, withElement.WithKeyword.GetLocation()); |
There was a problem hiding this comment.
likely not. t his was just the parsing PR. binding/testing was intended for you to do :)
There was a problem hiding this comment.
If we're adding an error code and binding logic, we should test it. Either way seems fine for this PR (remove logic or test)
| { | ||
| if (element is KeyValuePairElementSyntax keyValuePairElement) | ||
| { | ||
| MessageID.IDS_FeatureDictionaryExpressions.CheckFeatureAvailability(diagnostics, syntax, keyValuePairElement.ColonToken.GetLocation()); |
| } | ||
| else if (element is WithElementSyntax withElement) | ||
| { | ||
| MessageID.IDS_FeatureCollectionExpressionConstructionArguments.CheckFeatureAvailability(diagnostics, syntax, withElement.WithKeyword.GetLocation()); |
There was a problem hiding this comment.
likely not. t his was just the parsing PR. binding/testing was intended for you to do :)
|
|
||
| // 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()); |
There was a problem hiding this comment.
this was just to unblock the PR. i would expect us to want us to be very resilient in practice. but i did no binding work.
|
|
||
| IDS_FeatureFirstClassSpan = MessageBase + 12849, | ||
| IDS_FeatureDictionaryExpressions = MessageBase + 12850, | ||
| IDS_FeatureCollectionExpressionConstructionArguments = MessageBase + 12851, |
There was a problem hiding this comment.
Consider shortening, perhaps to IDS_FeatureCollectionExpressionArguments. #Closed
cston
left a comment
There was a problem hiding this comment.
LGTM.
Please squash commits when merging, thanks.
| return (WithElementSyntax)Syntax.InternalSyntax.SyntaxFactory.WithElement((Syntax.InternalSyntax.SyntaxToken)withKeyword.Node!, (Syntax.InternalSyntax.ArgumentListSyntax)argumentList.Green).CreateRed(); | ||
| } | ||
|
|
||
| #pragma warning disable RS0027 |
There was a problem hiding this comment.
note: this required changing the generator. but we've done that in the past for this exact issue. fbofw our generator generates a pattern which our RS rules don't particularly like (though we haven't had an actual problem with the syntax apis here, so it just is a conflict in philosophy).
| if (element is WithElementSyntax withElement) | ||
| { | ||
| Error(diagnostics, ErrorCode.ERR_WithElementMustBeFirst, withElement.WithKeyword.GetLocation()); | ||
| break; |
There was a problem hiding this comment.
Why are we breaking out of the loop? #Closed
There was a problem hiding this comment.
because we reported the error on the first vioaltor. I didn't see any value in continuing to report on further violations :)
There was a problem hiding this comment.
taht said, binding behavior is entirely in chuck's court. if he wants to change this, i have no issue with that.
...torFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs
Show resolved
Hide resolved
| var hasAttributeOrModifiersList = nd.Fields.Any(f => IsAttributeOrModifiersList(f)); | ||
|
|
||
| if (hasOptional && hasAttributeOrModifiersList) | ||
| var writePragma = hasOptional && (hasAttributeOrModifiersList || nd.Name == "WithElementSyntax"); |
There was a problem hiding this comment.
I'm lacking context. What is RS0027 and why does WithElementSyntax need special treatment here? #Closed
There was a problem hiding this comment.
i marked the place in teh PR where this has impact. RS2007 says that you should not have APIs that have optional members, if there is an api that has more non optional arguments. Thi sis a suspect, and unmainted roslyn-specific rule that we violate all the time. Basically, it's fine that one can do SyntaxFactory.WithElement() or SyntaxFactory.WithElement(someWithKeyword, someArgList).
this just suppresses that warning in the generated code (which we do with many other nodes).
There was a problem hiding this comment.
Thanks
Just to confirm these are the two APIs that would cause that analyzer diagnostic?
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WithElement(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax? argumentList = null) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax!
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WithElement(Microsoft.CodeAnalysis.SyntaxToken withKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax!
| [Fact] | ||
| public void WithElement2() | ||
| { | ||
| UsingExpression("[with()]"); |
There was a problem hiding this comment.
This looks like a breaking change. Let's document it.
Should it be made LangVer-dependent? #Closed
There was a problem hiding this comment.
We can doc, but def want to run by ldm first. Our investigations here indicate no usage of this in the wild. So we're going to see if we can get buyoff on this just being a unilateral break .
There was a problem hiding this comment.
this is part of hte final syntax/sign-off discussion there.
There was a problem hiding this comment.
Should it be made LangVer-dependent?
This is currently an open question.
There was a problem hiding this comment.
Since the PR implements a break, let's add a PROTOTYPE marker (to test with LangVer and document break).
There was a problem hiding this comment.
open LDM question.
There was a problem hiding this comment.
Since the PR implements a break, let's add a PROTOTYPE marker (to test with LangVer and document break).
Done.
There was a problem hiding this comment.
| UsingExpression("[with()]"); | |
| // PROTOTYPE test with LangVer and document break | |
| UsingExpression("[with()]"); |
My reasoning for pushing on this: If LDM were to approve the break as it is implemented by this PR, so nobody revisits this code, who is going to remember that we didn't document it? Usually, PRs that implement breaks also document them.
Thanks. I see this was addressed elsewhere
f806fd4
into
dotnet:features/dictionary-expressions
An exploration around adding a
with(...arguments...)element to collection expressions, to allow arguments to be passed to the final created collection. For example, for:Dictionary<string, int> nameToAge = [with(StringComparer.CaseInsensitive), "mads": 21, .. existingDic].Relates to test plan #76310