Validate diagnostic ID in Experimental attribute#70397
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.
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 ) |
| { | ||
| .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.
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> |
| public void NullDiagnosticId() | ||
| { | ||
| var libSrc = """ | ||
| [System.Diagnostics.CodeAnalysis.Experimental(null)] |
| 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); |
| public void DiagnosticIdWithTrailingNewline() | ||
| { | ||
| var libSrc = """ | ||
| [System.Diagnostics.CodeAnalysis.Experimental("Diag\n")] |
|
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); |
| """); | ||
| var analyzerConfig = dir.CreateFile(".editorconfig").WriteAllText(""" | ||
| [*.cs] | ||
| dotnet_diagnostic.CS9208.severity = warning |
There was a problem hiding this comment.
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.
Or did you mean to attempt to suppress CS9211 instead?
There was a problem hiding this comment.
Yes, should have been CS9211. Thanks
| """); | ||
| var analyzerConfig = dir.CreateFile(".editorconfig").WriteAllText(""" | ||
| [*.cs] | ||
| dotnet_diagnostic.CS9204.severity = warning |
| var src = """ | ||
| C.M(); | ||
|
|
||
| [System.Diagnostics.CodeAnalysis.Experimental("DiagID", "other")] |
|
|
||
| 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. |
| 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. |
| public void WhitespaceDiagnosticId_WithSuppression() | ||
| { | ||
| var src = """ | ||
| #pragma warning disable CS9204 |
There was a problem hiding this comment.
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.
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.
What's unexpected?
Errors are usually not suppressable
There was a problem hiding this comment.
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) |
|
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.
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.
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.
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.
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.
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.
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.
LGTM (commit 11), assuming CI is passing.
Corresponding spec update: dotnet/csharplang#7597
Relates to #68702
Relates to dotnet/runtime#85444