From 866bf990bf2d2257aba18205ad3a798f67028c8a Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Mon, 7 Jun 2021 15:25:38 -0700 Subject: [PATCH] Resolving ILLink warnings on Microsoft.Extensions.Options.ConfigurationManager (#53552) * Resolving ILLink warnings on Microsoft.Extensions.Options.ConfigurationManager * Fix message * Addressing messages feedback * Update src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.cs Co-authored-by: Eric Erhardt * Update remaining messages with suggestion. Co-authored-by: Eric Erhardt --- ...rosoft.Extensions.Logging.Configuration.cs | 3 +- ...ft.Extensions.Logging.Configuration.csproj | 3 ++ .../LoggerProviderConfigurationExtensions.cs | 6 +++- .../src/LoggerProviderConfigureOptions.cs | 4 ++- ...ft.Extensions.Logging.Configuration.csproj | 3 ++ .../Microsoft.Extensions.Logging.Console.cs | 6 ++-- ...icrosoft.Extensions.Logging.Console.csproj | 1 + .../src/ConsoleLoggerExtensions.cs | 14 +++++++-- ...icrosoft.Extensions.Logging.Console.csproj | 4 ++- ...ensions.Options.ConfigurationExtensions.cs | 28 +++++++++++------ ...ons.Options.ConfigurationExtensions.csproj | 3 ++ .../src/ConfigureFromConfigurationOptions.cs | 12 ++++++-- .../src/ILLink/ILLink.Suppressions.xml | 23 -------------- ...ons.Options.ConfigurationExtensions.csproj | 5 ++++ .../NamedConfigureFromConfigurationOptions.cs | 12 ++++++-- .../OptionsBuilderConfigurationExtensions.cs | 30 ++++++++++++------- ...onfigurationServiceCollectionExtensions.cs | 13 +++++--- 17 files changed, 111 insertions(+), 59 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.cs b/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.cs index a152a0a71c8..224bf6d4237 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.cs @@ -23,7 +23,8 @@ public partial interface ILoggerProviderConfiguration } public static partial class LoggerProviderOptions { - public static void RegisterProviderOptions(Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TOptions : class { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static void RegisterProviderOptions<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions, TProvider>(Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TOptions : class { } } public partial class LoggerProviderOptionsChangeTokenSource : Microsoft.Extensions.Options.ConfigurationChangeTokenSource { diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.csproj b/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.csproj index 880386c2298..96453d7f665 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/ref/Microsoft.Extensions.Logging.Configuration.csproj @@ -4,6 +4,9 @@ + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigurationExtensions.cs index f8673b86159..3cbbbd60667 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigurationExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; @@ -12,13 +13,16 @@ namespace Microsoft.Extensions.Logging.Configuration /// public static class LoggerProviderOptions { + internal const string TrimmingRequiresUnreferencedCodeMessage = "TOptions's dependent types may have their members trimmed. Ensure all required members are preserved."; + /// /// Indicates that settings for should be loaded into type. /// /// The to register on. /// The options class /// The provider class - public static void RegisterProviderOptions(IServiceCollection services) where TOptions : class + [RequiresUnreferencedCode(TrimmingRequiresUnreferencedCodeMessage)] + public static void RegisterProviderOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions, TProvider>(IServiceCollection services) where TOptions : class { services.TryAddEnumerable(ServiceDescriptor.Singleton, LoggerProviderConfigureOptions>()); services.TryAddEnumerable(ServiceDescriptor.Singleton, LoggerProviderOptionsChangeTokenSource>()); diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigureOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigureOptions.cs index 1510cc53770..c7e83445baa 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigureOptions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerProviderConfigureOptions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Options; namespace Microsoft.Extensions.Logging.Configuration @@ -8,8 +9,9 @@ namespace Microsoft.Extensions.Logging.Configuration /// /// Loads settings for into type. /// - internal sealed class LoggerProviderConfigureOptions : ConfigureFromConfigurationOptions where TOptions : class + internal sealed class LoggerProviderConfigureOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions, TProvider> : ConfigureFromConfigurationOptions where TOptions : class { + [RequiresUnreferencedCode(LoggerProviderOptions.TrimmingRequiresUnreferencedCodeMessage)] public LoggerProviderConfigureOptions(ILoggerProviderConfiguration providerConfiguration) : base(providerConfiguration.Configuration) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj index 387ecfe46af..976be509012 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj @@ -10,6 +10,9 @@ + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs index 4cca93a0012..d9ffb2dc19c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs @@ -11,8 +11,10 @@ public static partial class ConsoleLoggerExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) { throw null; } - public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsoleFormatter<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, TOptions>(this Microsoft.Extensions.Logging.ILoggingBuilder builder) where TFormatter : Microsoft.Extensions.Logging.Console.ConsoleFormatter where TOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { throw null; } - public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsoleFormatter<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, TOptions>(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) where TFormatter : Microsoft.Extensions.Logging.Console.ConsoleFormatter where TOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsoleFormatter<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.Logging.ILoggingBuilder builder) where TFormatter : Microsoft.Extensions.Logging.Console.ConsoleFormatter where TOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsoleFormatter<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) where TFormatter : Microsoft.Extensions.Logging.Console.ConsoleFormatter where TOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddJsonConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddJsonConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddSimpleConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj index 41c181ec7a7..e1a3dea400d 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj @@ -8,6 +8,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs index 372933b97e3..8a91327d95c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs @@ -16,10 +16,15 @@ namespace Microsoft.Extensions.Logging [UnsupportedOSPlatform("browser")] public static class ConsoleLoggerExtensions { + internal const string TrimmingRequiresUnreferencedCodeMessage = "TOptions's dependent types may have their members trimmed. Ensure all required members are preserved."; + /// /// Adds a console logger named 'Console' to the factory. /// /// The to use. + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "AddConsoleFormatter and RegisterProviderOptions are only dangerous when the Options type cannot be statically analyzed, but that is not the case here. " + + "The DynamicallyAccessedMembers annotations on them will make sure to preserve the right members from the different options objects.")] public static ILoggingBuilder AddConsole(this ILoggingBuilder builder) { builder.AddConfiguration(); @@ -123,7 +128,8 @@ internal static ILoggingBuilder AddConsoleWithFormatter(this ILoggingB /// Adds a custom console logger formatter 'TFormatter' to be configured with options 'TOptions'. /// /// The to use. - public static ILoggingBuilder AddConsoleFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, TOptions>(this ILoggingBuilder builder) + [RequiresUnreferencedCode(TrimmingRequiresUnreferencedCodeMessage)] + public static ILoggingBuilder AddConsoleFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this ILoggingBuilder builder) where TOptions : ConsoleFormatterOptions where TFormatter : ConsoleFormatter { @@ -141,7 +147,8 @@ internal static ILoggingBuilder AddConsoleWithFormatter(this ILoggingB /// /// The to use. /// A delegate to configure options 'TOptions' for custom formatter 'TFormatter'. - public static ILoggingBuilder AddConsoleFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, TOptions>(this ILoggingBuilder builder, Action configure) + [RequiresUnreferencedCode(TrimmingRequiresUnreferencedCodeMessage)] + public static ILoggingBuilder AddConsoleFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFormatter, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this ILoggingBuilder builder, Action configure) where TOptions : ConsoleFormatterOptions where TFormatter : ConsoleFormatter { @@ -157,10 +164,11 @@ internal static ILoggingBuilder AddConsoleWithFormatter(this ILoggingB } [UnsupportedOSPlatform("browser")] - internal sealed class ConsoleLoggerFormatterConfigureOptions : ConfigureFromConfigurationOptions + internal sealed class ConsoleLoggerFormatterConfigureOptions : ConfigureFromConfigurationOptions where TOptions : ConsoleFormatterOptions where TFormatter : ConsoleFormatter { + [RequiresUnreferencedCode(ConsoleLoggerExtensions.TrimmingRequiresUnreferencedCodeMessage)] public ConsoleLoggerFormatterConfigureOptions(ILoggerProviderConfiguration providerConfiguration) : base(providerConfiguration.Configuration.GetSection("FormatterOptions")) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj index c9f3ee93875..9f19864288f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj @@ -33,6 +33,8 @@ + + @@ -59,4 +61,4 @@ - + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.cs index 43e04c4327d..42a11a68afc 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.cs @@ -8,16 +8,23 @@ namespace Microsoft.Extensions.DependencyInjection { public static partial class OptionsBuilderConfigurationExtensions { - public static Microsoft.Extensions.Options.OptionsBuilder BindConfiguration(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, System.Action configureBinder = null) where TOptions : class { throw null; } - public static Microsoft.Extensions.Options.OptionsBuilder Bind(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class { throw null; } - public static Microsoft.Extensions.Options.OptionsBuilder Bind(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, Microsoft.Extensions.Configuration.IConfiguration config, System.Action configureBinder) where TOptions : class { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.Options.OptionsBuilder BindConfiguration<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, System.Action configureBinder = null) where TOptions : class { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.Options.OptionsBuilder Bind<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.Options.OptionsBuilder Bind<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, Microsoft.Extensions.Configuration.IConfiguration config, System.Action configureBinder) where TOptions : class { throw null; } } public static partial class OptionsConfigurationServiceCollectionExtensions { - public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.Configuration.IConfiguration config, System.Action configureBinder) where TOptions : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string name, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class { throw null; } - public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string name, Microsoft.Extensions.Configuration.IConfiguration config, System.Action configureBinder) where TOptions : class { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.Configuration.IConfiguration config, System.Action configureBinder) where TOptions : class { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string name, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] + public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string name, Microsoft.Extensions.Configuration.IConfiguration config, System.Action configureBinder) where TOptions : class { throw null; } } } namespace Microsoft.Extensions.Options @@ -29,13 +36,16 @@ public partial class ConfigurationChangeTokenSource : Microsoft.Extens public string Name { get { throw null; } } public Microsoft.Extensions.Primitives.IChangeToken GetChangeToken() { throw null; } } - public partial class ConfigureFromConfigurationOptions : Microsoft.Extensions.Options.ConfigureOptions where TOptions : class + public partial class ConfigureFromConfigurationOptions<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions> : Microsoft.Extensions.Options.ConfigureOptions where TOptions : class { + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] public ConfigureFromConfigurationOptions(Microsoft.Extensions.Configuration.IConfiguration config) : base (default(System.Action)) { } } - public partial class NamedConfigureFromConfigurationOptions : Microsoft.Extensions.Options.ConfigureNamedOptions where TOptions : class + public partial class NamedConfigureFromConfigurationOptions<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] TOptions> : Microsoft.Extensions.Options.ConfigureNamedOptions where TOptions : class { + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] public NamedConfigureFromConfigurationOptions(string name, Microsoft.Extensions.Configuration.IConfiguration config) : base (default(string), default(System.Action)) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")] public NamedConfigureFromConfigurationOptions(string name, Microsoft.Extensions.Configuration.IConfiguration config, System.Action configureBinder) : base (default(string), default(System.Action)) { } } } diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.csproj b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.csproj index b28dde039c4..85bfa45c269 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.csproj +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/ref/Microsoft.Extensions.Options.ConfigurationExtensions.csproj @@ -4,6 +4,9 @@ + + + diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ConfigureFromConfigurationOptions.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ConfigureFromConfigurationOptions.cs index ac0e09814c6..b9b3d00ee1f 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ConfigureFromConfigurationOptions.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ConfigureFromConfigurationOptions.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; namespace Microsoft.Extensions.Options { @@ -12,20 +14,26 @@ namespace Microsoft.Extensions.Options /// Configures an option instance by using against an . /// /// The type of options to bind. - public class ConfigureFromConfigurationOptions : ConfigureOptions + public class ConfigureFromConfigurationOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions> : ConfigureOptions where TOptions : class { /// /// Constructor that takes the instance to bind against. /// /// The instance. + //Even though TOptions is annotated, we need to annotate as RUC as we can't guarantee properties on referenced types are preserved. + [RequiresUnreferencedCode(OptionsBuilderConfigurationExtensions.TrimmingRequiredUnreferencedCodeMessage)] public ConfigureFromConfigurationOptions(IConfiguration config) - : base(options => ConfigurationBinder.Bind(config, options)) + : base(options => BindFromOptions(options, config)) { if (config == null) { throw new ArgumentNullException(nameof(config)); } } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The only call to this method is the constructor which is already annotated as RequiresUnreferencedCode.")] + private static void BindFromOptions(TOptions options, IConfiguration config) => ConfigurationBinder.Bind(config, options); } } diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml deleted file mode 100644 index f9ff691945b..00000000000 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - ILLink - IL2026 - member - M:Microsoft.Extensions.DependencyInjection.OptionsBuilderConfigurationExtensions.<>c__DisplayClass2_0`1.<BindConfiguration>b__0(`0,Microsoft.Extensions.Configuration.IConfiguration) - - - ILLink - IL2026 - member - M:Microsoft.Extensions.Options.ConfigureFromConfigurationOptions`1.<>c__DisplayClass0_0.<#ctor>b__0(`0) - - - ILLink - IL2026 - member - M:Microsoft.Extensions.Options.NamedConfigureFromConfigurationOptions`1.<>c__DisplayClass1_0.<#ctor>b__0(`0) - - - \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj index 822d4706702..5d30bfa93e2 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj @@ -7,6 +7,11 @@ + + + + + diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/NamedConfigureFromConfigurationOptions.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/NamedConfigureFromConfigurationOptions.cs index c86e799ccfe..df5b7e4cb92 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/NamedConfigureFromConfigurationOptions.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/NamedConfigureFromConfigurationOptions.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; namespace Microsoft.Extensions.Options { @@ -10,7 +12,7 @@ namespace Microsoft.Extensions.Options /// Configures an option instance by using against an . /// /// The type of options to bind. - public class NamedConfigureFromConfigurationOptions : ConfigureNamedOptions + public class NamedConfigureFromConfigurationOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions> : ConfigureNamedOptions where TOptions : class { /// @@ -18,6 +20,7 @@ public class NamedConfigureFromConfigurationOptions : ConfigureNamedOp /// /// The name of the options instance. /// The instance. + [RequiresUnreferencedCode(OptionsBuilderConfigurationExtensions.TrimmingRequiredUnreferencedCodeMessage)] public NamedConfigureFromConfigurationOptions(string name, IConfiguration config) : this(name, config, _ => { }) { } @@ -28,13 +31,18 @@ public NamedConfigureFromConfigurationOptions(string name, IConfiguration config /// The name of the options instance. /// The instance. /// Used to configure the . + [RequiresUnreferencedCode(OptionsBuilderConfigurationExtensions.TrimmingRequiredUnreferencedCodeMessage)] public NamedConfigureFromConfigurationOptions(string name, IConfiguration config, Action configureBinder) - : base(name, options => config.Bind(options, configureBinder)) + : base(name, options => BindFromOptions(options, config, configureBinder)) { if (config == null) { throw new ArgumentNullException(nameof(config)); } } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The only call to this method is the constructor which is already annotated as RequiresUnreferencedCode.")] + private static void BindFromOptions(TOptions options, IConfiguration config, Action configureBinder) => config.Bind(options, configureBinder); } } diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsBuilderConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsBuilderConfigurationExtensions.cs index a102c2b49da..3025442fb30 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsBuilderConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsBuilderConfigurationExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; @@ -12,6 +13,8 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class OptionsBuilderConfigurationExtensions { + internal const string TrimmingRequiredUnreferencedCodeMessage = "TOptions's dependent types may have their members trimmed. Ensure all required members are preserved."; + /// /// Registers a configuration instance which will bind against. /// @@ -19,7 +22,8 @@ public static class OptionsBuilderConfigurationExtensions /// The options builder to add the services to. /// The configuration being bound. /// The so that additional calls can be chained. - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config) where TOptions : class + [RequiresUnreferencedCode(TrimmingRequiredUnreferencedCodeMessage)] + public static OptionsBuilder Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this OptionsBuilder optionsBuilder, IConfiguration config) where TOptions : class => optionsBuilder.Bind(config, _ => { }); /// @@ -30,7 +34,8 @@ public static class OptionsBuilderConfigurationExtensions /// The configuration being bound. /// Used to configure the . /// The so that additional calls can be chained. - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config, Action configureBinder) where TOptions : class + [RequiresUnreferencedCode(TrimmingRequiredUnreferencedCodeMessage)] + public static OptionsBuilder Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this OptionsBuilder optionsBuilder, IConfiguration config, Action configureBinder) where TOptions : class { if (optionsBuilder == null) { @@ -54,7 +59,8 @@ public static class OptionsBuilderConfigurationExtensions /// or is . /// /// - public static OptionsBuilder BindConfiguration( + [RequiresUnreferencedCode(TrimmingRequiredUnreferencedCodeMessage)] + public static OptionsBuilder BindConfiguration<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>( this OptionsBuilder optionsBuilder, string configSectionPath, Action configureBinder = null) @@ -63,14 +69,18 @@ public static class OptionsBuilderConfigurationExtensions _ = optionsBuilder ?? throw new ArgumentNullException(nameof(optionsBuilder)); _ = configSectionPath ?? throw new ArgumentNullException(nameof(configSectionPath)); - optionsBuilder.Configure((opts, config) => - { - IConfiguration section = string.Equals("", configSectionPath, StringComparison.OrdinalIgnoreCase) - ? config - : config.GetSection(configSectionPath); - section.Bind(opts, configureBinder); - }); + optionsBuilder.Configure((opts, config) => BindFromOptions(opts, config, configSectionPath, configureBinder)); return optionsBuilder; } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The only call to this method is in BindConfiguration method which is already annotated as RequiresUnreferencedCode.")] + private static void BindFromOptions(TOptions opts, IConfiguration config, string configSectionPath, Action configureBinder) where TOptions : class + { + IConfiguration section = string.Equals("", configSectionPath, StringComparison.OrdinalIgnoreCase) + ? config + : config.GetSection(configSectionPath); + section.Bind(opts, configureBinder); + } } } diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsConfigurationServiceCollectionExtensions.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsConfigurationServiceCollectionExtensions.cs index 9d843cb3a52..3606ae73f9a 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsConfigurationServiceCollectionExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/OptionsConfigurationServiceCollectionExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; @@ -19,7 +20,8 @@ public static class OptionsConfigurationServiceCollectionExtensions /// The to add the services to. /// The configuration being bound. /// The so that additional calls can be chained. - public static IServiceCollection Configure(this IServiceCollection services, IConfiguration config) where TOptions : class + [RequiresUnreferencedCode(OptionsBuilderConfigurationExtensions.TrimmingRequiredUnreferencedCodeMessage)] + public static IServiceCollection Configure<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this IServiceCollection services, IConfiguration config) where TOptions : class => services.Configure(Options.Options.DefaultName, config); /// @@ -30,7 +32,8 @@ public static class OptionsConfigurationServiceCollectionExtensions /// The name of the options instance. /// The configuration being bound. /// The so that additional calls can be chained. - public static IServiceCollection Configure(this IServiceCollection services, string name, IConfiguration config) where TOptions : class + [RequiresUnreferencedCode(OptionsBuilderConfigurationExtensions.TrimmingRequiredUnreferencedCodeMessage)] + public static IServiceCollection Configure<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this IServiceCollection services, string name, IConfiguration config) where TOptions : class => services.Configure(name, config, _ => { }); /// @@ -41,7 +44,8 @@ public static class OptionsConfigurationServiceCollectionExtensions /// The configuration being bound. /// Used to configure the . /// The so that additional calls can be chained. - public static IServiceCollection Configure(this IServiceCollection services, IConfiguration config, Action configureBinder) + [RequiresUnreferencedCode(OptionsBuilderConfigurationExtensions.TrimmingRequiredUnreferencedCodeMessage)] + public static IServiceCollection Configure<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this IServiceCollection services, IConfiguration config, Action configureBinder) where TOptions : class => services.Configure(Options.Options.DefaultName, config, configureBinder); @@ -54,7 +58,8 @@ public static IServiceCollection Configure(this IServiceCollection ser /// The configuration being bound. /// Used to configure the . /// The so that additional calls can be chained. - public static IServiceCollection Configure(this IServiceCollection services, string name, IConfiguration config, Action configureBinder) + [RequiresUnreferencedCode(OptionsBuilderConfigurationExtensions.TrimmingRequiredUnreferencedCodeMessage)] + public static IServiceCollection Configure<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this IServiceCollection services, string name, IConfiguration config, Action configureBinder) where TOptions : class { if (services == null) -- GitLab