-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
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.
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
@@ -7809,4 +7809,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ | |||
<data name="ERR_ExpectedInterpolatedString" xml:space="preserve"> | |||
<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.
[Theory, CombinatorialData] | ||
public void NullDiagnosticId(bool inSource) | ||
[Fact] | ||
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.
[Theory, CombinatorialData] | ||
public void DiagnosticIdWithTrailingNewline(bool inSource) | ||
[Fact] | ||
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) |
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
@@ -204,6 +204,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic | |||
DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_DoNotUseCompilerFeatureRequired, arguments.AttributeSyntaxOpt.Location) | |||
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
@@ -226,6 +226,14 @@ protected void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments<At | |||
return; | |||
} | |||
|
|||
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) |
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