Skip to content
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
<None Include="$(RepositoryRoot)README.md" Pack="true" PackagePath="\"/>
</ItemGroup>

<ItemGroup>
<Compile Remove="$(CompilerGeneratedFilesOutputPath)\**\*.cs"/>
</ItemGroup>

<ItemGroup Condition="'$(IsTestProject)' == 'true'">
<None Include="$(MSBuildThisFileDirectory)testconfig.json">
<Link>$(AssemblyName).testconfig.json</Link>
Expand Down
6 changes: 6 additions & 0 deletions src/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@
<Target Name="ValidateNugetProperties" Condition="!$(IsTestProject) or $(IsTestProject) == ''" BeforeTargets="Compile">
<Error Condition="$(PackageDescription) == '' or $(PackageDescription) == $(DefaultPackageDescription)" Text="The Nuget PackageDescription property needs to be set for the project. Currently : '$(PackageDescription)'"/>
</Target>

<Target Name="RemoveReactiveUIPrimitivesR3BridgeAnalyzer" AfterTargets="ResolveLockFileAnalyzers">
<ItemGroup>
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.NuGetPackageId)' == 'ReactiveUI.Primitives' and '%(Analyzer.Filename)%(Analyzer.Extension)' == 'ReactiveUI.Primitives.R3Bridge.Generator.dll'"/>
</ItemGroup>
</Target>
</Project>
3 changes: 1 addition & 2 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<PropertyGroup Label="Shared Version Variables">
<PrimitivesVersion>5.4.0</PrimitivesVersion>
<PrimitivesVersion>5.6.0</PrimitivesVersion>
<TUnitVersion>1.56.0</TUnitVersion>
</PropertyGroup>

Expand All @@ -28,7 +28,6 @@
<!-- Core runtime / serialization dependencies -->
<ItemGroup Label="Core Runtime And Serialization">
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4"/>
<PackageVersion Include="System.Reactive" Version="6.1.0"/>
</ItemGroup>


