diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index fa1806ee4..8c1faff17 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -23,15 +23,22 @@ jobs:
runs-on: windows-latest
strategy:
matrix:
- dotnet: ['net48', 'net6.0', 'net7.0', 'net8.0']
+ dotnet: ['net48', 'net8.0', 'net9.0']
steps:
-
name: Checkout
uses: actions/checkout@v4
+ -
+ name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 9.0.x
-
name: Run tests
- run: dotnet test -f ${{ matrix.dotnet }}
+ run: dotnet test -c Debug -f ${{ matrix.dotnet }}
-
name: Upload Test Results
if: always()
@@ -47,12 +54,19 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- dotnet: ['net6.0', 'net7.0', 'net8.0']
+ dotnet: ['net8.0', 'net9.0']
steps:
-
name: Checkout
uses: actions/checkout@v4
+ -
+ name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 9.0.x
-
name: Run tests
run: dotnet test -f ${{ matrix.dotnet }}
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 61c85f4c3..ed1fd4b2e 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,49 +1,46 @@
-
- true
-
-
- [6.0.28,7)
-
-
- 7.0.17
-
-
- 8.0.3
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ true
+
+
+ 8.0.3
+
+
+ 9.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj b/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj
index f60295a8f..3d939e0fb 100644
--- a/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj
+++ b/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj
@@ -1,7 +1,7 @@
Exe
- net7.0
+ net9.0
false
preview
enable
diff --git a/gen/SourceGenerator/Extensions.cs b/gen/SourceGenerator/Extensions.cs
index 12daff3e6..f529412a1 100644
--- a/gen/SourceGenerator/Extensions.cs
+++ b/gen/SourceGenerator/Extensions.cs
@@ -21,7 +21,7 @@ public static IEnumerable FindClasses(this Compilation c
.SelectMany(model => model.SyntaxTree.GetRoot().DescendantNodes().OfType())
.Where(predicate);
- public static IEnumerable FindAnnotatedClass(this Compilation compilation, string attributeName, bool strict) {
+ public static IEnumerable FindAnnotatedClasses(this Compilation compilation, string attributeName, bool strict) {
return compilation.FindClasses(
syntax => syntax.AttributeLists.Any(list => list.Attributes.Any(CheckAttribute))
);
diff --git a/gen/SourceGenerator/ImmutableGenerator.cs b/gen/SourceGenerator/ImmutableGenerator.cs
index 7576359bd..e0860bd67 100644
--- a/gen/SourceGenerator/ImmutableGenerator.cs
+++ b/gen/SourceGenerator/ImmutableGenerator.cs
@@ -15,18 +15,28 @@
namespace SourceGenerator;
-[Generator]
-public class ImmutableGenerator : ISourceGenerator {
- public void Initialize(GeneratorInitializationContext context) { }
-
- public void Execute(GeneratorExecutionContext context) {
- var compilation = context.Compilation;
+[Generator(LanguageNames.CSharp)]
+public class ImmutableGenerator : IIncrementalGenerator {
+ public void Initialize(IncrementalGeneratorInitializationContext context) {
+ var c = context.CompilationProvider.SelectMany((x, _) => GetImmutableClasses(x));
+
+ context.RegisterSourceOutput(
+ c.Collect(),
+ static (ctx, sources) => {
+ foreach (var source in sources) {
+ ctx.AddSource(source.Item1, source.Item2);
+ }
+ }
+ );
+ return;
- var mutableClasses = compilation.FindAnnotatedClass("GenerateImmutable", strict: true);
+ IEnumerable<(string, SourceText)> GetImmutableClasses(Compilation compilation) {
+ var mutableClasses = compilation.FindAnnotatedClasses("GenerateImmutable", strict: true);
- foreach (var mutableClass in mutableClasses) {
- var immutableClass = GenerateImmutableClass(mutableClass, compilation);
- context.AddSource($"ReadOnly{mutableClass.Identifier.Text}.cs", SourceText.From(immutableClass, Encoding.UTF8));
+ foreach (var mutableClass in mutableClasses) {
+ var immutableClass = GenerateImmutableClass(mutableClass, compilation);
+ yield return ($"ReadOnly{mutableClass.Identifier.Text}.cs", SourceText.From(immutableClass, Encoding.UTF8));
+ }
}
}
diff --git a/gen/SourceGenerator/InheritedCloneGenerator.cs b/gen/SourceGenerator/InheritedCloneGenerator.cs
index 2bc635443..76b81911e 100644
--- a/gen/SourceGenerator/InheritedCloneGenerator.cs
+++ b/gen/SourceGenerator/InheritedCloneGenerator.cs
@@ -14,37 +14,44 @@
namespace SourceGenerator;
-[Generator]
-public class InheritedCloneGenerator : ISourceGenerator {
+[Generator(LanguageNames.CSharp)]
+public class InheritedCloneGenerator : IIncrementalGenerator {
const string AttributeName = "GenerateClone";
- public void Initialize(GeneratorInitializationContext context) { }
-
- public void Execute(GeneratorExecutionContext context) {
- var compilation = context.Compilation;
-
- var candidates = compilation.FindAnnotatedClass(AttributeName, false);
-
- foreach (var candidate in candidates) {
- var semanticModel = compilation.GetSemanticModel(candidate.SyntaxTree);
- var genericClassSymbol = semanticModel.GetDeclaredSymbol(candidate);
- if (genericClassSymbol == null) continue;
-
- // Get the method name from the attribute Name argument
- var attributeData = genericClassSymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass?.Name == $"{AttributeName}Attribute");
- var methodName = (string)attributeData.NamedArguments.FirstOrDefault(arg => arg.Key == "Name").Value.Value;
-
- // Get the generic argument type where properties need to be copied from
- var attributeSyntax = candidate.AttributeLists
- .SelectMany(l => l.Attributes)
- .FirstOrDefault(a => a.Name.ToString().StartsWith(AttributeName));
- if (attributeSyntax == null) continue; // This should never happen
-
- var typeArgumentSyntax = ((GenericNameSyntax)attributeSyntax.Name).TypeArgumentList.Arguments[0];
- var typeSymbol = (INamedTypeSymbol)semanticModel.GetSymbolInfo(typeArgumentSyntax).Symbol;
-
- var code = GenerateMethod(candidate, genericClassSymbol, typeSymbol, methodName);
- context.AddSource($"{genericClassSymbol.Name}.Clone.g.cs", SourceText.From(code, Encoding.UTF8));
+ public void Initialize(IncrementalGeneratorInitializationContext context) {
+ var c = context.CompilationProvider.SelectMany((x, _) => GetClones(x));
+
+ context.RegisterSourceOutput(
+ c.Collect(),
+ static (ctx, sources) => {
+ foreach (var source in sources) {
+ ctx.AddSource(source.Item1, source.Item2);
+ }
+ }
+ );
+ return;
+
+ IEnumerable<(string, SourceText)> GetClones(Compilation compilation) {
+ var candidates = compilation.FindAnnotatedClasses(AttributeName, false);
+
+ foreach (var candidate in candidates) {
+ var semanticModel = compilation.GetSemanticModel(candidate.SyntaxTree);
+ var genericClassSymbol = semanticModel.GetDeclaredSymbol(candidate);
+ if (genericClassSymbol == null) continue;
+
+ var attributeData = genericClassSymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass?.Name == $"{AttributeName}Attribute");
+ var methodName = (string)attributeData.NamedArguments.FirstOrDefault(arg => arg.Key == "Name").Value.Value;
+ var baseType = attributeData.NamedArguments.FirstOrDefault(arg => arg.Key == "BaseType").Value.Value;
+
+ // Get the generic argument type where properties need to be copied from
+ var attributeSyntax = candidate.AttributeLists
+ .SelectMany(l => l.Attributes)
+ .FirstOrDefault(a => a.Name.ToString().StartsWith(AttributeName));
+ if (attributeSyntax == null) continue; // This should never happen
+
+ var code = GenerateMethod(candidate, genericClassSymbol, (INamedTypeSymbol)baseType, methodName);
+ yield return ($"{genericClassSymbol.Name}.Clone.g.cs", SourceText.From(code, Encoding.UTF8));
+ }
}
}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 70ef2495c..85288d985 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -1,7 +1,7 @@
- netstandard2.0;net471;net48;net6.0;net7.0;net8.0
+ netstandard2.0;net471;net48;net8.0;net9.0
restsharp.png
Apache-2.0
https://restsharp.dev
diff --git a/src/RestSharp/Authenticators/OAuth/OAuthTools.cs b/src/RestSharp/Authenticators/OAuth/OAuthTools.cs
index e8cf4102a..4c70eab8e 100644
--- a/src/RestSharp/Authenticators/OAuth/OAuthTools.cs
+++ b/src/RestSharp/Authenticators/OAuth/OAuthTools.cs
@@ -83,12 +83,6 @@ public static string GetNonce() {
///
/// The value to escape.
/// The escaped value.
- ///
- /// The method is supposed to take on
- /// RFC 3986 behavior if certain elements are present in a .config file. Even if this
- /// actually worked (which in my experiments it doesn't), we can't rely on every
- /// host actually having this configuration element present.
- ///
[return: NotNullIfNotNull(nameof(value))]
public static string? UrlEncodeRelaxed(string? value) {
if (value == null) return null;
diff --git a/src/RestSharp/Extensions/GenerateImmutableAttribute.cs b/src/RestSharp/Extensions/GenerateImmutableAttribute.cs
index 172d7c24e..1cafdb049 100644
--- a/src/RestSharp/Extensions/GenerateImmutableAttribute.cs
+++ b/src/RestSharp/Extensions/GenerateImmutableAttribute.cs
@@ -19,8 +19,9 @@ namespace RestSharp.Extensions;
class GenerateImmutableAttribute : Attribute;
[AttributeUsage(AttributeTargets.Class)]
-class GenerateCloneAttribute : Attribute where T : class {
- public string? Name { get; set; }
+class GenerateCloneAttribute : Attribute {
+ public Type? BaseType { get; set; }
+ public string? Name { get; set; }
};
[AttributeUsage(AttributeTargets.Property)]
diff --git a/src/RestSharp/Options/RestClientOptions.cs b/src/RestSharp/Options/RestClientOptions.cs
index 74fde4ef0..96ebf9df1 100644
--- a/src/RestSharp/Options/RestClientOptions.cs
+++ b/src/RestSharp/Options/RestClientOptions.cs
@@ -181,16 +181,6 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
///
public CookieContainer? CookieContainer { get; set; }
- ///
- /// Maximum request duration in milliseconds. When the request timeout is specified using ,
- /// the lowest value between the client timeout and request timeout will be used.
- ///
- [Obsolete("Use Timeout instead.")]
- public int MaxTimeout {
- get => (int) (Timeout?.TotalMilliseconds ?? 0);
- set => Timeout = TimeSpan.FromMilliseconds(value);
- }
-
///
/// Request duration. Used when the request timeout is not specified using ,
///
diff --git a/src/RestSharp/Response/RestResponse.cs b/src/RestSharp/Response/RestResponse.cs
index dc48f2ddc..62b5d569a 100644
--- a/src/RestSharp/Response/RestResponse.cs
+++ b/src/RestSharp/Response/RestResponse.cs
@@ -24,7 +24,7 @@ namespace RestSharp;
/// Container for data sent back from API including deserialized data
///
/// Type of data to deserialize to
-[GenerateClone(Name = "FromResponse")]
+[GenerateClone(BaseType = typeof(RestResponse), Name = "FromResponse")]
[DebuggerDisplay($"{{{nameof(DebuggerDisplay)}()}}")]
public partial class RestResponse(RestRequest request) : RestResponse(request) {
///
diff --git a/src/RestSharp/RestSharp.csproj b/src/RestSharp/RestSharp.csproj
index d01835924..5643d4c02 100644
--- a/src/RestSharp/RestSharp.csproj
+++ b/src/RestSharp/RestSharp.csproj
@@ -12,9 +12,6 @@
-
-
-
RestClient.Extensions.cs
@@ -63,12 +60,21 @@
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index 9ad7f24e7..b3c32f6d1 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -3,7 +3,7 @@
true
false
- net48;net6.0;net7.0;net8.0
+ net48;net8.0;net9.0
disable
xUnit1033
trx%3bLogFileName=$(MSBuildProjectName).trx
diff --git a/test/RestSharp.InteractiveTests/RestSharp.InteractiveTests.csproj b/test/RestSharp.InteractiveTests/RestSharp.InteractiveTests.csproj
index 36f53edc9..75c24e34a 100644
--- a/test/RestSharp.InteractiveTests/RestSharp.InteractiveTests.csproj
+++ b/test/RestSharp.InteractiveTests/RestSharp.InteractiveTests.csproj
@@ -2,7 +2,7 @@
Exe
false
- net6.0
+ net9.0