Skip to content

Commit d111b6b

Browse files
committed
fixes
1 parent 4baa135 commit d111b6b

12 files changed

+149
-41
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#pragma warning disable IDE0079
5+
#pragma warning disable SA1101
6+
#pragma warning disable SA1116
7+
#pragma warning disable SA1117
8+
#pragma warning disable SA1512
9+
#pragma warning disable SA1623
10+
#pragma warning disable SA1642
11+
#pragma warning disable S3903
12+
13+
namespace System.Diagnostics.CodeAnalysis;
14+
15+
/// <summary>
16+
/// /// Suppresses reporting of a specific rule violation, allowing multiple suppressions on a
17+
/// single code artifact.
18+
/// </summary>
19+
/// <remarks>
20+
/// <see cref="UnconditionalSuppressMessageAttribute"/> is different than
21+
/// <see cref="SuppressMessageAttribute"/> in that it doesn't have a
22+
/// <see cref="ConditionalAttribute"/>. So it is always preserved in the compiled assembly.
23+
/// </remarks>
24+
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
25+
[ExcludeFromCodeCoverage]
26+
internal sealed class UnconditionalSuppressMessageAttribute : Attribute
27+
{
28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="UnconditionalSuppressMessageAttribute"/>
30+
/// class, specifying the category of the tool and the identifier for an analysis rule.
31+
/// </summary>
32+
/// <param name="category">The category for the attribute.</param>
33+
/// <param name="checkId">The identifier of the analysis rule the attribute applies to.</param>
34+
public UnconditionalSuppressMessageAttribute(string category, string checkId)
35+
{
36+
Category = category;
37+
CheckId = checkId;
38+
}
39+
40+
/// <summary>
41+
/// Gets the category identifying the classification of the attribute.
42+
/// </summary>
43+
/// <remarks>
44+
/// The <see cref="Category"/> property describes the tool or tool analysis category
45+
/// for which a message suppression attribute applies.
46+
/// </remarks>
47+
public string Category { get; }
48+
49+
/// <summary>
50+
/// Gets the identifier of the analysis tool rule to be suppressed.
51+
/// </summary>
52+
/// <remarks>
53+
/// Concatenated together, the <see cref="Category"/> and <see cref="CheckId"/>
54+
/// properties form a unique check identifier.
55+
/// </remarks>
56+
public string CheckId { get; }
57+
58+
/// <summary>
59+
/// Gets or sets the scope of the code that is relevant for the attribute.
60+
/// </summary>
61+
/// <remarks>
62+
/// The Scope property is an optional argument that specifies the metadata scope for which
63+
/// the attribute is relevant.
64+
/// </remarks>
65+
public string? Scope { get; set; }
66+
67+
/// <summary>
68+
/// Gets or sets a fully qualified path that represents the target of the attribute.
69+
/// </summary>
70+
/// <remarks>
71+
/// The <see cref="Target"/> property is an optional argument identifying the analysis target
72+
/// of the attribute. An example value is "System.IO.Stream.ctor():System.Void".
73+
/// Because it is fully qualified, it can be long, particularly for targets such as parameters.
74+
/// The analysis tool user interface should be capable of automatically formatting the parameter.
75+
/// </remarks>
76+
public string? Target { get; set; }
77+
78+
/// <summary>
79+
/// Gets or sets an optional argument expanding on exclusion criteria.
80+
/// </summary>
81+
/// <remarks>
82+
/// The <see cref="MessageId"/> property is an optional argument that specifies additional
83+
/// exclusion where the literal metadata target is not sufficiently precise. For example,
84+
/// the <see cref="UnconditionalSuppressMessageAttribute"/> cannot be applied within a method,
85+
/// and it may be desirable to suppress a violation against a statement in the method that will
86+
/// give a rule violation, but not against all statements in the method.
87+
/// </remarks>
88+
public string? MessageId { get; set; }
89+
90+
/// <summary>
91+
/// Gets or sets the justification for suppressing the code analysis message.
92+
/// </summary>
93+
public string? Justification { get; set; }
94+
}

src/Polly.Core/CircuitBreaker/CircuitBreakerResilienceStrategyBuilderExtensions.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55

66
namespace Polly;
77

8-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
9-
108
/// <summary>
119
/// Circuit breaker strategy extensions for <see cref="ResilienceStrategyBuilder"/>.
1210
/// </summary>
@@ -102,6 +100,10 @@ public static ResilienceStrategyBuilder AddSimpleCircuitBreaker(this ResilienceS
102100
return builder.AddSimpleCircuitBreakerCore(options);
103101
}
104102

103+
[UnconditionalSuppressMessage(
104+
"Trimming",
105+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
106+
Justification = "All options members preserved.")]
105107
private static TBuilder AddAdvancedCircuitBreakerCore<TBuilder, TResult>(this TBuilder builder, AdvancedCircuitBreakerStrategyOptions<TResult> options)
106108
where TBuilder : ResilienceStrategyBuilderBase
107109
{
@@ -118,6 +120,10 @@ private static TBuilder AddAdvancedCircuitBreakerCore<TBuilder, TResult>(this TB
118120
options);
119121
}
120122

