-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Unify RequiresUnreferencedCode and RequiresAssemblyFiles attributes #55274
Comments
Tagging subscribers to this area: @ajcvickers Issue DetailsBackground and MotivationCurrently the shape of these attributes is like: class RequiresUnreferencedCodeAttribute : Attribute
{
public RequiresUnreferencedCodeAttribute(string message);
public string Message { get; }
public string Url { get; set; }
}
class RequiresAssemblyFilesAttribute : Attribute
{
public RequiresAssemblyFilesAttribute();
public string Message { get; set; }
public string Url { get; set; }
} The two attributes are very similar in their usage, they annotate a certain method as problematic when used with trimming or single-file respectively. But their usage is different: [RequiresUnreferencedCode("This method doesn't play nice with trimming")]
[RequiresAssemblyFiles(Message = "This method doesn't play nice with single-file either")]
void ReallyProblematicMethod() {} The first attribute makes the From UX perspective we want people to specify the message if they at all can, since without it the produced warnings are not very actionable. It would also be good for these two attributes to have consistent usage patterns. Proposed APIWe can't really change namespace System.Diagnostics.CodeAnalysis;
class RequiresAssemblyFilesAttribute : Attribute
{
- public RequiresAssemblyFilesAttribute();
+ public RequiresAssemblyFilesAttribute(string message);
- public string Message { get; set; }
+ public string Message { get; }
public string Url { get; set; }
} Usage Examples[RequiresUnreferencedCode("This method doesn't play nice with trimming")]
[RequiresAssemblyFiles("This method doesn't play nice with single-file either")]
void ReallyProblematicMethod() {} Alternative solutionsA non-breaking solution (but a bit more messy would be to just add overloads to namespace System.Diagnostics.CodeAnalysis;
class RequiresAssemblyFilesAttribute : Attribute
{
public RequiresAssemblyFilesAttribute();
+ public RequiresAssemblyFilesAttribute(string message);
public string Message { get; set; }
public string Url { get; set; }
} RisksAs proposed it's a breaking change compared to previously released .NET 6 Previews. The alternative solution has basically no risk as it's purely additive. There's associated cost in the "breaking" change that we would need to fix all of the occurences of this attribute in the framework (less than 100) and that the Roslyn analyzer for this attribute will need to react to the change.
|
Looking across our code base, I only see 2 places that don't set a message, and they are both in a class that derives from Assembly. Lines 76 to 79 in fcd12b8
Lines 95 to 98 in fcd12b8
I agree that we should force a From the original API review I see:
Which I don't fully understand. cc @terrajobst |
Tagging subscribers to this area: @agocke, @vitek-karas, @VSadov Issue DetailsBackground and MotivationCurrently the shape of these attributes is like: class RequiresUnreferencedCodeAttribute : Attribute
{
public RequiresUnreferencedCodeAttribute(string message);
public string Message { get; }
public string Url { get; set; }
}
class RequiresAssemblyFilesAttribute : Attribute
{
public RequiresAssemblyFilesAttribute();
public string Message { get; set; }
public string Url { get; set; }
} The two attributes are very similar in their usage, they annotate a certain method as problematic when used with trimming or single-file respectively. But their usage is different: [RequiresUnreferencedCode("This method doesn't play nice with trimming")]
[RequiresAssemblyFiles(Message = "This method doesn't play nice with single-file either")]
void ReallyProblematicMethod() {} The first attribute makes the From UX perspective we want people to specify the message if they at all can, since without it the produced warnings are not very actionable. It would also be good for these two attributes to have consistent usage patterns. Proposed APIWe can't really change namespace System.Diagnostics.CodeAnalysis;
class RequiresAssemblyFilesAttribute : Attribute
{
- public RequiresAssemblyFilesAttribute();
+ public RequiresAssemblyFilesAttribute(string message);
- public string Message { get; set; }
+ public string Message { get; }
public string Url { get; set; }
} Usage Examples[RequiresUnreferencedCode("This method doesn't play nice with trimming")]
[RequiresAssemblyFiles("This method doesn't play nice with single-file either")]
void ReallyProblematicMethod() {} Alternative solutionsA non-breaking solution (but a bit more messy would be to just add overloads to namespace System.Diagnostics.CodeAnalysis;
class RequiresAssemblyFilesAttribute : Attribute
{
public RequiresAssemblyFilesAttribute();
+ public RequiresAssemblyFilesAttribute(string message);
public string Message { get; set; }
public string Url { get; set; }
} RisksAs proposed it's a breaking change compared to previously released .NET 6 Previews. The alternative solution has basically no risk as it's purely additive. There's associated cost in the "breaking" change that we would need to fix all of the occurences of this attribute in the framework (less than 100) and that the Roslyn analyzer for this attribute will need to react to the change.
|
Explaining the original api review, the premise was that we prefer having a url over having a message. If we have a good url that explains in detail then we don't need the message therefore it was optional. But since url is not always available that was also optional. |
Although something that wasn't discussed in the original RequiresAssemblyFiles API review was the actual implementation, so far we don't embed any URL information in the |
I could be persuaded that message should be optional - in which case we should make it optional on |
I definitely don't think RequiresUnreferencedCode should be applied without a message. Applying that basically means "you can never use this API in a trimmed or NativeAOT app. And you are on your own for figuring out why and what to use instead".
If we really believe that RequiresAssemblyFiles doesn't need a message because of this, I think that is enough reasoning to explain why the 2 attributes have different shaped APIs:
In that case, I would take the Alternative solution, but with a slight modification and remove the namespace System.Diagnostics.CodeAnalysis;
class RequiresAssemblyFilesAttribute : Attribute
{
public RequiresAssemblyFilesAttribute();
+ public RequiresAssemblyFilesAttribute(string message);
- public string Message { get; set; }
+ public string Message { get; }
public string Url { get; set; }
} |
I wanted to keep the message setter in the alternative solution basically just so that it doesn't break any existing usage... but we could go with your proposal as well. |
It's new in net6.0, right? We might as well make it "right" from the start. Having a ctor parameter and a setter is super confusing: [RequiresAssemblyFiles("A message", Message = "A Different Message")]
void Foo() {} |
OK- makes sense. I updated the proposal. |
namespace System.Diagnostics.CodeAnalysis
{
public sealed class RequiresAssemblyFilesAttribute : Attribute
{
public RequiresAssemblyFilesAttribute();
public RequiresAssemblyFilesAttribute(string message);
public string Message { get; }
public string Url { get; set; }
}
} |
Background and Motivation
Currently the shape of these attributes is like:
The two attributes are very similar in their usage, they annotate a certain method as problematic when used with trimming or single-file respectively. But their usage is different:
The first attribute makes the
Message
mandatory since it's a constructor parameter which can't be omitted. The second attribute makesMessage
optional and doesn't provide a way to specify it in the constructor.From UX perspective we want people to specify the message if they at all can, since without it the produced warnings are not very actionable. It would also be good for these two attributes to have consistent usage patterns.
Proposed API
We can't really change
RequiresUnreferencedCode
since that already shipped in .NET 5. But we can adaptRequiresAssemblyFiles
to match its behavior:If we think that message should be optional, then keep the parameter less constructor as well.
Usage Examples
Risks
As proposed it's a breaking change compared to previously released .NET 6 Previews. We don't expect this attribute to be used by many people yet.
There's associated cost in the "breaking" change that we would need to fix all of the occurrences of this attribute in the framework (less than 100) and that the Roslyn analyzer for this attribute will need to react to the change.
The text was updated successfully, but these errors were encountered: