Skip to content

Commit 25922ce

Browse files
Upgrade to support .NET 9 (#2275)
* Upgrade to support .NET 9 * Update build targets
1 parent ad6af08 commit 25922ce

File tree

14 files changed

+138
-119
lines changed

14 files changed

+138
-119
lines changed

.github/workflows/pull-request.yml

+17-3
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,22 @@ jobs:
2323
runs-on: windows-latest
2424
strategy:
2525
matrix:
26-
dotnet: ['net48', 'net6.0', 'net7.0', 'net8.0']
26+
dotnet: ['net48', 'net8.0', 'net9.0']
2727

2828
steps:
2929
-
3030
name: Checkout
3131
uses: actions/checkout@v4
32+
-
33+
name: Setup .NET
34+
uses: actions/setup-dotnet@v4
35+
with:
36+
dotnet-version: |
37+
8.0.x
38+
9.0.x
3239
-
3340
name: Run tests
34-
run: dotnet test -f ${{ matrix.dotnet }}
41+
run: dotnet test -c Debug -f ${{ matrix.dotnet }}
3542
-
3643
name: Upload Test Results
3744
if: always()
@@ -47,12 +54,19 @@ jobs:
4754
runs-on: ubuntu-latest
4855
strategy:
4956
matrix:
50-
dotnet: ['net6.0', 'net7.0', 'net8.0']
57+
dotnet: ['net8.0', 'net9.0']
5158

5259
steps:
5360
-
5461
name: Checkout
5562
uses: actions/checkout@v4
63+
-
64+
name: Setup .NET
65+
uses: actions/setup-dotnet@v4
66+
with:
67+
dotnet-version: |
68+
8.0.x
69+
9.0.x
5670
-
5771
name: Run tests
5872
run: dotnet test -f ${{ matrix.dotnet }}

Directory.Packages.props

+44-47
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,46 @@
11
<Project>
2-
<PropertyGroup>
3-
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4-
</PropertyGroup>
5-
<PropertyGroup Label="Package versions for .NET 6" Condition="$(TargetFramework) == 'net6.0'">
6-
<MicrosoftTestHostVer>[6.0.28,7)</MicrosoftTestHostVer>
7-
</PropertyGroup>
8-
<PropertyGroup Label="Package versions for .NET 7" Condition="$(TargetFramework) == 'net7.0'">
9-
<MicrosoftTestHostVer>7.0.17</MicrosoftTestHostVer>
10-
</PropertyGroup>
11-
<PropertyGroup Label="Package versions for .NET 8" Condition="$(TargetFramework) == 'net8.0'">
12-
<MicrosoftTestHostVer>8.0.3</MicrosoftTestHostVer>
13-
</PropertyGroup>
14-
<ItemGroup Label="Runtime dependencies">
15-
<PackageVersion Include="HttpMultipartParser" Version="8.4.0" />
16-
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
17-
<PackageVersion Include="CsvHelper" Version="33.0.1" />
18-
<PackageVersion Include="PolySharp" Version="1.14.1" />
19-
<PackageVersion Include="System.Text.Json" Version="8.0.4" />
20-
<PackageVersion Include="WireMock.Net" Version="1.5.60" />
21-
<PackageVersion Include="WireMock.Net.FluentAssertions" Version="1.5.51" />
22-
</ItemGroup>
23-
<ItemGroup Label="Compile dependencies">
24-
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
25-
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" />
26-
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
27-
<PackageVersion Include="MinVer" Version="5.0.0" />
28-
<PackageVersion Include="Nullable" Version="1.3.1" />
29-
<PackageVersion Include="Microsoft.NETFramework.ReferenceAssemblies.net472" Version="1.0.3" />
30-
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
31-
<PackageVersion Include="JetBrains.Annotations" Version="2024.2.0" />
32-
</ItemGroup>
33-
<ItemGroup Label="Testing dependencies">
34-
<PackageVersion Include="AutoFixture" Version="4.18.1" />
35-
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
36-
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
37-
<PackageVersion Include="HttpTracer" Version="2.1.1" />
38-
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="$(MicrosoftTestHostVer)" />
39-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
40-
<PackageVersion Include="Moq" Version="4.20.70" />
41-
<PackageVersion Include="Polly" Version="8.4.1" />
42-
<PackageVersion Include="rest-mock-core" Version="0.7.12" />
43-
<PackageVersion Include="RichardSzalay.MockHttp" Version="7.0.0" />
44-
<PackageVersion Include="System.Net.Http.Json" Version="8.0.0" />
45-
<PackageVersion Include="Xunit.Extensions.Logging" Version="1.1.0" />
46-
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" PrivateAssets="All" />
47-
<PackageVersion Include="xunit" Version="2.9.0" />
48-
</ItemGroup>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
<PropertyGroup Label="Package versions for .NET 8" Condition="$(TargetFramework) == 'net8.0'">
6+
<MicrosoftTestHostVer>8.0.3</MicrosoftTestHostVer>
7+
</PropertyGroup>
8+
<PropertyGroup Label="Package versions for .NET 9" Condition="$(TargetFramework) == 'net9.0'">
9+
<MicrosoftTestHostVer>9.0.0</MicrosoftTestHostVer>
10+
</PropertyGroup>
11+
<ItemGroup Label="Runtime dependencies">
12+
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3"/>
13+
<PackageVersion Include="CsvHelper" Version="33.0.1"/>
14+
<PackageVersion Include="System.Text.Json" Version="9.0.0"/>
15+
</ItemGroup>
16+
<ItemGroup Label="Compile dependencies">
17+
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0"/>
18+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0"/>
19+
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0"/>
20+
<PackageVersion Include="MinVer" Version="6.0.0"/>
21+
<PackageVersion Include="Nullable" Version="1.3.1"/>
22+
<PackageVersion Include="Microsoft.NETFramework.ReferenceAssemblies.net472" Version="1.0.3"/>
23+
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0"/>
24+
<PackageVersion Include="JetBrains.Annotations" Version="2024.3.0"/>
25+
</ItemGroup>
26+
<ItemGroup Label="Testing dependencies">
27+
<PackageVersion Include="HttpMultipartParser" Version="8.4.0"/>
28+
<PackageVersion Include="PolySharp" Version="1.15.0"/>
29+
<PackageVersion Include="AutoFixture" Version="4.18.1"/>
30+
<PackageVersion Include="coverlet.collector" Version="6.0.2"/>
31+
<PackageVersion Include="FluentAssertions" Version="7.0.0"/>
32+
<PackageVersion Include="HttpTracer" Version="2.1.1"/>
33+
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="$(MicrosoftTestHostVer)"/>
34+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
35+
<PackageVersion Include="Moq" Version="4.20.72"/>
36+
<PackageVersion Include="Polly" Version="8.5.0"/>
37+
<PackageVersion Include="rest-mock-core" Version="0.7.12"/>
38+
<PackageVersion Include="RichardSzalay.MockHttp" Version="7.0.0"/>
39+
<PackageVersion Include="System.Net.Http.Json" Version="9.0.0"/>
40+
<PackageVersion Include="Xunit.Extensions.Logging" Version="1.1.0"/>
41+
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" PrivateAssets="All"/>
42+
<PackageVersion Include="xunit" Version="2.9.2"/>
43+
<PackageVersion Include="WireMock.Net" Version="1.6.10"/>
44+
<PackageVersion Include="WireMock.Net.FluentAssertions" Version="1.5.51"/>
45+
</ItemGroup>
4946
</Project>

benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<OutputType>Exe</OutputType>
4-
<TargetFramework>net7.0</TargetFramework>
4+
<TargetFramework>net9.0</TargetFramework>
55
<IsPackable>false</IsPackable>
66
<LangVersion>preview</LangVersion>
77
<ImplicitUsings>enable</ImplicitUsings>

gen/SourceGenerator/Extensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public static IEnumerable<ClassDeclarationSyntax> FindClasses(this Compilation c
2121
.SelectMany(model => model.SyntaxTree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>())
2222
.Where(predicate);
2323

24-
public static IEnumerable<ClassDeclarationSyntax> FindAnnotatedClass(this Compilation compilation, string attributeName, bool strict) {
24+
public static IEnumerable<ClassDeclarationSyntax> FindAnnotatedClasses(this Compilation compilation, string attributeName, bool strict) {
2525
return compilation.FindClasses(
2626
syntax => syntax.AttributeLists.Any(list => list.Attributes.Any(CheckAttribute))
2727
);

gen/SourceGenerator/ImmutableGenerator.cs

+20-10
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,28 @@
1515

1616
namespace SourceGenerator;
1717

18-
[Generator]
19-
public class ImmutableGenerator : ISourceGenerator {
20-
public void Initialize(GeneratorInitializationContext context) { }
21-
22-
public void Execute(GeneratorExecutionContext context) {
23-
var compilation = context.Compilation;
18+
[Generator(LanguageNames.CSharp)]
19+
public class ImmutableGenerator : IIncrementalGenerator {
20+
public void Initialize(IncrementalGeneratorInitializationContext context) {
21+
var c = context.CompilationProvider.SelectMany((x, _) => GetImmutableClasses(x));
22+
23+
context.RegisterSourceOutput(
24+
c.Collect(),
25+
static (ctx, sources) => {
26+
foreach (var source in sources) {
27+
ctx.AddSource(source.Item1, source.Item2);
28+
}
29+
}
30+
);
31+
return;
2432

25-
var mutableClasses = compilation.FindAnnotatedClass("GenerateImmutable", strict: true);
33+
IEnumerable<(string, SourceText)> GetImmutableClasses(Compilation compilation) {
34+
var mutableClasses = compilation.FindAnnotatedClasses("GenerateImmutable", strict: true);
2635

27-
foreach (var mutableClass in mutableClasses) {
28-
var immutableClass = GenerateImmutableClass(mutableClass, compilation);
29-
context.AddSource($"ReadOnly{mutableClass.Identifier.Text}.cs", SourceText.From(immutableClass, Encoding.UTF8));
36+
foreach (var mutableClass in mutableClasses) {
37+
var immutableClass = GenerateImmutableClass(mutableClass, compilation);
38+
yield return ($"ReadOnly{mutableClass.Identifier.Text}.cs", SourceText.From(immutableClass, Encoding.UTF8));
39+
}
3040
}
3141
}
3242

gen/SourceGenerator/InheritedCloneGenerator.cs

+36-29
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,44 @@
1414

1515
namespace SourceGenerator;
1616

17-
[Generator]
18-
public class InheritedCloneGenerator : ISourceGenerator {
17+
[Generator(LanguageNames.CSharp)]
18+
public class InheritedCloneGenerator : IIncrementalGenerator {
1919
const string AttributeName = "GenerateClone";
2020

21-
public void Initialize(GeneratorInitializationContext context) { }
22-
23-
public void Execute(GeneratorExecutionContext context) {
24-
var compilation = context.Compilation;
25-
26-
var candidates = compilation.FindAnnotatedClass(AttributeName, false);
27-
28-
foreach (var candidate in candidates) {
29-
var semanticModel = compilation.GetSemanticModel(candidate.SyntaxTree);
30-
var genericClassSymbol = semanticModel.GetDeclaredSymbol(candidate);
31-
if (genericClassSymbol == null) continue;
32-
33-
// Get the method name from the attribute Name argument
34-
var attributeData = genericClassSymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass?.Name == $"{AttributeName}Attribute");
35-
var methodName = (string)attributeData.NamedArguments.FirstOrDefault(arg => arg.Key == "Name").Value.Value;
36-
37-
// Get the generic argument type where properties need to be copied from
38-
var attributeSyntax = candidate.AttributeLists
39-
.SelectMany(l => l.Attributes)
40-
.FirstOrDefault(a => a.Name.ToString().StartsWith(AttributeName));
41-
if (attributeSyntax == null) continue; // This should never happen
42-
43-
var typeArgumentSyntax = ((GenericNameSyntax)attributeSyntax.Name).TypeArgumentList.Arguments[0];
44-
var typeSymbol = (INamedTypeSymbol)semanticModel.GetSymbolInfo(typeArgumentSyntax).Symbol;
45-
46-
var code = GenerateMethod(candidate, genericClassSymbol, typeSymbol, methodName);
47-
context.AddSource($"{genericClassSymbol.Name}.Clone.g.cs", SourceText.From(code, Encoding.UTF8));
21+
public void Initialize(IncrementalGeneratorInitializationContext context) {
22+
var c = context.CompilationProvider.SelectMany((x, _) => GetClones(x));
23+
24+
context.RegisterSourceOutput(
25+
c.Collect(),
26+
static (ctx, sources) => {
27+
foreach (var source in sources) {
28+
ctx.AddSource(source.Item1, source.Item2);
29+
}
30+
}
31+
);
32+
return;
33+
34+
IEnumerable<(string, SourceText)> GetClones(Compilation compilation) {
35+
var candidates = compilation.FindAnnotatedClasses(AttributeName, false);
36+
37+
foreach (var candidate in candidates) {
38+
var semanticModel = compilation.GetSemanticModel(candidate.SyntaxTree);
39+
var genericClassSymbol = semanticModel.GetDeclaredSymbol(candidate);
40+
if (genericClassSymbol == null) continue;
41+
42+
var attributeData = genericClassSymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass?.Name == $"{AttributeName}Attribute");
43+
var methodName = (string)attributeData.NamedArguments.FirstOrDefault(arg => arg.Key == "Name").Value.Value;
44+
var baseType = attributeData.NamedArguments.FirstOrDefault(arg => arg.Key == "BaseType").Value.Value;
45+
46+
// Get the generic argument type where properties need to be copied from
47+
var attributeSyntax = candidate.AttributeLists
48+
.SelectMany(l => l.Attributes)
49+
.FirstOrDefault(a => a.Name.ToString().StartsWith(AttributeName));
50+
if (attributeSyntax == null) continue; // This should never happen
51+
52+
var code = GenerateMethod(candidate, genericClassSymbol, (INamedTypeSymbol)baseType, methodName);
53+
yield return ($"{genericClassSymbol.Name}.Clone.g.cs", SourceText.From(code, Encoding.UTF8));
54+
}
4855
}
4956
}
5057

src/Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'RestSharp.sln'))\props\Common.props"/>
33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net471;net48;net6.0;net7.0;net8.0</TargetFrameworks>
4+
<TargetFrameworks>netstandard2.0;net471;net48;net8.0;net9.0</TargetFrameworks>
55
<PackageIcon>restsharp.png</PackageIcon>
66
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
77
<PackageProjectUrl>https://restsharp.dev</PackageProjectUrl>

src/RestSharp/Authenticators/OAuth/OAuthTools.cs

-6
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,6 @@ public static string GetNonce() {
8383
/// </summary>
8484
/// <param name="value">The value to escape.</param>
8585
/// <returns>The escaped value.</returns>
86-
/// <remarks>
87-
/// The <see cref="Uri.EscapeDataString" /> method is <i>supposed</i> to take on
88-
/// RFC 3986 behavior if certain elements are present in a .config file. Even if this
89-
/// actually worked (which in my experiments it <i>doesn't</i>), we can't rely on every
90-
/// host actually having this configuration element present.
91-
/// </remarks>
9286
[return: NotNullIfNotNull(nameof(value))]
9387
public static string? UrlEncodeRelaxed(string? value) {
9488
if (value == null) return null;

src/RestSharp/Extensions/GenerateImmutableAttribute.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ namespace RestSharp.Extensions;
1919
class GenerateImmutableAttribute : Attribute;
2020

2121
[AttributeUsage(AttributeTargets.Class)]
22-
class GenerateCloneAttribute<T> : Attribute where T : class {
23-
public string? Name { get; set; }
22+
class GenerateCloneAttribute : Attribute {
23+
public Type? BaseType { get; set; }
24+
public string? Name { get; set; }
2425
};
2526

2627
[AttributeUsage(AttributeTargets.Property)]

src/RestSharp/Options/RestClientOptions.cs

-10
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,6 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
181181
/// </summary>
182182
public CookieContainer? CookieContainer { get; set; }
183183

184-
/// <summary>
185-
/// Maximum request duration in milliseconds. When the request timeout is specified using <seealso cref="RestRequest.Timeout"/>,
186-
/// the lowest value between the client timeout and request timeout will be used.
187-
/// </summary>
188-
[Obsolete("Use Timeout instead.")]
189-
public int MaxTimeout {
190-
get => (int) (Timeout?.TotalMilliseconds ?? 0);
191-
set => Timeout = TimeSpan.FromMilliseconds(value);
192-
}
193-
194184
/// <summary>
195185
/// Request duration. Used when the request timeout is not specified using <seealso cref="RestRequest.Timeout"/>,
196186
/// </summary>

src/RestSharp/Response/RestResponse.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace RestSharp;
2424
/// Container for data sent back from API including deserialized data
2525
/// </summary>
2626
/// <typeparam name="T">Type of data to deserialize to</typeparam>
27-
[GenerateClone<RestResponse>(Name = "FromResponse")]
27+
[GenerateClone(BaseType = typeof(RestResponse), Name = "FromResponse")]
2828
[DebuggerDisplay($"{{{nameof(DebuggerDisplay)}()}}")]
2929
public partial class RestResponse<T>(RestRequest request) : RestResponse(request) {
3030
/// <summary>

src/RestSharp/RestSharp.csproj

+12-6
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
<ItemGroup Condition="$(AddPolyfills) == 'true'">
1313
<PackageReference Include="Nullable" PrivateAssets="All"/>
1414
</ItemGroup>
15-
<ItemGroup Condition="$(AddSystemTextJson) == 'true'">
16-
<PackageReference Include="System.Text.Json"/>
17-
</ItemGroup>
1815
<ItemGroup>
1916
<Compile Update="RestClient.Extensions.Params.cs">
2017
<DependentUpon>RestClient.Extensions.cs</DependentUpon>
@@ -63,12 +60,21 @@
6360
</Compile>
6461
</ItemGroup>
6562
<ItemGroup Label="Source generator">
66-
<ProjectReference Include="$(RepoRoot)\gen\SourceGenerator\SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
63+
<ProjectReference Include="$(RepoRoot)\gen\SourceGenerator\SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
6764
</ItemGroup>
6865
<ItemGroup Label="Package README">
69-
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
66+
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
7067
</ItemGroup>
7168
<ItemGroup>
72-
<Using Include="System.Net"/>
69+
<Using Include="System.Net" />
70+
</ItemGroup>
71+
<ItemGroup Condition="'$(TargetFramework)' == 'net471'">
72+
<PackageReference Include="System.Text.Json" />
73+
</ItemGroup>
74+
<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
75+
<PackageReference Include="System.Text.Json" />
76+
</ItemGroup>
77+
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
78+
<PackageReference Include="System.Text.Json" />
7379
</ItemGroup>
7480
</Project>

test/Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<IsTestProject>true</IsTestProject>
55
<IsPackable>false</IsPackable>
6-
<TargetFrameworks>net48;net6.0;net7.0;net8.0</TargetFrameworks>
6+
<TargetFrameworks>net48;net8.0;net9.0</TargetFrameworks>
77
<Nullable>disable</Nullable>
88
<NoWarn>xUnit1033</NoWarn>
99
<VSTestLogger>trx%3bLogFileName=$(MSBuildProjectName).trx</VSTestLogger>

test/RestSharp.InteractiveTests/RestSharp.InteractiveTests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<OutputType>Exe</OutputType>
44
<IsTestProject>false</IsTestProject>
5-
<TargetFramework>net6.0</TargetFramework>
5+
<TargetFramework>net9.0</TargetFramework>
66
</PropertyGroup>
77
<ItemGroup>
88
<ProjectReference Include="$(RepoRoot)\src\RestSharp\RestSharp.csproj" />

0 commit comments

Comments
 (0)