123+
[UnconditionalSuppressMessage(
124+
"Trimming",
125+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
126+
Justification = "All options members preserved.")]
121127
private static TBuilder AddSimpleCircuitBreakerCore<TBuilder, TResult>(this TBuilder builder, SimpleCircuitBreakerStrategyOptions<TResult> options)
122128
where TBuilder : ResilienceStrategyBuilderBase
123129
{

src/Polly.Core/Fallback/FallbackResilienceStrategyBuilderExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Polly;
66

7-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
8-
97
/// <summary>
108
/// Provides extension methods for configuring fallback resilience strategies for <see cref="ResilienceStrategyBuilder"/>.
119
/// </summary>
@@ -46,6 +44,10 @@ internal static ResilienceStrategyBuilder AddFallback(this ResilienceStrategyBui
4644
return builder;
4745
}
4846

47+
[UnconditionalSuppressMessage(
48+
"Trimming",
49+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
50+
Justification = "All options members preserved.")]
4951
internal static void AddFallbackCore<TResult, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TOptions>(
5052
this ResilienceStrategyBuilderBase builder,
5153
FallbackStrategyOptions<TResult> options)

src/Polly.Core/Hedging/HedgingResilienceStrategyBuilderExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55

66
namespace Polly;
77

8-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
9-
108
/// <summary>
119
/// Provides extension methods for configuring hedging resilience strategies for <see cref="ResilienceStrategyBuilder"/>.
1210
/// </summary>
@@ -47,6 +45,10 @@ internal static ResilienceStrategyBuilder AddHedging(this ResilienceStrategyBuil
4745
return builder;
4846
}
4947

48+
[UnconditionalSuppressMessage(
49+
"Trimming",
50+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
51+
Justification = "All options members preserved.")]
5052
internal static void AddHedgingCore<TResult, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(
5153
this ResilienceStrategyBuilderBase builder,
5254
HedgingStrategyOptions<TResult> options)

src/Polly.Core/ResilienceStrategyBuilderBase.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ public abstract class ResilienceStrategyBuilderBase
1717
{
1818
private readonly List<Entry> _entries = new();
1919
private bool _used;
20-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
21-
private Action<ResilienceValidationContext> _validator = ValidationHelper.ValidateObject;
22-
#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
2320

2421
private protected ResilienceStrategyBuilderBase()
2522
{
@@ -121,11 +118,7 @@ private protected ResilienceStrategyBuilderBase(ResilienceStrategyBuilderBase ot
121118
/// </remarks>
122119
/// <exception cref="ArgumentNullException">Thrown when the attempting to assign <see langword="null"/> to this property.</exception>
123120
[EditorBrowsable(EditorBrowsableState.Never)]
124-
public Action<ResilienceValidationContext> Validator
125-
{
126-
get => _validator;
127-
internal set => _validator = Guard.NotNull(value);
128-
}
121+
public Action<ResilienceValidationContext> Validator { get; private protected set; } = ValidationHelper.ValidateObject;
129122

130123
internal abstract bool IsGenericBuilder { get; }
131124

src/Polly.Core/ResilienceStrategyBuilderExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@ public static class ResilienceStrategyBuilderExtensions
1717
/// <returns>The same builder instance.</returns>
1818
/// <exception cref="ArgumentNullException">Thrown when <paramref name="strategy"/> is null.</exception>
1919
/// <exception cref="InvalidOperationException">Thrown when this builder was already used to create a strategy. The builder cannot be modified after it has been used.</exception>
20+
[UnconditionalSuppressMessage(
21+
"Trimming",
22+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
23+
Justification = "The EmptyOptions have nothing to validate.")]
2024
public static TBuilder AddStrategy<TBuilder>(this TBuilder builder, ResilienceStrategy strategy)
2125
where TBuilder : ResilienceStrategyBuilderBase
2226
{
2327
Guard.NotNull(builder);
2428
Guard.NotNull(strategy);
2529

26-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
2730
return builder.AddStrategy(_ => strategy, EmptyOptions.Instance);
28-
#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
2931
}
3032

3133
/// <summary>

src/Polly.Core/Retry/RetryResilienceStrategyBuilderExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Polly;
66

7-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
8-
97
/// <summary>
108
/// Retry extension methods for the <see cref="ResilienceStrategyBuilder"/>.
119
/// </summary>
@@ -46,6 +44,10 @@ public static ResilienceStrategyBuilder<TResult> AddRetry<TResult>(this Resilien
4644
return builder;
4745
}
4846

47+
[UnconditionalSuppressMessage(
48+
"Trimming",
49+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
50+
Justification = "All options members preserved.")]
4951
private static void AddRetryCore<TResult, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(
5052
this ResilienceStrategyBuilderBase builder,
5153
RetryStrategyOptions<TResult> options)

src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
13
namespace Polly.Telemetry;
24

35
/// <summary>
@@ -31,6 +33,14 @@ internal ResilienceStrategyTelemetry(ResilienceTelemetrySource source, Diagnosti
3133
/// <param name="context">The resilience context associated with this event.</param>
3234
/// <param name="args">The event arguments.</param>
3335
/// <exception cref="ArgumentNullException">Thrown when <paramref name="context"/> is <see langword="null"/>.</exception>
36+
[UnconditionalSuppressMessage(
37+
"Trimming",
38+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
39+
Justification = "The reflection is not used when consuming the event.")]
40+
[UnconditionalSuppressMessage(
41+
"AOT",
42+
"IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
43+
Justification = "The reflection is not used when consuming the event.")]
3444
public void Report<TArgs>(ResilienceEvent resilienceEvent, ResilienceContext context, TArgs args)
3545
{
3646
Guard.NotNull(context);
@@ -44,11 +54,7 @@ public void Report<TArgs>(ResilienceEvent resilienceEvent, ResilienceContext con
4454

4555
var telemetryArgs = TelemetryEventArguments.Get(TelemetrySource, resilienceEvent, context, null, args!);
4656

47-
#pragma warning disable IL2026 // The consumer of this method is Polly.Extensions and it does not use reflection at all
48-
#pragma warning disable IL3050
4957
DiagnosticSource.Write(resilienceEvent.EventName, telemetryArgs);
50-
#pragma warning restore IL3050
51-
#pragma warning restore IL2026
5258

5359
TelemetryEventArguments.Return(telemetryArgs);
5460
}
@@ -60,6 +66,14 @@ public void Report<TArgs>(ResilienceEvent resilienceEvent, ResilienceContext con
6066
/// <typeparam name="TResult">The type of the result.</typeparam>
6167
/// <param name="resilienceEvent">The reported resilience event.</param>
6268
/// <param name="args">The event arguments.</param>
69+
[UnconditionalSuppressMessage(
70+
"Trimming",
71+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
72+
Justification = "The reflection is not used when consuming the event.")]
73+
[UnconditionalSuppressMessage(
74+
"AOT",
75+
"IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
76+
Justification = "The reflection is not used when consuming the event.")]
6377
public void Report<TArgs, TResult>(ResilienceEvent resilienceEvent, OutcomeArguments<TResult, TArgs> args)
6478
{
6579
args.Context.AddResilienceEvent(resilienceEvent);
@@ -71,11 +85,7 @@ public void Report<TArgs, TResult>(ResilienceEvent resilienceEvent, OutcomeArgum
7185

7286
var telemetryArgs = TelemetryEventArguments.Get(TelemetrySource, resilienceEvent, args.Context, args.Outcome.AsOutcome(), args.Arguments!);
7387

74-
#pragma warning disable IL2026 // The consumer of this method is Polly.Extensions and it does not use reflection at all
75-
#pragma warning disable IL3050
7688
DiagnosticSource.Write(resilienceEvent.EventName, telemetryArgs);
77-
#pragma warning restore IL3050
78-
#pragma warning restore IL2026
7989

8090
TelemetryEventArguments.Return(telemetryArgs);
8191
}

src/Polly.Core/Timeout/TimeoutResilienceStrategyBuilderExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Polly;
66

7-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
8-
97
/// <summary>
108
/// Extension methods for adding timeouts to a <see cref="ResilienceStrategyBuilder"/>.
119
/// </summary>
@@ -41,6 +39,10 @@ public static TBuilder AddTimeout<TBuilder>(this TBuilder builder, TimeSpan time
4139
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
4240
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
4341
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(TimeoutStrategyOptions))]
42+
[UnconditionalSuppressMessage(
43+
"Trimming",
44+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
45+
Justification = "All options members preserved.")]
4446
public static TBuilder AddTimeout<TBuilder>(this TBuilder builder, TimeoutStrategyOptions options)
4547
where TBuilder : ResilienceStrategyBuilderBase
4648
{

src/Polly.Core/Utils/ValidationHelper.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ namespace Polly.Utils;
88
internal static class ValidationHelper
99
{
1010
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(TimeSpan))]
11+
[UnconditionalSuppressMessage(
12+
"Trimming",
13+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
14+
Justification = "The member of options are preserved and no trimmed. See builder.AddStrategy() extension.")]
1115
public static void ValidateObject(ResilienceValidationContext context)
1216
{
1317
Guard.NotNull(context);
1418

1519
var errors = new List<ValidationResult>();
1620

17-
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
1821
if (!Validator.TryValidateObject(context.Instance, new ValidationContext(context.Instance), errors, true))
1922
{
2023
var stringBuilder = new StringBuilder(context.PrimaryMessage);
@@ -28,6 +31,5 @@ public static void ValidateObject(ResilienceValidationContext context)
2831

2932
throw new ValidationException(stringBuilder.ToString());
3033
}
31-
#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
3234
}
3335
}

0 commit comments

Comments
 (0)