Skip to content

Enable build time warnings for IDE code analysis rules #34215

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

Merged
merged 2 commits into from
Jul 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ dotnet_diagnostic.CA2208.severity = warning
dotnet_diagnostic.IDE0035.severity = warning

# IDE0036: Order modifiers
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on https://github.com/dotnet/runtime/blob/main/.editorconfig#L42 (also what the analyzer defaults to)

dotnet_diagnostic.IDE0036.severity = warning

# IDE0043: Format string contains invalid placeholder
Expand All @@ -204,7 +205,7 @@ dotnet_diagnostic.IDE0043.severity = warning
dotnet_diagnostic.IDE0044.severity = warning

# IDE0073: File header
dotnet_diagnostic.IDE0073.severity = warning
dotnet_diagnostic.IDE0073.severity = suggestion
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This trips on files from the runtime repo (that have an MIT license) as well as some other code that's copied from that repo. Skipping for now since it seems low value for now.

file_header_template = Copyright (c) .NET Foundation. All rights reserved.\nLicensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

[**/{test,samples,perf}/**.{cs,vb}]
Expand Down
3 changes: 3 additions & 0 deletions eng/targets/CSharp.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
'$(ISBenchmarkProject)' == 'true' OR
'$(IsSampleProject)' == 'true' OR
'$(IsMicrobenchmarksProject)' == 'true'">$(NoWarn);CA1416</NoWarn>

<!-- Enable .NET code style analysis during build for src projects. -->
<EnforceCodeStyleInBuild Condition="'$(EnforceCodeStyleInBuild)' == ''">true</EnforceCodeStyleInBuild>
Copy link
Contributor Author

@pranavkm pranavkm Jul 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BrennanConroy this enables these rules to run on the CLI.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes them when it finds them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, just makes it appear as errors. I used VS to apply the code fix. But presumably once we go thru a few passes of enabling and fixing warnings for individual rules, it's not going to be a big issue. Building in the IDE and on the CLI should produce these errors and they would be localized to new code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used VS to apply the code fix.

How long did this take you? Did you have to go project by project?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried applying it on the sln file but the fixes wouldn't stick. I was however able to get pretty much all of it covered by opening the MVC and Middleware slnfs, and having it load all transitive dependencies. There were a few strays that the build would catch, but not many.

I'm sure there's a better way to go about it, but it's not super painful.

</PropertyGroup>

<ItemGroup Condition=" '$(DotNetBuildFromSource)' != 'true' AND $(AddPublicApiAnalyzers) ">
Expand Down
2 changes: 1 addition & 1 deletion src/Analyzers/Analyzers/src/StartupAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Analyzers
{
internal class StartupAnalysis
{
private ImmutableDictionary<INamedTypeSymbol, ImmutableArray<object>> _analysesByType;
private readonly ImmutableDictionary<INamedTypeSymbol, ImmutableArray<object>> _analysesByType;

public StartupAnalysis(
StartupSymbols startupSymbols,
Expand Down
6 changes: 3 additions & 3 deletions src/Analyzers/Analyzers/src/StartupAnalyzer.Diagnostics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static Diagnostics()
});
}

internal readonly static DiagnosticDescriptor BuildServiceProviderShouldNotCalledInConfigureServicesMethod = new DiagnosticDescriptor(
internal static readonly DiagnosticDescriptor BuildServiceProviderShouldNotCalledInConfigureServicesMethod = new DiagnosticDescriptor(
"ASP0000",
"Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices'",
"Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'.",
Expand All @@ -36,7 +36,7 @@ static Diagnostics()
isEnabledByDefault: true,
helpLinkUri: "https://aka.ms/AA5k895");

internal readonly static DiagnosticDescriptor UnsupportedUseMvcWithEndpointRouting = new DiagnosticDescriptor(
internal static readonly DiagnosticDescriptor UnsupportedUseMvcWithEndpointRouting = new DiagnosticDescriptor(
"MVC1005",
"Cannot use UseMvc with Endpoint Routing.",
"Using '{0}' to configure MVC is not supported while using Endpoint Routing. To continue using '{0}', please set 'MvcOptions.EnableEndpointRouting = false' inside '{1}'.",
Expand All @@ -45,7 +45,7 @@ static Diagnostics()
isEnabledByDefault: true,
helpLinkUri: "https://aka.ms/YJggeFn");

internal readonly static DiagnosticDescriptor IncorrectlyConfiguredAuthorizationMiddleware = new DiagnosticDescriptor(
internal static readonly DiagnosticDescriptor IncorrectlyConfiguredAuthorizationMiddleware = new DiagnosticDescriptor(
"ASP0001",
"Authorization middleware is incorrectly configured.",
"The call to UseAuthorization should appear between app.UseRouting() and app.UseEndpoints(..) for authorization to be correctly evaluated.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI
[Obsolete("This is obsolete and will be removed in a future version. Use Microsoft.Identity.Web instead. See https://aka.ms/ms-identity-web.")]
internal class AzureADB2COpenIDConnectEventHandlers
{
private IDictionary<string, string> _policyToIssuerAddress =
private readonly IDictionary<string, string> _policyToIssuerAddress =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

public AzureADB2COpenIDConnectEventHandlers(string schemeName, AzureADB2COptions options)
Expand Down
4 changes: 2 additions & 2 deletions src/Caching/SqlServer/src/PlatformHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Caching.SqlServer
{
internal static class PlatformHelper
{
private static Lazy<bool> _isMono = new Lazy<bool>(() => Type.GetType("Mono.Runtime") != null);
private static readonly Lazy<bool> _isMono = new Lazy<bool>(() => Type.GetType("Mono.Runtime") != null);

public static bool IsMono
{
Expand All @@ -17,4 +17,4 @@ public static bool IsMono
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInt
{
/*MMBaseClass*/class UsesRendererTypesInDeclarations : Renderer
{
private Renderer /*MMField*/_field = null;
private readonly Renderer /*MMField*/_field = null;

public UsesRendererTypesInDeclarations()
/*MMInvocation*/: base(null, null)
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Components/src/CascadingParameterState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Components
{
internal readonly struct CascadingParameterState
{
private readonly static ConcurrentDictionary<Type, ReflectedCascadingParameterInfo[]> _cachedInfos = new();
private static readonly ConcurrentDictionary<Type, ReflectedCascadingParameterInfo[]> _cachedInfos = new();

public string LocalValueName { get; }
public ICascadingValueComponent ValueSupplier { get; }
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Components/src/DynamicComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Components
public class DynamicComponent : IComponent
{
private RenderHandle _renderHandle;
private RenderFragment _cachedRenderFragment;
private readonly RenderFragment _cachedRenderFragment;

/// <summary>
/// Constructs an instance of <see cref="DynamicComponent"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Components.Lifetime
public class ComponentApplicationLifetime
{
private bool _stateIsPersisted;
private List<ComponentApplicationState.OnPersistingCallback> _pauseCallbacks = new();
private readonly List<ComponentApplicationState.OnPersistingCallback> _pauseCallbacks = new();
private readonly Dictionary<string, byte[]> _currentState = new();
private readonly ILogger<ComponentApplicationLifetime> _logger;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
internal static class EventArgsTypeCache
{
private static ConcurrentDictionary<MethodInfo, Type> Cache = new ConcurrentDictionary<MethodInfo, Type>();
private static readonly ConcurrentDictionary<MethodInfo, Type> Cache = new ConcurrentDictionary<MethodInfo, Type>();

public static Type GetEventArgsType(MethodInfo methodInfo)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary>
public sealed class RenderTreeBuilder : IDisposable
{
private readonly static object BoxedTrue = true;
private readonly static object BoxedFalse = false;
private readonly static string ComponentReferenceCaptureInvalidParentMessage = $"Component reference captures may only be added as children of frames of type {RenderTreeFrameType.Component}";
private static readonly object BoxedTrue = true;
private static readonly object BoxedFalse = false;
private static readonly string ComponentReferenceCaptureInvalidParentMessage = $"Component reference captures may only be added as children of frames of type {RenderTreeFrameType.Component}";

private readonly RenderTreeFrameArrayBuilder _entries = new RenderTreeFrameArrayBuilder();
private readonly Stack<int> _openElementIndices = new Stack<int>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary>
internal class SimplifiedStringHashComparer : IEqualityComparer<string>
{
public readonly static SimplifiedStringHashComparer Instance = new SimplifiedStringHashComparer();
public static readonly SimplifiedStringHashComparer Instance = new SimplifiedStringHashComparer();

public bool Equals(string? x, string? y)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public TestRenderer() : base(new ServiceCollection().BuildServiceProvider(), Nul
{
}

private Dispatcher _dispatcher = Dispatcher.CreateDefault();
private readonly Dispatcher _dispatcher = Dispatcher.CreateDefault();

public override Dispatcher Dispatcher => _dispatcher;

Expand Down
4 changes: 2 additions & 2 deletions src/Components/Components/test/RendererTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4443,7 +4443,7 @@ protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
private class TestComponent : IComponent, IDisposable
{
private RenderHandle _renderHandle;
private RenderFragment _renderFragment;
private readonly RenderFragment _renderFragment;

public TestComponent(RenderFragment renderFragment)
{
Expand Down Expand Up @@ -5211,7 +5211,7 @@ public Task SetParametersAsync(ParameterView parameters)

private class TestErrorBoundary : AutoRenderComponent, IErrorBoundary
{
private TaskCompletionSource receivedErrorTaskCompletionSource = new();
private readonly TaskCompletionSource receivedErrorTaskCompletionSource = new();

public Exception ReceivedException { get; private set; }
public Task ReceivedErrorTask => receivedErrorTaskCompletionSource.Task;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1013,8 +1013,8 @@ public void SuppliesNullForUnusedHandlerParameters()

private class TestRouteTableBuilder
{
IList<(string Template, Type Handler)> _routeTemplates = new List<(string, Type)>();
Type _handler = typeof(object);
readonly IList<(string Template, Type Handler)> _routeTemplates = new List<(string, Type)>();
readonly Type _handler = typeof(object);

public TestRouteTableBuilder AddRoute(string template, Type handler = null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class ValidationStateChangedEventArgs : EventArgs
/// <summary>
/// Gets a shared empty instance of <see cref="ValidationStateChangedEventArgs"/>.
/// </summary>
public new static readonly ValidationStateChangedEventArgs Empty = new ValidationStateChangedEventArgs();
public static new readonly ValidationStateChangedEventArgs Empty = new ValidationStateChangedEventArgs();

/// <summary>
/// Creates a new instance of <see cref="ValidationStateChangedEventArgs" />
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Ignitor/src/NodeSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ private class Serializer
private readonly TextWriter _writer;
private int _depth;
private bool _atStartOfLine;
private HashSet<Node> _visited = new HashSet<Node>();
private readonly HashSet<Node> _visited = new HashSet<Node>();

public Serializer(TextWriter writer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ public async Task RenderComponentAsync<TComponent>(ParameterView initialParamete
private class TestComponent : IComponent, IHandleAfterRender
{
private RenderHandle _renderHandle;
private RenderFragment _renderFragment = (builder) =>
private readonly RenderFragment _renderFragment = (builder) =>
{
builder.OpenElement(0, "my element");
builder.AddContent(1, "some text");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Components.Server
{
public class RenderBatchWriterTest
{
static object NullStringMarker = new object();
static readonly object NullStringMarker = new object();

[Fact]
public void CanSerializeEmptyRenderBatch()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary>
public static class EditContextFieldClassExtensions
{
private readonly static object FieldCssClassProviderKey = new object();
private static readonly object FieldCssClassProviderKey = new object();

/// <summary>
/// Gets a string that indicates the status of the specified field as a CSS class. This will include
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Web/src/Forms/FieldCssClassProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary>
public class FieldCssClassProvider
{
internal readonly static FieldCssClassProvider Instance = new FieldCssClassProvider();
internal static readonly FieldCssClassProvider Instance = new FieldCssClassProvider();

/// <summary>
/// Gets a string that indicates the status of the specified field as a CSS class.
Expand Down
4 changes: 2 additions & 2 deletions src/Components/WebAssembly/Server/src/TargetPickerUi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class TargetPickerUi
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

private string _browserHost;
private string _debugProxyUrl;
private readonly string _browserHost;
private readonly string _debugProxyUrl;

/// <summary>
/// Initialize a new instance of <see cref="TargetPickerUi"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ public TestRemoteAuthenticationService(
public Func<RemoteAuthenticationContext<RemoteAuthenticationState>, Task<RemoteAuthenticationResult<RemoteAuthenticationState>>> CompleteSignOutCallback { get; set; }
public Func<ValueTask<ClaimsPrincipal>> GetAuthenticatedUserCallback { get; set; }

public async override Task<AuthenticationState> GetAuthenticationStateAsync() => new AuthenticationState(await GetAuthenticatedUserCallback());
public override async Task<AuthenticationState> GetAuthenticationStateAsync() => new AuthenticationState(await GetAuthenticatedUserCallback());

public override Task<RemoteAuthenticationResult<RemoteAuthenticationState>> CompleteSignInAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context) => CompleteSignInCallback(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.HotReload
public static class WebAssemblyHotReload
{
private static HotReloadAgent? _hotReloadAgent;
private static UpdateDelta[] _updateDeltas = new[]
private static readonly UpdateDelta[] _updateDeltas = new[]
{
new UpdateDelta(),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace HostedInAspNet.Server
{
public class BootResourceRequestLog
{
private ConcurrentBag<string> _requestPaths = new ConcurrentBag<string>();
private readonly ConcurrentBag<string> _requestPaths = new ConcurrentBag<string>();

public IReadOnlyCollection<string> RequestPaths => _requestPaths;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public PreferencesUserFactory(NavigationManager navigationManager, IAccessTokenP
_httpClient = new HttpClient { BaseAddress = new Uri(navigationManager.BaseUri) };
}

public async override ValueTask<ClaimsPrincipal> CreateUserAsync(
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
OidcAccount account,
RemoteAuthenticationUserOptions options)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ internal class PhotinoWebViewManager : WebViewManager
// because webview2 won't let you do top-level navigation to such a URL.
// On Linux/Mac, we must use a custom scheme, because their webviews
// don't have a way to intercept http:// scheme requests.
internal readonly static string BlazorAppScheme = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
internal static readonly string BlazorAppScheme = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? "http"
: "app";

internal readonly static string AppBaseUri
internal static readonly string AppBaseUri
= $"{BlazorAppScheme}://0.0.0.0/";

public PhotinoWebViewManager(PhotinoWindow window, IServiceProvider provider, Dispatcher dispatcher, Uri appBaseUri, IFileProvider fileProvider, string hostPageRelativePath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal class StaticContentProvider
private readonly Uri _appBaseUri;
private readonly string _hostPageRelativePath;
private static readonly FileExtensionContentTypeProvider ContentTypeProvider = new();
private static ManifestEmbeddedFileProvider _manifestProvider =
private static readonly ManifestEmbeddedFileProvider _manifestProvider =
new ManifestEmbeddedFileProvider(typeof(StaticContentProvider).Assembly);

public StaticContentProvider(IFileProvider fileProvider, Uri appBaseUri, string hostPageRelativePath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Microsoft.AspNetCore.Components.WebView
{
public class TestWebViewManager : WebViewManager
{
private static Uri AppBaseUri = new Uri("app://testhost/");
private List<string> _sentIpcMessages = new();
private static readonly Uri AppBaseUri = new Uri("app://testhost/");
private readonly List<string> _sentIpcMessages = new();

public TestWebViewManager(IServiceProvider provider, IFileProvider fileProvider)
: base(provider, Dispatcher.CreateDefault(), AppBaseUri, fileProvider, hostPageRelativePath: "index.html")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ namespace Wasm.Performance.Driver
class Selenium
{
const int SeleniumPort = 4444;
static bool RunHeadlessBrowser = true;
const bool RunHeadlessBrowser = true;

static bool PoolForBrowserLogs = true;
const bool PoolForBrowserLogs = true;

private static async ValueTask<Uri> WaitForServerAsync(int port, CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected virtual Task InitializeAsync()
return Task.CompletedTask;
}

protected async virtual Task DisposeAsync()
protected virtual async Task DisposeAsync()
{
if (TestSink != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public InteropReliabilityTests(BasicTestAppServerSiteFixture<ServerStartup> serv
{
}

protected async override Task InitializeAsync()
protected override async Task InitializeAsync()
{
var rootUri = ServerFixture.RootUri;
await ConnectAutomaticallyAndWait(new Uri(rootUri, "/subdir"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class PlaywrightTestBase : LoggedTest, IAsyncLifetime

public PlaywrightTestBase(ITestOutputHelper output) : base(output) { }

protected async override Task InitializeCoreAsync(TestContext context)
protected override async Task InitializeCoreAsync(TestContext context)
{
BrowserManager = await BrowserManager.CreateAsync(CreateConfiguration(), LoggerFactory);
BrowserContextInfo = new ContextInformation(LoggerFactory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ namespace BasicTestApp
internal class PrependMessageLoggerProvider : ILoggerProvider
{
ILogger _logger;
string _message;
ILogger _defaultLogger;
readonly string _message;
readonly ILogger _defaultLogger;
private bool _disposed = false;

public PrependMessageLoggerProvider(string message, IJSRuntime runtime)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class UserController : Controller
// to the client. It's up to the developer to choose what kind of authentication state
// data is needed on the client so it can display suitable options in the UI.
// In this class, we inform the client only about certain roles and certain other claims.
static string[] ExposedRoles = new[] { "IrrelevantRole", "TestRole" };
static readonly string[] ExposedRoles = new[] { "IrrelevantRole", "TestRole" };

// GET api/user
[HttpGet]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace TestServer
{
public class ResourceRequestLog
{
private List<string> _requestPaths = new List<string>();
private readonly List<string> _requestPaths = new List<string>();

public IReadOnlyCollection<string> RequestPaths => _requestPaths;

Expand Down
Loading