Skip to content

Commit

Permalink
Use C# 12 features
Browse files Browse the repository at this point in the history
- Use primary constructors where relevant.
- Use collection literals where relevant.
- Remove redundant analysis suppressions.
- Apply some IDE suggestions.
  • Loading branch information
martincostello committed Sep 30, 2023
1 parent 6cb7a08 commit ff95327
Show file tree
Hide file tree
Showing 14 changed files with 34 additions and 58 deletions.
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
<NeutralLanguage>en-US</NeutralLanguage>
<NoWarn>$(NoWarn);CA1054;CA2234</NoWarn>
<NoWarn Condition=" '$(GenerateDocumentationFile)' != 'true' ">$(NoWarn);SA0001</NoWarn>
<!-- HACK Workaround for https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3687 -->
<NoWarn>$(NoWarn);SA1010</NoWarn>
<PackageIcon>package-icon.png</PackageIcon>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/justeattakeaway/httpclient-interception</PackageProjectUrl>
Expand Down
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,8 @@ A working example of this approach can be found in the [sample application](http
/// A class that registers an intercepting HTTP message handler at the end of
/// the message handler pipeline when an <see cref="HttpClient"/> is created.
/// </summary>
public sealed class HttpClientInterceptionFilter : IHttpMessageHandlerBuilderFilter
public sealed class HttpClientInterceptionFilter(HttpClientInterceptorOptions options) : IHttpMessageHandlerBuilderFilter
{
private readonly HttpClientInterceptorOptions _options;

public HttpClientInterceptionFilter(HttpClientInterceptorOptions options)
{
_options = options;
}

/// <inheritdoc/>
public Action<HttpMessageHandlerBuilder> Configure(Action<HttpMessageHandlerBuilder> next)
{
Expand All @@ -177,12 +170,12 @@ public sealed class HttpClientInterceptionFilter : IHttpMessageHandlerBuilderFil
next(builder);

// Add the interceptor as the last message handler
builder.AdditionalHandlers.Add(_options.CreateHttpMessageHandler());
builder.AdditionalHandlers.Add(options.CreateHttpMessageHandler());
};
}
}
```
<sup><a href='/samples/SampleApp.Tests/HttpClientInterceptionFilter.cs#L9-L38' title='Snippet source file'>snippet source</a> | <a href='#snippet-interception-filter' title='Start of snippet'>anchor</a></sup>
<sup><a href='/samples/SampleApp.Tests/HttpClientInterceptionFilter.cs#L9-L31' title='Snippet source file'>snippet source</a> | <a href='#snippet-interception-filter' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

#### Setting Up HttpClient for Dependency Injection Manually
Expand Down
11 changes: 2 additions & 9 deletions samples/SampleApp.Tests/HttpClientInterceptionFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,8 @@ namespace SampleApp.Tests;
/// A class that registers an intercepting HTTP message handler at the end of
/// the message handler pipeline when an <see cref="HttpClient"/> is created.
/// </summary>
public sealed class HttpClientInterceptionFilter : IHttpMessageHandlerBuilderFilter
public sealed class HttpClientInterceptionFilter(HttpClientInterceptorOptions options) : IHttpMessageHandlerBuilderFilter
{
private readonly HttpClientInterceptorOptions _options;

public HttpClientInterceptionFilter(HttpClientInterceptorOptions options)
{
_options = options;
}

/// <inheritdoc/>
public Action<HttpMessageHandlerBuilder> Configure(Action<HttpMessageHandlerBuilder> next)
{
Expand All @@ -30,7 +23,7 @@ public Action<HttpMessageHandlerBuilder> Configure(Action<HttpMessageHandlerBuil
next(builder);

// Add the interceptor as the last message handler
builder.AdditionalHandlers.Add(_options.CreateHttpMessageHandler());
builder.AdditionalHandlers.Add(options.CreateHttpMessageHandler());
};
}
}
Expand Down
10 changes: 5 additions & 5 deletions samples/SampleApp.Tests/ReposTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ public async Task Can_Get_Organization_Repositories()
{
// Add a callback to log any HTTP requests made
Fixture.Interceptor.OnSend = (request) =>
{
OutputHelper.WriteLine($"HTTP {request.Method} {request.RequestUri}");
return Task.CompletedTask;
};
{
OutputHelper.WriteLine($"HTTP {request.Method} {request.RequestUri}");
return Task.CompletedTask;
};

// Arrange - use a scope to clean-up registrations
using (Fixture.Interceptor.BeginScope())
Expand Down Expand Up @@ -59,7 +59,7 @@ public async Task Can_Get_Organization_Repositories()
}

// Assert - Our application should have parsed the stub-names
actual.ShouldBe(new[] { "bar", "foo" });
actual.ShouldBe(["bar", "foo"]);
}
}

Expand Down
2 changes: 2 additions & 0 deletions samples/SampleApp/Extensions/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public static class HttpClientExtensions
{
public static IHttpClientBuilder AddHttpClients(this IServiceCollection services)
{
services.ConfigureHttpJsonOptions((options) => options.SerializerOptions.WriteIndented = true);

// Register a Refit-based typed client for use in the controller, which
// configures the HttpClient with the appropriate base URL and HTTP request
// headers. It also adds two custom delegating handlers.
Expand Down
7 changes: 2 additions & 5 deletions samples/SampleApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Copyright (c) Just Eat, 2017. All rights reserved.
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.

#pragma warning disable CA1852

using System.Text.Json;
using SampleApp.Extensions;
using SampleApp.Services;

Expand All @@ -21,7 +18,7 @@
ICollection<Repository> repositories = await github.GetRepositoriesAsync(organization, count ?? 100);

// Return the repositories' names
var names = new List<string>();
List<string> names = [];

foreach (var repository in repositories)
{
Expand All @@ -30,7 +27,7 @@

names.Sort();

return Results.Json(names, new JsonSerializerOptions() { WriteIndented = true });
return Results.Json(names);
});

app.Run();
4 changes: 2 additions & 2 deletions src/HttpClientInterception/HttpClientInterceptorOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ private static async Task<HttpResponseMessage> BuildResponseAsync(HttpRequestMes
}
else
{
byte[] content = await response.ContentFactory!().ConfigureAwait(false) ?? Array.Empty<byte>();
byte[] content = await response.ContentFactory!().ConfigureAwait(false) ?? [];
result.Content = new ByteArrayContent(content);
}

Expand Down Expand Up @@ -542,7 +542,7 @@ private sealed class OptionsScope : IDisposable
{
private readonly HttpClientInterceptorOptions _parent;
private readonly IDictionary<string, HttpInterceptionResponse> _old;
private readonly IDictionary<string, HttpInterceptionResponse> _new;
private readonly ConcurrentDictionary<string, HttpInterceptionResponse> _new;

internal OptionsScope(HttpClientInterceptorOptions parent)
{
Expand Down
15 changes: 4 additions & 11 deletions src/HttpClientInterception/StringSyntaxAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,17 @@
namespace System.Diagnostics.CodeAnalysis;

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
internal sealed class StringSyntaxAttribute : Attribute
internal sealed class StringSyntaxAttribute(string syntax, params object?[] arguments) : Attribute
{
public const string Uri = nameof(Uri);

public StringSyntaxAttribute(string syntax)
: this(syntax, [])
{
Syntax = syntax;
Arguments = Array.Empty<object?>();
}

public StringSyntaxAttribute(string syntax, params object?[] arguments)
{
Syntax = syntax;
Arguments = arguments;
}

public string Syntax { get; }
public string Syntax { get; } = syntax;

public object?[] Arguments { get; }
public object?[] Arguments { get; } = arguments;
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,8 @@ public InterceptionBenchmarks()
ContentSerializer = new SystemTextJsonContentSerializer(),
};

#pragma warning disable CA2000
_client = _options.CreateHttpClient();
_service = RestService.For<IGitHub>(_options.CreateHttpClient("https://api.github.com"), refitSettings);

Check failure on line 71 in tests/HttpClientInterception.Benchmarks/InterceptionBenchmarks.cs

View workflow job for this annotation

GitHub Actions / code-ql

Call System.IDisposable.Dispose on object created by '_options.CreateHttpClient("https://api.github.com")' before all references to it are out of scope (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2000)

Check failure on line 71 in tests/HttpClientInterception.Benchmarks/InterceptionBenchmarks.cs

View workflow job for this annotation

GitHub Actions / code-ql

Call System.IDisposable.Dispose on object created by '_options.CreateHttpClient("https://api.github.com")' before all references to it are out of scope (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2000)

Check failure on line 71 in tests/HttpClientInterception.Benchmarks/InterceptionBenchmarks.cs

View workflow job for this annotation

GitHub Actions / code-ql

Call System.IDisposable.Dispose on object created by '_options.CreateHttpClient("https://api.github.com")' before all references to it are out of scope (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2000)

Check failure on line 71 in tests/HttpClientInterception.Benchmarks/InterceptionBenchmarks.cs

View workflow job for this annotation

GitHub Actions / code-ql

Call System.IDisposable.Dispose on object created by '_options.CreateHttpClient("https://api.github.com")' before all references to it are out of scope (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2000)
#pragma warning restore CA2000
}

[Benchmark]
Expand Down
2 changes: 0 additions & 2 deletions tests/HttpClientInterception.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Just Eat, 2017. All rights reserved.
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.

#pragma warning disable CA1852

using BenchmarkDotNet.Running;
using JustEat.HttpClientInterception;

Expand Down
4 changes: 2 additions & 2 deletions tests/HttpClientInterception.Tests/Examples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public static async Task Intercept_Http_Get_For_Raw_Bytes()
byte[] content = await client.GetByteArrayAsync("https://files.domain.com/setup.exe");

// Assert
content.ShouldBe(new byte[] { 0, 1, 2, 3, 4 });
content.ShouldBe([0, 1, 2, 3, 4]);
}

[Fact]
Expand Down Expand Up @@ -286,7 +286,7 @@ public static async Task Intercept_Custom_Http_Method()
byte[] content = await response.Content.ReadAsByteArrayAsync();

// Assert
content.ShouldBe(new byte[] { 0, 1 });
content.ShouldBe([0, 1]);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static async Task RegisterGetJson_For_With_Defaults_Registers_Interceptio
{
// Arrange
string requestUri = "https://google.com/";
string[] expected = new[] { "foo", "bar" };
string[] expected = ["foo", "bar"];

var options = new HttpClientInterceptorOptions().RegisterGetJson(requestUri, expected);

Expand Down Expand Up @@ -212,7 +212,7 @@ public static void Register_For_Array_Throws_If_Options_Is_Null()
HttpClientInterceptorOptions options = null;

// Act and Assert
Should.Throw<ArgumentNullException>(() => options.Register(Array.Empty<HttpRequestInterceptionBuilder>()), "options");
Should.Throw<ArgumentNullException>(() => options.Register([]), "options");
}

[Fact]
Expand Down Expand Up @@ -267,7 +267,7 @@ public static void ThrowsOnMissingRegistration_Throws_If_Options_Is_Null()
HttpClientInterceptorOptions options = null;

// Act and Assert
Should.Throw<ArgumentNullException>(() => options.ThrowsOnMissingRegistration(), "options");
Should.Throw<ArgumentNullException>(options.ThrowsOnMissingRegistration, "options");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2212,7 +2212,7 @@ public static async Task Builder_For_Posted_Json_To_Match_Intercepts_Requests_Th
public static void Builder_ForAll_Throws_ArgumentNullException_If_Custom_Matching_Delegate_Is_Null()
{
// Arrange
HttpRequestInterceptionBuilder InterceptionBuilder() =>
static HttpRequestInterceptionBuilder InterceptionBuilder() =>
new HttpRequestInterceptionBuilder()
.Requests()
.ForHttps()
Expand All @@ -2230,7 +2230,7 @@ HttpRequestInterceptionBuilder InterceptionBuilder() =>
public static void Builder_ForAll_Throws_InvalidOperationException_If_Custom_Matching_Delegate_Is_Empty()
{
// Arrange
HttpRequestInterceptionBuilder InterceptionBuilder() =>
static HttpRequestInterceptionBuilder InterceptionBuilder() =>
new HttpRequestInterceptionBuilder()
.Requests()
.ForHttps()
Expand All @@ -2248,7 +2248,7 @@ HttpRequestInterceptionBuilder InterceptionBuilder() =>
public static void Builder_ForAll_Throws_ArgumentNullException_If_Async_Custom_Matching_Delegate_Is_Null()
{
// Arrange
HttpRequestInterceptionBuilder InterceptionBuilder() =>
static HttpRequestInterceptionBuilder InterceptionBuilder() =>
new HttpRequestInterceptionBuilder()
.Requests()
.ForHttps()
Expand All @@ -2266,7 +2266,7 @@ HttpRequestInterceptionBuilder InterceptionBuilder() =>
public static void Builder_ForAll_Throws_InvalidOperationException_If_Async_Custom_Matching_Delegate_Is_Empty()
{
// Arrange
HttpRequestInterceptionBuilder InterceptionBuilder() =>
static HttpRequestInterceptionBuilder InterceptionBuilder() =>
new HttpRequestInterceptionBuilder()
.Requests()
.ForHttps()
Expand All @@ -2284,7 +2284,7 @@ HttpRequestInterceptionBuilder InterceptionBuilder() =>
public static void Builder_ForAll_Throws_InvalidOperationException_If_At_Least_One_Async_Custom_Matching_Delegate_Is_Null()
{
// Arrange
HttpRequestInterceptionBuilder InterceptionBuilder() =>
static HttpRequestInterceptionBuilder InterceptionBuilder() =>
new HttpRequestInterceptionBuilder()
.Requests()
.ForHttps()
Expand All @@ -2302,7 +2302,7 @@ HttpRequestInterceptionBuilder InterceptionBuilder() =>
public static void Builder_ForAll_Throws_InvalidOperationException_If_At_Least_One_Custom_Matching_Delegate_Is_Null()
{
// Arrange
HttpRequestInterceptionBuilder InterceptionBuilder() =>
static HttpRequestInterceptionBuilder InterceptionBuilder() =>
new HttpRequestInterceptionBuilder()
.Requests()
.ForHttps()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static async Task SendAsync_Calls_OnSend_With_RequestMessage()
var requestUrl = "https://google.com/foo";

var options = new HttpClientInterceptorOptions()
.RegisterByteArray(HttpMethod.Get, new Uri(requestUrl), () => Array.Empty<byte>());
.RegisterByteArray(HttpMethod.Get, new Uri(requestUrl), Array.Empty<byte>);

int expected = 7;
int actual = 0;
Expand Down

0 comments on commit ff95327

Please sign in to comment.