diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..233e6128 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,39 @@ +# editorconfig.org + +# top-most EditorConfig file +root = true + +## Default settings ## +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +## Formatting rule ## +# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055 +dotnet_diagnostic.IDE0055.severity = error + +# 'Using' directive preferences +dotnet_sort_system_directives_first = false + +# New line preferences +dotnet_diagnostic.IDE2002.severity = error +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +dotnet_diagnostic.IDE2004.severity = error +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false +dotnet_diagnostic.IDE2005.severity = error +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false +dotnet_diagnostic.IDE2006.severity = error +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false +dotnet_diagnostic.IDE2000.severity = error +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_diagnostic.IDE2003.severity = error +dotnet_style_allow_statement_immediately_after_block_experimental = false + +[*.csproj] +indent_size = 2 +charset = utf-8 + +[*.json] +indent_size = 2 \ No newline at end of file diff --git a/examples/BlazorServerApp/BlazorServerApp.csproj b/examples/BlazorServerApp/BlazorServerApp.csproj index eeae537e..115de563 100644 --- a/examples/BlazorServerApp/BlazorServerApp.csproj +++ b/examples/BlazorServerApp/BlazorServerApp.csproj @@ -9,4 +9,8 @@ + + True + + diff --git a/examples/BlazorServerApp/BrowserFilter.cs b/examples/BlazorServerApp/BrowserFilter.cs index 5105b8a8..376f323e 100644 --- a/examples/BlazorServerApp/BrowserFilter.cs +++ b/examples/BlazorServerApp/BrowserFilter.cs @@ -45,7 +45,7 @@ private static bool IsChromeBrowser(string userAgentContext) return false; } - return userAgentContext.Contains("chrome", StringComparison.OrdinalIgnoreCase) && + return userAgentContext.Contains("chrome", StringComparison.OrdinalIgnoreCase) && !userAgentContext.Contains("edg", StringComparison.OrdinalIgnoreCase); } diff --git a/examples/BlazorServerApp/Program.cs b/examples/BlazorServerApp/Program.cs index 4a66f68c..1dfd1c43 100644 --- a/examples/BlazorServerApp/Program.cs +++ b/examples/BlazorServerApp/Program.cs @@ -48,4 +48,4 @@ public static void Main(string[] args) app.Run(); } } -} \ No newline at end of file +} diff --git a/examples/ConsoleApp/AccountServiceContext.cs b/examples/ConsoleApp/AccountServiceContext.cs index 85114371..95f85a33 100644 --- a/examples/ConsoleApp/AccountServiceContext.cs +++ b/examples/ConsoleApp/AccountServiceContext.cs @@ -4,4 +4,4 @@ class AccountServiceContext : IAccountContext { public string AccountId { get; set; } -} \ No newline at end of file +} diff --git a/examples/ConsoleApp/ConsoleApp.csproj b/examples/ConsoleApp/ConsoleApp.csproj index fe29b948..1ef47ac8 100644 --- a/examples/ConsoleApp/ConsoleApp.csproj +++ b/examples/ConsoleApp/ConsoleApp.csproj @@ -21,4 +21,8 @@ + + True + + diff --git a/examples/ConsoleApp/Program.cs b/examples/ConsoleApp/Program.cs index 12028ca2..fb43a50e 100644 --- a/examples/ConsoleApp/Program.cs +++ b/examples/ConsoleApp/Program.cs @@ -1,4 +1,7 @@ -using Microsoft.Extensions.Configuration; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.FeatureManagement; @@ -49,4 +52,4 @@ // Output results Console.WriteLine($"The {FeatureName} feature is {(enabled ? "enabled" : "disabled")} for the '{account}' account."); } -} \ No newline at end of file +} diff --git a/examples/FeatureFlagDemo/Authentication/QueryStringAuthenticationHandler.cs b/examples/FeatureFlagDemo/Authentication/QueryStringAuthenticationHandler.cs index 0049cca3..7770ed3d 100644 --- a/examples/FeatureFlagDemo/Authentication/QueryStringAuthenticationHandler.cs +++ b/examples/FeatureFlagDemo/Authentication/QueryStringAuthenticationHandler.cs @@ -2,14 +2,10 @@ // Licensed under the MIT license. // using Microsoft.AspNetCore.Authentication; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; -using System.Collections.Generic; -using System.Linq; using System.Security.Claims; using System.Text.Encodings.Web; -using System.Threading.Tasks; namespace FeatureFlagDemo.Authentication { diff --git a/examples/FeatureFlagDemo/BrowserFilter.cs b/examples/FeatureFlagDemo/BrowserFilter.cs index efeb8e70..335e6d4c 100644 --- a/examples/FeatureFlagDemo/BrowserFilter.cs +++ b/examples/FeatureFlagDemo/BrowserFilter.cs @@ -1,12 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; using Microsoft.FeatureManagement; -using System; -using System.Linq; -using System.Threading.Tasks; namespace FeatureFlagDemo.FeatureManagement.FeatureFilters { diff --git a/examples/FeatureFlagDemo/BrowserFilterSettings.cs b/examples/FeatureFlagDemo/BrowserFilterSettings.cs index 91b8211a..c4cce8a3 100644 --- a/examples/FeatureFlagDemo/BrowserFilterSettings.cs +++ b/examples/FeatureFlagDemo/BrowserFilterSettings.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System.Collections.Generic; - namespace FeatureFlagDemo.FeatureManagement.FeatureFilters { public class BrowserFilterSettings diff --git a/examples/FeatureFlagDemo/Controllers/BetaController.cs b/examples/FeatureFlagDemo/Controllers/BetaController.cs index 9b69d9cf..4fed13f8 100644 --- a/examples/FeatureFlagDemo/Controllers/BetaController.cs +++ b/examples/FeatureFlagDemo/Controllers/BetaController.cs @@ -7,7 +7,7 @@ namespace FeatureFlagDemo.Controllers { - public class BetaController: Controller + public class BetaController : Controller { private readonly IFeatureManager _featureManager; diff --git a/examples/FeatureFlagDemo/Controllers/HomeController.cs b/examples/FeatureFlagDemo/Controllers/HomeController.cs index 6e43fba2..e7bfcd43 100644 --- a/examples/FeatureFlagDemo/Controllers/HomeController.cs +++ b/examples/FeatureFlagDemo/Controllers/HomeController.cs @@ -1,13 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System.Diagnostics; -using Microsoft.AspNetCore.Mvc; using FeatureFlagDemo.Models; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Microsoft.FeatureManagement; using Microsoft.FeatureManagement.Mvc; -using System.Threading.Tasks; +using System.Diagnostics; namespace FeatureFlagDemo.Controllers { diff --git a/examples/FeatureFlagDemo/FeatureFlagDemo.csproj b/examples/FeatureFlagDemo/FeatureFlagDemo.csproj index fcf18a50..c3955ace 100644 --- a/examples/FeatureFlagDemo/FeatureFlagDemo.csproj +++ b/examples/FeatureFlagDemo/FeatureFlagDemo.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -32,4 +32,8 @@ + + True + + diff --git a/examples/FeatureFlagDemo/Models/ErrorViewModel.cs b/examples/FeatureFlagDemo/Models/ErrorViewModel.cs index 17542f32..bd9dea6c 100644 --- a/examples/FeatureFlagDemo/Models/ErrorViewModel.cs +++ b/examples/FeatureFlagDemo/Models/ErrorViewModel.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System; - namespace FeatureFlagDemo.Models { public class ErrorViewModel @@ -11,4 +9,4 @@ public class ErrorViewModel public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); } -} \ No newline at end of file +} diff --git a/examples/FeatureFlagDemo/SuperUserFilter.cs b/examples/FeatureFlagDemo/SuperUserFilter.cs index 25dc8e5f..4174c3c1 100644 --- a/examples/FeatureFlagDemo/SuperUserFilter.cs +++ b/examples/FeatureFlagDemo/SuperUserFilter.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. // using Microsoft.FeatureManagement; -using System.Threading.Tasks; namespace FeatureFlagDemo.FeatureManagement.FeatureFilters { diff --git a/examples/FeatureFlagDemo/ThirdPartyActionFilter.cs b/examples/FeatureFlagDemo/ThirdPartyActionFilter.cs index a2d3abd1..4fb4c550 100644 --- a/examples/FeatureFlagDemo/ThirdPartyActionFilter.cs +++ b/examples/FeatureFlagDemo/ThirdPartyActionFilter.cs @@ -1,9 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Logging; namespace FeatureFlagDemo { diff --git a/examples/FeatureFlagDemo/ThirdPartyMiddleware.cs b/examples/FeatureFlagDemo/ThirdPartyMiddleware.cs index 74907908..52bdeddf 100644 --- a/examples/FeatureFlagDemo/ThirdPartyMiddleware.cs +++ b/examples/FeatureFlagDemo/ThirdPartyMiddleware.cs @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; - namespace FeatureFlagDemo { public class ThirdPartyMiddleware diff --git a/examples/FeatureFlagDemo/Views/Shared/Error.cshtml.cs b/examples/FeatureFlagDemo/Views/Shared/Error.cshtml.cs index d832e108..79b17264 100644 --- a/examples/FeatureFlagDemo/Views/Shared/Error.cshtml.cs +++ b/examples/FeatureFlagDemo/Views/Shared/Error.cshtml.cs @@ -24,4 +24,4 @@ public void OnGet() RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; } } -} \ No newline at end of file +} diff --git a/examples/RazorPages/Pages/Error.cshtml.cs b/examples/RazorPages/Pages/Error.cshtml.cs index 74050d52..149f1f23 100644 --- a/examples/RazorPages/Pages/Error.cshtml.cs +++ b/examples/RazorPages/Pages/Error.cshtml.cs @@ -24,4 +24,4 @@ public void OnGet() RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; } } -} \ No newline at end of file +} diff --git a/examples/RazorPages/Pages/Index.cshtml.cs b/examples/RazorPages/Pages/Index.cshtml.cs index 05dd8805..55bed039 100644 --- a/examples/RazorPages/Pages/Index.cshtml.cs +++ b/examples/RazorPages/Pages/Index.cshtml.cs @@ -18,4 +18,4 @@ public void OnGet() } } -} \ No newline at end of file +} diff --git a/examples/RazorPages/Pages/Privacy.cshtml.cs b/examples/RazorPages/Pages/Privacy.cshtml.cs index c1cd207f..cf5897c5 100644 --- a/examples/RazorPages/Pages/Privacy.cshtml.cs +++ b/examples/RazorPages/Pages/Privacy.cshtml.cs @@ -1,5 +1,4 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Mvc.RazorPages; namespace RazorPages.Pages { @@ -16,4 +15,4 @@ public void OnGet() { } } -} \ No newline at end of file +} diff --git a/examples/RazorPages/RazorPages.csproj b/examples/RazorPages/RazorPages.csproj index 2a2cbb46..7eab2e16 100644 --- a/examples/RazorPages/RazorPages.csproj +++ b/examples/RazorPages/RazorPages.csproj @@ -10,4 +10,8 @@ + + True + + diff --git a/examples/TargetingConsoleApp/Identity/IUserRepository.cs b/examples/TargetingConsoleApp/Identity/IUserRepository.cs index 15fedc84..ea5a99f4 100644 --- a/examples/TargetingConsoleApp/Identity/IUserRepository.cs +++ b/examples/TargetingConsoleApp/Identity/IUserRepository.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System.Threading.Tasks; - namespace TargetingConsoleApp.Identity { interface IUserRepository diff --git a/examples/TargetingConsoleApp/Identity/InMemoryUserRepository.cs b/examples/TargetingConsoleApp/Identity/InMemoryUserRepository.cs index 450c7044..1159bda0 100644 --- a/examples/TargetingConsoleApp/Identity/InMemoryUserRepository.cs +++ b/examples/TargetingConsoleApp/Identity/InMemoryUserRepository.cs @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - namespace TargetingConsoleApp.Identity { class InMemoryUserRepository : IUserRepository diff --git a/examples/TargetingConsoleApp/Identity/User.cs b/examples/TargetingConsoleApp/Identity/User.cs index be27cac1..de1f4069 100644 --- a/examples/TargetingConsoleApp/Identity/User.cs +++ b/examples/TargetingConsoleApp/Identity/User.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System.Collections.Generic; - namespace TargetingConsoleApp.Identity { class User diff --git a/examples/TargetingConsoleApp/Program.cs b/examples/TargetingConsoleApp/Program.cs index 5b89807a..d8ee6359 100644 --- a/examples/TargetingConsoleApp/Program.cs +++ b/examples/TargetingConsoleApp/Program.cs @@ -54,4 +54,4 @@ // Output results Console.WriteLine($"The {FeatureName} feature is {(enabled ? "enabled" : "disabled")} for the user '{userId}'."); } -} \ No newline at end of file +} diff --git a/examples/TargetingConsoleApp/TargetingConsoleApp.csproj b/examples/TargetingConsoleApp/TargetingConsoleApp.csproj index e1ffbd53..c699e5ab 100644 --- a/examples/TargetingConsoleApp/TargetingConsoleApp.csproj +++ b/examples/TargetingConsoleApp/TargetingConsoleApp.csproj @@ -20,4 +20,9 @@ Always + + + True + + diff --git a/src/Microsoft.FeatureManagement.AspNetCore/FeatureGateAttribute.cs b/src/Microsoft.FeatureManagement.AspNetCore/FeatureGateAttribute.cs index fb15e5b1..caf30a28 100644 --- a/src/Microsoft.FeatureManagement.AspNetCore/FeatureGateAttribute.cs +++ b/src/Microsoft.FeatureManagement.AspNetCore/FeatureGateAttribute.cs @@ -106,9 +106,9 @@ public override async Task OnActionExecutionAsync(ActionExecutingContext context // // Enabled state is determined by either 'any' or 'all' features being enabled. - bool enabled = RequirementType == RequirementType.All ? - await Features.All(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)) : - await Features.Any(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)); + bool enabled = RequirementType == RequirementType.All + ? await Features.All(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)) + : await Features.Any(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)); if (enabled) { @@ -134,9 +134,9 @@ public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext contex // // Enabled state is determined by either 'any' or 'all' features being enabled. - bool enabled = RequirementType == RequirementType.All ? - await Features.All(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)) : - await Features.Any(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)); + bool enabled = RequirementType == RequirementType.All + ? await Features.All(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)) + : await Features.Any(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)); if (enabled) { diff --git a/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj b/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj index 73ab8dfa..c35cf77b 100644 --- a/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj +++ b/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj @@ -1,4 +1,4 @@ - + @@ -44,4 +44,8 @@ + + True + + diff --git a/src/Microsoft.FeatureManagement.AspNetCore/TagHelpers/FeatureTagHelper.cs b/src/Microsoft.FeatureManagement.AspNetCore/TagHelpers/FeatureTagHelper.cs index 4a0da1e0..2fddf486 100644 --- a/src/Microsoft.FeatureManagement.AspNetCore/TagHelpers/FeatureTagHelper.cs +++ b/src/Microsoft.FeatureManagement.AspNetCore/TagHelpers/FeatureTagHelper.cs @@ -54,9 +54,9 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu { IEnumerable names = Name.Split(',').Select(n => n.Trim()); - enabled = Requirement == RequirementType.All ? - await names.All(async n => await _featureManager.IsEnabledAsync(n).ConfigureAwait(false)) : - await names.Any(async n => await _featureManager.IsEnabledAsync(n).ConfigureAwait(false)); + enabled = Requirement == RequirementType.All + ? await names.All(async n => await _featureManager.IsEnabledAsync(n).ConfigureAwait(false)) + : await names.Any(async n => await _featureManager.IsEnabledAsync(n).ConfigureAwait(false)); } if (Negate) diff --git a/src/Microsoft.FeatureManagement/AssemblyInfo.cs b/src/Microsoft.FeatureManagement/AssemblyInfo.cs index 955518ef..75bfb2fa 100644 --- a/src/Microsoft.FeatureManagement/AssemblyInfo.cs +++ b/src/Microsoft.FeatureManagement/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // using System.Runtime.CompilerServices; @@ -9,4 +9,4 @@ "3ae70fbea5662f61dd9d640de2205b7bd5359a43dda006e51d83d1f5f7a7d3f849267a0a28676d" + "cf49727a32487d4c75c4aacd5febb0069e1adc66ec63bbd18ec2276091a0e3c1326aa626c9e4db" + "800714a134f2a81e405f35752b55220021923429cb61776cd2fa66d25c335f8dc27bb92292905a" + -"3798d896")] \ No newline at end of file +"3798d896")] diff --git a/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs b/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs index ebd1c621..28af7ce6 100644 --- a/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs +++ b/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs @@ -381,9 +381,9 @@ private IEnumerable GetFeatureDefinitionSections() .FirstOrDefault(section => string.Equals( section.Key, - _microsoftFeatureManagementSchemaEnabled ? - MicrosoftFeatureManagementFields.FeatureManagementSectionName : - ConfigurationFields.FeatureManagementSectionName, + _microsoftFeatureManagementSchemaEnabled + ? MicrosoftFeatureManagementFields.FeatureManagementSectionName + : ConfigurationFields.FeatureManagementSectionName, StringComparison.OrdinalIgnoreCase)); if (featureManagementConfigurationSection == null) diff --git a/src/Microsoft.FeatureManagement/ConfigurationFields.cs b/src/Microsoft.FeatureManagement/ConfigurationFields.cs index a5472cd8..8b6ba82c 100644 --- a/src/Microsoft.FeatureManagement/ConfigurationFields.cs +++ b/src/Microsoft.FeatureManagement/ConfigurationFields.cs @@ -17,4 +17,4 @@ internal static class ConfigurationFields public const string NameKeyword = "Name"; public const string FeatureManagementSectionName = "FeatureManagement"; } -} \ No newline at end of file +} diff --git a/src/Microsoft.FeatureManagement/ConfigurationWrapper.cs b/src/Microsoft.FeatureManagement/ConfigurationWrapper.cs index 99f0b2a6..61d921f5 100644 --- a/src/Microsoft.FeatureManagement/ConfigurationWrapper.cs +++ b/src/Microsoft.FeatureManagement/ConfigurationWrapper.cs @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System; -using System.Collections.Generic; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; namespace Microsoft.FeatureManagement { @@ -27,13 +27,13 @@ public string this[string key] set => _configuration[key] = value; } - public IEnumerable GetChildren() => - _configuration.GetChildren(); + public IEnumerable GetChildren() + => _configuration.GetChildren(); - public IChangeToken GetReloadToken() => - _configuration.GetReloadToken(); + public IChangeToken GetReloadToken() + => _configuration.GetReloadToken(); - public IConfigurationSection GetSection(string key) => - _configuration.GetSection(key); + public IConfigurationSection GetSection(string key) + => _configuration.GetSection(key); } -} \ No newline at end of file +} diff --git a/src/Microsoft.FeatureManagement/FeatureFilters/ISystemClock.cs b/src/Microsoft.FeatureManagement/FeatureFilters/ISystemClock.cs index 50c6743d..1fc9b667 100644 --- a/src/Microsoft.FeatureManagement/FeatureFilters/ISystemClock.cs +++ b/src/Microsoft.FeatureManagement/FeatureFilters/ISystemClock.cs @@ -17,4 +17,4 @@ internal interface ISystemClock /// public DateTimeOffset UtcNow { get; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.FeatureManagement/FeatureFilters/Recurrence/RecurrenceEvaluator.cs b/src/Microsoft.FeatureManagement/FeatureFilters/Recurrence/RecurrenceEvaluator.cs index 4dba080a..5e8b6872 100644 --- a/src/Microsoft.FeatureManagement/FeatureFilters/Recurrence/RecurrenceEvaluator.cs +++ b/src/Microsoft.FeatureManagement/FeatureFilters/Recurrence/RecurrenceEvaluator.cs @@ -339,7 +339,6 @@ private static int CalculateWeeklyDayOffset(DayOfWeek day1, DayOfWeek day2) return ((int)day1 - (int)day2 + DaysPerWeek) % DaysPerWeek; } - /// /// Sorts a collection of days of week based on their offsets from a specified first day of week. /// A collection of days of week. diff --git a/src/Microsoft.FeatureManagement/FeatureManagementBuilder.cs b/src/Microsoft.FeatureManagement/FeatureManagementBuilder.cs index 2b2af56c..ab07a595 100644 --- a/src/Microsoft.FeatureManagement/FeatureManagementBuilder.cs +++ b/src/Microsoft.FeatureManagement/FeatureManagementBuilder.cs @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // +using Microsoft.Extensions.DependencyInjection; +using Microsoft.FeatureManagement.FeatureFilters; using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.FeatureManagement.FeatureFilters; namespace Microsoft.FeatureManagement { @@ -35,7 +35,7 @@ public IFeatureManagementBuilder AddFeatureFilter() where T : IFeatureFilterM } IEnumerable featureFilterImplementations = implementationType.GetInterfaces() - .Where(i => i == typeof(IFeatureFilter) || + .Where(i => i == typeof(IFeatureFilter) || (i.IsGenericType && i.GetGenericTypeDefinition().IsAssignableFrom(typeof(IContextualFeatureFilter<>)))); if (featureFilterImplementations.Count() > 1) diff --git a/src/Microsoft.FeatureManagement/FeatureManager.cs b/src/Microsoft.FeatureManagement/FeatureManager.cs index 9080929d..ec7ae990 100644 --- a/src/Microsoft.FeatureManagement/FeatureManager.cs +++ b/src/Microsoft.FeatureManagement/FeatureManager.cs @@ -144,7 +144,7 @@ private async Task IsEnabledAsync(string feature, TContext appCo if (featureDefinition.RequirementType == RequirementType.All && _options.IgnoreMissingFeatureFilters) { throw new FeatureManagementException( - FeatureManagementError.Conflict, + FeatureManagementError.Conflict, $"The 'IgnoreMissingFeatureFilters' flag cannot use used in combination with a feature of requirement type 'All'."); } @@ -183,7 +183,7 @@ private async Task IsEnabledAsync(string feature, TContext appCo enabled = true; break; } - + continue; } @@ -268,7 +268,7 @@ await contextualFilter.EvaluateAsync(context, appContext).ConfigureAwait(false) { throw new FeatureManagementException(FeatureManagementError.MissingFeature, errorMessage); } - + Logger?.LogDebug(errorMessage); } @@ -335,7 +335,8 @@ private IFeatureFilterMetadata GetFeatureFilterMetadata(string filterName, Type { IFeatureFilterMetadata filter = _filterMetadataCache.GetOrAdd( $"{filterName}{Environment.NewLine}{appContextType?.FullName}", - (_) => { + (_) => + { IEnumerable matchingFilters = _featureFilters.Where(f => { @@ -413,7 +414,8 @@ private ContextualFeatureFilterEvaluator GetContextualFeatureFilter(string filte ContextualFeatureFilterEvaluator filter = _contextualFeatureFilterCache.GetOrAdd( $"{filterName}{Environment.NewLine}{appContextType.FullName}", - (_) => { + (_) => + { IFeatureFilterMetadata metadata = GetFeatureFilterMetadata(filterName, appContextType); diff --git a/src/Microsoft.FeatureManagement/IFilterParametersBinder.cs b/src/Microsoft.FeatureManagement/IFilterParametersBinder.cs index bd572e71..fe889893 100644 --- a/src/Microsoft.FeatureManagement/IFilterParametersBinder.cs +++ b/src/Microsoft.FeatureManagement/IFilterParametersBinder.cs @@ -18,4 +18,4 @@ public interface IFilterParametersBinder /// A settings object that is understood by the implementer of . object BindParameters(IConfiguration parameters); } -} \ No newline at end of file +} diff --git a/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj b/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj index 39cdd2e6..954d6361 100644 --- a/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj +++ b/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj @@ -1,4 +1,4 @@ - + @@ -52,4 +52,8 @@ + + True + + diff --git a/src/Microsoft.FeatureManagement/MicrosoftFeatureManagementFields.cs b/src/Microsoft.FeatureManagement/MicrosoftFeatureManagementFields.cs index 50351526..20b576b3 100644 --- a/src/Microsoft.FeatureManagement/MicrosoftFeatureManagementFields.cs +++ b/src/Microsoft.FeatureManagement/MicrosoftFeatureManagementFields.cs @@ -24,4 +24,4 @@ internal static class MicrosoftFeatureManagementFields public const string Name = "name"; public const string Parameters = "parameters"; } -} \ No newline at end of file +} diff --git a/src/Microsoft.FeatureManagement/ServiceCollectionExtensions.cs b/src/Microsoft.FeatureManagement/ServiceCollectionExtensions.cs index b0a9bdd6..50a6ba7f 100644 --- a/src/Microsoft.FeatureManagement/ServiceCollectionExtensions.cs +++ b/src/Microsoft.FeatureManagement/ServiceCollectionExtensions.cs @@ -42,21 +42,21 @@ public static IFeatureManagementBuilder AddFeatureManagement(this IServiceCollec // Add required services services.TryAddSingleton(); - services.AddSingleton(sp => + services.AddSingleton(sp => new FeatureManager( sp.GetRequiredService(), sp.GetRequiredService>().Value) - { - FeatureFilters = sp.GetRequiredService>(), - SessionManagers = sp.GetRequiredService>(), - Cache = sp.GetRequiredService(), - Logger = sp.GetRequiredService().CreateLogger() - }); + { + FeatureFilters = sp.GetRequiredService>(), + SessionManagers = sp.GetRequiredService>(), + Cache = sp.GetRequiredService(), + Logger = sp.GetRequiredService().CreateLogger() + }); services.AddScoped(); var builder = new FeatureManagementBuilder(services); - + // // Add built-in feature filters builder.AddFeatureFilter(); @@ -119,16 +119,16 @@ public static IFeatureManagementBuilder AddScopedFeatureManagement(this IService // Add required services services.TryAddSingleton(); - services.AddScoped(sp => + services.AddScoped(sp => new FeatureManager( sp.GetRequiredService(), sp.GetRequiredService>().Value) - { - FeatureFilters = sp.GetRequiredService>(), - SessionManagers = sp.GetRequiredService>(), - Cache = sp.GetRequiredService(), - Logger = sp.GetRequiredService().CreateLogger() - }); + { + FeatureFilters = sp.GetRequiredService>(), + SessionManagers = sp.GetRequiredService>(), + Cache = sp.GetRequiredService(), + Logger = sp.GetRequiredService().CreateLogger() + }); services.AddScoped(); @@ -138,7 +138,7 @@ public static IFeatureManagementBuilder AddScopedFeatureManagement(this IService // Add built-in feature filters builder.AddFeatureFilter(); - builder.AddFeatureFilter(sp => + builder.AddFeatureFilter(sp => new TimeWindowFilter() { Cache = sp.GetRequiredService() diff --git a/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs b/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs index b4b43bde..e2c3d5e4 100644 --- a/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs +++ b/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs @@ -132,7 +132,6 @@ public Task EvaluateAsync(FeatureFilterEvaluationContext context, ITargeti return Task.FromResult(IsTargeted(defaultContextId, settings.Audience.DefaultRolloutPercentage)); } - /// /// Determines if a given context id should be targeted based off the provided percentage /// diff --git a/tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs b/tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs index 3e5d6aa0..19e29dab 100644 --- a/tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs +++ b/tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs @@ -9,7 +9,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.FeatureManagement; -using System; using System.Collections.Generic; using System.Linq; using System.Net; diff --git a/tests/Tests.FeatureManagement.AspNetCore/MvcFilter.cs b/tests/Tests.FeatureManagement.AspNetCore/MvcFilter.cs index 0635a289..cbf617d5 100644 --- a/tests/Tests.FeatureManagement.AspNetCore/MvcFilter.cs +++ b/tests/Tests.FeatureManagement.AspNetCore/MvcFilter.cs @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Filters; +using System.Threading.Tasks; namespace Tests.FeatureManagement.AspNetCore { diff --git a/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj b/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj index b14bbfdb..33f4704a 100644 --- a/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj +++ b/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj @@ -1,4 +1,4 @@ - + net6.0;net7.0;net8.0 @@ -47,4 +47,8 @@ + + True + + diff --git a/tests/Tests.FeatureManagement/CustomTargetingFilter.cs b/tests/Tests.FeatureManagement/CustomTargetingFilter.cs index cc89482f..a0bdbace 100644 --- a/tests/Tests.FeatureManagement/CustomTargetingFilter.cs +++ b/tests/Tests.FeatureManagement/CustomTargetingFilter.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.FeatureManagement; @@ -26,7 +25,7 @@ public CustomTargetingFilter(IOptions options, ILogg public Task EvaluateAsync(FeatureFilterEvaluationContext context) { - return _contextualFilter.EvaluateAsync(context, new TargetingContext(){ UserId = "Jeff" }); + return _contextualFilter.EvaluateAsync(context, new TargetingContext() { UserId = "Jeff" }); } } } diff --git a/tests/Tests.FeatureManagement/FeatureManagement.cs b/tests/Tests.FeatureManagement/FeatureManagement.cs index 964f8dd4..ce337200 100644 --- a/tests/Tests.FeatureManagement/FeatureManagement.cs +++ b/tests/Tests.FeatureManagement/FeatureManagement.cs @@ -106,7 +106,6 @@ public async Task ReadsTopLevelConfiguration() Assert.True(await featureManager.IsEnabledAsync(feature)); } - [Fact] public void AddsScopedFeatureManagement() { @@ -175,7 +174,7 @@ public async Task AllowsDuplicatedFilterAlias() var appContext = new AppContext(); var dummyContext = new DummyContext(); - + var targetingContext = new TargetingContext(); Assert.True(await featureManager.IsEnabledAsync(featureName)); @@ -271,7 +270,7 @@ public async Task CustomFilterContextualTargetingWithNullSetting() IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); ServiceCollection services = new ServiceCollection(); - + var targetingContextAccessor = new OnDemandTargetingContextAccessor(); services.AddSingleton(targetingContextAccessor); @@ -343,7 +342,7 @@ public async Task TimeWindow() Assert.False(await featureManager.IsEnabledAsync(feature4)); Assert.True(await featureManager.IsEnabledAsync(feature5)); Assert.False(await featureManager.IsEnabledAsync(feature6)); - + for (int i = 0; i < 10; i++) { Assert.True(await featureManager.IsEnabledAsync(Features.RecurringTimeWindowTestFeature)); @@ -882,7 +881,6 @@ public async Task UsesRequirementType() // Set filters to all return true testFeatureFilter.Callback = _ => Task.FromResult(true); - Assert.True(await featureManager.IsEnabledAsync(anyFilterFeature)); Assert.True(await featureManager.IsEnabledAsync(allFilterFeature)); diff --git a/tests/Tests.FeatureManagement/RecurrenceEvaluation.cs b/tests/Tests.FeatureManagement/RecurrenceEvaluation.cs index 50c6e449..184f3612 100644 --- a/tests/Tests.FeatureManagement/RecurrenceEvaluation.cs +++ b/tests/Tests.FeatureManagement/RecurrenceEvaluation.cs @@ -594,7 +594,7 @@ public void MatchDailyRecurrenceTest() Range = new RecurrenceRange() } }, - false ), + false ) }; ConsumeEvaluationTestData(testData); @@ -1671,7 +1671,7 @@ public async void RecurrenceEvaluationThroughCacheTest() mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-7T00:00:00+08:00"); Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context)); - for (int i = 0; i < 10; i++ ) + for (int i = 0; i < 10; i++) { mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddDays(1); Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context)); diff --git a/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj b/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj index ebf99ad6..fbde38d2 100644 --- a/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj +++ b/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj @@ -1,4 +1,4 @@ - + net48;net6.0;net7.0;net8.0 @@ -51,4 +51,8 @@ + + True + +