-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Implement ExperimentalAttribute
#85444
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| namespace System.Diagnostics.CodeAnalysis | ||
| { | ||
| /// <summary> | ||
| /// Indicates that an API is experimental and it may change in the future. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental | ||
| /// feature is used. Authors can use this attribute to ship preview features in their assemblies. | ||
| /// </remarks> | ||
| [AttributeUsage(AttributeTargets.Assembly | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joperezr @stephentoub Let's not include "Assembly" and "Module" in the list. I don't think those targets are valid for other attributes of this kind (
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc: @terrajobst @geeknoid Thanks for the feedback @jcouv. Aside from the fact that other attributes don't support this, is there a particular reason why you don't think we should allow Assembly or Module use? Seems to me that there are valid scenarios where people developing new assemblies might opt to use it at that level, in the past this has been done mostly via using prerelease package versions but I think that not everybody uses that and there are some scenarios where it might be better to have stable p ackages with assemblies marked as experimental in them.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The main reason for my question is precedent. The secondary reason is implementation cost (deviating from existing attributes means additional complexity and testing).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fair enough. @bartonjs @terrajobst @stephentoub Do you know off the top of your head why the Obsolete attribute doesn't support Assembly or Module targets? I would have expected the same arguments should be made for both Obsolete and Experimental, since they are essentially the same attribute but just tracking the two opposing ends of an API lifecycle.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe dotnet/extensions has assembly-level applications of the attribute. E.g., https://github.com/dotnet/extensions/blob/d558f8de86adf93044bc5386bd4367b3d509ead3/Directory.Build.targets#L68-L72
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the platform compat attributes we allowed assembly/module and we use it quite a bit.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine with excluding them for now if we want to match ObsoleteAttribute. We can revisit then we run into limitations.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @geeknoid FYI
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI, the compiler/roslyn change was merged. |
||
| AttributeTargets.Module | | ||
| AttributeTargets.Class | | ||
| AttributeTargets.Struct | | ||
| AttributeTargets.Enum | | ||
| AttributeTargets.Constructor | | ||
| AttributeTargets.Method | | ||
| AttributeTargets.Property | | ||
| AttributeTargets.Field | | ||
| AttributeTargets.Event | | ||
| AttributeTargets.Interface | | ||
| AttributeTargets.Delegate, Inherited = false)] | ||
|
stephentoub marked this conversation as resolved.
Outdated
|
||
| public sealed class ExperimentalAttribute : Attribute | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joperezr @stephentoub I just want to confirm the expected user experience with an example. I'm re-using a message we already have for APIs marked as experimental. Let me know if you have any feedback.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, the above looks right to me. You can then also write a compilation which passes in the NoWarn for your diagnostic which should not show it any more, or alternatively suppress at each call site by using pragma.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
| { | ||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="ExperimentalAttribute"/> class, specifying the ID that the compiler will use | ||
| /// when reporting a use of the API the attribute applies to. | ||
| /// </summary> | ||
| /// <param name="diagnosticId">The ID that the compiler will use when reporting a use of the API the attribute applies to.</param> | ||
| public ExperimentalAttribute(string diagnosticId) | ||
| { | ||
| DiagnosticId = diagnosticId; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the ID that the compiler will use when reporting a use of the API the attribute applies to. | ||
| /// </summary> | ||
| /// <value>The unique diagnostic ID.</value> | ||
| /// <remarks> | ||
| /// The diagnostic ID is shown in build output for warnings and errors. | ||
| /// <para>This property represents the unique ID that can be used to suppress the warnings or errors, if needed.</para> | ||
| /// </remarks> | ||
| public string DiagnosticId { get; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the URL for corresponding documentation. | ||
| /// The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID. | ||
| /// </summary> | ||
| /// <value>The format string that represents a URL to corresponding documentation.</value> | ||
| /// <remarks>An example format string is <c>https://contoso.com/obsoletion-warnings/{0}</c>.</remarks> | ||
| public string? UrlFormat { get; set; } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using Xunit; | ||
|
|
||
| namespace System.Diagnostics.CodeAnalysis.Tests | ||
| { | ||
| public class ExperimentalAttributeTests | ||
| { | ||
| [Theory] | ||
| // Note: Once the compiler support is implemented these should fail | ||
| [InlineData("")] | ||
| [InlineData(" ")] | ||
| [InlineData("\t")] | ||
| // Note end | ||
| [InlineData("diagnosticId")] | ||
| public void TestConstructor(string expected) | ||
| { | ||
| var attr = new ExperimentalAttribute(expected); | ||
|
|
||
| Assert.Equal(expected, attr.DiagnosticId); | ||
| Assert.Null(attr.UrlFormat); | ||
| } | ||
|
|
||
| [Theory] | ||
| [InlineData(null)] | ||
| [InlineData("")] | ||
| [InlineData("https://contoso.com/obsoletion-warnings/{0}")] | ||
| public void TestSetUrlFormat(string urlFormat) | ||
| { | ||
| var attr = new ExperimentalAttribute("diagnosticId") | ||
| { | ||
| UrlFormat = urlFormat | ||
| }; | ||
|
|
||
| Assert.Equal("diagnosticId", attr.DiagnosticId); | ||
| Assert.Equal(urlFormat, attr.UrlFormat); | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.