-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Validate diagnostic ID in Experimental attribute #70397
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
Conversation
|
Moved out to 17.9 |
|
|
||
| comp.VerifyDiagnostics( | ||
| // 0.cs(1,1): error CS9204: 'C' is for evaluation purposes only and is subject to change or removal in future updates. | ||
| // 0.cs(1,1): error CS9204: 'C' is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added some command-line tests to configure the severity on various diagnostics
| extends [mscorlib]System.Object | ||
| { | ||
| // Experimental("Diag 01") | ||
| .custom instance void System.Diagnostics.CodeAnalysis.ExperimentalAttribute::.ctor(string) = ( 01 00 07 44 69 61 67 20 30 31 00 00 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| { | ||
| .get instance string System.Diagnostics.CodeAnalysis.ExperimentalAttribute::get_UrlFormat() | ||
| .set instance void System.Diagnostics.CodeAnalysis.ExperimentalAttribute::set_UrlFormat(string) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider removing if not needed, including backing field declaration. #Resolved
| <value>Expected interpolated string</value> | ||
| </data> | ||
| <data name="ERR_InvalidExperimentalDiagID" xml:space="preserve"> | ||
| <value>The argument to the 'Experimental' attribute must be a valid identifier</value> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| public void NullDiagnosticId() | ||
| { | ||
| var libSrc = """ | ||
| [System.Diagnostics.CodeAnalysis.Experimental(null)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (arguments.Attribute.IsTargetAttribute(this, AttributeDescription.ExperimentalAttribute) | ||
| && !SyntaxFacts.IsValidIdentifier((string?)arguments.Attribute.CommonConstructorArguments[0].ValueInternal)) | ||
| { | ||
| arguments.Diagnostics.DiagnosticBag.Add(ErrorCode.ERR_InvalidExperimentalDiagID, arguments.AttributeSyntaxOpt.Location); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| public void DiagnosticIdWithTrailingNewline() | ||
| { | ||
| var libSrc = """ | ||
| [System.Diagnostics.CodeAnalysis.Experimental("Diag\n")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
Done with review pass (commit 2) |
| if (arguments.Attribute.IsTargetAttribute(this, AttributeDescription.ExperimentalAttribute) | ||
| && !SyntaxFacts.IsValidIdentifier((string?)arguments.Attribute.CommonConstructorArguments[0].ValueInternal)) | ||
| { | ||
| Debug.Assert(arguments.AttributeSyntaxOpt is not null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| """); | ||
| var analyzerConfig = dir.CreateFile(".editorconfig").WriteAllText(""" | ||
| [*.cs] | ||
| dotnet_diagnostic.CS9208.severity = warning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this have any effect on the scenario? If yes, then consider including observations without this line present. If no, consider removing. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or did you mean to attempt to suppress CS9211 instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, should have been CS9211. Thanks
| """); | ||
| var analyzerConfig = dir.CreateFile(".editorconfig").WriteAllText(""" | ||
| [*.cs] | ||
| dotnet_diagnostic.CS9204.severity = warning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| var src = """ | ||
| C.M(); | ||
| [System.Diagnostics.CodeAnalysis.Experimental("DiagID", "other")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| comp.VerifyDiagnostics( | ||
| // 0.cs(1,1): error CS9204: 'C' is for evaluation purposes only and is subject to change or removal in future updates. | ||
| // 0.cs(1,1): error CS9204: 'C' is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| var comp = CreateCompilation(new[] { src, libSrc, experimentalAttributeSrc }); | ||
|
|
||
| comp.VerifyDiagnostics( | ||
| // 0.cs(1,1): error Diag\n: 'C' is for evaluation purposes only and is subject to change or removal in future updates.Suppress this diagnostic to proceed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| public void WhitespaceDiagnosticId_WithSuppression() | ||
| { | ||
| var src = """ | ||
| #pragma warning disable CS9204 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The effect of the pragma feels unexpected to me. However, this isn't primarily related to the goal of the PR. Therefore, not blocking #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's unexpected? We have a diagnostic that we're going to report as CS9204 and we suppress CS9204, therefore the diagnostic is suppressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's unexpected?
Errors are usually not suppressable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec this is not an error, it is merely reported as an error
It would be good to test if we can suppress this error with pragma. Not blocking. #Closed Refers to: src/Compilers/CSharp/Test/Emit2/Semantics/ExperimentalAttributeTests.cs:58 in 5d1c56d. [](commit_id = 5d1c56d, deletion_comment = False) |
AlekseyTs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 8)
|
Is this check already implemented for VB? #Resolved |
|
Added VB implementation |
I think that's already covered by test In reply to: 1771422464 Refers to: src/Compilers/CSharp/Test/Emit2/Semantics/ExperimentalAttributeTests.cs:58 in 5d1c56d. [](commit_id = 5d1c56d, deletion_comment = False) |
| End Sub | ||
|
|
||
| <Fact> | ||
| Public Sub ExperimentalWithValidDiagnosticID_WarnForDiagID() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test has dotnet_diagnostic.DiagID.severity = warning
| ElseIf arguments.Attribute.IsTargetAttribute(Me, AttributeDescription.RequiredMemberAttribute) Then | ||
| DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_DoNotUseRequiredMember, arguments.AttributeSyntaxOpt.Location) | ||
| ElseIf arguments.Attribute.IsTargetAttribute(Me, AttributeDescription.ExperimentalAttribute) AndAlso | ||
| Not SyntaxFacts.IsValidIdentifier(DirectCast(arguments.Attribute.CommonConstructorArguments(0).ValueInternal, String)) Then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using a nested if instead. So that we wouldn't keep checking for other well-known attributes once we run into the Experimental attribute. We might add checks for other attributes below in the future. #Closed
| } | ||
|
|
||
| if (arguments.Attribute.IsTargetAttribute(this, AttributeDescription.ExperimentalAttribute) | ||
| && !SyntaxFacts.IsValidIdentifier((string?)arguments.Attribute.CommonConstructorArguments[0].ValueInternal)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second thought, never mind. It looks like we do want to call DecodeWellKnownAttributeImpl below.
| { | ||
| var attrArgumentLocation = arguments.Attribute.GetAttributeArgumentSyntaxLocation(parameterIndex: 0, arguments.AttributeSyntaxOpt); | ||
| arguments.Diagnostics.DiagnosticBag.Add(ErrorCode.ERR_InvalidExperimentalDiagID, attrArgumentLocation); | ||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. The decoding of experimental attribute is done in EarlyDecodeWellKnownAttributes, before we get to DecodeWellKnownAttribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. The decoding of experimental attribute is done in EarlyDecodeWellKnownAttributes, before we get to DecodeWellKnownAttribute
First, the code should be robust to future changes and it feels reasonable to me that the fact you are referring to, if it is a fact, won't hold in the future.
Second, I actually see decoding done in DecodeWellKnownAttributeImpl for a SourceModuleSymbol today, for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right. The return broke things.
|
Done with review pass (commit 9) |
AlekseyTs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 11), assuming CI is passing.
Corresponding spec update: dotnet/csharplang#7597
Relates to #68702
Relates to dotnet/runtime#85444