Expand Down
6 changes: 2 additions & 4 deletions src/Refit.Newtonsoft.Json/NewtonsoftJsonContentSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,11 @@ public NewtonsoftJsonContentSerializer()
"AOT",
"IL3050:Calling members annotated with RequiresDynamicCodeAttribute may break when AOT compiling",
Justification = "Interface method is unannotated on net8.0+ so cannot propagate; Newtonsoft path is documented as unsuitable for trimmed/AOT apps.")]
public HttpContent ToHttpContent<T>(T item)
{
return new StringContent(
public HttpContent ToHttpContent<T>(T item) =>
new StringContent(
JsonConvert.SerializeObject(item, _jsonSerializerSettings.Value),
Encoding.UTF8,
"application/json");
}

/// <inheritdoc/>
[UnconditionalSuppressMessage(
Expand Down
12 changes: 0 additions & 12 deletions src/Refit/AnonymousDisposable.cs

This file was deleted.

12 changes: 4 additions & 8 deletions src/Refit/ApiResponse{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,23 +129,19 @@ public ApiResponse(
/// <returns>The current <see cref="ApiResponse{T}"/></returns>
/// <exception cref="ApiException">Thrown when an unsuccessful response was received from the server.</exception>
/// <exception cref="ApiRequestException">Thrown when the request failed before receiving a response from the server.</exception>
public Task<ApiResponse<T>> EnsureSuccessStatusCodeAsync()
{
return IsSuccessStatusCode
public Task<ApiResponse<T>> EnsureSuccessStatusCodeAsync() =>
IsSuccessStatusCode
? Task.FromResult(this)
: EnsureSlowAsync();
}

/// <summary>Ensures the request was successful and without any other error by throwing an exception in case of failure.</summary>
/// <returns>The current <see cref="ApiResponse{T}"/></returns>
/// <exception cref="ApiException">Thrown when an unsuccessful response was received from the server.</exception>
/// <exception cref="ApiRequestException">Thrown when the request failed before receiving a response from the server.</exception>
public Task<ApiResponse<T>> EnsureSuccessfulAsync()
{
return IsSuccessful
public Task<ApiResponse<T>> EnsureSuccessfulAsync() =>
IsSuccessful
? Task.FromResult(this)
: EnsureSlowAsync();
}

/// <inheritdoc/>
[SuppressMessage(
Expand Down
1 change: 1 addition & 0 deletions src/Refit/Refit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

<ItemGroup>
<InternalsVisibleTo Include="Refit.Tests"/>
<PackageReference Include="ReactiveUI.Primitives" ExcludeAssets="analyzers"/>
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 2 additions & 4 deletions src/Refit/RequestBuilderImplementation.Execution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,8 @@ await RequestExecutionHelpers.SendVoidAsync(
Justification = "Type parameter intentionally specified explicitly by callers.")]
[RequiresDynamicCode("Serializing a body by runtime Type requires runtime generic method instantiation.")]
private Func<HttpClient, CancellationToken, object[], Task<T?>> BuildCancellableTaskFuncForMethod<T, TBody>(
RestMethodInfoInternal restMethod)
{
return async (client, ct, paramList) =>
RestMethodInfoInternal restMethod) =>
async (client, ct, paramList) =>
{
RequestExecutionHelpers.ThrowIfBaseAddressMissing(client);

Expand All @@ -120,7 +119,6 @@ await RequestExecutionHelpers.SendVoidAsync(
request?.Dispose();
}
};
}

/// <summary>Processes a response for a reflection-built request using the shared runtime state machine.</summary>
/// <typeparam name="T">The result type returned to the caller.</typeparam>
Expand Down
93 changes: 0 additions & 93 deletions src/Refit/RequestBuilderImplementation.TaskToObservable.cs

This file was deleted.

19 changes: 10 additions & 9 deletions src/Refit/RequestBuilderImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using ReactiveUI.Primitives.Advanced;

namespace Refit
{
/// <summary>Reflection-based request builder that turns Refit interface calls into HTTP requests.</summary>
[SuppressMessage(
"Minor Code Smell",
"SST1432:Mark type as static",
Justification = "False positive: this is one part of a partial class whose other parts declare instance members; the type cannot be static.")]
internal partial class RequestBuilderImplementation : IRequestBuilder
{
/// <summary>Maximum stack-allocated buffer size, in characters, used when building paths and query strings.</summary>
Expand Down Expand Up @@ -441,17 +446,15 @@ private RestMethodInfoInternal CloseGenericMethodIfNeeded(
Justification = "Type parameter intentionally specified explicitly by callers.")]
[RequiresDynamicCode("Serializing a body by runtime Type requires runtime generic method instantiation.")]
private Func<HttpClient, object[], object?> BuildGeneratedSyncFuncForMethodGeneric<T, TBody>(
RestMethodInfoInternal restMethod)
{
return (client, paramList) =>
RestMethodInfoInternal restMethod) =>
(client, paramList) =>
RunSynchronous(() =>
ExecuteRequestAsync<T, TBody>(
client,
restMethod,
paramList,
paramsContainsCancellationToken: false,
CancellationToken.None));
}

/// <summary>Builds an observable invocation delegate for a method.</summary>
/// <typeparam name="T">The result type returned to the caller.</typeparam>
Expand All @@ -469,7 +472,7 @@ private RestMethodInfoInternal CloseGenericMethodIfNeeded(
var taskFunc = BuildCancellableTaskFuncForMethod<T, TBody>(restMethod);

return (client, paramList) =>
new TaskToObservable<T>(ct =>
new FromAsyncSignal<T?>(ct =>
{
var methodCt = CancellationToken.None;
if (restMethod.CancellationToken is not null)
Expand Down Expand Up @@ -539,9 +542,8 @@ private RestMethodInfoInternal CloseGenericMethodIfNeeded(
/// <returns>A delegate that returns a task with no result.</returns>
[RequiresDynamicCode("Serializing a body by runtime Type requires runtime generic method instantiation.")]
private Func<HttpClient, object[], Task> BuildVoidTaskFuncForMethod(
RestMethodInfoInternal restMethod)
{
return (client, paramList) =>
RestMethodInfoInternal restMethod) =>
(client, paramList) =>
{
var ct = CancellationToken.None;

Expand All @@ -557,6 +559,5 @@ private Func<HttpClient, object[], Task> BuildVoidTaskFuncForMethod(
restMethod.CancellationToken is not null,
ct);
};
}
}
}
2 changes: 1 addition & 1 deletion src/tests/Refit.GeneratorTests/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static class Fixture
[
typeof(Binder),
typeof(GetAttribute),
typeof(System.Reactive.Unit),
typeof(ReactiveUI.Primitives.RxVoid),
typeof(Enumerable),
typeof(Newtonsoft.Json.JsonConvert),
typeof(TestAttribute),
Expand Down
4 changes: 1 addition & 3 deletions src/tests/Refit.GeneratorTests/ParserCoverageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ public sealed class ParserCoverageTests
/// <summary>Verifies parser argument validation.</summary>
/// <returns>A task representing the asynchronous test.</returns>
[Test]
public async Task GenerateInterfaceStubsRejectsNullCompilation()
{
public async Task GenerateInterfaceStubsRejectsNullCompilation() =>
await Assert.That(
() => Parser.GenerateInterfaceStubs(
null!,
Expand All @@ -30,7 +29,6 @@ await Assert.That(
[],
CancellationToken.None))
.ThrowsExactly<ArgumentNullException>();
}

/// <summary>Verifies parser diagnostics and namespace normalization when Refit is not referenced.</summary>
/// <returns>A task representing the asynchronous test.</returns>
Expand Down
2 changes: 1 addition & 1 deletion src/tests/Refit.GeneratorTests/Refit.GeneratorTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PackageReference Include="Verify.DiffPlex" />
<PackageReference Include="Verify.SourceGenerators" />
<PackageReference Include="Verify.TUnit" />
<PackageReference Include="System.Reactive" />
<PackageReference Include="ReactiveUI.Primitives" ExcludeAssets="analyzers" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing" />
<ProjectReference Include="..\..\Refit.Newtonsoft.Json\Refit.Newtonsoft.Json.csproj" />
Expand Down
4 changes: 1 addition & 3 deletions src/tests/Refit.Tests/FormValueMultimapTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ public async Task EmptyIfNullPassedIn()
/// <summary>Verifies a null settings instance is rejected before source processing.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Test]
public async Task RejectsNullSettings()
{
public async Task RejectsNullSettings() =>
await Assert.That(() => new FormValueMultimap(new object(), null!))
.ThrowsExactly<ArgumentNullException>();
}

/// <summary>Verifies the multimap loads entries from a dictionary source.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
Expand Down
41 changes: 41 additions & 0 deletions src/tests/Refit.Tests/ObservableTestHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved.
// ReactiveUI and Contributors licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using ReactiveUI.Primitives.Advanced;
using ReactiveUI.Primitives.Concurrency;
using ReactiveUI.Primitives.Signals;

namespace Refit.Tests;

/// <summary>Test helpers for awaiting observable results through concrete Primitives types.</summary>
internal static class ObservableTestHelpers
{
/// <summary>The timeout used by observable integration tests.</summary>
private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(10);

/// <summary>Wraps the source in a timeout signal.</summary>
/// <typeparam name="T">The observable value type.</typeparam>
/// <param name="source">The source observable.</param>
/// <returns>A timeout-wrapped observable.</returns>
public static IObservable<T> WithTimeout<T>(IObservable<T> source) =>
new ExpireSignal<T>(source, DefaultTimeout, ThreadPoolSequencer.Instance);

/// <summary>Awaits the timeout-wrapped source.</summary>
/// <typeparam name="T">The observable value type.</typeparam>
/// <param name="source">The source observable.</param>
/// <returns>The final observable value.</returns>
public static Task<T> AwaitWithTimeout<T>(IObservable<T> source) =>
Await(WithTimeout(source));

/// <summary>Awaits the source through a concrete Primitives await signal.</summary>
/// <typeparam name="T">The observable value type.</typeparam>
/// <param name="source">The source observable.</param>
/// <returns>The final observable value.</returns>
public static async Task<T> Await<T>(IObservable<T> source)
{
AsyncSignal<T> signal = new();
using var subscription = source.Subscribe(signal);
return await signal;
}
}
2 changes: 1 addition & 1 deletion src/tests/Refit.Tests/Refit.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" />
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" />
<PackageReference Include="Moq" />
<PackageReference Include="ReactiveUI.Primitives" ExcludeAssets="analyzers" />
<PackageReference Include="TUnit" />
<PackageReference Include="System.Reactive" />
<PackageReference Include="RichardSzalay.MockHttp" />
<ProjectReference Include="..\..\Refit.HttpClientFactory\Refit.HttpClientFactory.csproj" />
<ProjectReference Include="..\..\Refit.Newtonsoft.Json\Refit.Newtonsoft.Json.csproj" />
Expand Down
Loading
Loading